<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/SetOfStatesTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool;

import java.util.HashSet;
import java.util.Set;

import junit.framework.TestCase;
import tlc2.tool.queue.DummyTLCState;
import tlc2.util.SetOfStates;

public class SetOfStatesTest extends TestCase {

	public void testSizeEmpty() {
		final SetOfStates s = new SetOfStates(16);
		
		assertEquals(16, s.capacity());
		assertEquals(0, s.size());
	}

	public void testSize() {
		final SetOfStates s = new SetOfStates(16);
		s.put(new DummyTLCState(1L));

		assertEquals(16, s.capacity());
		assertEquals(1, s.size());
	}

	public void testGrow() {
		final SetOfStates s = new SetOfStates(1);
		
		for(int i = 0; i < 32; i++) {
			s.put(new DummyTLCState(i));
		}

		assertTrue(s.capacity() > 32);
		assertEquals(32, s.size());
	}

	public void testIterate() {
		final SetOfStates s = new SetOfStates(1);
		
		for(int i = 1; i <= 32; i++) {
			assertFalse(s.put(new DummyTLCState(i)));
		}
		assertEquals(32, s.size());

		// successor is not equal to predecessor
		TLCState predecessor = null;
		for (int i = 0; i < s.size(); i++) {
			TLCState state = s.next();
			assertNotSame(predecessor, state);
			predecessor = state;
		}
		s.resetNext();
		
		// The combined sum of elements is correct
		long sum = 0L;
		for (int i = 0; i < s.size(); i++) {
			final TLCState elem = s.next();
			sum += elem.fingerPrint();
		}
		assertEquals((32 / 2) * (1 + 32), sum);
	}

	public void testDuplicates() {
		final SetOfStates s = new SetOfStates(1);
		
		for(int i = 1; i <= 32; i++) {
			assertFalse(s.put(new DummyTLCState(i)));
		}
		assertEquals(32, s.size());
		
		// Adding the same elements again fails
		final Set<TLCState> states = new HashSet<TLCState>(s.size());
		for (int i = 0; i < s.size(); i++) {
			states.add(s.next());
		}
		for (TLCState aState : states) {
			assertTrue(s.put(aState));
		}
		assertEquals(32, states.size());
	}

	public void testDuplicatesButNotEqual() {
		// duplicates in terms of fingerprints, but not in terms of equality
		// (symmetry).
		final SetOfStates s = new SetOfStates(1);
		
		int id = 1;
		for(int i = 1; i <= 32; i++) {
			assertFalse(s.put(new EqualityDummyTLCState(i, id++)));
		}
		assertEquals(32, s.size());
		
		// Add 32 more elements with identical fp but different ids
		for(int i = 1; i <= 32; i++) {
			assertFalse(s.put(new EqualityDummyTLCState(i, id++)));
		}
		assertEquals(64, s.size());

		// Add 32 more elements with identical fp and ids
		id = 1;
		for(int i = 1; i <= 32; i++) {
			assertTrue(s.put(new EqualityDummyTLCState(i, id++)));
		}
		assertEquals(64, s.size());
	}
	
	@SuppressWarnings("serial")
	private static class EqualityDummyTLCState extends DummyTLCState {
		
		private final int id;

		public EqualityDummyTLCState(final int fp, final int id) {
			super(fp);
			this.id = id;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + id;
			result = (int) (prime * result + fingerPrint());
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			EqualityDummyTLCState other = (EqualityDummyTLCState) obj;
			if (fingerPrint() != other.fingerPrint())
				return false;
			if (id != other.id)
				return false;
			return true;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/concepts/model.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

	<title>Main Topic</title>
</head>

<body>
<h1>Main Topic</h1>
Please enter your text here. this is ..doc/html/concepts/model.html
<A href="blah.html">This is a link.</A>
<ul>
<li> This is a list item
</li>
</ul>
</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/LSBDiskFPsetTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.rmi.RemoteException;

public class LSBDiskFPsetTest extends AbstractHeapBasedDiskFPSetTest {
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.HeapBasedDiskFPSetTest#getDiskFPSet(tlc2.tool.fp.FPSetConfiguration)
	 */
	protected DiskFPSet getDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		return new LSBDiskFPSet(fpSetConfig);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.HeapBasedDiskFPSetTest#getLowerLimit()
	 */
	protected long getLowerLimit() {
		return 1L << 9;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractHeapBasedDiskFPSetTest#getUpperLimit()
	 */
	protected long getUpperLimit() {
		// LSBDiskFPSet uses a temporary storage array which is limited by
		// java's array length restriction. This restriction is Integer.MAX_VALUE
		return 1L << 31;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/value/impl/SubsetBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import tlc2.util.FP64;
import tlc2.value.RandomEnumerableValues;
import tlc2.value.impl.Enumerable;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.SubsetValue;

@State(Scope.Benchmark)
public class SubsetBenchmark {

	static {
		RandomEnumerableValues.setSeed(15041980L);
		RandomEnumerableValues.reset();

		FP64.Init();
	}
	
	@Param({"10", "12", "14", "16", "20", "24"})
	public int numOfElements;
	
	@Param({"32", "64", "128", "256"})
	public int size;

	public SubsetValue subset;
		
	@Setup(Level.Invocation)
	public void setup() {
		if (size < 128 || (size >= 128 && numOfElements <= 20)) {
			subset = (SubsetValue) new SubsetValue(new IntervalValue(1, size)).normalize();
		} else {
			// This appears to be the only way to skip permutations from the parameter space
			// size X numOfElements. These permutations will go OOM or reach GC overhad
			// limit anyway.
			System.exit(0);
		}
	}

	@Benchmark
	public Enumerable randomSetOfSubsets() {
		return subset.getRandomSetOfSubsets(1 << numOfElements, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetsExact() {
		return subset.getRandomSetOfSubsets(1 << numOfElements, 10);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/DeleteModelHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCOutputSourceRegistry;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

public class DeleteModelHandler extends AbstractHandler implements IHandler
{
	private static final SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss");

    /**
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    @SuppressWarnings("unchecked")
	public Object execute(ExecutionEvent event) throws ExecutionException
    {
		// Get the currently selected models from the Eclipse SelectionService
		// (Ask UI what the current selection is). The CommandFramework makes
		// sure that only Model can be part of the selection.
        final ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
        if (selection != null && selection instanceof IStructuredSelection) {
        	final IStructuredSelection iss = (IStructuredSelection) selection;

        	// 1.) get confirmation from the user to delete all files/models
        	// if user cancels, just return
			boolean userConfirmedDeletion = MessageDialog.openQuestion(
					UIHelper.getShell(), "Confirm Delete",
					getLabel(iss));
			if(!userConfirmedDeletion) {
				return null;
			}
				 
			// 2.) user has confirmed deletion
			// check if any of the models is
			// currently running a model check
			// TODO better disable delete action in spec explorer for
			// currently model checking models
			final Iterator<Model> itr1 = iss.iterator();
			for (; itr1.hasNext();) {
        		final Model model = itr1.next();
				if(model.isRunning()) {
					MessageDialog
							.openError(
									UIHelper.getShell(),
									"Could not delete a model",
									"Could not delete the model "
											+ model.getName()
											+ ", because it is being model checked.");
					return null;
				}
			}
			
			// 3.) at this point, we are safe to delete all models (user has
			// confirmed, no model is used in model checking
			// But there might be open editors corresponding to the models which have to be closed first
			final Iterator<Model> itr2 = iss.iterator();
			for (; itr2.hasNext();) {
        		final Model model = itr2.next();

        		// close corresponding editor if open
        		final IEditorPart editorWithModelOpened = model.getAdapter(ModelEditor.class);
				if (editorWithModelOpened != null) {
					UIHelper.getActivePage().closeEditor(editorWithModelOpened,
							false);
				}
			}
			
			// Remove all to be deleted Models from the Selection so that
			// other UI handlers do not handle them during the backend job
			
			// Simply convert selection to ILC[]
			final Model[] models = (Model[]) iss
			.toList().toArray(new Model[iss.size()]);

			// 3.) remove any tlc output sources corresponding to this model
			// in case the user opens a new model of the same name in
			// the same toolbox session
			TLCOutputSourceRegistry.getModelCheckSourceRegistry()
					.removeTLCStatusSource(models);
			
			// 4.) UI is in ready state
			// Defer deletion to ResourceFramework outside the UI thread (makes
			// it cancel-able too, keeps track of conflicting resource
			// modifications, ...).
			// Warp model delete operation in a WorkspaceModifyOperation to notify listeners
			// after the model delete operation has finished. In other words, for the
			// listeners a wrapped delete operation is atomic. If not done atomic, the
			// UI might read the model while it's being deleted. This can result in a NPE
			// inside the UI thread.
			final WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
				@Override
				protected void execute(IProgressMonitor monitor)
						throws CoreException, InvocationTargetException, InterruptedException {
					for (Model model : models) {
						model.delete(monitor);
					}
				}
			};
			final IRunnableContext ctxt = new ProgressMonitorDialog(UIHelper.getShell());
			try {
				ctxt.run(true, false, operation);
			} catch (InvocationTargetException | InterruptedException e) {
				throw new ExecutionException(e.getMessage(), e);
			}
		}
        return null;
    }

	private String getLabel(final IStructuredSelection iss) {
		if (iss.size() > 1) {
			// The selected models.
			@SuppressWarnings("unchecked")
			final List<Model> list = (List<Model>) iss.toList();
			final Predicate<Model> p = Model::isSnapshot;
			final Set<Model> models = list.stream().filter(p.negate()).collect(Collectors.toSet());

			if (models.isEmpty()) {
				// Only Snapshots are selected.
				return String.format("Are you sure you want to delete the %s selected snapshots?", iss.size());
			} else {
				// The set of snapshots (either explicitly selected or implicit via parent
				// model) to be deleted.
				final Set<Model> allSnapshots = list.stream().map(Model::getSnapshots).flatMap(c -> c.stream())
						.collect(Collectors.toSet());

				if (models.size() > 1 && allSnapshots.isEmpty()) {
					return String.format("Are you sure you want to delete the %s selected models?", iss.size());
				} else {
					// The set of selected snapshots to be deleted.
					final Set<Model> selectedSnapshots = list.stream().filter(Model::isSnapshot)
							.collect(Collectors.toSet());

					if (models.size() == 1) {
						// 1 Model with its snapshots and selected snapshots.
						allSnapshots.addAll(selectedSnapshots);
						return String.format("Are you sure you want to delete the select model '%s' and %s snapshot%s?",
								models.iterator().next().getName(), allSnapshots.size(),
								isPlural(allSnapshots));
					} else {
						// N models with M snapshots
						allSnapshots.addAll(selectedSnapshots);
						return String.format("Are you sure you want to delete %s models and %s snapshot%s?",
								models.size(), allSnapshots.size(), isPlural(allSnapshots));
					}
				}
			}
		}
		return getLabel((Model) iss.getFirstElement());
	}
	
	private String getLabel(Model model) {
		final Model snapshotFor = model.getSnapshotFor();
		if (snapshotFor != model) {
			return String.format("Are you sure you want to delete the snapshot of %s of model '%s'?",
					sdf.format(model.getSnapshotTimeStamp()), snapshotFor.getName());
		}
		final Collection<Model> snapshots = model.getSnapshots();
		if (!snapshots.isEmpty()) {
			return String.format("Are you sure you want to delete the model '%s' and its %s snapshot%s?", model.getName(),
					snapshots.size(), isPlural(snapshots));
		}
		return String.format("Are you sure you want to delete the model '%s'?", model.getName());
	}
	
	private static String isPlural(final Collection<?> col) {
		return col.size() > 1 ? "s" : "";
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/queue/IStateQueue.java<|end_filename|>
package tlc2.tool.queue;

import java.io.IOException;

import tlc2.tool.StateVec;
import tlc2.tool.TLCState;
import tlc2.tool.Worker;

public interface IStateQueue {

	/* Enqueues the state. It is not thread-safe. */
	public abstract void enqueue(final TLCState state);

	/**
	 * Returns the first element in the queue. It returns null if the queue is
	 * empty. It is not thread-safe.
	 */
	public abstract TLCState dequeue();

	/* Enqueues a state. Wake up any waiting thread. */
	public abstract void sEnqueue(final TLCState state);

	/* Enqueues a list of states. Wake up any waiting thread. */
	public abstract void sEnqueue(final TLCState states[]);
	public abstract void sEnqueue(final StateVec stateVec);
	
	/* Return the first element in the queue. Wait if empty. */
	public abstract TLCState sDequeue();
	
	/**
	 * Returns the first element in the queue. Wait if empty. Does not remove the
	 * element. Can be null and blocks other consumers (sEnqueue and sDequeue).
	 */
	public abstract TLCState sPeek();

	/**
	 * Return (up to) the first count elements in the queue. Wait if empty.
	 * 
	 * @param cnt
	 *            Amount of states requested
	 * @return null iff no states are available && all work is done @see
	 *         {@link #isAvail()}, states otherwise
	 * @throws RuntimeException
	 *             if cnt <= 0
	 */
	public abstract TLCState[] sDequeue(int cnt);

	/**
	 * Signals all waiting {@link Worker} that all work is done. We can exit now.
	 */
	public abstract void finishAll();

	/**
	 * Suspends all access to the {@link StateQueue} for {@link Worker},
	 * potentially waiting for current accessing {@link Worker} to finish first.
	 * 
	 * @return False iff {@link #finish} is true, true otherwise
	 */
	public abstract boolean suspendAll();

	/**
	 * Resumes waiting {@link Worker} after a checkpoint
	 */
	public abstract void resumeAll();

	/**
	 * This is a no-op in regular. The only case is, when a worker is stuck in
	 * {@link #isAvail()}, {@link #isEmpty}, {@link #stop} is false and
	 * {@link #numWaiting} > 0. Bottom-line, it is assumed to be side-effect
	 * free when workers behave correctly except for the single case when a
	 * remote worker dies unexpectedly.
	 * 
	 * @see Bug #175 in general/bugzilla/index.html
	 */
	public abstract void resumeAllStuck();

	/* This method returns the size of the state queue. */
	public abstract long size();

	/* Checkpoint. */
	public abstract void beginChkpt() throws IOException;

	public abstract void commitChkpt() throws IOException;

	public abstract void recover() throws IOException;

	public abstract boolean isEmpty();

	/**
	 * TESTING ONLY!
	 * Delete disk files if any.
	 */
	abstract void delete() throws IOException;
}

<|start_filename|>tlatools/org.lamport.tlatools/test-long/tlc2/tool/fp/DiskFPSetTest.java<|end_filename|>
package tlc2.tool.fp;

import java.io.IOException;

public class DiskFPSetTest extends FPSetTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractFPSetTest#getFPSet(int)
	 */
	@Override
	protected FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws IOException {
		final DiskFPSet fpSet = new LSBDiskFPSet(fpSetConfig);
		System.out.println("DiskFPSet approx. consumes MiB: "
				+ ((fpSet.getMaxTblCnt() * (long) FPSet.LongSize) >> 20));
    	return fpSet;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/source/DummyListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.ITypedRegion;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.ITLCOutputListener;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;

import tlc2.output.MP;

public class DummyListener implements ITLCOutputListener {

	// done has been called on the parser
	private boolean done = false;
	
	// parser has failed to parse test input
	private boolean garbage = false;
	
	// all typed regions recognized by the parser
	private List<ITypedRegion> regions = new ArrayList<ITypedRegion>();
	
	// all states found by the parser
	private List<TLCState> states = new ArrayList<TLCState>();

	public Model getModel() {
		// nop
		return null;
	}

	public void onOutput(ITypedRegion region, String text) {
		// a) just store the region
		this.regions.add(region);

		// b) convert to TLCState if TLCRegion
		if (region instanceof TLCRegion) {
			TLCRegion tlcRegion = (TLCRegion) region;
			int severity = tlcRegion.getSeverity();
			switch (severity) {
			case MP.STATE:
				TLCState state = TLCState.parseState(text, "bogusModelName");
				this.states.add(state);
				return;
			}
		}
		
		// c) unexpected content
		this.garbage  = true;
	}

	public void onDone() {
		this.done = true;
	}

	public void onNewSource() {
		// nop
	}

	/**
	 * @return the done
	 */
	public boolean isDone() {
		return done;
	}

	/**
	 * @return the garbage
	 */
	public boolean hasGarbage() {
		return garbage;
	}
	
	/**
	 * @return the regions
	 */
	public List<ITypedRegion> getRegions() {
		return regions;
	}

	/**
	 * @return the states
	 */
	public List<TLCState> getStates() {
		return states;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/property/GenericFieldEditorPropertyPage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.property;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.dialogs.PropertyPage;

/**
 * @author <NAME>
 * @version $Id$
 */
public abstract class GenericFieldEditorPropertyPage extends PropertyPage implements IPropertyChangeListener
{
    private List fields;
    private FieldEditor invalidFieldEditor;

    protected void initialize()
    {
        if (fields != null)
        {
            Iterator e = fields.iterator();
            while (e.hasNext())
            {
                FieldEditor fieldEditor = (FieldEditor) e.next();
                fieldEditor.setPage(this);
                fieldEditor.setPreferenceStore(getPreferenceStore());
                fieldEditor.load();
            }
        }
    }

    protected void addEditor(FieldEditor editor)
    {
        if (fields == null)
        {
            fields = new ArrayList();
        }
        fields.add(editor);
    }

    /*
     * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
     */
    protected Control createContents(Composite parent)
    {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        composite.setLayout(layout);
        GridData layoutData = new GridData(GridData.FILL);
        layoutData.grabExcessHorizontalSpace = true;
        composite.setLayoutData(layoutData);

        createFieldEditors(composite);
        
        initialize();
        
        
        return composite;
    }

    public abstract void createFieldEditors(Composite composite);

    /**  
     * The field editor preference page implementation of a <code>PreferencePage</code>
     * method loads all the field editors with their default values.
     */
    protected void performDefaults()
    {
        if (fields != null)
        {
            Iterator e = fields.iterator();
            while (e.hasNext())
            {
                FieldEditor pe = (FieldEditor) e.next();
                pe.loadDefault();
            }
        }
        // Force a recalculation of my error state.
        checkState();
        super.performDefaults();
    }

    /** 
     * The field editor preference page implementation of this 
     * <code>PreferencePage</code> method saves all field editors by
     * calling <code>FieldEditor.store</code>. Note that this method
     * does not save the preference store itself; it just stores the
     * values back into the preference store.
     *
     * @see FieldEditor#store()
     */
    public boolean performOk()
    {
        if (fields != null)
        {
            Iterator e = fields.iterator();
            while (e.hasNext())
            {
                FieldEditor pe = (FieldEditor) e.next();
                pe.store();
            }
            
        }
        return true;
    }

    /**
     * The field editor preference page implementation of this <code>IPreferencePage</code>
     * (and <code>IPropertyChangeListener</code>) method intercepts <code>IS_VALID</code> 
     * events but passes other events on to its superclass.
     */
    public void propertyChange(PropertyChangeEvent event)
    {

        if (event.getProperty().equals(FieldEditor.IS_VALID))
        {
            boolean newValue = ((Boolean) event.getNewValue()).booleanValue();
            // If the new value is true then we must check all field editors.
            // If it is false, then the page is invalid in any case.
            if (newValue)
            {
                checkState();
            } else
            {
                setInvalidFieldEditor((FieldEditor) event.getSource());
                setValid(newValue);
            }
        }
    }

    /**
     * Recomputes the page's error state by calling <code>isValid</code> for
     * every field editor.
     */
    protected void checkState()
    {
        boolean valid = true;
        setInvalidFieldEditor(null);
        // The state can only be set to true if all
        // field editors contain a valid value. So we must check them all
        if (fields != null)
        {
            int size = fields.size();
            for (int i = 0; i < size; i++)
            {
                FieldEditor editor = (FieldEditor) fields.get(i);
                valid = valid && editor.isValid();
                if (!valid)
                {
                    setInvalidFieldEditor(editor);
                    break;
                }
            }
        }
        setValid(valid);
    }

    /**
     * @param invalidFieldEditor the invalidFieldEditor to set
     */
    public void setInvalidFieldEditor(FieldEditor invalidFieldEditor)
    {
        this.invalidFieldEditor = invalidFieldEditor;
    }

    /**
     * @return the invalidFieldEditor
     */
    public FieldEditor getInvalidFieldEditor()
    {
        return invalidFieldEditor;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCSetVariableValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.List;

public class TLCSetVariableValue extends TLCVariableValue implements TLCMultiVariableValue {

    private static final String[] DELIMETERS = { "{", ",", "}" };

	TLCSetVariableValue(List values) {
        this.value = values;
    }

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#getValue()
	 */
	public Object getValue() {
        return getElements();
    }

	public TLCVariableValue[] getElements() {
		List list = (List) value;
		return (TLCVariableValue[]) list.toArray(new TLCVariableValue[list.size()]);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#toSimpleString()
	 */
	public String toSimpleString() {
		TLCVariableValue[] elements = getElements();
		return arrayToSimpleStringBuffer(elements, DELIMETERS).toString();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCMultiVariableValue#asList()
	 */
	public List<TLCVariableValue> asList() {
		return (List<TLCVariableValue>) this.value;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#innerDiff(org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue)
	 */
	protected void innerDiff(TLCVariableValue other) {
		/*
		 * SETS For two sets, the only meaningful changes are additions and
		 * deletions.
		 */
		if (!(other instanceof TLCSetVariableValue)) {
			return;
		}
		TLCVariableValue[] firstElts = this.getElements();
		TLCVariableValue[] secondElts = ((TLCSetVariableValue) other).getElements();

		for (int i = 0; i < firstElts.length; i++) {
			boolean notfound = true;
			int j = 0;
			while (notfound && j < secondElts.length) {
				if (firstElts[i].toSimpleString().equals(secondElts[j].toSimpleString())) {
					notfound = false;
				}
				j++;
			}
			if (notfound) {
				firstElts[i].setDeleted();
			}
		}

		for (int i = 0; i < secondElts.length; i++) {
			boolean notfound = true;
			int j = 0;
			while (notfound && j < firstElts.length) {
				if (firstElts[j].toSimpleString().equals(secondElts[i].toSimpleString())) {
					notfound = false;
				}
				j++;
			}
			if (notfound) {
				secondElts[i].setAdded();
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/pprint/ParseException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:21:08 PST by lamport
//      modified on Fri Jun 11 17:52:39 PDT 1999 by yuanyu
//      modified on Thu Jun 10 11:00:01 EDT 1999 by tuttle

package tlc2.pprint;

public class ParseException extends Exception {

  ParseException(String s) {
    super(s);
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/debug/EWD998TraceDebuggerTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.debug;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import org.eclipse.lsp4j.debug.EvaluateResponse;
import org.junit.Test;

import tlc2.output.EC;
import tlc2.value.impl.TupleValue;

public class EWD998TraceDebuggerTest extends TLCDebuggerTestCase {

	private static final String FOLDER = "EWD998";
	private static final String MDL = "EWD998_TTrace";

	public EWD998TraceDebuggerTest() {
		super(MDL, FOLDER, new String[] { "-config", "EWD998_TTrace.tla", "-noGenerateSpecTE" }, EC.ExitStatus.VIOLATION_LIVENESS);
	}

	@Test
	public void testSpec() throws Exception {
		
		debugger.replaceAllBreakpointsWith(MDL, 67);
		debugger.continue_();
		
		EvaluateResponse var = debugger.evaluate(MDL, "_TETrace", 66, 22, 66, 29);
		assertEquals(TupleValue.EmptyTuple.getTypeString(), var.getType());
		assertNotEquals(0, var.getVariablesReference());
		assertEquals(
				"<<[color |-> (0 :> \"white\" @@ 1 :> \"white\" @@ 2 :> \"white\" @@ 3 :> \"white\" @@ 4 :> \"white\"), pending |-> (0 :> 0 @@ 1 :> 0 @@ 2 :> 0 @@ 3 :> 0 @@ 4 :> 0), active |-> (0 :> FALSE @@ 1 :> FALSE @@ 2 :> FALSE @@ 3 :> FALSE @@ 4 :> FALSE), counter |-> (0 :> 0 @@ 1 :> 0 @@ 2 :> 0 @@ 3 :> 0 @@ 4 :> 0), token |-> [color |-> \"black\", pos |-> 0, q |-> 0]], [color |-> (0 :> \"white\" @@ 1 :> \"white\" @@ 2 :> \"white\" @@ 3 :> \"white\" @@ 4 :> \"white\"), pending |-> (0 :> 0 @@ 1 :> 0 @@ 2 :> 0 @@ 3 :> 0 @@ 4 :> 0), active |-> (0 :> FALSE @@ 1 :> FALSE @@ 2 :> FALSE @@ 3 :> FALSE @@ 4 :> FALSE), counter |-> (0 :> 0 @@ 1 :> 0 @@ 2 :> 0 @@ 3 :> 0 @@ 4 :> 0), token |-> [color |-> \"white\", pos |-> 4, q |-> 0]]>>",
				var.getResult());
		
		// Remove all breakpoints and run the spec to completion.
		debugger.unsetBreakpoints();
		debugger.continue_();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/drivers/SemanticException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.drivers;

public class SemanticException extends Exception {}


<|start_filename|>tlatools/org.lamport.tlatools.impl.distributed/src/org/lamport/tlatools/impl/distributed/TLCDistributedFPSetWrapper.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tlatools.impl.distributed;

import java.net.URI;

import tlc2.IDistributedFPSet;
import tlc2.tool.distributed.fp.DistributedFPSet;

public class TLCDistributedFPSetWrapper extends TLCWrapper implements IDistributedFPSet {

	/* (non-Javadoc)
	 * @see tlc2.IDistributedFPSet#connect(java.net.URI)
	 */
	public boolean connect(URI uri) {
		super.connect("FPSet");
		try {
			DistributedFPSet.main(new String[] { uri.getHost() });
		} catch (Exception e) {
			// not expected to happen
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see tlc2.IDistributedFPSet#disconnect()
	 */
	public boolean disconnect() {
		try {
			DistributedFPSet.shutdown();
		} catch (Exception e) {
			// not expected to happen
			e.printStackTrace();
			return false;
		}
		return true;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/manager/ISpecManager.java<|end_filename|>
package org.lamport.tla.toolbox.spec.manager;

import org.lamport.tla.toolbox.spec.Spec;

/**
 * SpecManager is responsible for handling of specifications opened by the toolbox
 * 
 * @author zambrovski
 */
public interface ISpecManager
{
    /**
     * Retrieves a list of specification names
     * 
     * @return an array of strings
     */
    public Spec[] getRecentlyOpened();

    /**
     * Adds a specification to the list Note, the SpecManagerListener will be notified about this
     * 
     * @param spec
     *            , a specification to add
     */
    public void addSpec(Spec spec);

    /**
     * Sets a spec that is loaded
     * 
     * @param loadedSpec
     *            a spec that is loaded, or null if no spec is loaded The spec should be stored by the spec manager
     */
    public void setSpecLoaded(Spec loadedSpec);

    /**
     * Retrieves spec loaded by the toolbox
     * 
     * @return loaded Spec or null if no spec has been loaded
     */
    public Spec getSpecLoaded();

    /**
     * Delivers a spec with given name, or null if no such spec exists<br>
     * <b>Note:</b> This method should be used to determine if a new spec with given name can be created
     * 
     * @return a reference to existing spec or null
     */
    public Spec getSpecByName(String specName);

    /**
     * Delivers a spec with given root module, or null if no such spec exists<br>
     * <b>Note:</b> This method should be used to determine if a new spec with given root module can be created
     * 
     * @return a reference to existing spec or null
     */
    public Spec getSpecByRootModule(String rootModulePath);

    /**
     * Termination of the specManager
     */
    public void terminate();

    /**
     * Creates a spec name derived from the module name
     * @param moduleName
     * @param firstRunFlag
     * @return the name of the spec derived from a module
     */
    public String constructSpecName(String moduleName, boolean firstRunFlag);

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/view/ObligationsView.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.view;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.ExpandBar;
import org.eclipse.swt.widgets.ExpandItem;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ObligationStatus;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;
import org.lamport.tla.toolbox.util.FontPreferenceChangeListener;
import org.lamport.tla.toolbox.util.TLAMarkerHelper;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A view that shows information about interesting
 * obligations.
 * 
 * This view can be updated with information about
 * an obligation using the static method {@link ObligationsView#updateObligationView(IMarker)}
 * with a marker that contains information about an obligation.
 * Check the method documentation for how it works.
 * 
 * It is important that whenever this view is open, it shows only information on obligations
 * from the currently opened project, where the currently opened project is the project returned
 * by {@link Spec#getProject()} for the currently opened spec.
 * This is maintained in the following two ways:
 * 
 * 1.) When the view is opened, the method createPartControl() is called. This creates
 * a new {@link ExpandBar} widget for displaying obligation item information with no items.
 * The method then searches for all obligation markers on any module in the
 * currently opened project. This view assumes that all such markers are from the
 * same run of the prover and are from the most recent run of the prover on any module
 * in the project. If any markers are found from the currently opened project, the expand bar
 * is populated with one item for each marker that has information about an "interesting"
 * obligation.
 * 
 * 2.) The method {@link ObligationsView#refreshObligationView()} is called at the appropriate times.
 *
 *    -It is called when a spec is opened. This ensures that when the currently opened spec in the toolbox
 *     changes, obligation information from the previously opened spec is not shown.
 *    -It is called when obligation markers have been deleted. This should mean that the prover
 *     has been launched, causing the previous obligation markers to be removed. Calling refreshObligationView()
 *     will clear the information from these previous markers from the view, if the view is currently open.
 *     If the view is not currently open, it doesn't matter because the view stores no information.
 *     
 * The methods {@link #refreshObligationView()} and {@link #updateObligationView(IMarker)} ensure that when the
 * obligation view is empty, it is hidden. The only way to open an empty obligation view is to select the menu item
 * opening the view.
 *     
 * The font and syntax coloring of the items in the view is the same as that of the tla editor. The
 * syntax coloring is done by configuring the obligation items with the {@link ObligationSourceViewerConfiguration}
 * and the font is done by adding a listener to the preference for text editor font.
 * 
 * Side note :  I've noticed that the documentation for {@link IWorkbenchPart} claims that createPartControl()
 * should also be called when the view is made invisible and then visible again, but experimentation
 * shows that this is not the case.
 * 
 * @author <NAME>
 *
 */
public class ObligationsView extends ViewPart
{

    public static final String VIEW_ID = "org.lamport.tla.toolbox.tool.prover.ui.rejectedObligations";
    /**
     * The beginning of the view name. The total view name will be
     * PART_NAME_BASE + moduleName.
     */
    public static final String PART_NAME_BASE = "Interesting Obligations for ";
	/**
	 * Identifies the obligation
	 */
	private static final String KEY = ObligationsView.class.getName() + "ID";
	/**
	 * Identifies the stop button on the obligation
	 */
	private static final String KEY_BUTTON = ObligationsView.class.getName() + "BUTTON";
    /**
     * The widget that displays a list of items, each
     * containing information about an interesting obligation.
     */
    private ExpandBar bar = null;
    /**
     * A map of obligation id (as an Integer object)
     * to {@link ExpandItem}s.
     */
    private Map<Integer, ExpandItem> items;
    /**
     * A map from {@link ExpandItem} to their
     * associated {@link SourceViewer}.
     */
    private Map<ExpandItem, SourceViewer> viewers;
    /**
     * A listener that reacts to changes of the text editor font
     * by notifying all items in this view that they should update
     * their font.
     */
    private FontPreferenceChangeListener fontListener;
    /**
     * Listens to when the user clicks
     * on an item's widget and jumps to the marker.
     * 
     * This listener assumes that the data of the widget
     * is the marker. In general, every widget has a data
     * field that can be any object. In the method
     * newMarker(), we set the widget data to be the marker
     * for widgets that should jump to that marker.
     */
    private Listener obClickListener = new Listener() {

        public void handleEvent(Event event)
        {
            if (event.type == SWT.MouseDown)
            {

                if (event.widget.getData() instanceof IMarker)
                {
                    TLAMarkerHelper.gotoMarker((IMarker) event.widget.getData());
                }
            }
        }
    };

    /**
     * A listener for the stop obligation button for an obligation.
     * This sends a signal to the prover indicating that the proving
     * of that obligation should stop.
     */
    private SelectionListener stopObListener = new SelectionAdapter() {
        public void widgetSelected(SelectionEvent e)
        {
            if (e.widget instanceof Button && e.widget.getData() instanceof IMarker)
            {
                ProverHelper.stopObligation((IMarker) e.widget.getData());
            }
        }
    };

    // method added by LL on 1 Nov 2012
    private SelectionListener gotoObListener = new SelectionAdapter() {
        public void widgetSelected(SelectionEvent e)
        {
            if (e.widget instanceof Button && e.widget.getData() instanceof IMarker)
            {
                TLAMarkerHelper.gotoMarker((IMarker) e.widget.getData());
            }
        }
    };
    
	private final SpecLifecycleParticipant specLifecycleParticipant = new SpecLifecycleParticipant() {
		public boolean eventOccured(SpecEvent event) {
			if (event.getType() == SpecEvent.TYPE_OPEN) {
				ObligationsView.refreshObligationView();
			}
			return false;
		}
	};

    public ObligationsView()
    {
        items = new HashMap<Integer, ExpandItem>();
        viewers = new HashMap<ExpandItem, SourceViewer>();
        fontListener = new FontPreferenceChangeListener(null, JFaceResources.TEXT_FONT);
        JFaceResources.getFontRegistry().addListener(fontListener);
    }

    public void createPartControl(Composite parent)
    {
        /*
         * Create the expand bar that will contain
         * a list of ExpandItems with interesting information
         * about obligations. The items for each obligation are created
         * in the method newMarker().
         */
        bar = new ExpandBar(parent, SWT.V_SCROLL | SWT.BORDER);
        bar.setSpacing(8);

        fillFromCurrentSpec();
    }

    
    /* (non-Javadoc)
	 * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite)
	 */
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		// Register a SLP to refresh the obligation view once it has been
		// created. This used to be done as part of the
		// ProverSpecLifecycleParticipant. However, the PSLP is created from an
		// Extension Point which means it potentially runs *before* the UI is
		// fully initialized. If this is interleaved with a spec open event, it
		// means the UIHelper.runUIAsync(..) tries to create a UI and then
		// nullpointers.
		// See dipose() where the lifecycle participant is de-registered again.
		// It should be safe to receive events even if the Obligations View
		// isn't open, but it's good practice to remove listeners past disposal.
		// Even if it just saves a few CPU cycles in an hour.
		Activator.getSpecManager().addSpecLifecycleParticipant(specLifecycleParticipant);
	}

	/**
     * Used to refresh the obligation view if it is currently open. If the view
     * is not currently open, this method does nothing. If the view is currently open,
     * this takes the following two steps:
     * 
     * 1.) Removes all items from the expand bar for this view.
     * 
     * 2.) Retrieve all obligation statuses by calling {@link ProverHelper#getObligationStatuses()}.
     *     Fills the view with information from these statuses.
     * 
     * 3.) If there are no interesting obligations in the view after steps 1 and 2, then
     * the view is hidden.
     */
    public static void refreshObligationView()
    {
    	UIHelper.runUIAsync(new Runnable() {
			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {

		        final ObligationsView oblView = (ObligationsView) UIHelper.findView(VIEW_ID);
		        if (oblView != null)
		        {

		            /*
		             * Remove all items in the bar.
		             * 
		             * For each item:
		             * 1.) Dispose the item's control.
		             * 2.) Dispose the item.
		             * 
		             * After disposing of all items, clear
		             * the map of ids to items.
		             */
		            ExpandItem[] expandItems = oblView.bar.getItems();
		            for (int i = 0; i < expandItems.length; i++)
		            {
		                oblView.removeItem(expandItems[i]);
		            }

		            /*
		             * Fill the obligation view with markers from the current spec.
		             * If the obligations view is empty after doing this (there are
		             * no interesting obligations) then hide the view.
		             */
		            oblView.fillFromCurrentSpec();

		            if (oblView.isEmpty())
		            {
		                UIHelper.getActivePage().hideView(oblView);
		            }

		        }
			}
    	});
    }

    /**
     * Fills the obligation view with information
     * from the most recent launch of the prover on the
     * current spec if the most recent launch of the prover was on the current
     * spec. Otherwise, does nothing.
     */
    private void fillFromCurrentSpec()
    {
        ObligationStatus[] statuses = ProverHelper.getObligationStatuses();
        if (statuses != null)
        {
            for (int i = 0; i < statuses.length; i++)
            {
                updateItem(statuses[i]);
            }

        }

    }

    /**
     * Updates the view with the information in this obligation status message.
     * 
     * This method hides the view if after updating the item, the view is empty (there are no
     * more interesting obligations).
     * 
     * Must be run from the UI thread.
     * 
     * @param marker
     */
    public static void updateObligationView(ObligationStatus status)
    {
        /*
         * If the marker is not interesting, try to find the view.
         * If the view is found update the view with that marker.
         * 
         * If the view is not found, there is no need to update it
         * with the new markers.
         * 
         * If the marker is interesting, open the view and update it.
         */
        ObligationsView oblView;
        if (!ProverHelper.isInterestingObligation(status))
        {
            oblView = (ObligationsView) UIHelper.findView(VIEW_ID);
        } else
        {
            oblView = (ObligationsView) UIHelper.openView(VIEW_ID);
        }

        if (oblView != null)
        {

            String moduleName = status.getObMarker().getResource().getName();
            if (!oblView.getPartName().equals(PART_NAME_BASE + moduleName))
            {
                oblView.setPartName(PART_NAME_BASE + moduleName);
            }

            oblView.updateItem(status);

            /*
             * If after updating the item, the obligations view is empty, it should be hidden.
             */
            if (oblView.isEmpty())
            {
                UIHelper.getActivePage().hideView(oblView);
            }

        }

    }

    /**
     * Adds the information from the obligation status to the view.
     * 
     * If there is already an item with information of the same
     * obligation as the status, that item is updated. If no
     * such item exists, a new one is created.
     * 
     * Modified by LL on 1 Nov 2012 to add the Goto Obligation button
     * and remove the listener from the text widget so clicking on
     * the obligation text no longer goes to the obligation.
     */
    private void updateItem(ObligationStatus status)
    {
        int id = status.getId();
        if (id != -1)
        {
            /*
             * Try to retrieve an existing item with the same id.
             */
            ExpandItem item = items.get(new Integer(id));

            /*
             * If the marker represents an obligation that is
             * not interesting, we dispose of the existing item
             * (if there is one) and then return. There is nothing
             * more to do.
             */
            if (!ProverHelper.isInterestingObligation(status))
            {
                if (item != null)
                {
                    removeItem(item);
                }

                return;
            }

            /*
             * If there is no existing item, create
             * a new one.
             */
            if (item == null)
            {
                item = new ExpandItem(bar, SWT.None, 0);
                item.setData(KEY, new Integer(id));

                /*
                 * Create the widget that will appear when the
                 * item is expanded.
                 */
                Composite oblWidget = new Composite(bar, SWT.LINE_SOLID);
                GridLayout gl = new GridLayout(1, true);
                // no margin around the widget.
                gl.marginWidth = 0;
                gl.marginHeight = 0;
                oblWidget.setLayout(gl);

                // LL added buttonsWidget to be an inner composite to hold
                // the Stop Proving and Goto Obligation buttons on one line.
                Composite buttonsWidget = new Composite(oblWidget, SWT.LINE_SOLID);
                GridLayout buttonsGl = new GridLayout(2, true);
                buttonsGl.marginWidth = 0;
                buttonsGl.marginHeight = 0;
                buttonsWidget.setLayout(buttonsGl);
                buttonsWidget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                /*
                 * Add a button for stopping the obligation. This button is
                 * later disabled if the obligation is not being proved.
                 * 
                 * The data field for the button stores a pointer to the
                 * marker for the obligation. This allows a listener
                 * to retrieve the id of the obligation, or any other information
                 * which it must send to the prover to stop the proof.
                 */
                Button stopButton = new Button(buttonsWidget /*oblWidget*/, SWT.PUSH);
                stopButton.setText("Stop Proving");
                stopButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                stopButton.setData(status.getObMarker());
                stopButton.addSelectionListener(stopObListener);
                item.setControl(oblWidget);
                item.setData(KEY_BUTTON, stopButton);

                // gotoButton added by LL on 1 Nov 2012
                Button gotoButton = new Button(buttonsWidget /*oblWidget*/, SWT.PUSH);
                gotoButton.setText("Goto Obligation");
                gotoButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                gotoButton.setData(status.getObMarker());
                gotoButton.addSelectionListener(gotoObListener);
                
                /*
                 * We use a source viewer to display the
                 * obligation. This allows us to easily do
                 * syntax highlighting by configuring the source
                 * viewer with a source viewer configuration
                 * that basically takes some code from the editor
                 * plug-in. This code does the syntax highlighting.
                 * See ObligationSourceViewerConfiguration.
                 * 
                 * For the style bits, we want the source viewer to be read
                 * only, multiline, and have a horizontal scroll bar. We
                 * don't want the text to wrap because that makes the
                 * obligations difficult to read, so a horizontal scroll
                 * bar is necessary.
                 */
                SourceViewer viewer = new SourceViewer(oblWidget, null, SWT.READ_ONLY | SWT.MULTI | SWT.H_SCROLL);
                viewer.getTextWidget().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                viewer.configure(new ObligationSourceViewerConfiguration());
                viewer.getControl().setFont(JFaceResources.getTextFont());
                // add the control to the list of controls to be notified when the
                // text editor font changes.
                fontListener.addControl(viewer.getControl());

                // item maps to viewer for later access
                viewers.put(item, viewer);

                item.setControl(oblWidget);
                item.setExpanded(true);

                /*
                 * Set the data to be the marker so that when
                 * the user clicks on the item, we can jump to that marker.
                 * 
                 * See the documentation for listener.
                 */
                item.setData(status.getObMarker());
                viewer.getTextWidget().setData(status.getObMarker());
                oblWidget.setData(status.getObMarker());
                // adding the listener to the item seems to have no effect.
                item.addListener(SWT.MouseDown, obClickListener);
                // The following 2 lines were commented out by LL on 1 Nov 2012
                // so clicking on the textWidget does not goto the obligation.
                //
                // viewer.getTextWidget().addListener(SWT.MouseDown, obClickListener);
                // oblWidget.addListener(SWT.MouseDown, obClickListener);

                items.put(new Integer(id), item);
            }

            /*
             * Whether this marker gives information for an existing
             * item or a new item, we always update the title of the
             * item to display the current status of the obligation.
             */
            item.setText("Obligation " + id + " - status : " + status.getProverStatusString());

            /*
             * Enable the "Being Proved" button iff the obligation is being proved.
             */
            Button button = (Button) item.getData(KEY_BUTTON);
            button.setEnabled(ProverHelper.isBeingProvedObligation(status));

            /*
             * Get the item's viewer. If the viewer's document does not contain
             * the obligation string and the obligation string in the marker is not empty,
             * set the viewer's document to a new document containing
             * the obligation string.
             */
            SourceViewer viewer = (SourceViewer) viewers.get(item);
            Assert.isNotNull(viewer, "Expand item has been created without a source viewer. This is a bug.");
            String oblString = status.getObligationString();

            // On 14 April 2011, Denis changed tlapm so it does not include an
            // interesting obligation if a later message will indicate that
            // the obligation is proved.  On 16 April 2011, LL removed the assert
            // and had it treat a missing obligation as one with the null string.
            if (oblString == null) {
                oblString = "";
            }
            // Assert
            //       .isNotNull(oblString,
            //               "No obligation string for an interesting obligation. This is a bug. The obligation is :\n"
            //                       + status);
            if ((viewer.getDocument() == null || !viewer.getDocument().get().equals(oblString)) && !(oblString.length() == 0))
            {
                // set the viewers document to the obligation.
                viewer.setDocument(new Document(oblString.trim()));

                /*
                 * The following explanation for computing the height
                 * of each expand item is no longer used. Instead, we
                 * simply ask the expand item's control for its preferred height.
                 * This seems to work. However, we leave the old code and comments
                 * just in case.
                 * 
                 * Give the item the appropriate height to show
                 * the obligation. This includes both the height
                 * of the text of the obligation and the height
                 * of the horizontal scroll bar, if there is one.
                 */
                // StyledText text = viewer.getTextWidget();
                // ScrollBar hBar = text.getHorizontalBar();
                // item.setHeight(text.getLineHeight() * text.getLineCount() + (hBar != null ? hBar.getSize().y :
                // 0));
                item.setHeight(item.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y);
            } else if (oblString.length() == 0 && (viewer.getDocument() == null || viewer.getDocument().get().length() == 0))
            {
                /*
                 * A slight hack. For some interesting obligations, the prover
                 * does not send back the pretty printed obligation. This is
                 * a bug. In the meantime, we need the source viewer to be visible
                 * so that the user can click on it to jump to the obligation.
                 * The following does that.
                 */
                viewer.setDocument(new Document("No obligation text available."));
                item.setHeight(100);
            }

        }

    }

    private boolean isEmpty()
    {
        return bar.getItemCount() == 0;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    public void setFocus()
    {
    	// nop
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    public void dispose()
    {
        JFaceResources.getFontRegistry().removeListener(fontListener);
        super.dispose();
    }

    /**
     * Removes the item from the view, performing necessary
     * cleanup.
     * 
     * @param item
     */
    private void removeItem(ExpandItem item)
    {
        // remove the source viewer's control from the
        // font listener since it no longer needs to be
        // notified of font changes.
        fontListener.removeControl(((SourceViewer) viewers.get(item)).getControl());

        // retrieve the id for the item
        // the id is stored in the item's data, which should be a marker,
        // as set in the updateItem method
        final Object data = item.getData(KEY);
        items.remove(Integer.parseInt(data.toString()));

        item.getControl().dispose();
        item.dispose();
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PCalUnrecoverableErrorRuntimeException.java<|end_filename|>
package pcal;

/**
 * Exception thrown instead of System.exit().
 * 
 * @author <NAME>
 * @version $Id$
 * @deprecated TODO this should be re-factored and not used further 
 */
public class PCalUnrecoverableErrorRuntimeException extends RuntimeException
{

    public PCalUnrecoverableErrorRuntimeException(String message)
    {
        super(message);
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/CloseSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.ui.perspective.InitialPerspective;
import org.lamport.tla.toolbox.ui.view.ProblemView;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Closes the specification and switches the UI back to the initial perspective
 *
 * @author zambrovski
 */
public class CloseSpecHandler extends AbstractHandler implements IHandler
{
    public final static String COMMAND_ID = "toolbox.command.spec.close";
    
    // A QualifiedName for the project's last closed time persistent property.
    public static final QualifiedName LAST_CLOSED_DATE = 
        new QualifiedName(COMMAND_ID, "lastClosedTime");

    public Object execute(final ExecutionEvent event) throws ExecutionException
    {
        // Set the project's last closed time to the current time.
    	Spec specClosed = null;
        try
        {
            specClosed = Activator.getSpecManager().getSpecLoaded();
            // Cannot close specs if none is open
            if (specClosed == null) {
            	return null;
            }
            specClosed.getProject().setPersistentProperty(
               LAST_CLOSED_DATE, "" + System.currentTimeMillis());
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            Activator.getDefault().logDebug(
             "Exception thrown when setting project LAST_CLOSED time.");
        }
        
        // close all editors
        if (!UIHelper.getActivePage().closeAllEditors(true)) {
        	// There are still open editors because the user canceled out of the process
        	return Boolean.valueOf(false);
        }
        
        // hide errors
        UIHelper.hideView(ProblemView.ID);
        // switch perspective
        UIHelper.switchPerspective(InitialPerspective.ID);
        
        // unset the spec
        final WorkspaceSpecManager specManager = Activator.getSpecManager();
        specManager.setSpecLoaded(null);

        // Refresh the CommonViewer to causes it to align the icon shown in the SpecExplorer
        // with the state of the spec. E.g. if the spec is closed, make sure it shows the closed
        // project icon. It also re-evaluates the navigators SpecContentProvider#hasChildren. No children
        // means that the expand triangle isn't shown for the tree icon (spec). For that
        // WorkspaceSpecManager#setSpecLoaded(null) has to be called first (see above).
        final ToolboxExplorer toolboxExplorer = (ToolboxExplorer) UIHelper.findView(ToolboxExplorer.VIEW_ID);
        if (toolboxExplorer != null) {
			toolboxExplorer.getCommonViewer().refresh(specClosed);
        }

        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (Activator.getSpecManager().getSpecLoaded() == null) {
			return false;
		}
		return super.isEnabled();
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/PossibleErrorModel.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:49 PST by lamport
//      modified on Sat Mar 25 22:39:46 PST 2000 by yuanyu

package tlc2.tool.liveness;

import tlc2.util.BitVector;

/**
 * A {@link PossibleErrorModel} is technically a lookup table into its
 * corresponding {@link OrderOfSolution} Eventually Always, Infinitely often
 * action checks and infinitely often state checks. The
 * {@link PossibleErrorModel} basically selects the set of checks stored in
 * {@link OrderOfSolution} that a relevant for this {@link PossibleErrorModel}.
 * The mapping is done by storing the integer index of the relevant
 * {@link OrderOfSolution} checks in EAAction, AEState and AEAction.
 * <p>
 * The integer index is used in two places: Lookup the set of relevant OOS
 * checks
 * <ul>
 * <li>When the states and transitions (see
 * {@link GraphNode#addTransition(long, int, int, int, BitVector, int, int)})
 * are evaluated during "normal" model checking the PEM index selects the set of
 * relevant OOS checks. The result of each check is stored in a per node
 * {@link BitVector} index again by the corresponding PEM mapping.</li>
 * <li>During liveness checking (see {@link LiveWorker#checkSccs()} when the
 * pre-computed check result is being looked up in the node's {@link BitVector}.
 * </li>
 * </ul>
 * <p>
 * This class can be seen as a C-like struct (PEM's method are all related to
 * OOS#toString).
 * <p>
 * <p>
 * Theorie-wise, a {@link PossibleErrorModel} (there are as many PEMs as
 * disjuncts in the normal form (DNF) produced by
 * {@link Liveness#processLiveness(tlc2.tool.Tool)}) represents the negation of
 * the stated liveness properties. It is then applied onto the discovered
 * strongly-connected-components in {@link LiveWorker#checkComponent()} to check
 * if the PEM is "P-satisfiable". If it is, it shows that a violation of the
 * original liveness properties has been found (meaning they can't be
 * "P-valid"). A counter-example can be created.
 * <p>
 * A simplified example:<br>
 * Suppose Spec has the (trivial) liveness property '&lt;&gt;[](x \in Nat)' (
 * "eventually the variable x is always a natural number") defined. This will
 * result in a PEM looking for a state such that x \notin Nat. If there exists
 * such a behavior (SCC), it would violate the liveness property.
 */
public class PossibleErrorModel {
	final int[] EAAction; // <>[]act's (Eventually Always actions) (Strong fairness)
	final int[] AEState; // []<>state's (Infinitely Often states)
	final int[] AEAction; // []<>act's (Infinitely Often actions) (Weak fairness)
	
	public PossibleErrorModel(int[] aeAction, int[] aeState, int[] eaAction) {
		this.AEAction = aeAction;
		this.AEState = aeState;
		this.EAAction = eaAction;
	}
	
	public final boolean isEmpty() {
		return (this.EAAction.length == 0 && this.AEState.length == 0 && this.AEAction.length == 0);
	}

	public final String toString(LiveExprNode[] checkState, LiveExprNode[] checkAction) {
		StringBuffer sb = new StringBuffer();
		this.toString(sb, "", checkState, checkAction);
		return sb.toString();
	}

	public final void toString(StringBuffer sb, String padding, LiveExprNode[] checkState, LiveExprNode[] checkAction) {
		boolean noPadding = true;
		String padding1 = padding + "       ";

		for (int i = 0; i < this.EAAction.length; i++) {
			int idx = this.EAAction[i];
			if (noPadding) {
				noPadding = false;
			} else {
				sb.append(padding);
			}
			sb.append("/\\ <>[]");
			checkAction[idx].toString(sb, padding1);
			sb.append("\n");
		}
		for (int i = 0; i < this.AEState.length; i++) {
			int idx = this.AEState[i];
			if (noPadding) {
				noPadding = false;
			} else {
				sb.append(padding);
			}
			sb.append("/\\ []<>");
			checkState[idx].toString(sb, padding1);
			sb.append("\n");
		}
		for (int i = 0; i < this.AEAction.length; i++) {
			int idx = this.AEAction[i];
			if (noPadding) {
				noPadding = false;
			} else {
				sb.append(padding);
			}
			sb.append("/\\ []<>");
			checkAction[idx].toString(sb, padding1);
			sb.append("\n");
		}
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/FPSetManagerException.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp;

import java.rmi.RemoteException;

@SuppressWarnings("serial")
public class FPSetManagerException extends RemoteException {

	public FPSetManagerException(String s) {
		super(s);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/LogFileReader.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.source.ITLCOutputSource;
import org.lamport.tla.toolbox.tool.tlc.output.source.TagBasedTLCOutputIncrementalParser;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * Reads the log file and parses the content
 * 
 * @author <NAME>
 */
public class LogFileReader {
	
	private final TagBasedTLCOutputIncrementalParser parser;
	private final File logFile;

	public LogFileReader(Model model, IFile aLogFile, boolean isTraceExplorerLogFile) {
		this.logFile = new File(aLogFile.getLocation().toOSString());
		this.parser = new TagBasedTLCOutputIncrementalParser(model, ITLCOutputSource.PRIO_LOW, isTraceExplorerLogFile,
				TagBasedTLCOutputIncrementalParser.Mode.BATCH, this.logFile.length());
	}

    /**
	 * Reads the contents
	 */
	public void read(final IProgressMonitor monitor) throws IOException, BadLocationException {
		BufferedReader reader = null;
		try {
			final long numberOfLines = getLineNumbers();

			// I'm looking forward to the bug report where the int cast is
			// relevant.
			monitor.beginTask("Opening logfile "+logFile.getCanonicalPath(), (int) numberOfLines);

			reader = new BufferedReader(new FileReader(logFile));
			/*
			 * When the output file is somewhat large (several hundred KB) the
			 * toolbox hangs due to the parser inefficiently handling multiple
			 * lines at once. If the entire document representing that file is
			 * passed to the parser at once. We can send in pieces of it to
			 * solve this problem.
			 * 
			 * We send in one line at a time. Note that IDocument lines are
			 * 0-based.
			 */
			for (int lineNum = 0; lineNum < numberOfLines; lineNum++) {
				if (monitor.isCanceled()) {
					this.parser.clear();
					return;
				}
				if (lineNum % 1000 == 0) {
					monitor.worked(1000);
				}
				this.parser.addLine(reader.readLine().concat("\n"));
			}
			this.parser.done();
			monitor.worked(1);
		} catch (BadLocationException e) {
			TLCUIActivator.getDefault().logError("Error positioning in the TLC log file", e);
			throw e;
		} catch (FileNotFoundException e) {
			TLCUIActivator.getDefault().logError("Error accessing the TLC log file contents", e);
			throw e;
		} catch (IOException e) {
			TLCUIActivator.getDefault().logError("Error reading the TLC log file contents", e);
			throw e;
		} finally {
			/*
			 * The document provider is not needed. Always disconnect it to
			 * avoid a memory leak.
			 * 
			 * Keeping it connected only seems to provide synchronization of the
			 * document with file changes. That is not necessary in this
			 * context.
			 */
			monitor.done();
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					TLCUIActivator.getDefault().logError("Error closing the TLC log file contents", e);
				}
			}
		}
	}

	public long getLineNumbers() throws IOException {
		final LineNumberReader reader = new LineNumberReader(new FileReader(logFile));
		reader.skip(Long.MAX_VALUE);
		final int numberOfLines = reader.getLineNumber();
		reader.close();
		return numberOfLines;
	 }

	public ITLCOutputSource getSource() {
		return this.parser.getSource();
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/output/internal/TLAPMBroadcastStreamListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.output.internal;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;
import org.lamport.tla.toolbox.tool.prover.output.IProverProcessOutputSink;
import org.lamport.tla.toolbox.tool.prover.ui.ConsoleProverProcessOutputSink;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.output.TagBasedTLAPMOutputIncrementalParser;

/**
 * A listener that broadcasts streams to a {@link ConsoleProverProcessOutputSink}
 * and a {@link TagBasedTLAPMOutputIncrementalParser}.
 * 
 * A stream is TLAPM output for a given module.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLAPMBroadcastStreamListener implements IStreamListener
{
    private IProverProcessOutputSink[] listeners = null;

    /**
     * Constructs a stream listener for output for the given module. This will be passed
     * to listeners of TLAPM output.
     * 
     * The constructor also takes a progress monitor. This monitor can be sent to listeners
     * to TLAPM output so that they can report progress.
     * 
     * The prover job will also be sent to listeners so that they can have access to information
     * and useful data structures pertaining to the launch of the prover.
     * 
     * See {@link #getRegisteredStreamManagers(IFile, ProverJob, IProgressMonitor)} for the creation
     * of listeners.
     * 
     * @param monitor
     * 
     * @param module
     * @param proverJob the job provides access to the description of the prover launch and other
     * useful fields
     */
    public TLAPMBroadcastStreamListener(IFile module, ProverJob proverJob, IProgressMonitor monitor)
    {
        this.listeners = getRegisteredStreamManagers(module, proverJob, monitor);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.core.IStreamListener#streamAppended(java.lang.String, org.eclipse.debug.core.model.IStreamMonitor)
     */
    public synchronized void streamAppended(String text, IStreamMonitor monitor)
    {
        // broadcast the message
        for (int i = 0; i < listeners.length; i++)
        {
            if (listeners[i] != null)
            {
                try
                {
                    listeners[i].appendText(text);
                } catch (Exception e)
                {
                    ProverUIActivator.getDefault().logError("Error broadcasting the message", e);
                }
            }
        }
    }

    /**
     * When the stream is closed, this method tells all listeners created in
     * {@link #getRegisteredStreamManagers(IFile, ProverJob, IProgressMonitor)} that
     * the stream is closed.
     */
    public synchronized void streamClosed()
    {
        // broadcast the message
        for (int i = 0; i < listeners.length; i++)
        {
            try
            {

                if (listeners[i] != null)
                {
                    listeners[i].processFinished();
                }
            } catch (Exception e)
            {
                ProverUIActivator.getDefault().logError("Error broadcasting the stream closed event", e);
            }
        }
    }

    /**
     * Creates a {@link ConsoleProverProcessOutputSink} and a {@link TagBasedTLAPMOutputIncrementalParser}.
     * 
     * Calls {@link IProverProcessOutputSink#initializeSink(IFile, ProverJob, IProgressMonitor)} for each of those sinks
     * with the module, job, and monitor. The monitor can be used to report progress on TLAPM's output.
     * 
     * @param monitor TODO
     * 
     * @return an array of the instantiated sinks.
     */
    public static IProverProcessOutputSink[] getRegisteredStreamManagers(IFile module,
            ProverJob proverJob, IProgressMonitor monitor)
    {
        IProverProcessOutputSink[] outputSinks = new IProverProcessOutputSink[] { new ConsoleProverProcessOutputSink(),
                new TagBasedTLAPMOutputIncrementalParser() };
        outputSinks[0].initializeSink(module, proverJob, monitor);
        outputSinks[1].initializeSink(module, proverJob, monitor);
        return outputSinks;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/FPSetConfiguration.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.Serializable;

import tlc2.output.EC;
import tlc2.tool.distributed.fp.FPSetManager.FPSets;
import util.Assert;
import util.TLCRuntime;

@SuppressWarnings("serial")
public class FPSetConfiguration implements Serializable {
	
	/**
	 * N most significant bits used as address bits by a MultiFPSet. 
	 */
	protected int fpBits = 1;
	
	protected long memoryInBytes = -1L;
	protected double ratio;
	protected String implementation;

	public FPSetConfiguration() {
		// By default allocate 25% of memory for fingerprint storage
		this(.25d);
	}
	
	public FPSetConfiguration(Double aRatio) {
		// Read the implementation class from the System properties instead of
		// the cmd line. Right now I'm reluctant to expose the impl class as a 
		// cmd line parameter and carry it forth forever.
		this(aRatio, System.getProperty(FPSetFactory.IMPL_PROPERTY,
				FPSetFactory.getImplementationDefault()));
	}
	
	public FPSetConfiguration(Double aRatio, String implementation) {
		this.ratio = aRatio;
		this.implementation = implementation;
	}

	public boolean allowsNesting() {
		return getFpBits() > 0;
	}
	
	/**
	 * @return The number of most significant bits that must not be used by an
	 *         FPSet to calculate its index on. The bits are used by a
	 *         {@link MultiFPSet} to address individual {@link FPSets}.
	 *         Consequently, for an individual {@link FPSet} these bits are
	 *         fixed (always either zero or one for all fingerprints that the
	 *         {@link FPSet} sees).
	 */
	public int getFpBits() {
		if (fpBits == 0 && FPSetFactory.isDiskFPSet(implementation)) {
			// DiskFPSets always require two instances. A single DiskFPSet
			// essentially only uses 63. fingerprint bits and thus increases the
			// likelihood of hash collisions.
			fpBits = 1;
		}
		return fpBits;
	}

	public void setFpBits(int fpBits) {
		Assert.check(FPSet.isValid(fpBits), EC.GENERAL);
		this.fpBits = fpBits;
	}

	public long getMemoryInBytes() {
		final TLCRuntime instance = TLCRuntime.getInstance();
		
		// Here the user has given a ratio of available memory to 
		// use for fingerprint storage
		if (FPSetFactory.allocatesOnHeap(implementation)) {
			// If a user has set memory explicitly, we pass this value to 
			// getFPMemSize(double) which sanitizes the value.
			if (memoryInBytes > 0) {
				return instance.getFPMemSize(memoryInBytes * ratio);
			} else {
				return instance.getFPMemSize(ratio);
			}
		} else {
			// Right now the only consumer of non-heap memory is fingerprint
			// storage. Thus, it makes little sense to allocate less than
			// all non-heap memory dedicated to the VM process. Until this changes,
			// we override ratio to devote all non-heap mem to fingerprint storage.
			//
			// TODO Respect ratio once other TLC data structures start using
			// non-heap memory
			return (long) (instance.getNonHeapPhysicalMemory()/* *ratio */);
		}
	}
	
	public long getMemoryInFingerprintCnt() {
		//TODO Replace FPSet.LongSize with fingerprint length
		
		// Explicitly floor to indicate that an FPSet cannot store a portion of a fingerprint.
		return (long) Math.floor(getMemoryInBytes() / FPSet.LongSize);
	}

	public int getMultiFPSetCnt() {
		return 1 << getFpBits();
	}
	
	public void setRatio(double aRatio) {
		// Allowing aRatio to be 0.0 makes little sense semantically, but we
		// accept it anyway and let TLCRuntime deal with it.
		Assert.check(aRatio >= 0 && aRatio <= 1, EC.GENERAL);
		this.ratio = aRatio;
	}

	public double getRatio() {
		return ratio;
	}

	/**
	 * @deprecated DO NOT USE, will be removed once -fpmem cmd line parameter
	 *             only accepts a ratio rather than an absolute memory value
	 * @param fpMemSize
	 */
	public void setMemory(long fpMemSize) {
		Assert.check(fpMemSize >= 0, EC.GENERAL);
		this.memoryInBytes = fpMemSize;
	}
	
	public String getImplementation() {
		return implementation;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/Application.java<|end_filename|>
// Copyright (c) Jan 30, 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.ChooseWorkspaceData;

/**
 * This class controls all aspects of the application's execution
 * 
 * @author <NAME>
 */
@SuppressWarnings("restriction")
public class Application implements IApplication {

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
	 */
	public Object start(IApplicationContext context) throws InvocationTargetException, InterruptedException {
		Object argObject = context.getArguments().get(
				IApplicationContext.APPLICATION_ARGS);
		if (argObject != null && argObject instanceof String[]) {
			String[] args = (String[]) argObject;
			if (args.length != 0) {
				StandaloneActivator.getDefault().logDebug(context.getBrandingName() + " started with "
						+ args.length + " arguments.");
				for (int i = 0; i < args.length; i++) {
					StandaloneActivator.getDefault().logDebug(args[i]
							+ ((i == args.length - 1) ? "" : ", "));
				}
			} else {
				StandaloneActivator.getDefault().logDebug(context.getBrandingName()
						+ " started without arguments.");
			}
		}
		
		final Location instanceLocation = Platform.getInstanceLocation();
		
		// Check if the workspace has already been migrated to the new canonical
		// location starting with Toolbox 1.5.4. If it hasn't, we lookup the
		// previous location and copy its content to the canonical location
		// (unless for whatever reason the user decides to start fresh).
		// With a canonical location the cwd no longer matters from which the
		// Toolbox launcher is executed.
		if (!new File(instanceLocation.getURL().getFile() + File.separator + ".metadata" + File.separator).exists()) {
			final String previousInstanceLoc = getPreviousInstanceLocation(instanceLocation);
			if (previousInstanceLoc != null) {
				final String instanceLoc = instanceLocation.getURL().toExternalForm();
				if(!instanceLoc.equals(previousInstanceLoc)) {
					// Empty the recent workspaces to not show the dialog again.
					// Only clear it when the previous and current instance
					// location differ. This is the case when a user updates the
					// Toolbox and hits the restart button at the end of update.
					// This causes the Toolbox to restart with the previous
					// install location again.
					clearPreviousInstanceLocation(instanceLocation);
					
					// Open dialog and ask user to either import (migrate) the old workspace or create a fresh workspace.
					final MessageDialog md = new MessageDialog(PlatformUI.createDisplay().getActiveShell(), "Migrate Toolbox files.",
							null, 
									"Previously, your Toolbox used a different location to store its list of specifications and preferences. "
									+ "Starting with Toolbox release 1.5.4, the Toolbox keeps this data in a canonical location.\n\n"
									+ "If you do not let the Toolbox migrate this data, "
									+ "it will come up with default preferences and an empty spec explorer. "
									+ "You will have to manually configure the preferences and import your existing specifications.\n\n"
									+ "Click \"Migrate\" if you want the Toolbox to migrate the data now and continue Toolbox start-up.\n\n"
									+ "Click \"Start Fresh\" to continue Toolbox start-up and to manually import your specifications.",
							MessageDialog.QUESTION, new String[] {"Migrate", "Start Fresh"}, 0);
					
					if (md.open() == 0) {
						final ProgressMonitorDialog pmd = new ProgressMonitorDialog(Display.getCurrent().getActiveShell());
						pmd.run(true, false, new IRunnableWithProgress() {
							public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
								monitor.beginTask("Migrating Toolbox metadata to new location.", IProgressMonitor.UNKNOWN);
								
								copyRecurively(toPath(previousInstanceLoc, ".metadata"), toPath(instanceLoc), monitor);
								monitor.done();
							}
						});
					}
				}
			}
		}
		
		// The call to getStateLocation makes sure the instance location gets
		// initialized before we call .lock on it.
		StandaloneActivator.getDefault().getStateLocation();
		// Only allow a single Toolbox instance per workspace to prevent data
		// corruption in the workspace files.
		try {
			if (!instanceLocation.lock()) {
				final File workspaceDirectory = new File(Platform.getInstanceLocation().getURL().getFile());
				if (workspaceDirectory.exists()) {
					MessageDialog.openError(PlatformUI.createDisplay().getActiveShell(), "Toolbox files cannot be locked",
							NLS.bind(
									"Could not launch the Toolbox because the associated workspace is currently in use by another Toolbox. Opening two instances on the same workspace leads to data corruption.\n\n"
											+ "If this is incorrect and there is no other Toolbox running, an earlier Toolbox terminated without releasing the lock. Please manually delete the lock file ''{0}'' and try restarting the Toolbox.",
											workspaceDirectory.getAbsolutePath()
											.concat(File.separator + ".metadata" + File.separator + ".lock")));
				}
				// We showed an error to the user, lets do a "clean" (0) exit to
				// not raise a second window with a detailed technical error.
				System.exit(0);
			}
		} catch (IOException e) {
			StandaloneActivator.getDefault().logError("Toolbox files cannot be locked", e);
			MessageDialog.openError(PlatformUI.createDisplay().getActiveShell(), "Toolbox files cannot be locked",
					"Could not launch the Toolbox because acquiring the associated workspace lock failed. We are sorry, this is a bug. Please get in contact with us.");
			// We showed an error to the user, lets do a "clean" (0) exit to
			// not raise a second window with a detailed technical error.
			System.exit(0);
		}

		Display display = PlatformUI.createDisplay();
		try {
			int returnCode = PlatformUI.createAndRunWorkbench(display,
					new ApplicationWorkbenchAdvisor());
			if (returnCode == PlatformUI.RETURN_RESTART) {
				return IApplication.EXIT_RESTART;
			}
			return IApplication.EXIT_OK;
		} catch (Exception e) {
			throw new RuntimeException(e) {
				@Override
				public String toString() {
					return "The Toolbox failed to launch because of an unexpected error. Please try to launch the Toolbox with the \"-clean\" parameter.\n"
							+ "If \"-clean\" does not fix the problem, please open a bug and attach the .log file.\n\n" + super.toString();
				}
			};
		} finally {
			display.dispose();
		}
	}

	private static Path toPath(final String prefix) {
		return toPath(prefix, "");
	}

	// Converts our special path string coming from the BasicLocation to a valid
	// path for java.nio.file.Path.
	private static Path toPath(final String prefix, final String suffix) {
		if (prefix.replaceFirst("file:", "").contains(":")) {
			// Windows path, e.g. file:/C:/...
			return Paths.get(prefix.replaceFirst("file:/", ""), suffix);
		}
		return Paths.get(prefix.replaceFirst("file:", ""), suffix);
	}

	private static void clearPreviousInstanceLocation(final Location instanceLocation) {
		final ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLocation.getDefault());
		launchData.setRecentWorkspaces(new String[0]);
		launchData.writePersistedData();
	}

	private static String getPreviousInstanceLocation(final Location instanceLocation) {
		// CWD is Eclipse infrastructure which stores the location of the
		// current workspace in a (text) file in the configuration area (Toolbox
		// installation directory) in 1.5.3. With version 1.5.4 of the Toolbox, we will
		// use this information below to migrate all workspaces to @user.home/.tlaplus.
		final ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLocation.getDefault());
		final List<String> recentWorkspaces = Arrays.asList(launchData.getRecentWorkspaces());
		if (!recentWorkspaces.isEmpty()) {
			// Get the first non-null workspace. It is the most recently used one.
			for(int i = 0; i < recentWorkspaces.size(); i++) {
				if (recentWorkspaces.get(i) != null) {
					return recentWorkspaces.get(i);
				}
			}
		}
		return null;
	}
	
	// https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java
	private static void copyRecurively(final Path src, final Path dst, final IProgressMonitor monitor)
			throws InvocationTargetException {
		try {
			dst.toFile().mkdir();
			final Path target = dst.resolve(src.getFileName());
			Files.walkFileTree(src, new FileVisitor<Path>() {
				public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs)
						throws IOException {
					try {
						Files.copy(dir, target.resolve(src.relativize(dir)), StandardCopyOption.COPY_ATTRIBUTES);
					} catch (final FileAlreadyExistsException e) {
						// ignore
					}
					monitor.worked(1);
					return FileVisitResult.CONTINUE;
				}

				public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
					Files.copy(file, target.resolve(src.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES);
					monitor.worked(1);
					return FileVisitResult.CONTINUE;
				}

				public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException {
					return FileVisitResult.CONTINUE;
				}

				public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
					final FileTime time = Files.getLastModifiedTime(dir);
					Files.setLastModifiedTime(target.resolve(src.relativize(dir)), time);
					monitor.worked(1);
					return FileVisitResult.CONTINUE;
				}
			});
		} catch (IOException e) {
			throw new InvocationTargetException(e);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#stop()
	 */
	public void stop() {
		final IWorkbench workbench = PlatformUI.getWorkbench();
		if (workbench == null)
			return;
		final Display display = workbench.getDisplay();
		display.syncExec(new Runnable() {
			public void run() {
				if (!display.isDisposed())
					workbench.close();
			}
		});
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/HeapBasedDiskFPSet.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.concurrent.locks.Lock;
import java.util.logging.Level;

import tlc2.TLCGlobals;
import tlc2.tool.fp.management.DiskFPSetMXWrapper;
import tlc2.util.Striped;
import util.Assert;

@SuppressWarnings("serial")
public abstract class HeapBasedDiskFPSet extends DiskFPSet {

	/**
	 * Number of locks in the striped lock (#StripeLocks = 2^LogLockCnt).<br>
	 * Theoretically best performance should be seen with on lock per bucket in
	 * the primary hash table. An some point though (not yet measured), this
	 * performance benefit is probably eaten up by the memory consumption of the
	 * striped lock {@link DiskFPSet#rwLock} itself, which reduces the memory
	 * available to the hash set.
	 */
	protected static final int LogLockCnt = Integer.getInteger(DiskFPSet.class.getName() + ".logLockCnt", (31 - Integer.numberOfLeadingZeros(TLCGlobals.getNumWorkers()) + 8));
	/**
	 * protects n memory buckets
	 */
	protected final Striped rwLock;
	/**
	 * Is (1 << LogLockCnt) and exposed here for subclasses
	 */
	protected final int lockCnt;
	
	protected final int lockMask;
	/**
	 * in-memory buffer of new entries
	 */
	protected long[][] tbl;
	
	/**
	 * mask for computing hash function
	 */
	protected long mask;
	
	/**
	 * The calculated capacity of tbl. Will always be a power of two.
	 */
	protected final int capacity;
	
	/**
	 * 
	 */
	protected int logMaxMemCnt;

	protected static final int BucketSizeIncrement = 4;
	/**
	 * Log (base 2) of default number of new entries allowed to accumulate in
	 * memory before those entries are flushed to disk.
	 */
	protected static final int LogDefaultMaxTblCnt = 19;
	static final int DefaultMaxTblCnt = (1 << LogDefaultMaxTblCnt);

	protected HeapBasedDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);

		// Ideally we use one lock per bucket because even with relatively high
		// lock counts, we fall victim to the birthday paradox. However, locks
		// ain't cheap, which is why we have to find the sweet spot. We
		// determined the constant 8 empirically on Intel Xeon CPU E5-2670 v2 @
		// 2.50GHz. This is based on the number of cores only. We ignore their
		// speed. MultiThreadedMSBDiskFPSet is the most suitable performance
		// test available for the job. It just inserts long values into the
		// set. int is obviously going to be too small once 2^23 cores become
		// commonplace.
		this.lockCnt = 1 << LogLockCnt;
		this.rwLock = Striped.readWriteLock(lockCnt);

		// Reserve a portion of the memory for the auxiliary storage
		long maxMemCnt = (long) (fpSetConfig.getMemoryInFingerprintCnt() / getAuxiliaryStorageRequirement());

		// default if not specific value given
		if ((maxMemCnt - LogMaxLoad) <= 0) {
			maxMemCnt = DefaultMaxTblCnt;
		}
		
		// approximate next lower 2^n ~= maxMemCnt
		logMaxMemCnt = (Long.SIZE - 1) - Long.numberOfLeadingZeros(maxMemCnt);
		
		// guard against underflow
		// LL modified error message on 7 April 2012
		Assert.check(logMaxMemCnt - LogMaxLoad >= 0, "Underflow when computing HeapBasedDiskFPSet");
		
		// Guard against a capacity overflow with large amounts (e.g. ~1TB) of
		// dedicated memory. If cap overflows, the VMs maximum allowed array
		// size is used.
		final int cap = 1 << (logMaxMemCnt - LogMaxLoad);
		if (cap < 0) {
			// You wonder why 8 and not 42? Ask the VM gods!
			this.capacity = Integer.MAX_VALUE - 8;
		} else {
			this.capacity = cap;
		}
		
		// maxTblCnt mathematically has to be an upper limit for the in-memory storage 
		// so that a disk flush occurs before an _evenly_ distributed fp distribution fills up 
		// the collision buckets to a size that exceeds the VM limit (unevenly distributed 
		// fp distributions can still cause a OutOfMemoryError which this guard).
		this.maxTblCnt = (1L << logMaxMemCnt); // maxTblCnt := 2^logMaxMemCnt

		Assert.check(maxTblCnt <= fpSetConfig.getMemoryInFingerprintCnt(), "Exceeded upper memory storage limit");

		// guard against negative maxTblCnt
		// LL modified error message on 7 April 2012
		Assert.check(maxTblCnt > capacity && capacity > getTblCnt(),
				"negative maxTblCnt");

		this.mask = capacity - 1;
		
		this.lockMask = lockCnt - 1;

		this.tbl = new long[capacity][];
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#sizeof()
	 */
	public long sizeof() {
		long size = 44; // approx size of this DiskFPSet object
		rwLock.acquireAllLocks();
		size += 16 + (this.tbl.length * 4); // for this.tbl
		for (int i = 0; i < this.tbl.length; i++) {
			if (this.tbl[i] != null) {
				// 16 bytes overhead for each row in tbl!
				size += 16 + (this.tbl[i].length * (long) LongSize);
			}
		}
		// size of index array if non-null
		size += getIndexCapacity() * 4;
		rwLock.releaseAllLocks();
		return size;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getLockCnt()
	 */
	public int getLockCnt() {
		return this.rwLock.size();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getTblCapacity()
	 */
	public long getTblCapacity() {
		return tbl.length;
	}

	/**
	 * calculate hash value (just n least significat bits of fp) which is used as an index address
	 * @param fp
	 * @return
	 */
	protected int getIndex(long fp) {
		return (int) index(fp, this.mask);
		
	}	
	
	protected int getLockIndex(long fp) {
		// In case of overflow, a NegativeArrayOffset will be thrown
		// subsequently.
		return (int) index(fp, this.lockMask);
	}
	
	protected long index(long fp, long aMask) {
		return fp & aMask;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#contains(long)
	 * 
     * 0 and {@link Long#MIN_VALUE} always return false
	 */
	public final boolean contains(long fp) throws IOException {
		fp = checkValid(fp);
		// zeros the msb
		long fp0 = fp & 0x7FFFFFFFFFFFFFFFL;
		final Lock readLock = this.rwLock.getAt(getLockIndex(fp0)).readLock();
		readLock.lock();
		// First, look in in-memory buffer
		if (this.memLookup(fp0)) {
			readLock.unlock();
			this.memHitCnt.increment();
			return true;
		}

		// block if disk is being re-written
		// next, look on disk
		boolean diskHit = this.diskLookup(fp0);
		// increment while still locked
		if(diskHit) {
			diskHitCnt.increment();
		}

		// end read; add to memory buffer if necessary
		readLock.unlock();
		return diskHit;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#memLookup(long)
	 */
	boolean memLookup(long fp) {
		long[] bucket = this.tbl[getIndex(fp)];
		if (bucket == null)
			return false;

		int bucketLen = bucket.length;
		// Linearly search the bucket; 0L is an invalid fp and marks the end of
		// the allocated bucket
		for (int i = 0; i < bucketLen && bucket[i] != 0L; i++) {
			// zero the long msb (which is 1 if fp has been flushed to disk)
			if (fp == (bucket[i] & 0x7FFFFFFFFFFFFFFFL))
				return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#put(long)
	 * 
     * 0 and {@link Long#MIN_VALUE} always return false
     * 
     * Locking is as follows:
     * 
     * Acquire mem read lock
     * Acquire disk read lock
     * Release mem read lock
     * 
     * Acquire mem read/write lock
     * Release disk read lock // interleaved 
     *  insert into mem
     * Acquire disk write lock (might cause potential writer to wait() which releases mem read lock (monitor))
     * 	flushToDisk
     * Release disk write lock
     * Release mem read lock
     * 
     * asserts:
     * - Exclusive access to disk and memory for a writer
     * 
	 */
	public final boolean put(long fp) throws IOException {
		fp = checkValid(fp);
		// zeros the msb
		long fp0 = fp & 0x7FFFFFFFFFFFFFFFL;
		
		final Lock readLock = rwLock.getAt(getLockIndex(fp0)).readLock();
		readLock.lock();
		// First, look in in-memory buffer
		if (this.memLookup(fp0)) {
			readLock.unlock();
			this.memHitCnt.increment();
			return true;
		}
		
		// blocks => wait() if disk is being re-written 
		// (means the current thread returns rwLock monitor)
		// Why not return monitor first and then acquire read lock?
		// => prevent deadlock by acquiring threads in same order? 
		
		// next, look on disk
		boolean diskHit = this.diskLookup(fp0);
		
		// In event of disk hit, return
		if (diskHit) {
			readLock.unlock();
			this.diskHitCnt.increment();
			return true;
		}
		
		readLock.unlock();
		
		// Another writer could write the same fingerprint here if it gets
		// interleaved. This is no problem though, because memInsert again
		// checks existence for fp to be inserted
		
		final Lock w = rwLock.getAt(getLockIndex(fp0)).writeLock();
		w.lock();
		
		// if disk lookup failed, add to memory buffer
		if (this.memInsert(fp0)) {
			w.unlock();
			this.memHitCnt.increment();
			return true;
		}
		
		// test if buffer is full && block until there are no more readers 
		if (needsDiskFlush() && this.flusherChosen.compareAndSet(false, true)) {
			
			// statistics
			growDiskMark++;
			final long timestamp = System.currentTimeMillis();
			final long insertions = getTblCnt();
			
			// acquire _all_ write locks
			rwLock.acquireAllLocks();
			
			// flush memory entries to disk
			flusher.flushTable();
			
			// release _all_ write locks
			rwLock.releaseAllLocks();
			
			// reset forceFlush to false
			forceFlush = false;
			
			// finish writing
			this.flusherChosen.set(false);

			long l = System.currentTimeMillis() - timestamp;
			flushTime += l;
			
			LOGGER.log(Level.FINE, "Flushed disk {0} {1}. time, in {2} sec after {3} insertions.", new Object[] {
					((DiskFPSetMXWrapper) diskFPSetMXWrapper).getObjectName(), getGrowDiskMark(), l, insertions});
		}
		w.unlock();
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#memInsert(long)
	 */
	boolean memInsert(long fp) {
		int index = getIndex(fp);
		
		// try finding an existing bucket 
		long[] bucket = this.tbl[index];
		
		// no existing bucket found, create new one
		if (bucket == null) {
			bucket = new long[InitialBucketCapacity];
			bucket[0] = fp;
			this.tbl[index] = bucket;
			this.bucketsCapacity += InitialBucketCapacity; 
			this.tblLoad.increment();
		} else {
			// search for entry in existing bucket
			int bucketLen = bucket.length;
			int i = -1;
			int j = 0;
			for (; j < bucketLen && bucket[j] != 0L; j++) {
				long fp1 = bucket[j];
				// zero the long msb
				long l = fp1 & 0x7FFFFFFFFFFFFFFFL;
				if (fp == l) {
					// found in existing bucket
					return true;
				}
				// fp1 < 0 iff fp1 is on disk;
				// In this case, keep fp1 idx for new fingerprint fp
				if (i == -1 && fp1 < 0) {
					i = j;
				}
			}
			if (i == -1) {
				if (j == bucketLen) {
					// bucket is full; grow the bucket by BucketSizeIncrement
					long[] oldBucket = bucket;
					bucket = new long[bucketLen + BucketSizeIncrement];
					System.arraycopy(oldBucket, 0, bucket, 0, bucketLen);
					this.tbl[index] = bucket;
					this.bucketsCapacity += BucketSizeIncrement;
				}
				// add to end of bucket
				bucket[j] = fp;
			} else {
				if (j != bucketLen) {
					bucket[j] = bucket[i];
				}
				bucket[i] = fp;
			}
		}
		this.tblCnt.increment();
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#acquireTblWriteLock()
	 */
	void acquireTblWriteLock() {
		rwLock.acquireAllLocks();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#releaseTblWriteLock()
	 */
	void releaseTblWriteLock() {
		rwLock.releaseAllLocks();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/eclipse/jdt/internal/ui/actions/FoldingMessages.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.actions;

import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * Class that gives access to the folding messages resource bundle.
 */
public class FoldingMessages {

	private static final String BUNDLE_NAME= "org.eclipse.jdt.internal.ui.actions.FoldingMessages"; //$NON-NLS-1$

	private static final ResourceBundle RESOURCE_BUNDLE= ResourceBundle.getBundle(BUNDLE_NAME);

	private FoldingMessages() {
		// no instance
	}

	/**
	 * Returns the resource string associated with the given key in the resource bundle. If there isn't
	 * any value under the given key, the key is returned.
	 *
	 * @param key the resource key
	 * @return the string
	 */
	public static String getString(String key) {
		try {
			return RESOURCE_BUNDLE.getString(key);
		} catch (MissingResourceException e) {
			return '!' + key + '!';
		}
	}

	/**
	 * Returns the resource bundle managed by the receiver.
	 *
	 * @return the resource bundle
	 * @since 3.0
	 */
	public static ResourceBundle getResourceBundle() {
		return RESOURCE_BUNDLE;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/Operators.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified onFri  2 Mar 2007 at 15:40:00 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.parser;

import java.util.Enumeration;
import java.util.Hashtable;

import util.UniqueString;

public class Operators {
  static public int assocNone = 0;
  static public int assocLeft = 1;
  static public int assocRight = 2;

  /*************************************************************************
  * The following appear to be classes of operators.                       *
  *************************************************************************/
  static public int nofix = 0;
    /***********************************************************************
    * What is a nofix operator?????????                                    *
    ***********************************************************************/
  static public int prefix = 1;
  static public int postfix = 2;
  static public int infix = 3;
  static public int nfix = 4;// \X
    /***********************************************************************
    * The only operator of class nfix seems to be \X (aka \times).         *
    ***********************************************************************/
  static Hashtable DefinitionTable = new Hashtable();
    /***********************************************************************
    * Contains the Operator objects for all operators.  It is constructed  *
    * from the data in ConfigConstants.defaultConfig.                      *
    ***********************************************************************/
  static Hashtable BuiltinTable = new Hashtable();
    /***********************************************************************
    * It appears that this is not used.                                    *
    ***********************************************************************/
    
  static public void addOperator( UniqueString name, Operator op ) {
    DefinitionTable.put(name, op);
  }

  static public Operator getOperator( UniqueString name ) {
    return (Operator) DefinitionTable.get( name );
  }

  static public Operator getMixfix( Operator op ) {
     if (op.isPrefix()) return op;
     else {
       UniqueString id = UniqueString.uniqueStringOf( op.getIdentifier().toString() + ".");
       return (Operator) DefinitionTable.get( id );
     }
  }
  
  static public boolean existsOperator( UniqueString name ) {
    return ( DefinitionTable.get( name ) != null );
  }

  static public void addSynonym( UniqueString template, UniqueString match ) {
    /*
       do make sure that the operator already exists.
       We make the new definition point to the other one.
    */
    Operator n = (Operator) DefinitionTable.get( match );
    if (n != null) {
      DefinitionTable.put(template, n);
    } /* else {
       error
    } */
  }
  
  /*************************************************************************
  * resolveSynonym has the property that                                   *
  *                                                                        *
  *    resolveSynonym(a) = resolveSynonym(b)                               *
  *                                                                        *
  * iff either a = b or a and b are synonyms (like (+) and \oplus).  If a  *
  * has no synonmys, then resolveSynonym(a) = a.                           *
  *************************************************************************/
  static public UniqueString resolveSynonym( UniqueString name ) {
    Operator n = (Operator) DefinitionTable.get( name );
    if ( n == null ) return name;
    else return n.getIdentifier();
  }

  static public void addBuiltinAssoc( UniqueString symbol, UniqueString builtin ) {
    BuiltinTable.put( symbol, builtin );
  }

  /*************************************************************************
  * It appears that the following method is not used.                      *
  *************************************************************************/
  static public UniqueString getBuiltinAssoc( UniqueString symbol ) {
    /* first, resolve synonyms */
    Operator n = (Operator) DefinitionTable.get(symbol);
    if (n != null) {
      UniqueString name = n.getIdentifier(); /* can't be null */
      /* then lookup solution */
      return (UniqueString) (BuiltinTable.get(name));
    } else
      return null;
  }

/* debugging help */
  static public void printTable() {
    System.out.println("printing Operators table");
    Enumeration Enum = DefinitionTable.keys();
    while( Enum.hasMoreElements() ) { System.out.println("-> " + ((UniqueString)Enum.nextElement()).toString() ); }
  }

// shouldn't be necessary
//  static public Operator operatorFromASTNode ( ASTNode tn ) {
//     Operator n = (Operator) DefinitionTable.get( tn.getToken().image );
//        return n;
//  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ThmOrAssumpDefNode.java<|end_filename|>
// Copyright (c) 2007 Microsoft Corporation.  All rights reserved.

// last modified on Thu  2 July 2009 at 15:44:33 PST by lamport
/***************************************************************************
* The ThmOrAssumpDefNode constructor is invoked in                         *
* semantic/Generator.java to construct the nodes corresponding to the      *
* definition in something like                                             *
*                                                                          *
*   THEOREM Foo == ...                                                     *
*                                                                          *
* The following are the only public methods that a tool is likely to       *
* call.  (Search for the method to find an explanation of what it does.)   *
*                                                                          *
*    LevelNode getBody()                                                   *
*    ModuleNode getOriginallyDefinedInModuleNode()                         *
*    boolean  isTheorem()                                                  *
*    boolean isSuffices()                                                  *
*    ProofNode getProof()                                                  *
*    FormalParamNode[] getParams()                                         *
*    ModuleNode getInstantiatedFrom()                                      *
***************************************************************************/

package tla2sany.semantic;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import tla2sany.xml.SymbolContext;
import util.UniqueString;
import util.WrongInvocationException;

/***************************************************************************
* This node represents the definition of Foo in                            *
*                                                                          *
*    THEOREM Foo == ...                                                    *
*    ASSUME  Foo == ...                                                    *
***************************************************************************/

public class ThmOrAssumpDefNode extends SymbolNode
         implements OpDefOrLabelNode, AnyDefNode {

  // T.L. 2014 - the actual theorem or assumption associated with this def
  // this is required in order to simplify presentation. After all normalizations
  // we dont really need this def any more
  // this field is being set by TheoremNode or AssumeNode
  protected LevelNode thmOrAssump  = null;
  private LevelNode body        = null;
  private ModuleNode originallyDefinedInModule = null;
  private boolean theorem       = true;
    /***********************************************************************
    * True if a theorem, false if an assumption.                           *
    ***********************************************************************/
  private boolean suffices = false ;
    /***********************************************************************
    * If this represents a theorem, then this is the value of the          *
    * TheoremNode's suffices field (which is false unless the TheoremNode  *
    * represents a SUFFICES proof step).  This is a kludge added for the   *
    * following reason.  To check if a reference to a subexpression of an  *
    * ASSUME/PROVE is legal, we need to know whether or not the            *
    * ASSUME/PROVE lies within a SUFFICES step.  However, the reference    *
    * accesses the ThmOrAssumpDefNode, while it's the TheoremNode that     *
    * contains the suffices field.  It might seem sensible to have the     *
    * ThmOrAssumpDefNode contain a pointer to the TheoremNode.  However,   *
    * that's problematic.  For one thing, instantiation creates a new      *
    * ThmOrAssumpDefNode for the imported definition, but does not create  *
    * a new TheoremNode.  So, we copy just the suffices field (which will  *
    * be false for an instantiated node because proof steps don't get      *
    * instantiated).                                                       *
    *                                                                      *
    * This field is set by setSuffices() and read by isSuffices() ;        *
    ***********************************************************************/


  /*************************************************************************
  * The following field is used to implement the OpDefOrLabel interface.   *
  * It is a hashtable of OpDefNode objects representing labels within      *
  * the body that are not within the scope of an inner label or LET        *
  * definition.                                                            *
  *************************************************************************/
  private Hashtable<UniqueString, LabelNode> labels = null ;
  public Hashtable<UniqueString, LabelNode>  getLabelsHT() {
      /***********************************************************************
      * Return the labels field.  Used to "clone" an OpDefNode for module    *
      * instantiation.                                                       *
      ***********************************************************************/
      return labels ;
     }

  public int arity = 0 ;
  private FormalParamNode[] params = new FormalParamNode[0];
    /***********************************************************************
    * A theorem or assumption definition like                              *
    *                                                                      *
    *   THEOREM foo == ...                                                 *
    *                                                                      *
    * has no parameters.  However, it can acquire parameters when          *
    * the module it's in is instantiated.                                  *
    ***********************************************************************/
   ProofNode proof;
     /**********************************************************************
     * The proof, if there is one; else null.  Obviously, only a theorem   *
     * can have a proof.                                                   *
     **********************************************************************/

  private ModuleNode instantiatedFrom = null ;
    /***********************************************************************
    * If the theorem or assumption was obtained by instantiation, then     *
    * this is the module from which it was instantiated.                   *
    ***********************************************************************/

  /**
   *  The source field and its methods was added by LL on 15 June 2010.
   *  I don't know why it wasn't added to this class when it was added
   *  to OpDefNode.  However, it's needed by the Toolbox, so it's being
   *  added now by trying to duplicate what was done for OpDefNode
   */
  private ThmOrAssumpDefNode source = null;

  public ThmOrAssumpDefNode getSource() {
      if (source == null) {
          return this;
      }
      return source;
  }

  /*************************************************************************
  * The Constructor.                                                      *
  *************************************************************************/
  public ThmOrAssumpDefNode(
           UniqueString name,       // The thm/assump name.
           boolean      thm,        // true if a theorem, false if an assump.
           LevelNode    exp,        // The body
           ModuleNode   oModNode,   // Name of module.
           SymbolTable  st,         // The current value of
                                    // Generator.symbolTable
           TreeNode stn,            // The syntax node.
           FormalParamNode[] parms, // The parameters, or null if none.
           ModuleNode   iFrom,      // The instantiatedFrom field.
           ThmOrAssumpDefNode src   // The source field.
                           ) {
    super(ThmOrAssumpDefKind, stn, name) ;
    this.theorem    = thm;
    this.body       = exp;
    this.originallyDefinedInModule = oModNode;
      /*********************************************************************
      * Note that when this theorem or assumption is instantiated with a   *
      * parameter substitution, then the newly created ThmOrAssumpDefNode  *
      * has this field set to the instantiating module.  Thus, this field  *
      * is not useful to track down the module of origin of a theorem.     *
      *********************************************************************/
    // On 1 Nov 2012,, LL moved the following two statements to here from
    // the end of the constructor.  It's necessary for the source field to be
    // set before addSymbol is called.
    this.instantiatedFrom = iFrom ;
    this.source = src;

    if (st != null) {st.addSymbol(name, this);} ;
      /*********************************************************************
      * By some magic, this eventually puts the name into the current      *
      * module's context.                                                  *
      *********************************************************************/
    if (parms != null) {
      this.params = parms;
      this.arity = parms.length;
     } ;
  }

  /*************************************************************************
  * A place-holder constructor and a method for setting the remaining      *
  * fields.  It is used in Generator.processTheorem, where the object      *
  * needs to be created before its body is generated.  This method is      *
  * not used when created a ThmOrAssumpDefNode by instantiation, so        *
  * getInstantitedFrom will be null for this object.                       *
  *************************************************************************/
  public ThmOrAssumpDefNode(UniqueString name, TreeNode stn) {
    super(ThmOrAssumpDefKind, stn, name) ;
   }

  public void construct(
           boolean      thm,       // true if a theorem, false if an assump.
           LevelNode    exp,       // The body
           ModuleNode   oModNode,  // Name of module.
           SymbolTable  st,        // The current value of
                                   // Generator.symbolTable
           FormalParamNode[] parms // The parameters, or null if none.
                           ) {
    this.theorem    = thm;
    this.body       = exp;
    this.originallyDefinedInModule = oModNode;
    if (st != null) {st.addSymbol(name, this);} ;
      /*********************************************************************
      * By some magic, this eventually puts the name into the current      *
      * module's context.                                                  *
      *********************************************************************/
    if (parms != null) {
      this.params = parms;
      this.arity = parms.length;
     } ;
  }

  /*************************************************************************
  * The methods.                                                           *
  *************************************************************************/
  public LevelNode getBody() {return this.body; } ;
    /***********************************************************************
    * Note: this is a LevelNode rather than an ExprNode because it could   *
    * be either an ExprNode, AssumeProve node, or an APSubstInNode whose   *
    * body is either an ExprNode or an AssumeProve node.  To check if a    *
    * node N is an ExprNode, use the test                                  *
    *                                                                      *
    *    N instanceof ExprNode                                             *
    ***********************************************************************/

  public ModuleNode getOriginallyDefinedInModuleNode()
    /***********************************************************************
    * This is the module for which the node was created, which for a       *
    * theorem or assumption instantiated with substitution is not the      *
    * module from which the theorem or assumption came.                    *
    ***********************************************************************/
    { return originallyDefinedInModule; }

  public ModuleNode getInstantiatedFrom() { return this.instantiatedFrom ; }
    /***********************************************************************
    * If the theorem or assumption was obtained by instantiation, then     *
    * this is the module from which it was instantiated.  Otherwise, it    *
    * is null.                                                             *
    ***********************************************************************/

  public boolean  isTheorem()  {return this.theorem ;}
  public boolean isSuffices()  {return this.suffices ;};
         void    setSuffices() {this.suffices = true;};

  /*************************************************************************
  * Return the proof of the theorem, which is null unless this is a        *
  * theorem and it has a proof.                                            *
  *************************************************************************/
  public final ProofNode getProof() {return this.proof;}

  public final FormalParamNode[] getParams() { return this.params; }

  public final boolean isExpr() { return this.body instanceof ExprNode; }
    /***********************************************************************
    * Returns true iff the body is an ExprNode (rather than an             *
    * AssumeProveNode or APSubstInNode).                                   *
    ***********************************************************************/


  /*************************************************************************
  * Implementations of the abstract methods of the SymbolNode superclass.  *
  *************************************************************************/
  public final int getArity() { return this.arity;}
    /***********************************************************************
    * The name of a theorem or assumption has no parameters.               *
    ***********************************************************************/

  // Modified by LL on 30 Oct 2012 to handle locally instantiated theorems
  // and assumptions.
  private boolean local = false ;
  public final boolean isLocal() { return local; }
    /***********************************************************************
    * Theorem and assumption definitions are local iff imported with a     *
    * LOCAL instance.                                                      *
    ***********************************************************************/
  public final void setLocal(boolean localness) {
      local = localness ;
  }

//  public final ModuleNode getModuleNode() { return this.moduleNode; }

  public final boolean match( OpApplNode test, ModuleNode mn ) {
    /***********************************************************************
    * True iff the current object has the same arity as the node operator  *
    * of the OpApplNode test.                                              *
    ***********************************************************************/
    SymbolNode odn = test.getOperator();
    return odn.getArity() == 0;
  }


  /*************************************************************************
  * The following methods implement the OpDefOrLabel interface.            *
  *                                                                        *
  * These are the same as the other classes that implement the interface.  *
  * There doesn't seem to be any easy way to write these methods only      *
  * once.                                                                  *
  *************************************************************************/
  public void setLabels(Hashtable<UniqueString, LabelNode> ht) {labels = ht; }
    /***********************************************************************
    * Sets the set of labels.                                              *
    ***********************************************************************/

  public LabelNode getLabel(UniqueString us) {
    /***********************************************************************
    * If the hashtable `labels' contains a LabelNode with name `us',       *
    * then that LabelNode is returned; otherwise null is returned.         *
    ***********************************************************************/
    if (labels == null) {return null;} ;
    return (LabelNode) labels.get(us) ;
   }

  public boolean addLabel(LabelNode odn) {
    /***********************************************************************
    * If the hashtable `labels' contains no OpDefNode with the same name   *
    * as odn, then odn is added to the set and true is return; else the    *
    * set is unchanged and false is returned.                              *
    ***********************************************************************/
    if (labels == null) {labels = new Hashtable<>(); } ;
    if (labels.containsKey(odn.getName())) {return false ;} ;
    labels.put(odn.getName(), odn) ;
    return true;
   }

  public LabelNode[] getLabels() {
    /***********************************************************************
    * Returns an array containing the Label objects in the hashtable       *
    * `labels'.                                                            *
    ***********************************************************************/
    if (labels == null) {return new LabelNode[0];} ;
    Vector<LabelNode> v = new Vector<>() ;
    Enumeration<LabelNode> e = labels.elements() ;
    while (e.hasMoreElements()) { v.addElement(e.nextElement()); } ;
    LabelNode[] retVal = new LabelNode[v.size()] ;
    for (int i = 0 ; i < v.size() ; i++)
      {retVal[i] = v.elementAt(i); } ;
    return retVal ;
   }

// On 24 Oct 2012 replaced the following levelCheck method with the current
// one, which was obtained by cloning the method from OpDefNode with some
// simplifications that were possible because a theorem or assumption, unlike
// and ordinary definition, cannot appear in the scope of a RECURSIVE declaration.
// He also made the ThmOrAssumpDefNode implement the AnyNode interface.
// See the comments in AnyDefNode.java for an explanation of why.

//  /*************************************************************************
//  * Level checking.                                                        *
//  *************************************************************************/
//  public boolean levelCheck(int iter) {
//    if (levelChecked >= iter) {return levelCorrect;} ;
//    levelChecked = iter ;
//    levelCorrect        = this.body.levelCheck(iter) ;
//    level               = this.body.level ;
//    levelParams         = this.body.levelParams ;
//    allParams           = this.body.allParams ;
//    levelConstraints    = this.body.levelConstraints ;
//    argLevelConstraints = this.body.argLevelConstraints ;
//    argLevelParams      = this.body.argLevelParams ;
//    return levelCorrect ;
//   }
//
////  /*************************************************************************
////  * The implementation of the LevelNode abstract methods.  They simply     *
////  * return the corresponding values for the body.                          *
////  *************************************************************************/
////  public final LevelNode getBody()  {return this.body;}
////  public boolean levelCheck()       {return this.body.levelCheck();}
////  public int getLevel()             {return this.body.getLevel();}
////  public HashSet getLevelParams()   {return this.body.getLevelParams();}
////  public SetOfLevelConstraints getLevelConstraints()
////    {return this.body.getLevelConstraints() ;}
////  public SetOfArgLevelConstraints getArgLevelConstraints()
////    {return this.body.getArgLevelConstraints() ; }
////  public HashSet getArgLevelParams()
////    {return this.body.getArgLevelParams() ; }

  /*************************************************************************
  * The fields used for level checking.                                    *
  *************************************************************************/
// These fields are now present in all LevelNode subclasses
//  private boolean levelCorrect;
//  private int level;
//  private HashSet levelParams;
//  private SetOfLevelConstraints levelConstraints;
//  private SetOfArgLevelConstraints argLevelConstraints;
//  private HashSet argLevelParams;


  int[] maxLevels;
  int[] weights;
  int[][] minMaxLevel;
    /***********************************************************************
    * According to LevelSpec.tla, if this is the OpDefNode for the         *
    * definition of op, then op.minMaxLevel[i][k] is the minimum value of  *
    * oparg.maxLevels[k] for the i-th argument of Op.  Thus,               *
    * op.minMaxLevels[i] is a sequence whose length is the number of       *
    * arguments taken by the i-th argument of Op.  (It equals 0 if the     *
    * i-th argument of Op is not an operator argument.)                    *
    ***********************************************************************/

  boolean[] isLeibnizArg;
  boolean   isLeibniz;
    /***********************************************************************
    * If this is the OpDefNode for the definition of op, then              *
    * isLeibnizArg[i] is true iff the i-th argument of op is Leibniz, and  *
    * isLeibniz = \A i : isLeibnizArg[i]                                   *
    ***********************************************************************/
  public boolean[] getIsLeibnizArg() {
      return isLeibnizArg;
  }
  public boolean getIsLeibniz() {
      return isLeibniz;
  }
  private boolean[][][] opLevelCond;
    /***********************************************************************
    * According to LevelSpec.tla, if thisnode defines op,                  *
    * then op.opLevelCond[i][j][k] is true iff                             *
    * the i-th argument of op is an operator argument opArg, and the       *
    * definition of op contains an expression in which the j-th formal     *
    * parameter of the definition of op appears within the k-th argument   *
    * of opArg.                                                            *
    ***********************************************************************/
  @Override
  public final boolean levelCheck(int itr) {
      if (this.levelChecked >= itr) { return this.levelCorrect; }
      this.levelChecked = itr ;

      /***********************************************************************
      * Initialize maxLevels to the least restrictive value and weights to 0.*
      * Initialize isLeibniz and all isLeibniz[i] to true.                   *
      ***********************************************************************/
      this.maxLevels    = new int[this.params.length];
      this.weights      = new int[this.params.length];
      for (int i = 0 ; i < this.params.length ; i++) {
          this.maxLevels[i] = MaxLevel ;
          this.weights[i] = 0 ;
          this.isLeibniz    = true;
          this.isLeibnizArg = new boolean[this.params.length];
          this.isLeibnizArg[i] = true ;
        } ;


   // Level check the body:
      this.levelCorrect = this.body.levelCheck(itr);
      this.level = this.body.getLevel();

      SetOfLevelConstraints lcSet = this.body.getLevelConstraints();
      for (int i = 0; i < this.params.length; i++) {
         Object plevel = lcSet.get(params[i]);
         if (plevel != null) {
             this.maxLevels[i] = ((Integer)plevel).intValue();
           }
      }

      for (int i = 0; i < this.params.length; i++) {
          if (this.body.getLevelParams().contains(this.params[i])) {
            this.weights[i] = this.weights[i];
          }
        }

      this.minMaxLevel = new int[this.params.length][];
      SetOfArgLevelConstraints alcSet = this.body.getArgLevelConstraints();
      for (int i = 0; i < this.params.length; i++) {
        int alen = this.params[i].getArity();
        this.minMaxLevel[i] = new int[alen];
        for (int j = 0; j < alen; j++) {
          Object alevel = alcSet.get(new ParamAndPosition(this.params[i], j));
          if (alevel == null) {
            this.minMaxLevel[i][j] = MinLevel;
          }
          else {
            this.minMaxLevel[i][j] = ((Integer)alevel).intValue();
          }
        }
      }

      this.opLevelCond = new boolean[this.params.length][this.params.length][];
      HashSet alpSet = this.body.getArgLevelParams();
      for (int i = 0; i < this.params.length; i++) {
        for (int j = 0; j < this.params.length; j++) {
          this.opLevelCond[i][j] = new boolean[this.params[i].getArity()];
          for (int k = 0; k < this.params[i].getArity(); k++) {
            ArgLevelParam alp = new ArgLevelParam(this.params[i], k, this.params[j]);
            this.opLevelCond[i][j][k] = alpSet.contains(alp);
          }
        }
      }

      this.levelParams.addAll(this.body.getLevelParams());
      this.allParams.addAll(this.body.getAllParams());
      this.nonLeibnizParams.addAll(this.body.getNonLeibnizParams());
      for (int i = 0; i < this.params.length; i++) {
        this.levelParams.remove(this.params[i]);
        this.allParams.remove(this.params[i]);
        if (this.nonLeibnizParams.contains(this.params[i])) {
          /*******************************************************************
          * The i-th argument is non-Leibniz if this.params[i] is in the     *
          * body's nonLeibnizParams hashset (and hence now in this node's    *
          * nonLeibnizParams hashset.                                        *
          *******************************************************************/
          this.nonLeibnizParams.remove(this.params[i]) ;
          this.isLeibnizArg[i] = false ;
          this.isLeibniz = false ;
         } ;
      }

      this.levelConstraints = (SetOfLevelConstraints)lcSet.clone();
      for (int i = 0; i < this.params.length; i++) {
        this.levelConstraints.remove(this.params[i]);
      }

      this.argLevelConstraints = (SetOfArgLevelConstraints)alcSet.clone();
      for (int i = 0; i < this.params.length; i++) {
        int alen = this.params[i].getArity();
        for (int j = 0; j < alen; j++) {
          this.argLevelConstraints.remove(new ParamAndPosition(this.params[i], j));
        }
      }

      Iterator iter = alpSet.iterator();
      while (iter.hasNext()) {
        ArgLevelParam alp = (ArgLevelParam)iter.next();
        if (!alp.op.occur(this.params) ||
            !alp.param.occur(this.params)) {
          this.argLevelParams.add(alp);
        }
      }

      return levelCorrect ;
  }

  /***************************************************************************
  * The following Asserts can be removed after debugging.                    *
  ***************************************************************************/
    public final int getMaxLevel(int i) {
      if (this.levelChecked == 0)
        {throw new WrongInvocationException("getMaxLevel called before levelCheck");};
      int idx = (this.getArity() == -1) ? 0 : i;
      return this.maxLevels[idx];
    }

    public final int getWeight(int i) {
      if (this.levelChecked == 0)
        {throw new WrongInvocationException("getWeight called before levelCheck");};
      int idx = (this.getArity() == -1) ? 0 : i;
      return this.weights[idx];
    }

    public final int getMinMaxLevel(int i, int j) {
      if (this.levelChecked == 0)
        {throw new WrongInvocationException("getMinMaxLevel called before levelCheck");};
      if (this.minMaxLevel == null) {
        return ConstantLevel;
      }
      return this.minMaxLevel[i][j];
    }

    public final boolean getOpLevelCond(int i, int j, int k) {
      if (this.levelChecked == 0)
        {throw new WrongInvocationException("getOpLevelCond called before levelCheck");};
      if (this.opLevelCond == null) {
        return false;
      }
      return this.opLevelCond[i][j][k];
    }

  /**
   * toString, levelDataToString and walkGraph methods to implement
   * ExploreNode interface
   */
//  public final String levelDataToString() {
//    return this.body.levelDataToString();
//   }



  /**
   *  The body is the node's only child.
   */
  @Override
  public SemanticNode[] getChildren() {
    return new SemanticNode[] {this.body};
  }

  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    if(this.body != null) {this.body.walkGraph(semNodesTable, visitor) ;} ;
    visitor.postVisit(this);
   }

  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";
    String ret =
          "\n*ThmOrAssumpDefNode: " + this.getName().toString() +
            "  " + super.toString(depth) +
            " arity: " + this.arity +
            " module: " + (originallyDefinedInModule != null
                             ? originallyDefinedInModule.getName().toString()
                             : "<null>" ) ;
    if (instantiatedFrom != null) {ret += " instantiatedFrom: " +
                                          instantiatedFrom.getName() ; } ;
    if (params != null) {
      String tempString = "\nFormal params: " + params.length;
      for (int i = 0; i < params.length; i++) {
        tempString += Strings.indent(2, ((params[i] != null)
                                        ? params[i].toString(depth-1)
                                         : "\nnull"));
        } ;
      ret += Strings.indent(2,tempString);
     } ;
    if (body != null) {
        ret += Strings.indent(2,
                             "\nisTheorem(): " + theorem +
                             "\nBody:" +
                              Strings.indent(2, this.body.toString(depth-1)) +
                             "\nsuffices: " + this.isSuffices());
      } // if
    /***********************************************************************
    * The following is the same for all classes that implement the         *
    * OpDefOrLabelNode interface.                                          *
    ***********************************************************************/
    if (labels != null) {
       ret += "\n  Labels: " ;
       Enumeration<UniqueString> list = labels.keys() ;
       while (list.hasMoreElements()) {
          ret += list.nextElement().toString() + "  " ;
         } ;
      }
    else {ret += "\n  Labels: null";};

    return ret ;
   }

  /**
   *
   */
  protected String getNodeRef() {
    if (theorem) {
      assert(thmOrAssump instanceof TheoremNode);
      return "TheoremDefRef";
    }
    else {
      assert(thmOrAssump instanceof  AssumeNode);
      return "AssumeDefRef";
    }
  }

  protected Element getSymbolElement(Document doc, tla2sany.xml.SymbolContext context) {
    assert(this.body != null); //A theorem or assumption definition without a body does not make sense.
    Element e = null;
    if (theorem) {
      e = doc.createElement("TheoremDefNode");
    }
    else {
      e = doc.createElement("AssumeDef");
    }

    e.appendChild(appendText(doc, "uniquename", getName().toString() ));
    e.appendChild(body.export(doc, context));
    return e;
  }

  /* overrides LevelNode.export and exports a UID reference instad of the full version*/
  @Override
  public Element export(Document doc, SymbolContext context) {
    // first add symbol to context
    context.put(this, doc);
    Element e = doc.createElement(getNodeRef());
    e.appendChild(appendText(doc,"UID",Integer.toString(myUID)));
    return e;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/DiskObjectStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:28 PST by lamport  
//      modified on Tue Jan  8 23:38:34 PST 2002 by yuanyu   

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import tlc2.output.EC;
import util.Assert;
import util.FileUtil;

/**
 * Alternative implementation
 * not used currently
 * @version $Id$
 */
public class DiskObjectStack extends ObjectStack {
  private final static int BufSize = 8192;

  /**
   * Invariants:
   * I1. Entries in buf1 are in the indices: [0, index1)
   * I2. Entries in buf2 are in the indices: [0, index2)
   * I3. /\ 0 <= index <= buf.length
   *     /\ index == 0 => buffer empty
   *     /\ index == buf.length => buffer full
   */
    
  /* Fields */
  private final String filePrefix;
  protected Object[] buf1, buf2, buf;
  protected int index;
  protected ObjectPoolStack diskStack;
  
  /* Constructors */
  public DiskObjectStack(String diskdir, String name) {
    this.buf1 = new Object[BufSize];
    this.buf2 = new Object[BufSize];
    this.buf = this.buf1;
    this.index = 0;
    this.filePrefix = diskdir + FileUtil.separator + name;
    this.diskStack = new ObjectPoolStack(BufSize, this.filePrefix);
  }
  
  final void enqueueInner(Object state) {
    if (this.index == BufSize && this.buf == this.buf2) {
      // need to flush buf1 to disk      
      try {
	this.buf = this.diskStack.write(this.buf1);
	this.buf1 = this.buf2;
	this.buf2 = this.buf;
	this.index = 0;
      }
      catch (Exception e) {
          Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES, new String[]{"stack", e.getMessage()});      
      }
    }
    this.buf[this.index++] = state;
  }
  
  final Object dequeueInner() {
    if (this.buf == this.buf1 && this.index < BufSize/2) {
      // need to fill buffers
      try {
	Object[] tempBuf = this.diskStack.read(this.buf);
	if (tempBuf != null) {
	  this.buf2 = this.buf1;
	  this.buf1 = tempBuf;
	  this.buf = this.buf2;
	}
      }
      catch (Exception e) {
	Assert.fail(EC.SYSTEM_ERROR_READING_STATES, new String[]{"stack", e.getMessage()});
      }
    }
    return this.buf[--this.index];
  }

  /* Checkpoint.  */
  public final void beginChkpt() throws IOException {
    String filename = this.filePrefix + ".tmp";
    ObjectOutputStream oos = FileUtil.newOBFOS(filename);
    oos.writeInt(this.len);
    int index1 = (this.buf == this.buf1) ? this.index : BufSize;
    int index2 = (this.buf == this.buf1) ? 0 : this.index;
    oos.writeInt(index1);
    oos.writeInt(index2);
    for (int i = 0; i < index1; i++) {
      oos.writeObject(this.buf1[i]);
    }
    for (int i = 0; i < index2; i++) {
      oos.writeObject(this.buf2[i]);
    }
    oos.close();
  }

  public final void commitChkpt() throws IOException {
    // SZ 23.02.2009: filename is not used  
    // String filename = this.filePrefix + ".chkpt"; 
    File oldChkpt = new File(this.filePrefix + ".chkpt");
    File newChkpt = new File(this.filePrefix + ".tmp");
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      String msg = "DiskObjectStack.commitChkpt: cannot delete " + oldChkpt;
      throw new IOException(msg);
    }
  }

  public final void recover() throws IOException {
    String filename = this.filePrefix + ".chkpt";
    
    ObjectInputStream ois = FileUtil.newOBFIS(filename);
    this.len = ois.readInt();
    int index1 = ois.readInt();
    int index2 = ois.readInt();
    try {
      for (int i = 0; i < index1; i++) {
	this.buf1[i] = ois.readObject();
      }
      for (int i = 0; i < index2; i++) {
	this.buf2[i] = ois.readObject();
      }
    }
    catch (ClassNotFoundException e) {
        Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e.getMessage());
    }
    finally {
      ois.close();
    }
    if (index2 == 0) {
      this.buf = this.buf1;
      this.index = index1;
    }
    else {
      this.buf = this.buf2;
      this.index = index2;
    }
  }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TBGraph.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:50 PST by lamport
//      modified on Thu Sep 21 12:05:08 PDT 2000 by yuanyu

package tlc2.tool.liveness;

import tlc2.util.Vect;

@SuppressWarnings("serial")
public class TBGraph extends Vect<TBGraphNode> {
	/**
	 * TBGraph represents the nodes in the tableau graph.
	 */
	public final LiveExprNode tf;
	private int initCnt;

	public TBGraph() {
		this.tf = null;
		this.initCnt = 0;
	}

	/**
	 * Given a starting TBGraphNode, constructTableau constructs the tableau for
	 * it. Read MP for details. It returns a list of all the nodes in the
	 * tableau graph.
	 */
	public TBGraph(final LiveExprNode tf) {
		this.tf = tf;
		// The following assert follows from comments and has been validated with the
		// TLC test suite.  It is commented to not cause regressions if for some reason
		// the comments are wrong.  That would be fatal, though, because the tableau
		// method in Manna & Pnueli book does not consider actions because it is for LTL.
		//assert !tf.containAction();
		
		this.initCnt = 0;
		
		final TBPar initTerms = new TBPar(1);
		initTerms.addElement(tf);
		
		// TBPar#particleClosure implements the tableau construction method described on
		// page 452 of the Manna & Pnueli book, which works under the assumption that
		// the temporal formulae (tf) are in positive form, i.e., negation is only
		// applies to/is pushed down to the (state) formulas (atoms).  The tf here has been
		// brought into positive form in Liveness.java during the conversion into disjunct
		// normal form (DNF).  Thus, we should probably assert that tf is in positive form.
		// Unfortunately, neither the TLC test suite nor the TLA+ examples have properties
		// that are locally inconsistent.  In other words, the test coverage WRT to local
		// consistency is zero.
		//assert tf.isPositiveForm();
		final TBParVec pars = initTerms.particleClosure();

		for (int i = 0; i < pars.size(); i++) {
			final TBGraphNode gn = new TBGraphNode(pars.parAt(i));
			this.addElement(gn);
		}
		this.setInitCnt(this.size());
		// We now repeatedly compute the outlinks of each node:
		for (int i = 0; i < this.size(); i++) {
			final TBGraphNode gnSrc = (TBGraphNode) this.elementAt(i);
			final TBPar imps = gnSrc.getPar().impliedSuccessors();
			final TBParVec succs = imps.particleClosure();
			for (int j = 0; j < succs.size(); j++) {
				final TBPar par = succs.parAt(j);
				final TBGraphNode gnDst = findOrCreateNode(par);
				gnSrc.nexts.addElement(gnDst);
			}
		}
		// Assign each node in the tableau an index.
		for (int i = 0; i < this.size(); i++) {
			this.getNode(i).setIndex(i);
		}
	}
	
	/**
	 * The method findOrCreateNode, given a list of particles, either finds the
	 * particle in that list, or creates a new one and puts it in the list. If
	 * it does create a node, then it also sticks that node into allnodes.
	 */
	private TBGraphNode findOrCreateNode(final TBPar par) {
		for (int i = 0; i < this.size(); i++) {
			final TBGraphNode gn = (TBGraphNode) this.elementAt(i);
			if (par.equals(gn.getPar())) {
				return gn;
			}
		}
		final TBGraphNode gn = new TBGraphNode(par);
		this.addElement(gn);
		return gn;
	}

	public TBGraphNode getNode(int idx) {
		return (TBGraphNode) this.elementAt(idx);
	}

	public final void setInitCnt(int n) {
		this.initCnt = n;
	}

	public int getInitCnt() {
		return this.initCnt;
	}
	
	private boolean isInitNode(TBGraphNode aNode) {
		return aNode.getIndex() < getInitCnt();
	}

	public final void toString(StringBuffer sb, String padding) {
		for (int i = 0; i < this.size(); i++) {
			TBGraphNode tnode = this.getNode(i);
			sb.append(padding);
			sb.append("Node " + i + ".\n");
			tnode.getPar().toString(sb, padding);
			sb.append(" --> ");
			for (int j = 0; j < tnode.nexts.size(); j++) {
				sb.append(tnode.nextAt(j).getIndex() + " ");
			}
			sb.append("\n");
		}
	}

	public final String toString() {
		StringBuffer sb = new StringBuffer();
		this.toString(sb, "");
		return sb.toString();
	}

	/**
	 * @see AbstractDiskGraph#toDotViz()
	 */
	public String toDotViz() {
		final StringBuffer sb = new StringBuffer();
		sb.append("digraph TableauGraph {\n");
		sb.append("nodesep = 0.7\n");
		sb.append("rankdir=LR;\n"); // Left to right rather than top to bottom
		for(int i = 0; i < size(); i++) {
			final TBGraphNode node = getNode(i);
			sb.append(node.toDotViz(isInitNode(node)));
		}
		sb.append("}");
		return sb.toString();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/dialog/InformationDialog.java<|end_filename|>
package org.lamport.tla.toolbox.ui.dialog;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A dialog for displaying a selectable, copy-and-pastable information
 * message. The eclipse-provided information dialogs from the class
 * {@link MessageDialog} do not seem to have those features.
 * 
 * This dialog will have a single button that says OK. It will stick to
 * the top of the toolbox and will not allow you to click on other stuff
 * until you click OK.
 * 
 * The image that appears next to the message can be set using {@link #setImage(Image)}.
 * The title for the dialog can be set using {@link #setTitle(String)}.
 * 
 * There are three static convenience methods for opening dialogs:
 * 
 *  {@link #openError(String, String)}
 *  {@link #openInformation(String, String)}
 *  {@link #openWarning(String, String)}
 * 
 * @author <NAME>
 *
 */
public class InformationDialog extends Dialog
{

    /**
     * The text widget displaying the warning
     * message.
     */
    private Text dialogText;
    /**
     * The message to be displayed in the dialog.
     */
    private String message;
    /**
     * The title of the dialog.
     */
    private String title;
    /**
     * The image for the dialog.
     */
    private Image image;

    /**
     * Creates a new dialog that can be opened in the shell returned
     * by the given shell provider. This dialog will display the
     * given message when opened. See {@link #open()}.
     * 
     * @param parentShell
     * @param message
     */
    protected InformationDialog(IShellProvider parentShell, String message)
    {
        super(parentShell);
        setShellStyle(SWT.OK | SWT.APPLICATION_MODAL);
        setBlockOnOpen(true);
        this.message = message;
    }

    /**
     * This method overrides the method in {@link Dialog} in order
     * to return the {@link Composite} that contains the widgets for
     * displaying the image (if there is one) and the message text.
     */
    protected Control createDialogArea(Composite parent)
    {

        // create the composite that will contain the image and message
        // for the dialog
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        composite.setLayout(new GridLayout(2, false));

        // creates the widget displaying the image, if there is one
        if (image != null)
        {
            Label imageLabel = new Label(composite, SWT.NULL);
            image.setBackground(imageLabel.getBackground());
            imageLabel.setImage(image);
            /*
             * The following sets the alignment and spacing of the image label within
             * the dialog. It was copied from the createMessageArea method for IconAndMessageDialog.
             */
            GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING).applyTo(imageLabel);
        }

        // creates the widget displaying the message
        dialogText = new Text(composite, SWT.MULTI | SWT.WRAP);
        dialogText.setText(message);
        dialogText.setEditable(false);
        /*
         * The following sets the alignment and spacing of the dialog text within
         * the dialog. It was copied from the createMessageArea method for IconAndMessageDialog.
         */
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).hint(
                convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT).applyTo(
                dialogText);

        return composite;
    }

    /**
     * Convenience method for opening a warning dialog displaying the
     * given title and message in the currently active shell. The image
     * for this dialog will be the swt warning image as returned by
     * UIHelper.getSWTImage(SWT.ICON_WARNING).
     * 
     * @param message
     */
    public static void openWarning(String message, String title)
    {
        InformationDialog dialog = new InformationDialog(UIHelper.getShellProvider(), message);
        dialog.setTitle(title);
        dialog.setImage(UIHelper.getSWTImage(SWT.ICON_WARNING));

        dialog.open();
    }

    /**
     * Convenience method for opening an error dialog displaying the
     * given title and message in the currently active shell. The image
     * for this dialog will be the swt error image as returned by
     * UIHelper.getSWTImage(SWT.ICON_ERROR).
     * 
     * @param message
     */
    public static void openError(String message, String title)
    {
        InformationDialog dialog = new InformationDialog(UIHelper.getShellProvider(), message);
        dialog.setTitle(title);
        dialog.setImage(UIHelper.getSWTImage(SWT.ICON_ERROR));

        dialog.open();
    }

    /**
     * Convenience method for opening an information dialog displaying the
     * given title and message in the currently active shell. The image
     * for this dialog will be the swt information image as returned by
     * UIHelper.getSWTImage(SWT.ICON_INFORMATION).
     * 
     * @param message
     */
    public static void openInformation(String message, String title)
    {
        InformationDialog dialog = new InformationDialog(UIHelper.getShellProvider(), message);
        dialog.setTitle(title);
        dialog.setImage(UIHelper.getSWTImage(SWT.ICON_INFORMATION));

        dialog.open();
    }

    /**
     * Sets the title for the dialog.
     * 
     * @param title
     */
    public void setTitle(String title)
    {
        this.title = title;
    }

    /**
     * Sets the image that will be displayed next to the message
     * in the dialog.
     * 
     * @param image
     */
    public void setImage(Image image)
    {
        this.image = image;
    }

    /**
     * This method was mostly copied from {@link MessageDialog}. Apparently
     * this is the way to set the title for a dialog.
     */
    protected void configureShell(Shell shell)
    {
        super.configureShell(shell);
        if (title != null)
        {
            shell.setText(title);
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCMultiLineRule.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;

public class TLCMultiLineRule implements IPredicateRule {

	private Token successToken;
	
	public TLCMultiLineRule(Token successToken) {
		this.successToken = successToken;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.rules.IRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner)
	 */
	public IToken evaluate(ICharacterScanner scanner) {
		return evaluate(scanner, false);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.rules.IPredicateRule#getSuccessToken()
	 */
	public IToken getSuccessToken() {
		return successToken;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.rules.IPredicateRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner, boolean)
	 */
	public IToken evaluate(ICharacterScanner scanner, boolean resume) {
		// impl does not support resume!
		if(resume) {
			throw new UnsupportedOperationException("Not implemented");
		}
		return doEvaluate(scanner);
	}

	/**
	 * Consumes every character except "@" which marks the beginning of a tag line
	 */
	private IToken doEvaluate(ICharacterScanner scanner) {
		// if there is nothing for us to read, just return
		if (TLCCharScanner.isEOF(scanner) || TLCCharScanner.isTag(scanner, TagBasedTLCOutputTokenScanner.HEAD_DELIM)) {
			return Token.UNDEFINED;
		} else {
			while (!TLCCharScanner.isEOF(scanner)
					&& !TLCCharScanner.isTag(scanner, TagBasedTLCOutputTokenScanner.HEAD_DELIM)) {
				scanner.read();
			}
			return successToken;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/OpDefNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.


// last modified on Sat 28 June 2008 at  0:45:44 PST by lamport
/***************************************************************************
* The OpDefNode constructor is invoked only in semantic/Generator.java     *
* and configuration/Configuration.java.  The latter invokes it only to     *
* construct OpDefNode objects to represent the built-in TLA+ operators,    *
* which are put in the initial context.  (I don't remember why these were  *
* represented as OpDefNode objects rather than OpDecl objects in the       *
* spec.)                                                                   *
***************************************************************************/

/***************************************************************************
* For a recursive operator definition, the OpDefNode is created when the   *
* RECURSIVE statement is processed.  The syntax tree node returned by      *
* getTreeNode() is the one for the symbol's declaration in the RECURSIVE   *
* statement.  Only after processing the actual definition is the syntax    *
* tree node changed to the N_OperatorDefinition node.                      *
***************************************************************************/

/***************************************************************************
* To minimize the number of changes that must be made to the existing      *
* code, a lambda expression is represented as an OpDefNode of kind         *
* UserDefinedOpKind with name "LAMBDA".  To avoid putting this name in     *
* any symbol table, the constructor should be called for a lambda          *
* expression with the SymbolTable argument equal to null.                  *
***************************************************************************/

package tla2sany.semantic;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.parser.SyntaxTreeNode;
import tla2sany.st.Location;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import tla2sany.xml.SymbolContext;
import tlc2.tool.BuiltInOPs;
import util.UniqueString;
import util.WrongInvocationException;

  /**
   * An OpDefNode can have one of the following kinds:
   *
   *     ModuleInstanceKind
   *        Represents a module instantiation name, such as the M
   *        in  M(a, b) == INSTANCE ...
   *
   *     UserDefinedOpKind
   *        Represents a user definition, for example the definition
   *        of the symbol Foo in  Foo(A, B) == expr.
   *
   *     BuiltInKind
   *        An imaginary declaration for a built-in operator of TLA+
   *        such as \cup.
   *
   *     NumberedProofStepKind
   *        Represents a numbered proof step that is not an assertion
   *        (so it doesn't get represented as a theorem).  It seems
   *        useful to keep those step numbers in the appropriate
   *        symbol tables in case the user refers to them even
   *        where inappropriate, if only to generate better error
   *        messages.  Currently, the only legal reference to a proof
   *        number of such a step is to a definition step in
   *        the DEF clause of a USE or HIDE step or a BY proof.
   *
   * All TLA+ constructs such as record constructors that produce an
   * expression are represented as OppApplNodes for special operators.
   * There is an OpDefNode of kind BuiltInKind for each of these special
   * operators.  The special operators are:
   *
   *     $FcnApply
   *        f[x] is represented as $FcnApply(f, x), and f[x,y]
   *        is represented as $FcnApply(f, <<x, y>>).
   *
   *     $RcdSelect
   *        r.c is represented as $RcdSelect(r, "c").  Note that,
   *        semantically, $RcdSelect(r, "c") is equivalent to
   *        $FcnApply(r, "c").  But, a tool might want to handle
   *        records differently from other functions for efficiency.
   *
   *     $NonRecursiveFcnSpec
   *        The definition  f[x \in S] == exp  is represented as
   *        $NonRecursiveFcnSpec(x, S, exp) if f does not appear in exp.
   *
   *     $RecursiveFcnSpec
   *        Similar to $NonRecursiveFcnSpec, except for recursive
   *        function definitions.
   *
   *     $Pair
   *     $RcdConstructor
   *        We represent [L1 |-> e1, L2 |-> e2] as
   *        $RcdConstructor($Pair("L1", e1), $Pair("L2", e2))
   *
   *     $SetOfRcds
   *        Used to represent [L1 : e1, L2 : e2] much like
   *        $RcdConstructor.
   *
   *     $Except
   *     $Seq
   *        We represent [f EXCEPT ![a].b[q] = c, ![d,u][v] = e]
   *        as $Except(f, $Pair( $Seq(a, "b", q), c ),
   *                      $Pair( $Seq(<<d,u>>, v), e )).
   *        We are representing the equivalent expressions
   *        [r EXCEPT !["a"] = b] and [r EXCEPT !.a = b] the same, even
   *        though we represent r["a"] and r.a differently.  This
   *        inconsistency resulted from a compromise between supporting
   *        efficient implementation and keeping the api simple.  If
   *        consistency is desired, we should probably eliminate
   *        $RcdSelect.
   *
   *     $Tuple
   *        We represent <<a, b, c>> as $Tuple(a, b, c).
   *
   *     $CartesianProd
   *        Represents  A \X B \X C  as  $CartesianProd(A, B, C)
   *
   *     $BoundedChoose
   *        Represents CHOOSE x \in S : P
   *
   *     $UnboundedChoose
   *        Represents CHOOSE x : P.
   *
   *     $BoundedForall
   *        Represents \A x \in S : P.
   *
   *     $UnboundedForall
   *        Represents \A x : P.
   *
   *     $BoundedExists
   *        Represents \E x \in S : P.
   *
   *     $UnboundedExists
   *        Represents \E x : P.
   *
   *     $SetEnumerate
   *        Represents {a, b, c}.
   *
   *     $SubsetOf
   *        Represents {x \in S : p}.
   *
   *     $SetOfAll
   *        Represents {e : x \in S}.
   *
   *     $FcnConstructor
   *        Represents [x \in S |-> e].
   *
   *     $SetOfFcns
   *        Represents [S -> T].
   *
   *     $IfThenElse
   *     $ConjList
   *     $DisjList
   *         These are fairly obvious.
   *
   *     $Case
   *        We represent CASE p1 -> e1 [] p2 -> e2 as
   *        $Case( $Pair(p1, e1), $Pair(p2, e2) ) and we represent
   *        CASE p1 -> e1 [] p2 -> e2 [] OTHER -> e3  as
   *        $Case( $Pair(p1, e1), $Pair(p2, e2), $Pair(null, e3))
   *
   *     $SquareAct
   *        We represent [A]_e as $SquareAct(A, e).
   *
   *     $AngleAct
   *        We represent <<A>>_e as $AngleAct(A, e).
   *
   *     $WF(e, A)
   *     $SF(e, A)
   *        We represent WF_e(A) as $WF(e, A), etc.
   *
   *     $TemporalExists
   *     $TemporalForall
   *        Represent \EE and \AA.
   *
   *  On 24 Oct 2012, LL added the AnyDefNode interface and made the OpDefNode
   *  class implement it.  He also added the getIsLeibnizArg method.  See
   *  the comments in AnyDefNode.java for an explanation.
   */

public class OpDefNode extends OpDefOrDeclNode
         implements OpDefOrLabelNode, AnyDefNode {


/*************************************************************************
* The fields.                                                            *
*************************************************************************/
  private boolean           local  = false;
     // Is this definition local to the module?
  private ExprNode          body   = null;
    // the expression that is the def'n of the operator
  private FormalParamNode[] params = null;
    // Array of FormalParamNodes that this operator takes

  private LevelNode stepNode = null;
    /***********************************************************************
    * For a NumberedProofStepKind, this is the step node it's numbering.   *
    * It can be a DefStepNode, UseOrHideNode, or InstanceNode.  Otherwise, *
    * it is null.                                                          *
    ***********************************************************************/

  /**
   * This is the module from which this definition is ultimately obtained.
   * The field originallyDefinedInModule purports to be that, but when the
   * definition is instantiated, this can create a new OpDefNode whose
   * originallyDefinedInModule field is the instantiating module.  In that
   * case, the sourceModule field is the same as that of the OpDefNode of
   * the instantiated definition.  Hence, this really is the module containing
   * the ultimate source of the definition.
   *
   * This field added by LL on 1 Nov 2012 to fix a bug in which the exact
   * same definition imported by two different routes generated a warning.
   * (This warning was originally harmless, but it became a problem when
   * it was decided that the Toolbox would regard warnings as errors.)
   *
   */
//  private ModuleNode sourceModule = null ;
//
//  public ModuleNode getSourceModule() {
//      return sourceModule ;
//  }

  /*************************************************************************
  * The following fields state if an operator is recursively defined, and  *
  * give some potentially useful information having to do with recursive   *
  * operator definitions.                                                  *
  *************************************************************************/
  int letInLevel = -1 ;
    /***********************************************************************
    * The let/in level of a node is 0 if it does not occur within a        *
    * LET/IN statement, and it has level i > 0 if it occurs directly       *
    * within a LET/IN statement that occurs at level i-1.                  *
    ***********************************************************************/

  boolean inRecursive = false;
    /***********************************************************************
    * True iff this node's operator appears in a RECURSIVE statement.      *
    ***********************************************************************/
  public boolean getInRecursive() { return inRecursive; }

/***************************************************************************
* XXXXX The uses of "recursive section" in the names of the next two       *
* fields do not have the same meaning.  Hence, one of these names should   *
* be changed.                                                              *
***************************************************************************/

  boolean inRecursiveSection = false ;
    /***********************************************************************
    * This field is set true iff this node's operator appears in a         *
    * RECURSIVE statement, or if the definition represented by this OpDef  *
    * node comes between a RECURSIVE statement at the same let/in level    *
    * and the definition of some operator declared in that recursive       *
    * statement.                                                           *
    ***********************************************************************/

  int recursiveSection = -1 ;
    /***********************************************************************
    * A recursive section is any maximal region of the spec within which   *
    * some operator has been declared in a RECURSIVE statement but not     *
    * yet defined.  This field is positive iff the object represents a     *
    * definition that occurs within a recursive section.  (This can be     *
    * true iff inRecursiveSection = false because the definition can       *
    * occur in a LET that is within a recursive section but contains no    *
    * RECURSIVE statement.)  Two OpDefNode objects with the same           *
    * non-negative recursiveSection value appeared in the same recursive   *
    * section.                                                             *
    ***********************************************************************/

// The following fields (except for isDefined) were removed by LL on 7 Apr
// 2007 (after being added by LL).  They were to be used for computing and
// displaying the connected components in the dependency graph, as
// explained in the comments.  They may be added back later if those
// dependencies are ever computed.

//  OpDefNode nextDependency = null ;
    /***********************************************************************
    * When the complete semantic tree has been constructed this field has  *
    * the following property.                                              *
    *                                                                      *
    * For OpDefNode objects n1 and n2, we say that n1 depends on n2,       *
    * written n1 -> n2, iff the operator defined by n2 occurs in the       *
    * definition of b1, some operator with OpDefNode n3 such that either   *
    * n1=n3 or n1 -> n3.                                                   *
    *                                                                      *
    * Define the dependency graph to be the graph with nodes all           *
    * OpDefNode objects and with edges defined by ->.                      *
    *                                                                      *
    * Define a dependency component C to be a strongly connected           *
    * component of the dependency graph, except that C consists of a       *
    * single node n only if n -> n.  Thus, a node belongs to a dependency  *
    * component iff it is contained in some cycle in the dependency        *
    * graph.                                                               *
    *                                                                      *
    * If a node n occurs in a dependency component then all nodes in that  *
    * component can be found by following nextDependency pointers.  In     *
    * otherwords, the nodes in any dependency component can be ordered to  *
    * form a sequence <<s[1], ...  , s[k]>> such that s[i].nextDependency  *
    * = s[i+1] for 1 \leq i < k and s[k].nextDependency = s[1].            *
    *                                                                      *
    * A node n does not occur in a dependency cycle iff n.nextDependency   *
    * = null.                                                              *
    ***********************************************************************/

  /*************************************************************************
  * The following fields are used in constructing the semantic tree.  They *
  * are of no use when the tree has been constructed, but we don't bother  *
  * getting rid of them.  They're not private because they're used by      *
  * methods in semantic/Generator.java.                                    *
  *                                                                        *
  * The first field is used to check that an operator that is defined in   *
  * a RECURSIVE statement is defined exactly once.                         *
  *************************************************************************/
  boolean isDefined = false;
    /***********************************************************************
    * If the operator is declared in a RECURSIVE statement, then the       *
    * OpDefNode is created when the RECURSIVE statement is processed and   *
    * this field is set false.  It is set true when processing the         *
    * operator's actual definition.                                        *
    *                                                                      *
    * This is used in the obvious way to detect duplicate definitions of   *
    * the operator.  It is used as follows to detect if the operator was   *
    * declared in a RECURSIVE statement but never defined.  A stack of     *
    * counts of not-yet defined operators at different levels is kept so   *
    * that, upon finishing the processing of a LET/IN or of the entire     *
    * module, we can detect that some operator has been declared but not   *
    * defined.  We can then use the data structure described by the        *
    * fields below constructed to compute dependency components to find    *
    * the undefined operator(s).                                           *
    ***********************************************************************/

  /*************************************************************************
  * The following fields are used to implement a version of Tarjan's       *
  * algorithm for computing connected-components that computes the         *
  * dependency components (and sets the nextDependency fields of the       *
  * nodes).  See the file semantic/Generator.java for a description of     *
  * this algorithm.                                                        *
  *************************************************************************/
//  boolean participating = false ;
    /***********************************************************************
    * True iff the node is participating in the current dependency         *
    * component computation.  An OpDefNode can appear in a connected       *
    * component only if it is represents a definition that appears in a    *
    * region where some operator has been declared in a RECURSIVE          *
    * statement but not yet defined.  This field is set to true if the     *
    * OpDefNode is constructed when this is the case.  The dependency      *
    * component computation is then run on all participating objects,      *
    * setting their participating fields false.                            *
    ***********************************************************************/

  /*************************************************************************
  * The remaining fields are meaningful, and have the indicated meaning,   *
  * only when participating = true.                                        *
  *************************************************************************/
//  Vector nbrs = null ;
    /***********************************************************************
    * This is a vector of OpDefNode objects containing all the OpDefNode   *
    * objects whose operators occur in the definition of this node's       *
    * operator.  The same object may appear multiple times.  Tarjan's      *
    * algorithm works with multiple copies (they're equivalent to          *
    * multiple arcs between the same two nodes), and it's easier and       *
    * faster to just add nodes to nbrs without checking if they're         *
    * already there.                                                       *
    ***********************************************************************/

//  int lowlink      = -1 ;
//  int dfs          = -1 ;
//  boolean examined = false;
    /***********************************************************************
    * These fields are used in Tarjan's algorithm.  See the file           *
    * Tarjan.tla for a +Cal version of the algorithm and an explanation    *
    * of what these fields are used for.                                   *
    ***********************************************************************/

    /***********************************************************************
    * The following field is used to implement the OpDefOrLabel interface. *
    * It is a hashtable of OpDefNode objects representing labels within    *
    * the body that are not within the scope of an inner label or LET      *
    * definition.                                                          *
    ***********************************************************************/
    private Hashtable labels = null ;

    private OpDefNode source = null ;
    
	private UniqueString[] compoundID = null;
      /*********************************************************************
      * If this OpDefNode was created through a chain of INSTANCEs, then   *
      * this field points to the original OpDefNode object from where it   *
      * came.  Otherwise, it equals null.  It is accessed with             *
      * getSource().                                                       *
      *********************************************************************/

/***************************************************************************
* The constructors.                                                        *
***************************************************************************/
  /* Used only for creating nullODN */
  public OpDefNode(UniqueString us) {
    super(us, 0, -2, null, null, SyntaxTreeNode.nullSTN);
    if (st != null) {
      st.addSymbol(us, this);
    }
  }

  /* Invoked in configuration.Configuration for built-in ops */
  public OpDefNode(UniqueString us, int k, int ar, FormalParamNode[] parms,
                   boolean localness, ExprNode exp, ModuleNode oModNode,
                   SymbolTable symbolTable, TreeNode stn) {
    super(us, k, (parms == null ? -1 : parms.length), oModNode, symbolTable, stn);
    params = parms;

    // Create phony FormalParamNodes for built-in operators
    if ( arity >= 0 ) {
      for (int i = 0; i < params.length; i++ ) {
        params[i] = new FormalParamNode(UniqueString.uniqueStringOf("Formal_" + i),
                                        0, null, symbolTable, oModNode);
      }
    }
    if (st != null) {
      st.addSymbol(us, this);
    }
    isDefined = true ;
      /*********************************************************************
      * All built-in operators are obviously defined.                      *
      *********************************************************************/
  }

  /* Invoked by ordinary operator definition. */
   /************************************************************************
   * This constructor is invoked only in semantic/Generator, by            *
   * the following methods:                                                *
   *                                                                       *
   *    processOperator (by call to startOpDefNode)                        *
   *       To produce a node for an operator definition, either at module  *
   *       level or in a LET/IN                                            *
   *                                                                       *
   *    processFunction                                                    *
   *       To produce a node for a function definition, either at module   *
   *       level or in a LET/IN                                            *
   *                                                                       *
   *    generateLambda                                                     *
   *       To produce a lambda expression                                  *
   *                                                                       *
   *    processModuleDefinition                                            *
   *       Twice to construct a clone of a node from the instantiated      *
   *       module.  (It also has another call to a differerent             *
   *       constructor--see below.)                                        *
   *                                                                       *
   *    generateInstance -                                                 *
   *       Three times, both times to construct a clone of a node from     *
   *       the instantiated module                                         *
   *                                                                       *
   * Note: the defined argument sets the isDefined field.  It is used      *
   * when the OpDefNode is being created before it is actually defined.    *
   * See semantic/Generator.java/startOpDefNode, and its uses.  This       *
   * argument was added by LL on 7 Apr 2007.                               *
   ************************************************************************/
   public OpDefNode(UniqueString us,
                    int k,                   // The kind
                    FormalParamNode[] parms,
                    boolean localness,
                    ExprNode exp,             // The body
                    ModuleNode oModNode,      // Originally defining module.
                    SymbolTable symbolTable,
                    TreeNode stn,
                    boolean defined,
                    OpDefNode src             // The source
                   ) {
    super(us, k, (parms != null ? parms.length : 0),
          oModNode, symbolTable, stn);
    this.local = localness;
    this.params = (parms != null ? parms : new FormalParamNode[0]);
    this.body = exp;
    this.isDefined = defined ;
    this.source = src ;
    /***********************************************************************
    * Initialize maxLevels to the least restrictive value and weights to   *
    * 0; initialize isLeibniz and all isLeibniz[i] to true.                *
    ***********************************************************************/
    this.maxLevels    = new int[this.params.length];
    this.weights      = new int[this.params.length];
    this.isLeibniz    = true;
    this.isLeibnizArg = new boolean[this.params.length];
    for (int i = 0 ; i < this.params.length ; i++) {
      this.maxLevels[i] = MaxLevel ;
      this.weights[i] = 0 ;
      this.isLeibnizArg[i] = true ;
      } ;

    if (st != null) {
      st.addSymbol(us, this);
    }
  }

   public OpDefNode(UniqueString us,
           int k,                   // The kind
           FormalParamNode[] parms,
           boolean localness,
           ExprNode exp,             // The body
           ModuleNode oModNode,      // Originally defining module.
           SymbolTable symbolTable,
           TreeNode stn,
           boolean defined,
           OpDefNode src,             // The source
           UniqueString[] compoundID
          ) {
	   this(us,k,parms,localness,exp,oModNode,symbolTable,stn,defined,src);
	   this.compoundID = compoundID;
   }
   
   final UniqueString[] getCompoundId() {
	   if (compoundID != null) {
		   return compoundID;
	   }
	   return new UniqueString[] {getName()};
   }

	public final UniqueString getLocalName() {
		   if (compoundID != null) {
			   return compoundID[compoundID.length - 1];
		   }
		   return getName();
	}
	
	public final boolean hasPath() {
		   if (compoundID != null) {
			   return compoundID.length > 1;
		   }
		   return false;
	}

	public final UniqueString getPathName() {
		   if (compoundID != null) {
			   // drop last segment.
			   return UniqueString.join("!", compoundID.length - 1, compoundID);
		   }
		   return UniqueString.of("");
	}

  /* Used for ModuleInstance names */
  /*************************************************************************
  * This constructor is missing the following parameters that are present  *
  * in the preceding constructor:                                          *
  *    kind    - always ModuleInstanceKind,                                *
  *    body    - there is none                                             *
  *    defined - always true because it can't be declared RECURSIVE.       *
  *************************************************************************/
  public OpDefNode(UniqueString us,
                   FormalParamNode[] parms,
                   boolean localness,
                   ModuleNode oModNode,
                   SymbolTable symbolTable,
                   TreeNode stn,
                   OpDefNode src  // the source
                  ) {
    super(us, ModuleInstanceKind, (parms == null ? -1 : parms.length),
          oModNode, symbolTable, stn);
    this.params = parms;
    this.local = localness;
    this.source = src;
    if (st != null) {
      st.addSymbol(us, this);
    }
  }

  /*************************************************************************
  * Constructor for NumberedProofStepKind nodes.  It should never be       *
  * called with symbolTable null.                                          *
  *************************************************************************/
  public OpDefNode(UniqueString us,  LevelNode step, ModuleNode oModNode,
                   SymbolTable symbolTable, TreeNode stn) {
    super(us, NumberedProofStepKind, 0, oModNode, symbolTable, stn) ;
    this.stepNode = step ;
    st.addSymbol(us, this);
   }
  /*************************************************************************
  * The methods that return or check properties of the node.               *
  *************************************************************************/
  /**
   * When applied to a user-defined op node or a built-in op
   * with a fixed number of params, returns an array of the formal
   * parameter nodes associated with this operator.  For example,
   * with
   *
   *   F(A(_,_), b, c) == A(b,c)
   *
   * it returns an array of length 3.
   *
   * When applied to a module instance node, returns (new) parameter
   * nodes introduced by that module instance. For example, with
   *
   *   D(x,y) == INSTANCE FooMod WITH c <- +
   *
   * it returns an array of length 2.
   *
   * When applied to a builtin op with a variable number of args, returns null.
   */
  public final FormalParamNode[] getParams() { return this.params; }

  /*************************************************************************
  * The setParams method is invoked in semantic/Generator.java to set the  *
  * params field for a node that was originally constructed with a dummy   *
  * field when processing a RECURSIVE declaration.                         *
  *************************************************************************/
  public final void setParams(FormalParamNode[] pms) { this.params = pms ;}


  /**
   * For a UserDefinedOp node, the getBody() method returns the
   * definition.  For other kinds of OpDefNodes, the method is
   * meaningless and should return null.  For example, if nOp is the
   * UserDefinedOp node for the operator Op defined by
   *
   *    Op(a, b) == expr
   *
   * then nOp.getBody() is a ref to the ExprNode for expr.
   *
   * A tool can use the setBody method to change the definition of a
   * user-defined operator.  For example, TLC can implement the
   * replacement A <- B by setting the Body of A's UserDefinedOp node
   * to equal the Body of B's UserDefinedOp node.
   *
   * The setBody method checks that body.getParent() equals the
   * current node, and raises an exception if it doesn't.
   */
  public final ExprNode getBody() { return this.body; }

  /**
   * Sets the body of this definition to the expression in body.  See
   * documentation for getBody();
   */
  /*************************************************************************
  * setBody() is also used by semantic/Generator.endOpDefNode.             *
  *************************************************************************/
  public final void setBody(ExprNode body) { this.body = body; }


  /*************************************************************************
  * Return the source node--the original OpDefNode from which this one     *
  * came.  It is different from this node iff the node was created by a    *
  * chain of instantiations.                                               *
  *************************************************************************/
  public final OpDefNode getSource() {
    return (this.source == null)? this : this.source ;
    }

  public final boolean hasSource() {
	  return this.source != null;
  }

  /**
   * Returns true iff this definition is declared LOCAL; definitions
   * that are in fact local, e.g. in LETs or inner modules, but that do not
   * get declared so using the LOCAL modifier are NOT
   * local for this purpose.
   */
  public final boolean isLocal() { return this.local; }

  /**
   * Returns the arity of this operator, or -1 in the case of an operator
   * that takes a variable number of args.
   */
  public final int getArity() { return this.arity; }

  public final LevelNode getStepNode() {return this.stepNode ;}

  /**
   * This method tests whether an operand is a legal instance of an
   * operator being passed as argument to another operator.
   * 
   * Bug discovered in July 2017: This method was testing if the
   * arg is an operator argument that may be used as parameter 
   * number i of the operator described by this OpDefNode.  For example,
   * if
   * 
   *     D(Op(_)) == Op(42)
   *     
   * then the argument of D must be an operator that takes a single
   * expression as an argument.  However, this method returned true
   * if the argument is an operator like D, that takes a single
   * OPERATOR as an argument.  LL rewrote the code on 22 July 2017 
   * to catch this case.
   * 
   * @see IllegalOperatorTest
   */
  private boolean matchingOpArgOperand (ExprOrOpArgNode arg, int i) {
	  // Set result to true iff arg is an operator argument of the
	  // correct arity.
	  boolean result = (arg instanceof OpArgNode) &&
			           (params[i].getArity() == ((OpArgNode)arg).getArity()) ;
	  
	  // We now must check that arg does not expect an operator as any
	  // of its arguments.  The comments in OpArgNode.java state that 
	  // OpArgNode.op is an OpDefNode, OpDeclNode, or FormalParamNode.  Of
	  // those, only an OpDefNode represents an operator that can have 
	  // an argument that is an operator.  Note that an argument j of an
	  // OpDefNode is an operator iff its arity is  0.
	  if (result) {
		  OpArgNode argOpArg = (OpArgNode) arg ;
		  if (argOpArg.getOp() instanceof OpDefNode) {
			  OpDefNode opdefArg = (OpDefNode) argOpArg.getOp() ;
			  for (int j = 0; j < opdefArg.getArity() ; j++) {
				  if (opdefArg.getParams()[j].getArity() > 0) {
					  result = false ;
				  }
			  }
		  }
	  }
		  
      return result ;
	  	           
   // Code before 22 July 2017 change.
   //    return ((arg instanceof OpArgNode) &&
   //              params[i].getArity() == ((OpArgNode)arg).getArity());
  }

  /* This method shortens the match() method right after it */
  private boolean errReport(Location loc, String s) {
    errors.addError(loc, s);
    return false;
  }

  /**
   * This method is called at the end of OpApplNode constructors to
   * make sure the OpApplNode is correct by "matching" the argument
   * expressions against the parameter list requirements.
   *
   * The OpApplNode must have the same number of args as parameters,
   * unless the operator takes a variable number of parameters.  Also,
   * FormalParamNodes that specify operators of arity > 0 must be
   * matched by arguments that OpArgNodes of the appropriate arity.
   *
   * Constructor argument oan is an OpApplNode having THIS OpDefNode
   * as its operator part.  This method decides whether the arguments
   * to oan (i.e args[]) match the argument pattern required by THIS
   * OpDefNode in terms of arity, etc.
   */
  public final boolean match(OpApplNode oanParent, ModuleNode mn) throws AbortException {
    ExprOrOpArgNode[] args       = oanParent.getArgs();  // arg expr's that THIS operator is being applied to
    boolean           result     = true;                 // Remains true unless an error is detected
    boolean           tempResult = true;

    Location loc = (oanParent.getTreeNode() != null
                    ? oanParent.getTreeNode().getLocation()
                    : null);

    // If THIS OpDefNode defines a module instance, then something is clearly wrong
    //   since a module instance node should not be under an OpApplNode
    if (this.getKind() == ModuleInstanceKind) {
      errors.addError(loc, "Module instance identifier where operator should be.");
      result = false;
    }
    else if ( arity == -1 ) {
      // if THIS OpDefNode is for an operator that takes a variable number of args ...
      if ( args != null ) { // args vector may have length zero, but should not be null
        for ( int i = 0; i < args.length; i++ ) {
          if (args[i] instanceof OpArgNode) {
            errors.addError(loc, "Illegal expression used as argument " + (i+1) +
                            " to operator '" + this.getName() + "'.");
            result = false;
          }
        }
      }
      else  {// null arg vector; supposedly cannot happen
        errors.addAbort(loc, "Internal error: null args vector for operator '" +
                        this.getName() + "' that should take variable number of args.",true);
      }
    }
    else {
      // It is an operator with a fixed number of params (possibly zero)
      if (args == null | params == null) { // args vector should never be null
        errors.addAbort(loc, "Internal error: Null args or params vector for operator '" +
                        this.getName() + "'.", true);
      }
      else { // Normal case: params != null & args != null
        // if the number of args does not match the number of params
        if (params.length != args.length) {
          errors.addError(loc, "Wrong number of arguments (" + args.length +
                          ") given to operator '" + this.getName() + "', \nwhich requires " +
                          params.length + " arguments.");
          result = false;
        }
        else {
          // we have the correct number of args
          // if the operator is a built-in op... (We separate out the logic for the builtin ops
          // because there are no FormalParamNodes in the semantic tree to describe their arguments
          if ( this.getKind() == BuiltInKind ) {
            // for each arg, check that an expression, not an operator, is used as argument,
            // since no built-in operators take operators as arguments
            for ( int i = 0; i < params.length; i++ ) {
              if (args[i] instanceof OpArgNode) {
                errors.addError(loc, "Non-expression used as argument number " + (i + 1)
                                + " to BuiltIn operator '"
                                + this.getName() + "'.");
                result = false;
              }
            }
          }
          else if ( this.getKind() == UserDefinedOpKind ) {
            // for each formal parameter to THIS OpDef
            for (int i = 0; i < params.length; i++ ) {
              // if i'th FormalParamNode shows arity == 0, then an expression is expected as argument
              if (params[i].getArity() == 0) {
                if (args[i] instanceof OpArgNode) {
                  // No ops can be passed in this parm position
                  errors.addError(loc, "Operator used in argument number " + (i+1)
                                  + " has incorrect number of arguments.");
                  result = false;
                }
              }
              else if (params[i].getArity() > 0) {
                // OpArgNode of correct arity must be passed in this arg position
                if (! matchingOpArgOperand(args[i],i)) {
                  errors.addError(loc, "Argument number " + (i+1) + " to operator '"
                                  + this.getName() + "' \nshould be a " + params[i].getArity()
                                  + "-parameter operator.");
                  result = false;
                }
              } else { // if params[i].getArity() < 0
                errors.addError(loc,
                                "Internal error: Operator '" + this.getName() +
                                "' indicates that it requires \na negative number of arguments.");
              }
            } // end for
          }
          else {
            errors.addAbort(Location.nullLoc,
                            "Internal error: operator neither BuiltIn nor UserDefined" +
                            " \nin call to OpDefNode.match()", true);
          }
        }
      } // end "normal case"
    } // end "arity != -1" case

    return result;
  } // end match()

  /*************************************************************************
  * The following methods implement the OpDefOrLabel interface.            *
  *                                                                        *
  * These are the same as the other classes that implement the interface.  *
  * There doesn't seem to be any easy way to write these methods only      *
  * once.                                                                  *
  *************************************************************************/
  public void setLabels(Hashtable ht) {labels = ht; }
    /***********************************************************************
    * Sets the set of labels.                                              *
    ***********************************************************************/

  public LabelNode getLabel(UniqueString us) {
    /***********************************************************************
    * If the hashtable `labels' contains a LabelNode with name `us',       *
    * then that LabelNode is returned; otherwise null is returned.         *
    ***********************************************************************/
    if (labels == null) {return null;} ;
    return (LabelNode) labels.get(us) ;
   }

  public boolean addLabel(LabelNode odn) {
    /***********************************************************************
    * If the hashtable `labels' contains no OpDefNode with the same name   *
    * as odn, then odn is added to the set and true is return; else the    *
    * set is unchanged and false is returned.                              *
    ***********************************************************************/
    if (labels == null) {labels = new Hashtable(); } ;
    if (labels.containsKey(odn)) {return false ;} ;
    labels.put(odn.getName(), odn) ;
    return true;
   }

  public LabelNode[] getLabels() {
    /***********************************************************************
    * Returns an array containing the Label objects in the hashtable       *
    * `labels'.                                                            *
    ***********************************************************************/
    if (labels == null) {return new LabelNode[0];} ;
    Vector v = new Vector() ;
    Enumeration e = labels.elements() ;
    while (e.hasMoreElements()) { v.addElement(e.nextElement()); } ;
    LabelNode[] retVal = new LabelNode[v.size()] ;
    for (int i = 0 ; i < v.size() ; i++)
      {retVal[i] = (LabelNode) v.elementAt(i); } ;
    return retVal ;
   }

  public Hashtable  getLabelsHT() {
    /***********************************************************************
    * Return the labels field.  Used to "clone" an OpDefNode for module    *
    * instantiation.                                                       *
    ***********************************************************************/
    return labels ;
   }

  /*************************************************************************
  * The fields used for level checking.                                    *
  *************************************************************************/

// These fields are now present in all LevelNode subclasses
//  private boolean levelCorrect;
//  private int level;
//  private HashSet levelParams;
//  private SetOfLevelConstraints levelConstraints;
//  private SetOfArgLevelConstraints argLevelConstraints;
//  private HashSet argLevelParams;

  int[] maxLevels;
  int[] weights;
  int[][] minMaxLevel;
    /***********************************************************************
    * According to LevelSpec.tla, if this is the OpDefNode for the         *
    * definition of op, then op.minMaxLevel[i][k] is the minimum value of  *
    * oparg.maxLevels[k] for the i-th argument of Op.  Thus,               *
    * op.minMaxLevels[i] is a sequence whose length is the number of       *
    * arguments taken by the i-th argument of Op.  (It equals 0 if the     *
    * i-th argument of Op is not an operator argument.)                    *
    ***********************************************************************/

  boolean[] isLeibnizArg;
  boolean   isLeibniz;
    /***********************************************************************
    * If this is the OpDefNode for the definition of op, then              *
    * isLeibnizArg[i] is true iff the i-th argument of op is Leibniz, and  *
    * isLeibniz = \A i : isLeibnizArg[i]                                   *
    ***********************************************************************/
  /**
   * This "getters" for isLeibnizArg and isLeibniz were added by LL on 24 Oct 2012.
   *  See the comments in AnyDefNode.java for an explanation of why.
   */
  public boolean[] getIsLeibnizArg() {
      return isLeibnizArg;
  }
  public boolean getIsLeibniz() {
      return isLeibniz;
  }


  private boolean[][][] opLevelCond;
    /***********************************************************************
    * According to LevelSpec.tla, if this is the OpDefNode for the         *
    * definition of op, then op.opLevelCond[i][j][k] is true iff           *
    * the i-th argument of op is an operator argument opArg, and the       *
    * definition of op contains an expression in which the j-th formal     *
    * parameter of the definition of op appears within the k-th argument   *
    * of opArg.                                                            *
    ***********************************************************************/

  /* Set the level information for this builtin operator. */
  public final void setBuiltinLevel(BuiltInLevel.Data d) {
    if (d.arity == -1) {
      if (d.argMaxLevels.length > 0) {
        /*******************************************************************
        * This test added on 3 Aug 2007 because the newly-introduced       *
        * $Witness builtin operator has arity -1 but no arguments.         *
        *******************************************************************/
        this.maxLevels = new int[1];
        this.maxLevels[0] = d.argMaxLevels[0];
        this.weights = new int[1];
        this.weights[0] = d.argWeights[0];

       }
      else {
        this.maxLevels = new int[0];
        this.weights = new int[0];
       }
    }
    else {
      this.maxLevels = d.argMaxLevels;
      this.weights = d.argWeights;
    };

    /***********************************************************************
    * Set Leibniz fields.                                                  *
    ***********************************************************************/
    this.isLeibniz = true;
    this.isLeibnizArg = new boolean[d.argWeights.length] ;
    for (int i = 0 ; i < d.argWeights.length ; i++) {
      this.isLeibnizArg[i] = (d.argWeights[i] > 0) ;
      this.isLeibniz = this.isLeibniz && isLeibnizArg[i] ;
     } ;

    this.level              = d.opLevel;
    this.levelChecked       = 99 ;
      /*********************************************************************
      * Never need to level-check a built-in operator.                     *
      *********************************************************************/
// These are now the default values
//    this.levelCorrect        = true;
//    this.levelParams         = EmptySet;
//    this.levelConstraints    = EmptyLC;
//    this.argLevelConstraints = EmptyALC;
//    this.argLevelParams      = EmptySet;
  }

  @Override
  public final boolean levelCheck(int itr) {
    if (   (this.levelChecked >= itr)
        || (    (! inRecursiveSection)
             && (this.levelChecked > 0))) return this.levelCorrect;
      /*********************************************************************
      * Need only level-check the definition once if not in a recursive    *
      * section.                                                           *
      *********************************************************************/
    this.levelChecked = itr ;

    if (this.getKind() == NumberedProofStepKind) {
      /*********************************************************************
      * We should never have to level check a NumberedProofStepKind node,  *
      * but just in case some reorganization of things causes it to        *
      * happen...                                                          *
      *********************************************************************/
      LevelNode[] subs = new LevelNode[1] ;
      subs[0] = stepNode ;
      this.levelCorrect = this.stepNode.levelCheck(itr);
      return this.levelCheckSubnodes(itr, subs) ;
     }

    // Level check the body:
      this.levelCorrect = this.body.levelCheck(itr);
    /***********************************************************************
    * Modified for recursive checking so the level never decreases with    *
    * repeated computation.                                                *
    ***********************************************************************/
    // Calculate level information:
    this.level = Math.max(this.level, this.body.getLevel());

     SetOfLevelConstraints lcSet = this.body.getLevelConstraints();
    for (int i = 0; i < this.params.length; i++) {
      /*********************************************************************
      * Modified to never increase maxLevels[i].                           *
      *********************************************************************/
      Object plevel = lcSet.get(params[i]);
      if (plevel != null) {
        this.maxLevels[i] = Math.min(this.maxLevels[i],
                                     ((Integer)plevel).intValue());
      }
    }

   /************************************************************************
   * For handling of recursive level checking, we now modify the           *
   * computation of weights so they never get decreased.  (This is         *
   * probably not necessary.)                                              *
   ************************************************************************/
//    this.weights = new int[this.params.length];
    for (int i = 0; i < this.params.length; i++) {
      if (this.body.getLevelParams().contains(this.params[i])) {
        this.weights[i] = Math.max(this.weights[i], 1);
      }
    }

    this.minMaxLevel = new int[this.params.length][];
    SetOfArgLevelConstraints alcSet = this.body.getArgLevelConstraints();
    for (int i = 0; i < this.params.length; i++) {
      int alen = this.params[i].getArity();
      this.minMaxLevel[i] = new int[alen];
      for (int j = 0; j < alen; j++) {
        Object alevel = alcSet.get(new ParamAndPosition(this.params[i], j));
        if (alevel == null) {
          this.minMaxLevel[i][j] = MinLevel;
        }
        else {
          this.minMaxLevel[i][j] = ((Integer)alevel).intValue();
        }
      }
    }

    this.opLevelCond = new boolean[this.params.length][this.params.length][];
    HashSet alpSet = this.body.getArgLevelParams();
    for (int i = 0; i < this.params.length; i++) {
      for (int j = 0; j < this.params.length; j++) {
        this.opLevelCond[i][j] = new boolean[this.params[i].getArity()];
        for (int k = 0; k < this.params[i].getArity(); k++) {
          ArgLevelParam alp = new ArgLevelParam(this.params[i], k, this.params[j]);
          this.opLevelCond[i][j][k] = alpSet.contains(alp);
        }
      }
    }

    /***********************************************************************
    * Modified for recursive definition handling so levelParams increases  *
    * monotonically with multiple computations.                            *
    *                                                                      *
    * allParams and nonLeibnizParams are also handled in the same way.     *
    ***********************************************************************/
    this.levelParams.addAll(this.body.getLevelParams());
    this.allParams.addAll(this.body.getAllParams());
    this.nonLeibnizParams.addAll(this.body.getNonLeibnizParams());
    for (int i = 0; i < this.params.length; i++) {
      this.levelParams.remove(this.params[i]);
      this.allParams.remove(this.params[i]);
      if (this.nonLeibnizParams.contains(this.params[i])) {
        /*******************************************************************
        * The i-th argument is non-Leibniz if this.params[i] is in the     *
        * body's nonLeibnizParams hashset (and hence now in this node's    *
        * nonLeibnizParams hashset.                                        *
        *******************************************************************/
        this.nonLeibnizParams.remove(this.params[i]) ;
        this.isLeibnizArg[i] = false ;
        this.isLeibniz = false ;
       } ;
    }

    this.levelConstraints = (SetOfLevelConstraints)lcSet.clone();
    for (int i = 0; i < this.params.length; i++) {
      this.levelConstraints.remove(this.params[i]);
    }

    this.argLevelConstraints = (SetOfArgLevelConstraints)alcSet.clone();
    for (int i = 0; i < this.params.length; i++) {
      int alen = this.params[i].getArity();
      for (int j = 0; j < alen; j++) {
        this.argLevelConstraints.remove(new ParamAndPosition(this.params[i], j));
      }
    }

//    this.argLevelParams = new HashSet();
    Iterator iter = alpSet.iterator();
    while (iter.hasNext()) {
      ArgLevelParam alp = (ArgLevelParam)iter.next();
      if (!alp.op.occur(this.params) ||
          !alp.param.occur(this.params)) {
        this.argLevelParams.add(alp);
      }
    }
    return this.levelCorrect;
  }

// These get... methods now use the default ones defined in
// the superclass LevelNode
//
//  public final int getLevel() {
//    this.levelCheck();
//    return this.level;
//  }
//
//  public final HashSet getLevelParams() {
//    this.levelCheck();
//    return this.levelParams;
//  }
//
//  public final SetOfLevelConstraints getLevelConstraints() {
//    this.levelCheck();
//    return this.levelConstraints;
//  }
//
//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    this.levelCheck();
//    return this.argLevelConstraints;
//  }
//
//  public final HashSet getArgLevelParams() {
//    this.levelCheck();
//    return this.argLevelParams;
//  }

/***************************************************************************
* The following Asserts can be removed after debugging.                    *
***************************************************************************/
  public final int getMaxLevel(int i) {
    if (this.levelChecked == 0)
      {throw new WrongInvocationException("getMaxLevel called before levelCheck");};
    int idx = (this.getArity() == -1) ? 0 : i;
    return this.maxLevels[idx];
  }

  public final int getWeight(int i) {
    if (this.levelChecked == 0)
      {throw new WrongInvocationException("getWeight called before levelCheck");};
    int idx = (this.getArity() == -1) ? 0 : i;
    return this.weights[idx];
  }

  public final int getMinMaxLevel(int i, int j) {
    if (this.levelChecked == 0)
      {throw new WrongInvocationException("getMinMaxLevel called before levelCheck");};
    if (this.minMaxLevel == null) {
      return ConstantLevel;
    }
    return this.minMaxLevel[i][j];
  }

  public final boolean getOpLevelCond(int i, int j, int k) {
    if (this.levelChecked == 0)
      {throw new WrongInvocationException("getOpLevelCond called before levelCheck");};
    if (this.opLevelCond == null) {
      return false;
    }
    return this.opLevelCond[i][j][k];
  }

  /**
   * toString, levelDataToString, and walkGraph methods to implement
   * ExploreNode interface
   */
  @Override
  public final String levelDataToString() {
    if (   (this.getKind() == ModuleInstanceKind)
        || (this.getKind() == NumberedProofStepKind)) {return "";} ;
        /*******************************************************************
        * A ModuleInstanceKind node is never level checked, and I don't    *
        * think a NumberedProofStepKind is either.                         *
        *******************************************************************/
    if (this.arity < 0) {
      return "Arity: "               + this.arity                   + "\n" +
             "Level: "               + this.getLevel()              + "\n" +
             "MaxLevel: "            + this.maxLevels[0]            + "\n";
    }
    else {
      /*********************************************************************
      * Modified by LL on 24 Mar 2007 to print the maxLevels array         *
      * properly.                                                          *
      *********************************************************************/
      String maxLevelStr = "" ;
        for (int i = 0; i < this.maxLevels.length; i++) {
           if (i > 0) {maxLevelStr = maxLevelStr + ", ";};
           maxLevelStr = maxLevelStr + this.maxLevels[i];
           } ;
      String isLeibnizArgStr = "" ;
        for (int i = 0; i < this.isLeibnizArg.length; i++) {
           if (i > 0) {isLeibnizArgStr = isLeibnizArgStr + ", ";};
           isLeibnizArgStr = isLeibnizArgStr + this.isLeibnizArg[i];
           } ;
      String opLevelCondStr = "" ;
      if (opLevelCond != null) {
        opLevelCondStr = "[" ;
        for (int i = 0; i < opLevelCond.length; i++) {
          opLevelCondStr = opLevelCondStr + " [" ;
          for (int j = 0; j < opLevelCond[i].length; j++) {
            opLevelCondStr = opLevelCondStr + " [" ;
            for (int k = 0; k < opLevelCond[i][j].length; k++) {
               String foo = " " ;
               if (k==0) {foo = "";}
               opLevelCondStr = opLevelCondStr + foo +
                   this.opLevelCond[i][j][k] ;
             } // for k
            opLevelCondStr = opLevelCondStr + "]" ;
           } // for j
          opLevelCondStr = opLevelCondStr + "]" ;
         } ; // for i
        opLevelCondStr = opLevelCondStr + "]" ;
       } ; // if (opLevelCond != null)
      return "Arity: "               + this.arity                    + "\n" +
             "Level: "               + this.getLevel()               + "\n" +
             "LevelParams: "         + this.getLevelParams()         + "\n" +
             "LevelConstraints: "    + this.getLevelConstraints()    + "\n" +
             "ArgLevelConstraints: " + this.getArgLevelConstraints() + "\n" +
             "ArgLevelParams: "      + ALPHashSetToString(this.getArgLevelParams()) + "\n" +
             "MaxLevel: "            + maxLevelStr                   + "\n" +
             "opLevelCond: "         + opLevelCondStr                + "\n" +
             "AllParams: "           + HashSetToString(this.getAllParams()) + "\n" +
             "NonLeibnizParams: "    + HashSetToString(this.getNonLeibnizParams()) + "\n" +
             "IsLeibniz: "           + this.isLeibniz                + "\n" +
             "isLeibnizArg: "       + isLeibnizArgStr               + "\n" ;
    }
  }


  public boolean hasOpcode(final int opCode) {
      return opCode == BuiltInOPs.getOpCode(getName());
  }

  /**
   * The body is the node's only child.
   */

  @Override
  public SemanticNode[] getChildren() {
    return new SemanticNode[] {this.body};
  }

  /**
   * walkGraph finds all reachable nodes in the semantic graph
   * and inserts them in the Hashtable semNodesTable for use by
   * the Explorer tool.
   */
  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    if (params != null && params.length > 0) {
      for (int i = 0; i < params.length; i++) {
        if (params[i] != null) params[i].walkGraph(semNodesTable, visitor);
      }
    }
    if (body != null) body.walkGraph(semNodesTable, visitor);
    if (stepNode != null) stepNode.walkGraph(semNodesTable, visitor);
    visitor.postVisit(this);
  }

	@Override
	public String getSignature() {
		final StringBuffer buf = new StringBuffer();
		buf.append(getName().toString());
		if (getArity() > 0 && getKind() != ASTConstants.BuiltInKind) {
			buf.append("(");
			//TODO This hack doesn't work for infix operators
			final FormalParamNode[] params = getParams();
			for (int i = 0; i < params.length - 1; i++) {
				final FormalParamNode formalParamNode = params[i];
				if (formalParamNode.getTreeNode() != null) {
					final SyntaxTreeNode treeNode = (SyntaxTreeNode) formalParamNode.getTreeNode();
					buf.append(treeNode.getHumanReadableImage());
					buf.append(", ");
				}
			}
			if (params[params.length - 1].getTreeNode() != null) {
				final TreeNode treeNode = params[params.length - 1].getTreeNode();
				buf.append(treeNode.getHumanReadableImage());
			}
			buf.append(")");
		}
		return buf.toString();
	}

  /**
   * Displays this node as a String, implementing ExploreNode
   * interface; depth parameter is a bound on the depth of the portion
   * of the tree that is displayed.
   */
  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";

    String ret = "\n*OpDefNode: " + this.getName().toString()
                + "\n  "
                + super.toString(depth)
                + "\n  local: " + local
                + "\n  letInLevel: " + letInLevel
                + "\n  inRecursive: " + inRecursive
                + "\n  inRecursiveSection: " + inRecursiveSection
                + "\n  recursiveSection: " + recursiveSection
                + "\n  local: " + local
                + "\n  source: " +
                  ((source == null) ? "this" :
                       (source.getName().toString() +
                            " (uid: " + source.myUID + ")"))
                + "\n  originallyDefinedInModule: " +
                     ((originallyDefinedInModule == null) ? "null" :
                       (originallyDefinedInModule.getName().toString() +
                          " (uid: " + originallyDefinedInModule.myUID + ")"))
                + ((stepNode == null) ? "" :
                        ("\n  stepNode: " +
                          Strings.indent(4,stepNode.toString(depth-3))))
                                                   ;

//  nextDependency has been removed.
//                + "\n  nextDependency: " ;
//    if(nextDependency == null) {ret = ret + "null";}
//     else {ret = ret + nextDependency.getName().toString();} ;
    if (params != null) {
      String tempString = "\n  Formal params: " + params.length;
      for (int i = 0; i < params.length; i++) {
        tempString += Strings.indent(4, ((params[i] != null)
                                         ? params[i].toString(depth-1)
                                         : "\nnull"));
      }
      ret += tempString;
    }
    else {
      ret += Strings.indent(2, "\nFormal params: null");
    }

    // Only print this stuff if user asks for a larger than necessary depth
    if (depth > 1) {
      if (st != null) {
        ret += "\n  SymbolTable: non-null";
      }
      else {
        ret += "\n  SymbolTable: null";
      }
    }
    if (body != null) {
      ret += Strings.indent(2,"\nBody:" + Strings.indent(2,body.toString(depth-1)));
    }
    else {
      ret += Strings.indent(2,"\nBody: null");
    }

    /***********************************************************************
    * The following is the same for all classes that implement the         *
    * OpDefOrLabelNode interface.                                          *
    ***********************************************************************/
    if (labels != null) {
       ret += "\n  Labels: " ;
       Enumeration list = labels.keys() ;
       while (list.hasMoreElements()) {
          ret += ((UniqueString) list.nextElement()).toString() + "  " ;
         } ;
      }
    else {ret += "\n  Labels: null";};

    return ret;
  }

	@Override
	public String getHumanReadableImage() {
		// This ony gets pre-comments (directly in front of the operator definition).
		// In-line comments - e.g. found in the standard modules - are not pre-comments.
		final String comment = getComment();
		
		final StringBuffer buf = new StringBuffer(comment);
		buf.append("\n");
		
		TreeNode[] ones = getTreeNode().one();
		if (ones != null) {
			for (TreeNode treeNode : ones) {
				// TODO This omits all whitespaces from the definition and is thus hard to read.
				// I couldn't figure out a better way to obtain the original image though.
				buf.append(treeNode.getHumanReadableImage());
				buf.append(" ");
			}
		} else {
			// In most cases, toString will print the nodes location.
			buf.append(toString());
		}
		return buf.toString().trim();
	}
  
  protected String getNodeRef() {
    switch (getKind()) {
      case UserDefinedOpKind:
        return "UserDefinedOpKindRef";
      case BuiltInKind:
        return "BuiltInKindRef";
      case ModuleInstanceKind:
        return "ModuleInstanceKindRef";
      default: throw new IllegalArgumentException("unsupported kind: " + getKind() + " in xml export");
    }
  }

  protected Element getSymbolElement(Document doc, SymbolContext context) {
    Element ret = null;
    switch (getKind()) {
      case UserDefinedOpKind:
        ret = doc.createElement("UserDefinedOpKind");
        ret.appendChild(appendText(doc,"uniquename",getName().toString()));
        ret.appendChild(appendText(doc,"arity",Integer.toString(getArity())));
        ret.appendChild(appendElement(doc,"body",body.export(doc,context)));
        if (params != null) {
          Element arguments = doc.createElement("params");
          for (int i=0; i<params.length; i++) {
            Element lp = doc.createElement("leibnizparam");
            lp.appendChild(params[i].export(doc,context));
            if (isLeibnizArg != null && isLeibnizArg[i]) lp.appendChild(doc.createElement("leibniz"));
            arguments.appendChild(lp);
          }
          ret.appendChild(arguments);
      }
        if (inRecursive) ret.appendChild(doc.createElement("recursive"));
      break;
      case BuiltInKind:
        ret = doc.createElement("BuiltInKind");
        ret.appendChild(appendText(doc,"uniquename",getName().toString()));
        ret.appendChild(appendText(doc,"arity",Integer.toString(getArity())));
        Element arguments2 = doc.createElement("params");
        if (params != null) {
          for (int i=0; i<params.length; i++) {
            Element lp = doc.createElement("leibnizparam");
            lp.appendChild(params[i].export(doc,context));
            if (isLeibnizArg != null && isLeibnizArg[i]) lp.appendChild(doc.createElement("leibniz"));
            arguments2.appendChild(lp);
          }
          ret.appendChild(arguments2);
        }
        break;
      case ModuleInstanceKind:
        ret = doc.createElement("ModuleInstanceKind");
        ret.appendChild(appendText(doc,"uniquename",getName().toString()));
        break;
      default: throw new IllegalArgumentException("unsupported kind: " + getKind() + " in xml export");
    }
    return ret;
  }
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/OutputFileWriter.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS OutputFileWriter                                                   *
*                                                                          *
* An OutputFileWriter returns an object for writing an ouput file in the   *
* user's directory.  The object's public methods are putLine(str), which   *
* writes the string str as a line of the output file, and close().         *
***************************************************************************/
package tla2tex;

import java.io.FileWriter;

public class OutputFileWriter
 { private FileWriter fileWriter = null ;
   private String name = "" ;

   public OutputFileWriter(String fileName)
     /**********************************************************************
     * Construct an OutputFileWriter from a file name.                     *
     **********************************************************************/
    { name = fileName ;
      try {fileWriter = new FileWriter(fileName) ;}
      catch (java.io.IOException e)
       { Debug.ReportError( 
           "TLATeX cannot open output file " + name + ".\n"
         + "    Perhaps the file is write-protected");
       };
    }

   public void putLine(String out)
     /**********************************************************************
     * Writes the string out followed by '\n'.                             *
     **********************************************************************/
    { try {fileWriter.write(out + "\n");
           fileWriter.flush();
          }
      catch (java.io.IOException e)
       { Debug.ReportError( 
           "Error trying to write to output file " + name + ".\n"
         + "    Perhaps there is a file-system problem.");
       };
    }
     
   public void close()
    {try {fileWriter.close();}
      catch (java.io.IOException e)
       { Debug.ReportError( 
           "Error trying to close output file " + name + ".\n"
         + "    Perhaps there is a file-system problem.");
       };
    }


 }  // END class

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/preference/ParserPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.preference;

import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * Preferences for TLA+ Parser
 * @author <NAME>
 * @version $Id$
 */
public class ParserPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{

    private BooleanFieldEditor parseSpecField;

    /**
     * Constructor
     */
    public ParserPreferencePage()
    {
        super(GRID);
        setPreferenceStore(PreferenceStoreHelper.getInstancePreferenceStore());
        getPreferenceStore().addPropertyChangeListener(this);
        setDescription("TLA+ Parser preferences");
    }

    protected Control createContents(Composite parent)
    {
        Control pageControl = super.createContents(parent);
        UIHelper.setHelp(pageControl, IHelpConstants.PARSER_PREFERENCE_PAGE);
        return pageControl;
    }

    /**
     * Create field editors
     */
    protected void createFieldEditors()
    {

        addField(new BooleanFieldEditor(IPreferenceConstants.I_PARSER_POPUP_ERRORS,
                "&Always pop up Parsing Errors view", getFieldEditorParent()));

        addField(new BooleanFieldEditor(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY, "&Re-parse module on save",
                getFieldEditorParent()));

        /*addField(new BooleanFieldEditor(IPreferenceConstants.I_PARSE_FILES_ON_MODIFY,
                "&Automatic re-parse all module dependent files (experimental)", getFieldEditorParent()));*/

        /* It is necessary to make this a field in order to enable and disable it when
         * parse module on modify is selected and de-selected
         */
        parseSpecField = new BooleanFieldEditor(IPreferenceConstants.I_PARSE_SPEC_ON_MODIFY,
                "&Re-parse specification on spec module save", getFieldEditorParent());
        if (!getPreferenceStore().getBoolean(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY))
        {
            parseSpecField.setEnabled(false, getFieldEditorParent());
        }
        addField(parseSpecField);

    }

    public void init(IWorkbench workbench)
    {

    }

    protected void initialize()
    {
        // sync the auto-build
        getPreferenceStore().setValue(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY,
                ResourcesPlugin.getWorkspace().isAutoBuilding());
        super.initialize();
    }

    protected void performApply()
    {
        super.performApply();
        this.setAutoBuilding();
    }

    public boolean performOk()
    {
        boolean result = super.performOk();
        this.setAutoBuilding();
        return result;
    }

    /**
     * Sets the value of the workspace auto-build to the module auto-build 
     */
    private void setAutoBuilding()
    {
        boolean autoBuildModule = getPreferenceStore().getBoolean(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY);

        // set the workspace auto-build flag
        IWorkspaceDescription description = ResourcesPlugin.getWorkspace().getDescription();
        if (autoBuildModule != ResourcesPlugin.getWorkspace().isAutoBuilding())
        {
            try
            {
                description.setAutoBuilding(autoBuildModule);
                ResourcesPlugin.getWorkspace().setDescription(description);
            } catch (CoreException e)
            {
                // TODO
                e.printStackTrace();
            }
        }
    }

    /**
     * This overrides the method in {@link FieldEditorPreferencePage}.
     * It disables the parse spec on spec module modify if the parse
     * module on modify option is de-selected and enables it when parse
     * module on modify is selected.
     */
    public void propertyChange(PropertyChangeEvent event)
    {
        if (event.getSource() instanceof BooleanFieldEditor)
        {
            BooleanFieldEditor parseModuleOnModifyField = (BooleanFieldEditor) event.getSource();
            if (parseModuleOnModifyField.getPreferenceName().equals(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY))
            {
                boolean parseModuleOnModify = parseModuleOnModifyField.getBooleanValue();
                if (parseModuleOnModify)
                {
                    parseSpecField.setEnabled(true, getFieldEditorParent());
                } else
                {
                    parseSpecField.setEnabled(false, getFieldEditorParent());
                }
            }
        }
        super.propertyChange(event);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ASTConstants.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

// last modified on Mon 16 February 2009 at  9:57:46 PST by lamport 

package tla2sany.semantic;

import util.UniqueString;

public interface ASTConstants {

  /* The following are kinds of SemanticNodes. */
  public final int ModuleKind         = 1;  // Used for ModuleNodes
  public final int ConstantDeclKind   = 2;  
     // A kind of OpDeclNode; used for constants
  public final int VariableDeclKind   = 3;  
     // A kind of OpDeclNode; used for variables
  public final int BoundSymbolKind    = 4;  
    // A kind of OpDeclNode; used for symbols bound by quantifier-like ops
  public final int UserDefinedOpKind  = 5;  
     // A kind of OpDefNode; used for OpDefNodes for user-defined ops
  public final int ModuleInstanceKind = 6;  
     // A kind of OpDefNode; used for "M" in M(x) == INSTANCE Foo ...
  public final int BuiltInKind        = 7;  
    // A kind of OpDefNode; used only for OpDefNodes of built-in ops
  public static final int OpArgKind          = 8;
  public static final int OpApplKind         = 9;
  public static final int LetInKind          = 10;
  public static final int FormalParamKind    = 11;
  public static final int TheoremKind        = 12;
  public static final int SubstInKind        = 13;
  public static final int AssumeProveKind    = 14;
//  public static final int ProofKind          = 15;
  public static final int NumeralKind        = 16;
  public static final int DecimalKind        = 17;
  public static final int StringKind         = 18;
  public static final int AtNodeKind         = 19;
  public static final int AssumeKind         = 20;
  public static final int InstanceKind       = 21; 
    // Used for InstanceNodes, representing an INSTANCE stmt
    // or def (whether named or not). Not to be confused with
    // ModuleInstanceKind above, which represents a name that
    // must not be (re)used for a user-defined operator.
  public static final int NewSymbKind        = 22; 
    // Added by LL on 15 Mar 2007
  public static final int ThmOrAssumpDefKind = 23; 
    // Added by LL on 17 Mar 2007

  /*************************************************************************
  * The following are kinds of OpDeclNode used for a declaration in the    *
  * assumptions list of an AssumeProve.                                    *
  *                                                                        *
  * Added by LL on 22 Mar 2007                                             *
  *************************************************************************/
  public static final int NewConstantKind    = 24;
  public static final int NewVariableKind    = 25;
  public static final int NewStateKind       = 26;
  public static final int NewActionKind      = 27;
  public static final int NewTemporalKind    = 28;

  public static final int LabelKind          = 29; 
  public static final int APSubstInKind      = 30; 
  public static final int UseKind            = 31;
  public static final int HideKind           = 32;
  public static final int LeafProofKind      = 33;
  public static final int NonLeafProofKind   = 34;
  public static final int QEDStepKind        = 35;
  public static final int DefStepKind        = 36;
  public static final int NumberedProofStepKind = 37;


  /*************************************************************************
  * AN array of printable names for the constants defined above.           *
  *************************************************************************/
  public static final String[] kinds = {
    /*  0 */ null,
    /*  1 */ "ModuleKind",
    /*  2 */ "ConstantDeclKind",
    /*  3 */ "VariableDeclKind",
    /*  4 */ "BoundSymbolKind",
    /*  5 */ "UserDefinedOpKind",
    /*  6 */ "ModuleInstanceKind",
    /*  7 */ "BuiltInKind",
    /*  8 */ "OpArgKind",    
    /*  9 */ "OpApplKind",
    /* 10 */ "LetInKind",
    /* 11 */ "FormalParamKind",
    /* 12 */ "TheoremKind",
    /* 13 */ "SubstInKind",
    /* 14 */ "AssumeProveKind",
    /* 15 */ "ProofKind",
    /* 16 */ "NumeralKind",
    /* 17 */ "DecimalKind",
    /* 18 */ "StringKind",
    /* 19 */ "AtNodeKind",
    /* 20 */ "AssumeKind",
    /* 21 */ "InstanceKind",
    /* 22 */ "NewSymbKind",
    /* 23 */ "ThmOrAssumpDefKind",
    /* 24 */ "NewConstantKind",
    /* 25 */ "NewVariableKind",
    /* 26 */ "NewStateKind",
    /* 27 */ "NewActionKind",
    /* 28 */ "NewTemporalKind",
    /* 29 */ "LabelKind",
    /* 30 */ "APSubstInKind",
    /* 31 */ "UseKind",
    /* 32 */ "HideKind",
    /* 33 */ "LeafProofKind",
    /* 34 */ "NonLeafProofKind",
    /* 35 */ "QEDStepKind",
    /* 36 */ "DefStepKind",
    /* 37 */ "NumberedProofStepKind"
  };

  /* Operators */
  public static UniqueString OP_aa   = UniqueString.uniqueStringOf("$AngleAct");
  public static UniqueString OP_bc   = UniqueString.uniqueStringOf("$BoundedChoose");
  public static UniqueString OP_be   = UniqueString.uniqueStringOf("$BoundedExists");
  public static UniqueString OP_bf   = UniqueString.uniqueStringOf("$BoundedForall");
  public static UniqueString OP_case = UniqueString.uniqueStringOf("$Case");
  public static UniqueString OP_cp   = UniqueString.uniqueStringOf("$CartesianProd");
  public static UniqueString OP_cl   = UniqueString.uniqueStringOf("$ConjList");
  public static UniqueString OP_dl   = UniqueString.uniqueStringOf("$DisjList");
  public static UniqueString OP_exc  = UniqueString.uniqueStringOf("$Except");
  public static UniqueString OP_fa   = UniqueString.uniqueStringOf("$FcnApply");
  public static UniqueString OP_fc   = UniqueString.uniqueStringOf("$FcnConstructor");
  public static UniqueString OP_ite  = UniqueString.uniqueStringOf("$IfThenElse");
  public static UniqueString OP_nrfs = UniqueString.uniqueStringOf("$NonRecursiveFcnSpec");
  public static UniqueString OP_pair = UniqueString.uniqueStringOf("$Pair");
  public static UniqueString OP_rc   = UniqueString.uniqueStringOf("$RcdConstructor");
  public static UniqueString OP_rs   = UniqueString.uniqueStringOf("$RcdSelect");
  public static UniqueString OP_rfs  = UniqueString.uniqueStringOf("$RecursiveFcnSpec");
  public static UniqueString OP_seq  = UniqueString.uniqueStringOf("$Seq");
  public static UniqueString OP_sa   = UniqueString.uniqueStringOf("$SquareAct");
  public static UniqueString OP_se   = UniqueString.uniqueStringOf("$SetEnumerate");
  public static UniqueString OP_sf   = UniqueString.uniqueStringOf("$SF");
  public static UniqueString OP_soa  = UniqueString.uniqueStringOf("$SetOfAll");
  public static UniqueString OP_sor  = UniqueString.uniqueStringOf("$SetOfRcds");
  public static UniqueString OP_sof  = UniqueString.uniqueStringOf("$SetOfFcns");
  public static UniqueString OP_sso  = UniqueString.uniqueStringOf("$SubsetOf");
  public static UniqueString OP_tup  = UniqueString.uniqueStringOf("$Tuple");
  public static UniqueString OP_te   = UniqueString.uniqueStringOf("$TemporalExists");
  public static UniqueString OP_tf   = UniqueString.uniqueStringOf("$TemporalForall");
  public static UniqueString OP_uc   = UniqueString.uniqueStringOf("$UnboundedChoose");
  public static UniqueString OP_ue   = UniqueString.uniqueStringOf("$UnboundedExists");
  public static UniqueString OP_uf   = UniqueString.uniqueStringOf("$UnboundedForall");
  public static UniqueString OP_wf   = UniqueString.uniqueStringOf("$WF");

  /*************************************************************************
  * The following added by LL 2-3 Aug 2007.                                *
  *************************************************************************/
  public static UniqueString OP_nop  = UniqueString.uniqueStringOf("$Nop");
  public static UniqueString OP_qed     = UniqueString.uniqueStringOf("$Qed");
  public static UniqueString OP_pfcase  = UniqueString.uniqueStringOf("$Pfcase");
  public static UniqueString OP_have    = UniqueString.uniqueStringOf("$Have");
  public static UniqueString OP_take    = UniqueString.uniqueStringOf("$Take");
  public static UniqueString OP_pick    = UniqueString.uniqueStringOf("$Pick");
  public static UniqueString OP_witness = 
    UniqueString.uniqueStringOf("$Witness");

  /*************************************************************************
  * OP_suffices added by LL 16 Feb 2009.                                   *
  *************************************************************************/
  public static UniqueString OP_suffices  = UniqueString.uniqueStringOf("$Suffices");
  
  /*************************************************************************
  * OP_prime added by LL 2 Dec 2012.                                       *
  *************************************************************************/
  public static UniqueString OP_prime  = UniqueString.uniqueStringOf("'");

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/source/StateTagBasedTLCOutputIncrementalParserTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.easymock.EasyMock;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.text.BadLocationException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariable;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue;

public class StateTagBasedTLCOutputIncrementalParserTest {

	private static final int STATE_NUM = 1;
	private static final String LABEL = " <Initial predicate>";
	private static final int EXPECTED_VARS = 41;

	//TODO make multiple values work
	private static final long STATES = 1L;

	private String state;
	private Map<String, String> vars = new HashMap<String,String>();
	
	private TagBasedTLCOutputIncrementalParser parser;
	private DummyListener testListener;
	private static Map<String, Map<String, Long>> results = new HashMap<String, Map<String, Long>>();;

	@Before
	public void setUp() {
		vars.put("pos_f", "defaultInitValue");
		vars.put("foundTokenSpecs", "<<>>");
		vars.put("delim", "defaultInitValue");
		vars.put("leftTok", "defaultInitValue");
		vars.put("left_", "defaultInitValue");
		vars.put("returnVal", "defaultInitValue");
		vars.put("delimLen_", "defaultInitValue");
		vars.put("line", "( 0 :> \";\" @@"
			+ "1 :> \";\" @@"
			+ "2 :> \";\" @@"
			+ "3 :> \";\" @@"
			+ "4 :> \";\" @@"
			+ "5 :> \";\" @@"
			+ "6 :> \";\" @@"
			+ "7 :> \";\" @@"
			+ "8 :> \";\" @@"
			+ "9 :> \";\" @@"
			+ "10 :> \"f\" @@"
			+ "11 :> \"(\" @@"
			+ "12 :> \"b\" @@"
			+ "13 :> \")\" @@"
			+ "14 :> \" \" @@"
			+ "15 :> \";\" @@"
			+ "16 :> \";\" @@"
			+ "17 :> \";\" @@"
			+ "18 :> \";\" @@"
			+ "19 :> \";\" @@"
			+ "20 :> \";\" @@"
			+ "21 :> \";\" @@"
			+ "22 :> \";\" @@"
			+ "23 :> \";\" @@"
			+ "24 :> \";\" )(");
		vars.put("jdelim_", "defaultInitValue");
		vars.put("i", "defaultInitValue");
		vars.put("foundBangToken", "defaultInitValue");
		vars.put("pos", "defaultInitValue");
		vars.put("pc", "\"Lbl_77\"");
		vars.put("ipos_", "defaultInitValue");
		vars.put("pos_fi", "defaultInitValue");
		vars.put("pos_fin", "defaultInitValue");
		vars.put("notDone", "defaultInitValue");
		vars.put("pos_find", "defaultInitValue");
		vars.put("temp1", "defaultInitValue");
		vars.put("temp2", "defaultInitValue");
		vars.put("temp3", "defaultInitValue");
		vars.put("delimLen", "defaultInitValue");
		vars.put("rt", "defaultInitValue");
		vars.put("notLastToken", "FALSE");
		vars.put("ipos", "defaultInitValue");
		vars.put("left", "defaultInitValue");
		vars.put("token", "<<>>");
		vars.put("rt_", "defaultInitValue");
		vars.put("rightTok", "defaultInitValue");
		vars.put("jdelim", "defaultInitValue");
		vars.put("tokIdx", "defaultInitValue");
		vars.put("pos_", "defaultInitValue");
		vars.put("curPos", "11");
		vars.put("delim_", "defaultInitValue");
		vars.put("tokArray", "defaultInitValue");
		vars.put("lastToken", "FALSE");
		vars.put("currentToken", "defaultInitValue");
		vars.put("stack", "<<>>");
		vars.put("tempVar1", "defaultInitValue");
		vars.put("tempVar2", "defaultInitValue");
		vars.put("tempVar3", "defaultInitValue");
		
		StringBuffer buf = new StringBuffer();
		
		// start tag
		buf.append("@!@!@STARTMSG 2217:4 @!@!@\n");
		
		// state num and state label
		buf.append(STATE_NUM + ":" + LABEL + "\n");
		
		// trace expression
		StringBuffer te = new StringBuffer();
		for (Map.Entry<String, String> entry: vars.entrySet()) {
			String key = entry.getKey();
			String value = entry.getValue();
			te.append("/\\ " + key + " = " + value + "\n");
		}
		buf.append(te);
		
		// end tag
		buf.append("@!@!@ENDMSG 2217 @!@!@\n");
		
		this.state = buf.toString();
		
		this.parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		
		// Register test listener with parser output
		ITLCOutputSource source = parser.getSource();
		testListener = new DummyListener();
		source.addTLCOutputListener(testListener);
	}
	
	@After
	public void tearDown() {
		MethodInvocationCounter.clear();
	}

	@AfterClass
	public static void printStatistics() {
		
		// print invocation statistics
		for (Map.Entry<String, Map<String, Long>> entry: results.entrySet()) {
			StringBuffer buf = new StringBuffer();

			// method name
			String methodName = entry.getKey();
			buf.append("MethodName: ");
			buf.append(methodName);
			buf.append("\n\t");
			
			for (Map.Entry<String, Long> subEntry: entry.getValue().entrySet()) {
				// mode
				String parserMode = subEntry.getKey();
				buf.append("Mode: ");
				buf.append(parserMode);
				
				// invocations
				Long invocations = subEntry.getValue();
				buf.append(" : ");
				buf.append(invocations);
				buf.append("\n\t");
			}
			System.out.println(buf.toString());
		}

	}

	/*
	 *  State by state
	 */
	@Test
	public void parseStateByState()
			throws BadLocationException {

		for(int i = 0; i < STATES; i++) {
			parser.addIncrement(state);
		}
		parser.done();

		collectInvocationStatistics("parseStateByState");
		verifyParserOutput();
	}

	/*
	 * Line by line
	 */
	@Test
	public void parseLineByLine()
			throws BadLocationException {
		final String[] lines = state.split("\n");
		for(int i = 0; i < STATES; i++) {
			for (int j = 0; j < lines.length; j++) {
				parser.addIncrement(lines[j] + "\n");
			}
		}
		parser.done();

		collectInvocationStatistics("parseLineByLine");
		verifyParserOutput();
	}

	/*
	 * Fully
	 */
	@Test
	public void parseAllAtOnce()
			throws BadLocationException {
		String states = "";
		for(int i = 0; i < STATES; i++) {
			states += state + "\n";
		}

		// measure single line performance
		parser.addIncrement(states);
		parser.done();

		collectInvocationStatistics("parseAllAtOnce");
		verifyParserOutput();
	}

	private void collectInvocationStatistics(String parserMode) {
		final Map<String, Long> invocations = MethodInvocationCounter.getInvocations();
		for (Map.Entry<String, Long> entry: invocations.entrySet()) {
			Map<String, Long> value = results.get(entry.getKey());
			if(value == null) {
				value = new HashMap<String, Long>();
				results.put(entry.getKey(), value);
			}
			value.put(parserMode, entry.getValue());
		}
	}

	// verify parser finished successfully recognizing all STATES
	private void verifyParserOutput() {
		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());
		
		// confirm parser has recognized all states
		final List<TLCState> parsedStates = testListener.getStates();
		Assert.assertEquals(STATES, parsedStates.size());
		
		// check each state individually
		for (Iterator<TLCState> iterator = parsedStates.iterator(); iterator.hasNext();) {
			final TLCState tlcState = iterator.next();
			
			final int stateNumber = tlcState.getStateNumber();
			Assert.assertEquals(STATE_NUM, stateNumber);
			
			final String label = tlcState.getLabel();
			Assert.assertEquals(LABEL, label);
			
			final TLCVariable[] variables = tlcState.getVariables();
			Assert.assertEquals(EXPECTED_VARS, variables.length);
			for (int i = 0; i < variables.length; i++) {
				final TLCVariable tlcVariable = variables[i];
				final String varName = tlcVariable.getName();
				final String expectedValue = vars.get(varName.trim());
				
				TLCVariableValue actualValue = tlcVariable.getValue();
				Assert.assertEquals(expectedValue, actualValue.toString());
			}
		}
		
		Assert.assertEquals(STATES, testListener.getRegions().size());
	}
	
	private class DummyModel extends Model {

		DummyModel() {
			super(EasyMock.createNiceMock(ILaunchConfiguration.class));
		}
		
		public String getName() {
			// Stop super from delegating to ILC
			return "StateTagBasedTLCOutputIncrementalParserTest";
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-verify/tlc2/tool/fp/OffHeapDiskFPSetJPFTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

import gov.nasa.jpf.util.test.TestJPF;

// This class verifies a core part of tlc2.tool.fp.OffHeapDiskFPSet. It is - more or less - a verbatim copy.
public class OffHeapDiskFPSetJPFTest extends TestJPF {
	private static final int PROBE_LIMIT = 2;

	@Test
	public void test() throws InterruptedException, BrokenBarrierException {
		if (verifyNoPropertyViolation("+listener=.listener.AssertionProperty,.listener.ErrorTraceGenerator")) {
			final int size = 3;
			final int max = 3;
			final DummyOffHeapDiskFPSet fpSet = new DummyOffHeapDiskFPSet(size, max);

			// Two concurrent writers.
			for (int i = 0; i < 2; i++) {
				Thread worker = new Thread(new Runnable() {
					public void run() {
						for (long i = 1; i <= max; i++) {
							fpSet.memInsert(i);
						}
					}
				}, "Worker");
				worker.start();
			}
			assert fpSet.checkInvariant() : "FPSet violates its invariant: " + Arrays.toString(fpSet.array.array);
		}
	}
	
	private static class DummyOffHeapDiskFPSet {

		private static final int EMPTY = 0;
		
		private final OffHeapDiskFPSet.Indexer indexer;
		private final DummyLongArray array;
		// AtomicInteger should be LongAdder but JPF fails with what seems to be an
		// internal bug.
		private final AtomicInteger tblCnt;

		public DummyOffHeapDiskFPSet(int positions, long max) {
			this.tblCnt = new AtomicInteger(0);
			this.array = new DummyLongArray(positions);
			this.indexer = new OffHeapDiskFPSet.Indexer(positions, 1, max);
		}

		// This is what we want to verify.
		public boolean memInsert(final long fp) {
			for (int i = 0; i < PROBE_LIMIT; i++) {
				final int position = (int) indexer.getIdx(fp, i);
				final long expected = array.get(position);
				if (expected == EMPTY) {
					if (array.trySet(position, expected, fp)) {
						tblCnt.incrementAndGet();
						return false;
					} else {
						i = i - 1;
						continue;
					}
				}
				if (expected == fp) {
					return true;
				}
			}
			return false;
		}
		
		// Heap-variant of LongArray with synchronized instead of CAS. JPF does
		// not seem to support sun.misc.Unsafe.
		private static class DummyLongArray {
			private final long[] array;
			
			public DummyLongArray(int positions) {
				this.array = new long[positions];
			}

			public long get(int position) {
				return this.array[position];
			}

			public synchronized boolean trySet(int position, long expected, long l) {
				if (this.array[position] == expected) {
					this.array[position] = l;
					return true;
				}
				return false;
			}
		}

		//**** Assertion Helper ****//
		
		public synchronized boolean checkInvariant() {
			// No duplicates.
			int cnt = 0;
			final Set<Long> s = new HashSet<Long>(array.array.length);
			for (int i = 0; i < array.array.length; i++) {
				if (array.array[i] > 0) {
					s.add(array.array[i]);
					cnt++;
				}
			}
			return cnt == s.size();
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCCompoundVariableValue.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.data;

public class TLCCompoundVariableValue extends TLCVariableValue
{

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/tool/ToolboxHandle.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.ModuleParserLauncher;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;

import tla2sany.modanalyzer.SpecObj;

/**
 * Provides shortcuts to the internal toolbox methods, that should be made accessible to the other tools
 */
public class ToolboxHandle
{
    public static String I_RESTORE_LAST_SPEC = IPreferenceConstants.I_RESTORE_LAST_SPEC;

    /**
     * Retrieves the root file of the loaded spec or <code>null</code> if no spec selected
     */
    public static IFile getRootModule()
    {
        return ((Activator.getSpecManager().getSpecLoaded() == null) ? null : Activator.getSpecManager()
                .getSpecLoaded().getRootFile());
    }
    /**
     * Retrieves the root file of the specification project
     * @param project
     * @return the resource
     */
    public static IResource getRootModule(IProject project) 
    {
        return PreferenceStoreHelper.readProjectRootFile(project);
    }

    /**
     * Returns the instance preference store
     */
    public static IPreferenceStore getInstanceStore()
    {
        return PreferenceStoreHelper.getInstancePreferenceStore();
    }


    /**
     * Returns the SpecObj of the current loaded specification
     * @return SpecObj produced by the previous SANY run, or null
     */
    public static SpecObj getSpecObj()
    {
        Spec spec = null;
        try
        {
            spec = Activator.getSpecManager().getSpecLoaded();
        } catch (IllegalStateException e)
        {
            // this happens is the workspace is closed
            // just return null for e.G. JUnit tests
        }
        if (spec != null)
        {
            return spec.getValidRootModule();
        }
        return null;
    }

    /**
     * Retrieves the spec by name
     * @param name
     * @return
     */
    public static Spec getSpecByName(String name)
    {
        return Activator.getSpecManager().getSpecByName(name);
    }

    /**
     * @return
     */
    public static Spec getCurrentSpec()
    {
        return Activator.getSpecManager().getSpecLoaded();
    }

    /**
     * Determines if the module is a user module (not StandardModule)<br>
     * Note: only looks for parsed spec...
     * @param name a filename of the module (like foo.tla)
     * @return true if the user belongs to the spec
     * 
     */
    public static boolean isUserModule(String name)
    {
        if (name == null || name.length() == 0)
        {
            return false;
        }
        return Activator.getModuleDependencyStorage().hasModule(name);
    }

    /**
     * Retrieves the list of modules that are EXTEND-ed by current module
     * <br><b>Note:</b>Only works for current spec
     * @param rootModule, name of the module
     * @return list of modules it depends (EXTEND) on
     */
    @SuppressWarnings("unchecked")
	public static List<String> getExtendedModules(String moduleName)
    {
        return Activator.getModuleDependencyStorage().getListOfExtendedModules(moduleName);
    }

    /**
     * Returns the classpath entry of the tla2tool.jar (the TLA tools) 
     */
    public static IPath getTLAToolsClasspath() {
    	Bundle bundle = null;
    	
    	// find the tlatools bundle among all installed bundles
    	// (this code assumes tlatools has a bundle shape "dir")
		Bundle[] bundles = Activator.getDefault().getBundle()
				.getBundleContext().getBundles();
        for (int i = 0; i < bundles.length; i++) {
			Bundle aBundle = bundles[i];
			if ("org.lamport.tlatools".equals(aBundle.getSymbolicName())) {
				// OSGi supports multiple bundles with the same symbolic name, but
				// different versions. This e.g. occurs after a Toolbox update
				// before the old bundle version gets purged from the
				// installation directory.
				// Without this explicitly version check, the Toolbox
				// might accidentally use an old tla version which leads to
				// undefined behavior.
				// @see Bug #285 in general/bugzilla/index.html
				Version otherVersion = bundle != null ? bundle.getVersion()
						: Version.parseVersion("0.0.0");
				if (aBundle.getVersion().compareTo(otherVersion) > 0) {
					bundle = aBundle;
				}
			}
		}
        if (bundle == null)
            return null;

        URL local = null;
        try
        {
            local = FileLocator.toFileURL(bundle.getEntry("/")); //$NON-NLS-1$
        } catch (IOException e)
        {
            return null;
        }
        String fullPath = new File(local.getPath()).getAbsolutePath();
        return Path.fromOSString(fullPath);
    }
    
    /**
     * Parses the module
     * @param resource
     * @param monitor
     */
    public static IParseResult parseModule(IResource resource, IProgressMonitor monitor, boolean installMarkers, boolean updateDependencies)
    {
        ModuleParserLauncher moduleParser = new ModuleParserLauncher();
        ParseResult result = moduleParser.parseModule(resource, monitor, installMarkers, updateDependencies);
        return result;
    }
    
 
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/MemIntQueueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.NoSuchElementException;

import org.junit.Test;

public class MemIntQueueTest {

	@Test
	public void testDequeuePastLastElement() {
		final MemIntQueue queue = new MemIntQueue("irrelevant", "irrelevant");
		queue.enqueueInt(1);
		
		assertEquals(1, queue.dequeueInt());
		try {
			queue.dequeueInt();
		} catch (NoSuchElementException e) {
			return;
		}
		fail("Returned element where there should be none.");
	}
	
	// Add 0 three times and make sure it's only returned this many times. 0
	// is MemIntQueue's internal default for an empty slot.
	@Test
	public void testEnqueueZeros() {
		final MemIntQueue queue = new MemIntQueue("irrelevant", "irrelevant");
		queue.enqueueInt(0);
		queue.enqueueInt(0);
		queue.enqueueInt(0);
		
		assertEquals(0, queue.dequeueInt());
		assertEquals(0, queue.dequeueInt());
		assertEquals(0, queue.dequeueInt());
		
		try {
			queue.dequeueInt();
		} catch (NoSuchElementException e) {
			return;
		}
		fail("Returned element where there should be none.");
	}
	
	@Test
	public void testEnqueueLong() {
		final MemIntQueue queue = new MemIntQueue("irrelevant", "irrelevant");
		queue.enqueueLong(0);
		
		assertEquals(0, queue.dequeueInt());
		assertEquals(0, queue.dequeueInt());

		try {
			queue.dequeueInt();
		} catch (NoSuchElementException e) {
			return;
		}
		fail("Returned element where there should be none.");
	}
	
	@Test
	public void testEnqueueDequeueLong() {
		final MemIntQueue queue = new MemIntQueue("irrelevant", "irrelevant");
		queue.enqueueLong(0);
		
		assertEquals(0, queue.dequeueLong());

		try {
			queue.dequeueLong();
		} catch (NoSuchElementException e) {
			return;
		}
		fail("Returned element where there should be none.");
	}
	
	@Test
	public void testGrow() {
		final MemIntQueue queue = new MemIntQueue("irrelevant", "irrelevant", 4);
		queue.enqueueInt(0);
		queue.enqueueInt(1);
		queue.enqueueInt(2);
		queue.enqueueInt(3);
		assertEquals(4, queue.size());

		queue.dequeueInt();
		queue.dequeueInt();
		queue.dequeueInt();
		queue.dequeueInt();
		assertEquals(0, queue.size());

		queue.enqueueInt(4);
		queue.enqueueInt(5);
		queue.enqueueInt(6);
		queue.enqueueInt(7);
		assertEquals(4, queue.size());

		queue.dequeueInt();

		// This should make the queue grow internally.
		queue.enqueueInt(8);
		queue.enqueueInt(9);
		for(int i = 5; i < 10; i++) {
			assertEquals(i, queue.dequeueInt());
		}
		assertEquals(0, queue.size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/UnhandledInvalidSyntaxTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Arrays;

import org.junit.Test;

import util.ToolIO;

public class UnhandledInvalidSyntaxTest extends PCalTest {

	@Test
	public void test1() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("MissingSemicolonTest1", 
				"---- MODULE algo ----\n" + 
				"(*\n" + 
				" --algorithm algo\n" + 
				" begin\n" + 
				" await;\n" +
				" end algorithm;\n" +
				"*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Unknown error at or before\n"
					+ "    line 5, column 2.\n"));
	}
	
	@Test
	public void test2() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("MissingSemicolonTest2", 
				"---- MODULE algo ----\n" + 
				"(*\n" + 
				" --algorithm algo\n" + 
				" begin\n" + 
				" if TRUE then\n" + // missing semicolon
				" end if;\n" +
				" end algorithm;\n" +
				"*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Unknown error at or before\n"
					+ "    line 6, column 8.\n"));
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/DynamicFPSetManager.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import tlc2.tool.distributed.TLCWorker;

/**
 * Contrary to {@link FPSetManager}, this class is a {@link UnicastRemoteObject}
 * . This results in it being a singleton for a distributed TLC model checker
 * and thus a single point of failure and bottleneck.<br>
 * On the up side, it results in {@link TLCWorker}s seeing a consistent
 * distributed fingerprint set at all times.
 */
@SuppressWarnings("serial")
public class DynamicFPSetManager extends FPSetManager implements Serializable {

	private int expectedNumOfServers;

	public DynamicFPSetManager(int expectedNumOfServers) throws RemoteException {
		super();
		// If expectedNumOfServers is no power of two, a subset of FPSet
		// servers will act as passive backups. Each time a FPSet from
		// the active set is lost, all workers switch over to the next
		// available passive one on a list. The list has to be known
		// prior to when the workers start (it's possible to send out
		// list updates, but it hasn't been implemented).
		this.expectedNumOfServers = expectedNumOfServers;
		
		// Guard against invalid values
		if (expectedNumOfServers <= 0) {
			throw new IllegalArgumentException();
		}
		
		// Round expectedNumOfServers to power of 2
		int log = 0;
		while (expectedNumOfServers > 0) {
			expectedNumOfServers = expectedNumOfServers / 2;
			log++;
		}
		
		// Zero upper bits of mask which won't be used when addressing the
		// fingerprint servers anyway. See IFPSetManager#getFPSetIndex.
		this.mask = (1L << log) - 1L;
	}


	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#register(tlc2.tool.distributed.FPSetRMI)
	 */
	public synchronized void register(FPSetRMI aFPSet, String hostname) throws FPSetManagerException {
		// Only accept additional FPSets as long as we haven't reached the
		// expected number of FPSets. Adding more FPSets to the set than
		// expected, would screw up the fail over code in reassign() as workers
		// potentially see an inconsistent list of FPSets.
		// This is due to the fact that workers immediately retrieve the
		// FPSetManager once the expected number of FPSets have registered.
		if (fpSets.size() < expectedNumOfServers) {
		        fpSets.add(new FPSets(aFPSet, hostname));
		} else {
		        throw new FPSetManagerException(
		                        "Limit for FPset servers reached (" + expectedNumOfServers
		                                        + "). Cannot handle additional servers");
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/iterator/TLCIterator1Test.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.fp.iterator;

public class TLCIterator1Test extends TLCIteratorTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.iterator.TLCIteratorTest#getBuffer()
	 */
	@Override
	protected long[][] getBuffer() {
		final long[][] buff = new long[8][];
		buff[0] = getArray(8, 1, 8);
		buff[1] = getArray(8, 9, 6);
		buff[2] = null;
		
		buff[3] = new long[4];
		buff[3][0] = -1;
		buff[3][1] = -1;
		buff[3][2] = -1;
		buff[3][3] = -1;
		
		buff[4] = getArray(8, 15, 3);
		buff[5] = null;
		buff[6] = getArray(8, 18, 4);
		buff[7] = null;
		return buff;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/UsageGenerator.java<|end_filename|>
package util;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A helper class to print usage text for a command-line-application in a motif reminiscent of manpages.
 *  
 * In a world where we were not concerned with jar size, i would import Apache Commons CLI and take advantage
 * 	of those classes.
 */
public class UsageGenerator {
	private static final String NAME = "NAME";
	private static final String SYNOPSIS = "SYNOPSIS";
	private static final String DESCRIPTION = "DESCRIPTION";
	private static final String OPTIONS = "OPTIONS";
	private static final String TIPS = "TIPS";
	
	private static Comparator<Argument> NAME_COMPARATOR = new Comparator<Argument>() {
		@Override
		public int compare(final Argument a, final Argument b) {
			return a.getArgumentName().compareTo(b.getArgumentName());
		}
	};
	
	private static Comparator<Argument> NAME_DASH_COMPARATOR = new Comparator<Argument>() {
		@Override
		public int compare(final Argument a, final Argument b) {
			final boolean aDash = a.isDashArgument();
			final boolean bDash = b.isDashArgument();
			
			if (aDash != bDash) {
				return aDash ? -1 : 1;
			}
			
			return a.getArgumentName().compareTo(b.getArgumentName());
		}
	};
	
	
	public static void displayUsage(final PrintStream ps, final String commandName, final String version,
									final String commandShortSummary, final String commandDescription,
									final List<List<Argument>> commandVariants, final List<String> tips,
									final char valuedArgumentsSeparator) {
		ps.println();
		ps.println(generateSectionHeader(NAME));
		ps.println('\t' + commandName + " - " + commandShortSummary
						+ ((version != null) ? (" - " + version) : "") + "\n\n");

		
		final String boldName = markupWord(commandName, true);
		
		
		final HashSet<Argument> arguments = new HashSet<>();
		ps.println(generateSectionHeader(SYNOPSIS));
		for (final List<Argument> variant : commandVariants) {
			ps.println("\t" + generateCommandForVariant(boldName, variant, arguments, valuedArgumentsSeparator));
		}
		ps.println();
		
		
		final String commandNameRegex = commandName + "(\\)|\\s|$)";
		final Pattern p = Pattern.compile(commandNameRegex);
		final Matcher m = p.matcher(commandDescription);
		final String markedUpDescription;
		if (m.find()) {
			final StringBuilder sb = new StringBuilder();
			
			if (m.start() > 0) {
				sb.append(commandDescription.substring(0, m.start()));
			}
			sb.append(boldName).append(m.group(1));
			
			int lastEnd = m.end();
			while (m.find()) {
				sb.append(commandDescription.substring(lastEnd, m.start())).append(boldName).append(m.group(1));
				lastEnd = m.end();
			}
			sb.append(commandDescription.substring(lastEnd, commandDescription.length()));
			
			markedUpDescription = sb.toString();
		} else {
			markedUpDescription = commandDescription;
		}
		
		ps.println(generateSectionHeader(DESCRIPTION));
		ps.println("\t" + markedUpDescription.replaceAll("(\\r\\n|\\r|\\n)", "\n\t"));
		ps.println();
		
		
		final List<Argument> orderedArguments = new ArrayList<>(arguments);
		Collections.sort(orderedArguments, NAME_COMPARATOR);
		ps.println(generateSectionHeader(OPTIONS));
		for (final Argument arg : orderedArguments) {
			if (arg.expectsValue() || arg.isOptional() || (!arg.expectsValue() && arg.isDashArgument())) {
				ps.println(generateOptionText(arg, valuedArgumentsSeparator));
			}
		}
		ps.println();
		
		
		if ((tips != null) && (tips.size() > 0)) {
			ps.println(generateSectionHeader(TIPS));
			for (final String tip : tips) {
				ps.println("\t" + tip.replaceAll("(\\r\\n|\\r|\\n)", "\n\t") + "\n");
			}
		}
	}
	
	private static String generateCommandForVariant(final String boldedCommandName, final List<Argument> variant,
													final HashSet<Argument> arguments,
													final char valuedArgumentsSeparator) {
		final List<Argument> optionalSingleDashValueless = new ArrayList<>();
		final List<Argument> optionalDoubleDashValueless = new ArrayList<>();
		final List<Argument> optionalValued = new ArrayList<>();
		final List<Argument> requiredValued = new ArrayList<>();
		final List<Argument> requiredValueless = new ArrayList<>();
		
		for (final Argument arg : variant) {
			if (arg.expectsValue()) {
				if (arg.isOptional()) {
					optionalValued.add(arg);
				} else {
					requiredValued.add(arg);
				}
			} else {
				if (arg.isOptional()) {
					if (arg.isDashArgument()) {
						optionalSingleDashValueless.add(arg);
					} else if (arg.isDashDashArgument()) {
						optionalDoubleDashValueless.add(arg);
					}
				} else {
					requiredValueless.add(arg);
				}
			}
		}

		Collections.sort(optionalSingleDashValueless, NAME_COMPARATOR);
		Collections.sort(optionalDoubleDashValueless, NAME_COMPARATOR);
		Collections.sort(optionalValued, NAME_COMPARATOR);
		Collections.sort(requiredValued, NAME_COMPARATOR);
		Collections.sort(requiredValueless, NAME_DASH_COMPARATOR);

		final StringBuilder sb = new StringBuilder(boldedCommandName);
		
		if (optionalSingleDashValueless.size() > 0) {
			final StringBuilder concatenation = new StringBuilder("-");
			final List<Argument> nonShortArguments = new ArrayList<>();
			for (final Argument arg : optionalSingleDashValueless) {
				if (arg.isShortArgument()) {
					concatenation.append(arg.getDashlessArgumentName());
				} else {
					nonShortArguments.add(arg);
				}
			}
			if (concatenation.length() > 1) {
				sb.append(" [").append(markupWord(concatenation.toString(), true)).append(']');
			}
			
			for (final Argument arg : nonShortArguments) {
				sb.append(" [").append(markupWord(("-" + arg.getDashlessArgumentName()), true));
				if (arg.hasSubOptions()) {
					sb.append(" [").append(arg.getSubOptions()).append("]");
				}
				sb.append(']');
			}
		}
		
		if (optionalDoubleDashValueless.size() > 0) {
			for (final Argument arg : optionalDoubleDashValueless) {
				sb.append(" [").append(markupWord(arg.getArgumentName(), true));
				if (arg.hasSubOptions()) {
					sb.append(" [").append(arg.getSubOptions()).append("]");
				}
				sb.append(']');
			}
		}
		
		if (optionalValued.size() > 0) {
			for (final Argument arg : optionalValued) {
				sb.append(" [").append(markupWord(arg.getArgumentName(), true)).append(valuedArgumentsSeparator);
				if (arg.hasSubOptions()) {
					sb.append("[").append(arg.getSubOptions()).append("] ");
				}
				sb.append(markupWord(arg.getSampleValue(), false)).append(']');
			}
		}
		
		if (requiredValued.size() > 0) {
			for (final Argument arg : requiredValued) {
				sb.append(" ").append(markupWord(arg.getArgumentName(), true)).append(valuedArgumentsSeparator);
				sb.append(markupWord(arg.getSampleValue(), false));
			}
		}
		
		if (requiredValueless.size() > 0) {
			for (final Argument arg : requiredValueless) {
				sb.append(" ").append(arg.getArgumentName());
				if (arg.hasSubOptions()) {
					sb.append(" [").append(arg.getSubOptions()).append("]");
				}
			}
		}
		
		arguments.addAll(variant);
		
		return sb.toString();
	}
	
	private static String generateOptionText(final Argument argument, final char valuedArgumentsSeparator) {
		final StringBuilder sb = new StringBuilder("\t");

		sb.append(markupWord(argument.getArgumentName(), true));
		if (argument.expectsValue()) {
			sb.append(valuedArgumentsSeparator).append(markupWord(argument.getSampleValue(), false));
		}
		sb.append("\n\t\t").append(argument.getDescription().replaceAll("(\\r\\n|\\r|\\n)", "\n\t\t"));

		return sb.toString();
	}
		
	private static String generateSectionHeader(final String title) {
		final StringBuilder sb = new StringBuilder(markupWord(title, true));
		
		sb.append('\n');
		
		return sb.toString();
	}
	
	/**
	 * @param bold if true, the word will be bolded; false, the word will be italicized
	 */
	private static String markupWord(final String word, final boolean bold) {
		final StringBuilder sb = new StringBuilder(bold ? TLAConstants.ANSI.BOLD_CODE : TLAConstants.ANSI.ITALIC_CODE);
		
		sb.append(word).append(TLAConstants.ANSI.RESET_CODE);
		
		return sb.toString();
	}
	
	
	public static class Argument {
		private final String argumentName;
		private final String sampleValue;
		private final String description;
		private final boolean optional;
		private final String subOptions;
		
		/**
		 * This calls {@code this(key, optionDescription, false);}
		 * 
		 * @param key
		 * @param optionDescription
		 */
		public Argument(final String key, final String optionDescription) {
			this(key, optionDescription, false);
		}
		
		public Argument(final String key, final String optionDescription, final boolean isOptional) {
			this(key, null, optionDescription, isOptional);
		}
		
		/**
		 * This calls {@code this(key, exampleValue, optionDescription, false);}
		 */
		public Argument(final String key, final String exampleValue, final String optionDescription) {
			this(key, exampleValue, optionDescription, false);
		}
		
		public Argument(final String key, final String exampleValue, final String optionDescription,
						final boolean isOptional) {
			this(key, exampleValue, optionDescription, isOptional, null);
		}
		
		public Argument(final String key, final String exampleValue, final String optionDescription,
						final boolean isOptional, final String concatenatedSuboptions) {
			argumentName = key;
			sampleValue = exampleValue;
			description = optionDescription;
			optional = isOptional;
			subOptions = concatenatedSuboptions;
		}
		
		public boolean isOptional() {
			return optional;
		}
		
		public boolean expectsValue() {
			return (sampleValue != null);
		}
		
		/**
		 * @return if the argument name starts with "-", but not "--", this returns true
		 */
		public boolean isDashArgument() {
			return argumentName.startsWith("-") && !isDashDashArgument();
		}
		
		public boolean isDashDashArgument() {
			return argumentName.startsWith("--");
		}
		
		/**
		 * @return true if the argument name is of length 1 (two if this is a dash argument)
		 */
		public boolean isShortArgument() {
			return ((isDashArgument() && (argumentName.length() == 2)) || (argumentName.length() == 1));
		}
		
		public boolean hasSubOptions() {
			return (subOptions != null);
		}

		public String getArgumentName() {
			return argumentName;
		}
		
		/**
		 * @return if {@link #isDashArgument()} returns true, this retuns the argument name without the prefacing dash,
		 * 				otherwise this returns the entire argument name
		 */
		public String getDashlessArgumentName() {
			if (isDashArgument()) {
				return argumentName.substring(1);
			}
			
			return argumentName;
		}

		public String getSampleValue() {
			return sampleValue;
		}

		public String getDescription() {
			return description;
		}
		
		public String getSubOptions() {
			return subOptions;
		}

		@Override
		public int hashCode() {
			return Objects.hash(argumentName);
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj) {
				return true;
			}
			
			if (obj == null) {
				return false;
			}
			
			if (getClass() != obj.getClass()) {
				return false;
			}
			
			final Argument other = (Argument) obj;
			return Objects.equals(argumentName, other.argumentName);
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/FormatComments.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS FormatComments                                                     *
*                                                                          *
* A that provides the following methods having to do with the formating    *
* of comments:                                                             *
*                                                                          *
* WriteComment(writer, vec, commentType, indentOrWidth, tlaMode)           *
*    Writes the comment, which is represented as a vector vec of the       *
*    strings that form the lines of the comment.  The tlaMode argument     *
*    determines if the comments are to be formatted (true), or treated     *
*    as raw LaTeX input (false).                                           *
*                                                                          *
* Initialize                                                               *
*    Initializes the tables used by the methods.                           *
*                                                                          *
* IsWord(str)                                                              *
*    True iff str is in the list of common English words.                  *
*                                                                          *
* isAmbiguous(str)                                                         *
*    True iff str is a built-in symbol that can also appear as             *
*    ordinary punctuation.                                                 *
*                                                                          *
* isRepeatChar(ch)                                                         *
*    True iff ch is a character like "~", a sequence of which is           *
*    treated as a single token.                                            *
*                                                                          *
* getRepeatCharMin(ch)                                                     *
*    If ch is a repeat character, then this is the minimum number of       *
*    ch characters regarded as a single repeated-sequence token.           *
*                                                                          *
* ------------------------------------------------------------------------ *
*                                                                          *
* THINGS POSSIBLY TO CLEAN UP:                                             *
*                                                                          *
* - If "foo" and "bar" are determined not to be TLA tokens, then           *
*   "foo (+) bar" has more space around the (+) than if they were          *
*   TLA tokens.  Should this be fixed?                                     *
*                                                                          *
* - Various built-in symbols should produce different output when          *
*   used in a comment.  What they should produce depends on the            *
*   context.  For example,                                                 *
*                                                                          *
*   * ELSE, LET, and IN  shouldn't have extra space around them            *
*     if they're not part of a TLA expression.  In fact, it might          *
*     be better to type them in Roman, since they could be part            *
*     of a title.                                                          *
*                                                                          *
*   * IN should probably have extra space after it in a TLA expression     *
*     only if it begins the line.                                          *
*                                                                          *
*   At the moment, this doesn't seem worth bothering with.                 *
*                                                                          *
* - The program does a pretty hackish job of formatting shaped             *
*   paragraphs, essentially just starting a new paragraph when it          *
*   thinks the text should start on a new line.  Should we try to do       *
*   some clever alignment, using tabular environments?                     *
*                                                                          *
* - It currently typesets most all-uppercase words like symbols,           *
*   in italics.  Should this be changed so an all upper-case English       *
*   word is typeset in Roman or small caps.  (The latter would             *
*   work reasonably well if the user types "WOMEN IN LOVE", and            *
*   the "IN" is typeset as a TLA built-in symbol.                          *
***************************************************************************/
package tla2tex;
import java.util.Hashtable;
import java.util.Vector;

public final class FormatComments
{ public static void WriteComment(OutputFileWriter writer, 
                                  Vector           vec, 
                                  int              commentType,
                                  float            indentOrWidth,
                                  boolean          tlaMode )
    /***********************************************************************
    * Writes the comment to the writer.                                    *
    *                                                                      *
    *    vec: A vector of the strings that form the lines of the           *
    *         comment.                                                     *
    *                                                                      *
    *    commentType: The type of comment.                                 *
    *                                                                      *
    *    indentOrWidth: For a multi-line comment, either the               *
    *      amount it is to be indented, or its width, depending            *
    *      on the commentType.                                             *
    *                                                                      *
    *                                                                      *
    * The possible commentTypes, and the meaning of the indentOrWidth      *
    * argument for them, is as follows:                                    *
    *                                                                      *
    *   ONE_LINE                                                           *
    *     A one-line comment typeset in LR mode.  The other arguments      *
    *     are ignored.  For this commentType, the com argument must have   *
    *     at most one line.                                                *
    *                                                                      *
    *   ZERO_WIDTH                                                         *
    *     Like ONE-LINE, except it is typeset as a zero-width box.         *
    *                                                                      *
    *   PAR                                                                *
    *     A multi-line comment typeset in paragraph mode as a              *
    *     sequence of paragraphs indented indentOrWidth points             *
    *     from the left margin using the LaTeXCommentPar                   *
    *     environment.  However, if indentOrWidth < -1,                    *
    *     then the indentation is determined by the minimum                *
    *     number of spaces at the beginning of lines.                      *
    *                                                                      *
    *   RIGHT_MULTI                                                        *
    *     A multi-line comment typeset as a zero-depth box                 *
    *     of width indentOrWidth points, using the                         *
    *     LaTeXRightMultiLineComment environment.                          *
    *                                                                      *
    * The tlaMode argument is true iff this is called for the tlatex.TLA   *
    * program; it is false if called for the tlatex.TeX program.           *
    *                                                                      *
    * This will start writing on a new line, so the caller must be careful *
    * to end the previous output line with a "%" if necessary to avoid     *
    * adding an unwanted space in the TeX output.                          *
    ***********************************************************************/
    { 
      /*********************************************************************
      * Tokenize the comment.                                              *
      *********************************************************************/
      CToken[][] tokens = null ;
      if(tlaMode)
        { tokens = TokenizeComment.Tokenize(vec);
        }
      else
        { tokens = TokenizeComment.TeXTokenize(vec);
        } ;

      if (tokens == null) { return; };
        /*******************************************************************
        * Return if called with a null comment (one having no lines).      *
        * This can happen if the input contains a (*******) not followed   *
        * by any aligned comment lines, in which case the (*****) becomes  *
        * a BEGIN_MULTI token with no following MULTI or NULL token.       *
        *******************************************************************/
      CToken.FindPfStepCTokens(tokens) ;
// INSERT here code to create PFLEVELNUM tokens in the array `tokens'
// Debug.print2DArray(tokens, "comtok");
        
      /*********************************************************************
      * Try to determine which of the tokens should be formated as         *
      * symbols.                                                           *
      *********************************************************************/
      if(tlaMode)
        { adjustIsTLA(tokens) ;
        } ;

      /*********************************************************************
      * Write out the comment.                                             *
      *********************************************************************/
      InnerWriteComment(writer, tokens, commentType, indentOrWidth);
    }

  
/* ------------------------ THE HASH TABLES ------------------------------ */

  public static void Initialize ()
    /***********************************************************************
    * Initializes the hash tables.                                         *
    ***********************************************************************/
    { ReadWordFile();
      InitializeAmbiguousHashtable();
      InitializeRepeatCharHashtable();
      InitializeAlignTokenHashtable();
    }


  private static String nullString = ""; 
    /***********************************************************************
    * Often, we want a hashtable that just keeps a bunch of keys, without  *
    * associating a value to the key.  But a Java hashtable entry needs a  *
    * value, which must be an object.  A string is an object, so a simple  *
    * null value is the empty string "".  However, if we just use "" as    *
    * the value, then Java creates a new object each time.  By using       *
    * nullString, there's just one object and lots of pointers to it.      *
    ***********************************************************************/
    

  /* ---------------------- THE word HASH TABLE ------------------------- */

  private static Hashtable wordHashTable  = new Hashtable(100000);
    /***********************************************************************
    * A hashtable of all common English words.                             *
    ***********************************************************************/

  public static boolean IsWord(String str) 
      /*********************************************************************
      * Returns true iff str is a common English word.                     *
      *********************************************************************/
      { return null !=  wordHashTable.get(str);
      } ;   

  private static void ReadWordFile()
    /***********************************************************************
    * Reads in the WordFile and puts its contents in wordHashTable.        *
    ***********************************************************************/
    { 
      ResourceFileReader wordFileReader
                     = new ResourceFileReader(Parameters.WordFile);

      String word = wordFileReader.getLine();
      while (word != null)
        { wordHashTable.put(word, nullString);
          wordHashTable.put(word.substring(0,1).toUpperCase() 
                                + word.substring(1), new String());
          word = wordFileReader.getLine() ;
        } ;
      wordFileReader.close();
    } ;


  /* -------------------- THE ambiguous HASH TABLE ---------------------- */

  private static Hashtable ambiguousHashTable  = new Hashtable(100);
    /***********************************************************************
    * A hashtable of all built-in symbols that can appear as ordinary      *
    * punctuation.  The entry for a symbol is the TeX string that          *
    * produces it.  (That string need work only outside math mode.)        *
    ***********************************************************************/

  public static boolean isAmbiguous(String str) 
    /***********************************************************************
    * Returns true iff str is a built-in symbol that can also appear as    *
    * ordinary punctuation.                                                *
    ***********************************************************************/
      { return null !=  ambiguousHashTable.get(str);
      } ;   

  private static String getAmbiguous(String str) 
    /***********************************************************************
    * Returns the true non-TLA TeX string for an ambiguous symbol.         *
    ***********************************************************************/
      { return (String) ambiguousHashTable.get(str);
      } ;   

  private static void add(String tla, String tex)
    /***********************************************************************
    * Adds an entry to the ambiguousHashTable.                             *
    ***********************************************************************/
    { ambiguousHashTable.put(tla, tex); } ;


  private static void InitializeAmbiguousHashtable()
    /***********************************************************************
    * Initializes the hash-table of ambiguous built-in symbols.            *
    ***********************************************************************/
    { add("_",    "\\_");
      add("(",    "(");
      add("[",    "[");
      add(")",    ")");
      add("]",    "]");
      add("~",    "\\ensuremath{\\sim}");
      add("'",    "\\mbox{'}");
      add("-",    "-");
      add("+",    "+");
      add("*",    "*");
      add("/",    "/");
      add("&",    "\\&");
      add("#",    "\\#");
      add(":",    ":");
      add("...",  "\\.{\\dots}");
      add("$",    "\\.{\\$}");
      add("?",    "\\.{?}");
      add("??",   "\\.{??}");
      add("%",    "\\.{\\%}");
      add("!!",   "\\.{!!}");
      add(",",    ",");
      add("!",    "!");
      add(".",    ".");
      add("@",    "@");
      add("--",   "--");
    } 

  /* -------------------- THE repeatChar HASH TABLE --------------------- */

  private static Hashtable repeatCharHashTable  = new Hashtable(100);
    /***********************************************************************
    * A hashtable of all characters that can be repeated to make some      *
    * sort of "dash", for example writing "==========".  We should define  *
    * a new object type for the entries.  However, to avoid the hassle,    *
    * we just let the entry be a Symbol object, where the fields have the  *
    * following meaning.                                                   *
    *                                                                      *
    *     TeXString  : A command \foo such that \foo{n} produces           *
    *                  the output for a string of n of the characters.     *
    *                  It equals "" if the TeXified characters themselves  *
    *                  should be used.                                     *
    *                                                                      *
    *     symbolType : The minimum number of characters needed             *
    *                  to qualify as a REP_CHAR CToken.                    *
    ***********************************************************************/

  public static boolean isRepeatChar(char ch) 
    /***********************************************************************
    * Returns true iff ch is a repeatable char.                            *
    ***********************************************************************/
      { return null !=  repeatCharHashTable.get("" + ch);
      } ;   

  private static String getRepeatCharCommand(char ch) 
    /***********************************************************************
    * Returns the command \foo such that \foo{n} produces the output for   *
    * a string of n ch characters, or "" if Misc.TeXify(the string of n    *
    * ch's) should be output.                                              *
    ***********************************************************************/
      { return ((Symbol) repeatCharHashTable.get("" + ch)).TeXString ;
      } ;   

  public static int getRepeatCharMin(char ch) 
    /***********************************************************************
    * Returns the minimum number of ch characters that constitutes a       *
    * REPEATED_CHAR CToken.                                                *
    ***********************************************************************/
      { return ((Symbol) repeatCharHashTable.get("" + ch)).symbolType ;
      } ;   

  private static void addRepeatChar(char ch, String tex, int min)
    /***********************************************************************
    * Adds an entry to the RepeatCharHashTable.                             *
    ***********************************************************************/
    { repeatCharHashTable.put("" + ch, 
                              new Symbol("", tex, min, 0));
    } ;

  private static void InitializeRepeatCharHashtable()
    { 
      addRepeatChar('-', "\\cdash", 3);
      addRepeatChar('=', "\\ceqdash", 3) ;
      addRepeatChar('^', "", 3) ;
      addRepeatChar('#', "", 3) ;
      addRepeatChar('_', "\\usdash", 2) ;
      addRepeatChar('~', "\\tdash", 2) ;
      addRepeatChar('*', "", 3) ;
      addRepeatChar('.', "", 4) ;
      addRepeatChar('+', "", 3) ;
    } ;


  /* -------------------- THE alignToken HASH TABLE --------------------- */

  private static Hashtable alignTokenHashTable  = new Hashtable(100);
    /***********************************************************************
    * A hashtable of all alignment tokens.  An alignment token t is one    *
    * such that, if two successive lines in a comment have t in the same   *
    * column, then those lines are considered to be aligned.  (Currently,  *
    * that alignment just causes the lines to begin separate paragraphs.)  *
    ***********************************************************************/

  private static boolean isAlignToken(String str)
    /***********************************************************************
    * Returns true iff str is (the string representation of) an alignment  *
    * comment token.                                                       *
    ***********************************************************************/
      { return null !=  alignTokenHashTable.get(str);
      } ;   

  private static void addAlignToken(String str)
    /***********************************************************************
    * Adds an entry to the alignTokenHashTable.                             *
    ***********************************************************************/
    { alignTokenHashTable.put(str, nullString);
    } ;

  private static void InitializeAlignTokenHashtable()
    /***********************************************************************
    * Sets the AlignToken hash table.  The idea is to consider a built-in  *
    * symbol to be an alignment token unless it seems likely that it will  *
    * lead to spurious alignments in ordinary text.                        *
    ***********************************************************************/
    {   addAlignToken("=>");
        addAlignToken("\\cdot");
        addAlignToken("<=>");
        addAlignToken("\\equiv");
        addAlignToken("~>");
        addAlignToken("-+->");
        addAlignToken("\\ll");
        addAlignToken("\\gg");
        addAlignToken("\\");
        addAlignToken("\\cap");
        addAlignToken("\\intersect");
        addAlignToken("\\cup");
        addAlignToken("\\union");
        addAlignToken("/\\");
        addAlignToken("\\/");
        addAlignToken("\\land");
        addAlignToken("\\lor");
        addAlignToken("\\X");
        addAlignToken("-");
        addAlignToken("+");
        addAlignToken("*");
        addAlignToken("^");
        addAlignToken("|");
        addAlignToken("||");
        addAlignToken("&");
        addAlignToken("&&");
        addAlignToken("++");
        addAlignToken("--");
        addAlignToken("**");
        addAlignToken("^^");
        addAlignToken("|-");
        addAlignToken("|=");
        addAlignToken("-|");
        addAlignToken("=|");
        addAlignToken("<:");
        addAlignToken(":>");
        addAlignToken(":=");
        addAlignToken("::=");
        addAlignToken("(+)");
        addAlignToken("(-)");
        addAlignToken("\\oplus");
        addAlignToken("\\ominus");
        addAlignToken("(.)");
        addAlignToken("\\odot");
        addAlignToken("(/)");
        addAlignToken("\\oslash");
        addAlignToken("(\\X)");
        addAlignToken("\\otimes");
        addAlignToken("\\uplus");
        addAlignToken("\\sqcap");
        addAlignToken("\\sqcup");
        addAlignToken("\\div");
        addAlignToken("\\star");
        addAlignToken("\\o");
        addAlignToken("\\circ");
        addAlignToken("\\bigcirc");
        addAlignToken("\\bullet");
        addAlignToken("\\in");
        addAlignToken("\\notin");
        addAlignToken("=");
        addAlignToken("#");
        addAlignToken("/=");
        addAlignToken("<");
        addAlignToken(">");
        addAlignToken("=<");
        addAlignToken(">=");
        addAlignToken("\\prec");
        addAlignToken("\\succ");
        addAlignToken("\\preceq");
        addAlignToken("\\succeq");
        addAlignToken("\\sim");
        addAlignToken("\\simeq");
        addAlignToken("\\approx");
        addAlignToken("\\doteq");
        addAlignToken("\\asymp");
        addAlignToken("\\sqsubset");
        addAlignToken("\\sqsupset");
        addAlignToken("\\sqsubseteq");
        addAlignToken("\\sqsupseteq");
        addAlignToken("\\propto");
        addAlignToken(":");
        addAlignToken("->");
        addAlignToken("|->");
        addAlignToken("<-");
        addAlignToken("==");
        addAlignToken("ELSE");
        addAlignToken("THEN");
        addAlignToken("LET");
        addAlignToken("IN");
        addAlignToken("[]");
        addAlignToken("..");
        addAlignToken("...");
        addAlignToken("$");
        addAlignToken("$$");
        addAlignToken("%");
        addAlignToken("%%");
        addAlignToken("##");
        addAlignToken("@@");
        addAlignToken("\\times");
        addAlignToken("\\leq");
        addAlignToken("\\geq");
        addAlignToken("\\mod");
        addAlignToken("\\wr");
        addAlignToken("\\cong");
        addAlignToken("-.");
        addAlignToken("@");

    } ;


/* ---------------------- MISCELLANEOUS METHODS ------------------------- */

  private static boolean 
      PossibleAlignment(CToken[][] com, int line, int itemNo)
    /***********************************************************************
    * True iff the token at com[line][item] is a candidate for an          *
    * word-alignment position.                                             *
    *                                                                      *
    *   Precondition: 0 < itemNo                                           *
    ***********************************************************************/
    { 
      return          (com[line][itemNo].column >
                         com[line][itemNo  - 1].column + 
                            com[line][itemNo - 1].getWidth() + 1)
                   || (   (com[line][itemNo].column >
                             com[line][itemNo - 1].column + 
                               com[line][itemNo - 1].getWidth())
                       && (com[line][itemNo - 1].type == CToken.BUILTIN)
                       && ! com[line][itemNo - 1].string.equals(".") 
                       && ! com[line][itemNo - 1].string.equals(",")) ;
    }

    
  private static CToken nextCToken(CToken[][] com, int line, int item)
    /***********************************************************************
    * The CToken following com[line][item].  However, if item is the last  *
    * one the line, then it equals a null Token (one with type NULL) if    *
    * the following line is blank, or the null value if this is the last   *
    * line.                                                                *
    ***********************************************************************/
    { if (item + 1 < com[line].length)
       { return com[line][item+1];
       }
      else
       { if (   (line + 1 < com.length)
             && (com[line + 1].length != 0)) 
           {return com[line + 1][0];}
       } ;
      return CToken.nullCToken ;
    }     


  private static CToken previousCToken(CToken[][] com, int line, int item)
    /***********************************************************************
    * The CToken preceding com[line][item].  However, if item is the       *
    * first one on the line, then it equals a null Token (one with type    *
    * NULL) if the previous line is blank, or the null value if this is    *
    * the first line.                                                      *
    ***********************************************************************/
    { if (item > 0)
       { return com[line][item - 1];
       }
      else
       { if (   (line > 0)
             && (com[line - 1].length != 0))
           {return com[line - 1][com[line - 1].length - 1];}
       } ;
      return CToken.nullCToken ;
    }     

  private static boolean isPreviousAdjacent(CToken[][] com, int line, int item)
    /***********************************************************************
    * True iff the token preceding the one at position (line, item) is     *
    * adjacent to the token at (line, item), with no intervening spaces.   *
    ***********************************************************************/
    { return    (item > 0)
             && (com[line][item-1].column + 
                   com[line][item-1].getWidth() == com[line][item].column) ;
    }
    

  

  private static boolean isNextAdjacent(CToken[][] com, int line, int item)
    /***********************************************************************
    * True iff the token following the one at position (line, item) is     *
    * adjacent to the token at (line, item), with no intervening spaces.   *
    ***********************************************************************/
    { return    (item + 1 < com[line].length)
             && (com[line][item].column + 
                   com[line][item].getWidth() == com[line][item+1].column) ;
    }
    


/* --------------------- THE adjustIsTLA METHODS ------------------------ */

  public static void adjustIsTLA(CToken[][] com)
    /***********************************************************************
    * Called after creating com with TokenizeComment.  That method sets    *
    * the isTLA field of tokens it determines to be TLA tokens (ones       *
    * typeset in math mode), and sets the isAmbiguous field of tokens      *
    * that might be TLA tokens.  The adjustIsTLA method decides which      *
    * ambiguous tokens should become TLA tokens.                           *
    ***********************************************************************/
    {int line = 0;
     int item = 0;
     CToken tok  = null ;
     CToken ptok = null ;
     CToken ntok = null ;
     /**********************************************************************
     * Check for the following special cases.                              *
     *  - a "'" token is immediately followed by an IDENT.                 *
     *  - a "-" token is either:                                           *
     *     * Ends the line and is immediately preceded by an IDENT id1     *
     *     * Is immediately preceded by an IDENT and immediately           *
     *       followed by an IDENT that are not both TLA tokenS.            *
     * - a "+" token immediately following "TLA".                          *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        {tok = com[line][item];
         if (!tok.isTLA)
          { ptok = previousCToken(com, line, item) ;
            ntok = nextCToken(com, line, item) ;

            if(tok.string.equals("'"))
             { if (   (isNextAdjacent(com, line, item))
                   && (ntok.type == CToken.IDENT))
                 { tok.isAmbiguous = false ;
                   ntok.isAmbiguous = false ;
                   ntok.isTLA = false ; 
                 };
             } ;

            if(tok.string.equals("-"))
             { if(isPreviousAdjacent(com, line, item))
                { if (   (item == com[line].length - 1)
                      && (ptok.type == CToken.IDENT)
                      && (! ptok.isTLA) )
                    { tok.isAmbiguous = false ;
                      ptok.isAmbiguous = false ;
                    };
                  
                  if (   (isNextAdjacent(com, line, item))
                      && (ntok.type == CToken.IDENT)
                      && (  (! ntok.isTLA) 
                          ||(! ptok.isTLA) ))
                    { tok.isAmbiguous = false ;
                      ptok.isAmbiguous = false ;
                      ntok.isAmbiguous = false ;
                    };
                } 
             }

            if(   (tok.string.equals("+"))
               && isPreviousAdjacent(com, line, item)
               && ptok.string.equals("TLA"))
             { tok.isAmbiguous = false ;
               ptok.isAmbiguous = false ;
             };
           };
         item = item + 1;
        };                   // END while (item < ...)
       line = line + 1;
      } ;                    // END while (line < ...)


     /**********************************************************************
     * Set the isTLA field true in the following cases:                    *
     *                                                                     *
     *  - If an IDENT immediately follows a "." (with no space),           *
     *    set true for Ident and ".".  If the "." is also                  *
     *    immediately preceded by a token (with no intervening space),     *
     *    set true for that token too.                                     *
     *                                                                     *
     *  - If a "(" or "[" immediately follows a token (with no space),     *
     *    set true for it and the preceding token.                         *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        {
         tok  = com[line][item] ;
         if(   (tok.string.equals("."))
            && isNextAdjacent(com, line, item)
            && (com[line][item + 1].type == CToken.IDENT))
           { tok.isTLA  = true ;
             com[line][item + 1].isTLA = true ;
             if (isPreviousAdjacent(com, line, item))
               { com[line][item - 1].isTLA = true ;
               }
           }
         else
           { if (   (   (tok.string.equals("("))
                     || (tok.string.equals("[")))
                 && isPreviousAdjacent(com, line, item))
              { tok.isTLA = true ;
                com[line][item - 1].isTLA = true ;
              }
           } ;
         item = item + 1;
        }
       line = line + 1;
      } ;    // END while


     /**********************************************************************
     * Set the isTLA field for any ambiguous IDENT that is NOT either      *
     *                                                                     *
     *     (i) All lower-case or                                           *
     *                                                                     *
     *    (ii) All-upper case whose lower-case form is in the dictionary.  *
     *                                                                     *
     *   (iii) All letters with the first letter capitalized that either   *
     *           (a) follows a ".", "(", ")", double-quote, or two or      *
     *               more spaces, or                                       *
     *           (b) is the first token of the line.                       *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        { tok = com[line][item] ;
          ptok = previousCToken(com, line, item);
          String tstr = tok.string;
          if (   (tok.type == CToken.IDENT)
              && tok.isAmbiguous
              && ! (   Misc.IsLowerCase(tstr)
                    || (   Misc.IsUpperCase(tstr)
                        && IsWord(tstr.toLowerCase()))
                    || (   Misc.IsCapitalized(tstr)
                        && (   (item == 0)
                            || ptok.string.equals(".")
                            || ptok.string.equals("(")
                            || ptok.string.equals(")")
                            || (ptok.type == CToken.RIGHT_DQUOTE)
                            || (ptok.type == CToken.LEFT_DQUOTE)
                            || (ptok.column + ptok.getWidth() 
                                  <= tok.column - 2 )))))
            { tok.isTLA = true; }
            
         item = item + 1;
        }
       line = line + 1;
      } ;    // END while

     /**********************************************************************
     * We now catch anomalies like "CONSTANT DECLARATIONS", to turn the    *
     * "CONSTANT" from a BUILTIN token to an IDENT. We do this if the      *
     * BUILTIN is an upper-case word and is adjacent to an upper-case      *
     * IDENT.                                                              *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;     
       while (item < com[line].length)
        { tok = com[line][item] ;
          if (   (tok.type == CToken.BUILTIN)
              && Misc.IsUpperCase(tok.string)
              && (   (   (item > 0)
                      && (com[line][item-1].type == CToken.IDENT)
                      && ! com[line][item-1].isTLA
                      && Misc.IsUpperCase(com[line][item-1].string))
                  || (   (item + 1 < com[line].length)
                      && (com[line][item+1].type == CToken.IDENT)
                      && ! com[line][item+1].isTLA
                      && Misc.IsUpperCase(com[line][item+1].string))))
            { tok.type = CToken.IDENT;
              tok.isTLA = false;
            } ;
  
          item = item + 1;
        }
       line = line + 1;
      } ;      
       
     /**********************************************************************
     * For each built-in symbol of type LEFT_PAREN whose isTLA field is    *
     * true, set the isTLA field true of every token through the next      *
     * matching RIGHT_PAREN, "]_", or next blank line.                     *
     **********************************************************************/
     int parenLevel = 0 ;
       /********************************************************************
       * The number of levels deep within a LEFT_PAREN token with isTLA =  *
       * true.                                                             *
       ********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       if (com.length == 0) 
        { parenLevel = 0 ; } ;
       while (item < com[line].length)
        {
         tok  = com[line][item] ;
         if (parenLevel > 0)
          { tok.isTLA = true; } ;

         if (   (tok.type == CToken.BUILTIN)
             && (BuiltInSymbols.GetBuiltInSymbol(tok.string, true).symbolType
                   == Symbol.LEFT_PAREN)
             && (   (parenLevel > 0)
                 || tok.isTLA))
          { parenLevel = parenLevel + 1; }

         else
          { if (   (tok.type == CToken.BUILTIN)
                && (  (BuiltInSymbols.GetBuiltInSymbol(tok.string, true).symbolType
                         == Symbol.RIGHT_PAREN)
                    || tok.string.equals("]_"))
                && (parenLevel > 0) )
             { parenLevel = parenLevel - 1; };
          };
         item = item + 1;
        }

       line = line + 1;
      }     

     /**********************************************************************
     * Try to resolve ambiguous tokens based on what's next to them,       *
     * using the following rules:                                          *
     *                                                                     *
     *  - Set isTLA true for an ambiguous IDENT if it is preceded by       *
     *    an INFIX or PREFIX operator or is followed by a POSTFIX          *
     *    operator--or if the -tlaComment option is chosen.                *
     *                                                                     *
     *  - Set isTLA true for an ambiguous INFIX operator if it is          *
     *    preceded or followed by an isTLA or ambiguous token.             *
     *                                                                     *
     *  - Set isTLA true for an ambiguous PREFIX/POSTFIX operator          *
     *    if it is followed/preceded by an isTLA or ambiguous token.       *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        {tok  = com[line][item] ;
         ptok = previousCToken(com, line, item);
         ntok = nextCToken(com, line, item);
         if ( (! tok.isTLA) && tok.isAmbiguous)
          { switch (tok.type)
             {case CToken.IDENT  :
              case CToken.NUMBER :
                if (Parameters.TLACommentOption)
                 { tok.isTLA = true ;
                 }
                else
                 {
                   if (ptok.type == CToken.BUILTIN)
                    {int stype = 
                      BuiltInSymbols.GetBuiltInSymbol(ptok.string, true).symbolType;
                      if (   (   (stype == Symbol.INFIX)
                              || (stype == Symbol.PREFIX))
                          && ( ptok.isTLA || ptok.isAmbiguous))
                       { tok.isTLA = true ;
                         ptok.isTLA = true ;
                       }
                    } ;
                  } ;
                if (ntok.type == CToken.BUILTIN)
                 {int stype = 
                   BuiltInSymbols.GetBuiltInSymbol(ntok.string, true).symbolType;
                   if (   (   (stype == Symbol.INFIX)
                           || (stype == Symbol.POSTFIX))
                       && ( ntok.isTLA || ntok.isAmbiguous))
                    { tok.isTLA = true ;
                      ntok.isTLA = true ;
                    }
                 } ;
                break;
              case CToken.BUILTIN  :
                int stype = 
                     BuiltInSymbols.GetBuiltInSymbol(tok.string, true).symbolType;
                if (   (   (stype == Symbol.PREFIX)
                        || (stype == Symbol.INFIX) )
                    && ( ntok.isTLA || ntok.isAmbiguous))
                 { tok.isTLA = true ;
                   ntok.isTLA = true ;
                 } ;
                if (   (   (stype == Symbol.INFIX) 
                        || (stype == Symbol.POSTFIX))
                    && ( ptok.isTLA || ptok.isAmbiguous))
                 { tok.isTLA = true ;
                   ptok.isTLA = true ;
                 } ;
                break;
              default :
                Debug.ReportBug("FormatComments.adjustIsTLA: "
                  + "ambiguous CToken of wrong type");
             }
          }
         item = item + 1;
        }

       line = line + 1;
      }     

     /**********************************************************************
     * For each ambiguous IDENT token, set it to be a TLA token if it      *
     * occurs anywhere in the comment as a TLA token and is not a word.    *
     **********************************************************************/
     
     /**********************************************************************
     * Set thisCommentTLA to be a hash table of all TLA IDENT tokens.      *
     **********************************************************************/
     Hashtable thisCommentTLA  = new Hashtable(100);     
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        {tok = com[line][item];
         if (   (tok.type == CToken.IDENT)
             && tok.isTLA)
          { thisCommentTLA.put(tok.string, nullString);
          }
         item = item + 1;
        }
       line = line + 1;
      }  

     /**********************************************************************
     * Set all the ambiguous IDENTs that are in thisCommentTLA to TLA      *
     * tokens..                                                            *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        { tok = com[line][item];
          if (   (tok.isAmbiguous)
              && (! IsWord(tok.string))
              && null != thisCommentTLA.get(tok.string))
            { tok.isTLA = true; }
          item = item + 1;
        }
       line = line + 1;
      }  

     /**********************************************************************
     * We now set the isTLA field false for any VERB and TEX token.  (The  *
     * field can get set for these tokens by bizarre inputs, and it's      *
     * easier to just reset them here than worry about it in the code      *
     * above.)                                                             *
     **********************************************************************/
     line = 0 ;
     while (line < com.length)
      {item = 0 ;
       while (item < com[line].length)
        { tok = com[line][item];
          if (   (tok.type == CToken.VERB)
              || (tok.type == CToken.TEX))
            { tok.isTLA = false; }
          item = item + 1;
        }
       line = line + 1;
      }  

    }                       // END public static void adjustIsTLA


/* ------------------- THE InnerWriteComment METHOD --------------------- */

  private static boolean IsTLALine(CToken[] tokLine)
    /***********************************************************************
    * Returns true iff every token in tokLine is a TLA token.              *
    ***********************************************************************/
    { boolean result = true ;
      int i = 0;
      while ( result && (i < tokLine.length))
        { result = tokLine[i].isTLA ;
          i = i + 1;
        } ;
      return result ;
    } 
    
  private static void InnerWriteComment(OutputFileWriter writer, 
                                        CToken[][]       com, 
                                        int              commentType,
                                        float            indentOrWidth)
   /************************************************************************
   * This does the actual writing of the output for the WriteComment       *
   * method.                                                               *
   ************************************************************************/
   { // BEGIN InnerWriteComment(...)

  /*************************************************************************
  * PARAGRAPH SHAPING                                                      *
  *                                                                        *
  * Paragraph shaping is defined by the following rules, where the         *
  * prevailing (left) margin is initially the left-most column occupied by *
  * a token.  The EDGE of a line is the column of its left-most token.     *
  *                                                                        *
  * Two paragraphs need not have a blank line between them.  If they       *
  * don't, then there is no vertical space between them.                   *
  *                                                                        *
  * If line i begins a paragraph, then it is a one-line paragraph if it    *
  * consists entirely of TLA tokens, it is aligned in some way with the    *
  * following line, or the following line is indented less than it is.     *
  * Otherwise, its paragraph ends with either the first blank line, or     *
  * the first line whose left edge is different from the left edge of the  *
  * paragraph's SECOND line.                                               *
  *                                                                        *
  * The prevailing margin at the start of a paragraph is the most recent   *
  * prevailing margin that is at or to the left of the left-most edge of   *
  * the lines of the paragraph.  For example, if the prevailing margin     *
  * after each paragraph iiiiii is at its left edge, then the prevailing   *
  * margin at the start of 3333 in                                         *
  *     1111                                                               *
  *        2222                                                            *
  *       3333                                                             *
  * is the edge of 1111.                                                   *
  *                                                                        *
  * The prevailing margin after the paragraph is the edge of the           *
  * paragraph's SECOND line--or its first if it only has one line.  (Hence *
  * the new prevailing margin is always \geq the old prevailing margin.)   *
  *                                                                        *
  * The shape of the paragraph is determined according to these two        *
  * cases, where d is the distance between the new and old prevailing      *
  * left margins.                                                          *
  *                                                                        *
  * - Edge of line 1 = Edge of line 2:                                     *
  *      old margin ->|    111111                                          *
  *                        222222                                          *
  *           new margin ->|                                               *
  *                                                                        *
  * d is determined by number of columns between old margin and line 1.    *
  * A single-line paragraph is also shaped in this way.                    *
  *                                                                        *
  * - Edge of line 1 to left of Edge of line 2:                            *
  *   If the edge of line 2 aligns with the beginning of a                 *
  *   token in line 1, then this is a labeled paragraph                    *
  *                                                                        *
  *      old margin ->|    111 111                                         *
  *                            222222                                      *
  *               new margin ->|                                           *
  *                                                                        *
  *   where line 2 is aligned with the token, and the space to the         *
  *   left of the label and between the label and the rest of line 1       *
  *   is determined by the number of spaces in the input.  Otherwise,      *
  *                                                                        *
  *      old margin ->|    111111                                          *
  *                            222222                                      *
  *               new margin ->|                                           *
  *                                                                        *
  *   Where the indentations of line 1 and of line 2 are determined by     *
  *   the number of columns of indentation in the input.                   *
  *                                                                        *
  *************************************************************************/
    int[] lineType    = new int[com.length];
    String[] parStart = new String [com.length];
      /*********************************************************************
      * These arrays determine the paragraph shape of the comment.  The    *
      * value of lineType[i] has the following meaning:                    *
      *                                                                    *
      *    -2 : A blank line.                                              *
      *                                                                    *
      *    -1 : A non-blank line that does not begin a paragraph.          *
      *                                                                    *
      *     0 : A non-blank line that begins an unlabeled paragraph        *
      *                                                                    *
      *   > 0 : A non-blank line that begins a labeled paragraph.  In this *
      *         case, the first lineType[i] tokens of the line form        *
      *         the paragraph's label.                                     *
      *                                                                    *
      * If lineType[i] = 0, then parStart[i] is the "\begin{...}" command  *
      * that begins the paragraph.  If lineType[i] > 0, it's the command   *
      * "\begin...{", which must then be followed by the label and the     *
      * closing "}"                                                        *
      *                                                                    *
      * For a one-line comment, they are arrays of length 1 with           *
      * lineType[0] = -1                                                   *
      *                                                                    *
      * Invariant :                                                        *
      *    (lineType[i] > 0) => (lineType[i] + 1 < com[i].length)          *
      *                                                                    *
      * In other words, there are always more than lineType[i] tokens      *
      * on a non-blank line.                                               *
      *********************************************************************/

      /*********************************************************************
      * We first set oneLine[i] to be true iff line i is a one-line        *
      * paragraph.  This is the case if either:                            *
      *                                                                    *
      *  1. It is a line of all TLA tokens.                                *
      *                                                                    *
      *  2. There is an alignment or REP_CHAR token tok in this            *
      *     line aligned with an identical token in the next line,         *
      *     where tok is not immediately adjacent to the tokens on         *
      *     both sides.  Moreover, in this case, the following line is     *
      *     also a one-line par if the line after it is outdented from     *
      *     it.  In this case, we also mark the following line as a        *
      *     one-line paragraph if it ends the paragraph--that is, if it    *
      *     is followed by a blank line or ends the comment.               *
      *********************************************************************/
      boolean[] oneLine = new boolean[com.length] ;

      boolean thisAligned = false ;
      boolean prevAligned = false;
        /*******************************************************************
        * True iff this or the previous line was aligned (case 2).         *
        *******************************************************************/
      int line = 0 ;
      while (line < com.length)
       { thisAligned = false ;
         if (   (line + 1 < com.length)
             && (com[line+1].length != 0) )
          { int m = 0 ;
            int n = 0 ;
            int lastn = com[line+1].length ;
            while (   !thisAligned
                   && (m < com[line].length)
                   && (com[line][m].column <= com[line+1][lastn-1].column))
             {CToken mtok = com[line][m] ;
              if (   (   isAlignToken(mtok.string)
                      || (mtok.type == CToken.REP_CHAR))
                  && ! (   isPreviousAdjacent(com, line, m)
                        && isNextAdjacent(com, line, m)))
               {while (   !thisAligned
                       && (n < lastn)
                       && (mtok.column >= com[line+1][n].column))
                {CToken ntok = com[line+1][n] ;
                 if (   (mtok.column == ntok.column)
                     && (mtok.string.equals(ntok.string))
                     && ! (   isPreviousAdjacent(com, line+1, n)
                           && isNextAdjacent(com, line+1, n)))
                  { thisAligned = true;
                  } ;
                 n = n+1 ;
                } ;              
               }
               m = m + 1;
             }
           };
         oneLine[line] =    thisAligned 
                         || IsTLALine(com[line])
                         || (   prevAligned
                             && (line + 1 < com.length)
                             && (com[line + 1].length > 0)
                             && (com[line][0].column 
                                    > com[line + 1][0].column)) ;
         if (   (thisAligned)
             && (   (line + 2 == com.length)
                 || (com[line + 2].length == 0)))
          { oneLine[line + 1] = true ; } ;

         prevAligned = thisAligned ;
         line = line + 1;
       } ;

    /***********************************************************************
    * Now we look for successive lines that begin with the same token.     *
    * If there are n successive lines beginning with the same token that   *
    * is not a short (fewer than 4-character) or unambiguous lower-case    *
    * word we make the first n-1 of them one-line paragraphs.  If the      *
    * n-th is the end of a paragraph, we make it a one-line paragraph      *
    * too.                                                                 *
    ***********************************************************************/
    line = 0;
    while (line + 1 < com.length)    
     { if (com[line].length != 0)
         { CToken tok = com[line][0] ;
           if (   (com[line+1].length != 0)
               && tok.string.equals(com[line+1][0].string)
               && (   (tok.type != CToken.IDENT)
                   || (  (tok.string.length() >= 4)
                       && tok.isAmbiguous)
                   || tok.isTLA )
               && (tok.isTLA == com[line+1][0].isTLA))
                    /*******************************************************
                    * We might get lucky and avoid a chance alignment      *
                    * with this condition.                                 *
                    *******************************************************/
             { oneLine[line] = true ;
               if (   (line + 2 == com.length)
                   || (com[line + 2].length == 0))
                 { oneLine[line + 1] = true ; }
             } ;
         };
       line = line + 1;
     } ;

    /***********************************************************************
    * Now we look for successive lines that begin with a number.  If       *
    * there are n successive lines beginning with a number, we make the    *
    * first n-1 of them one-line paragraphs.  If the n-th is the end of a  *
    * paragraph, we make it a one-line paragraph too.                      *
    ***********************************************************************/
    line = 0;
    while (line + 1 < com.length)    
     { if (   (com[line].length != 0)
           && (com[line][0].type == CToken.NUMBER)
           && (com[line+1].length != 0)
           && (com[line+1][0].type == CToken.NUMBER))
         { oneLine[line] = true ;
           if (   (line + 2 == com.length)
               || (com[line + 2].length == 0))
             { oneLine[line + 1] = true ; }
         };
       line = line + 1;
     } ;


    /***********************************************************************
    * We next look for alignments of arbitrary words that suggest some     *
    * sort of table--for example                                           *
    *                                                                      *
    *      foo:    XXX                                                     *
    *      grunch: XXX                                                     *
    *      a:      XXX                                                     *
    *                                                                      *
    * We regard this as an alignment if there are at least three           *
    * successive aligned lines, the aligned tokens have the same item      *
    * number, which is betweem 1 and 5, and each token has either two or   *
    * more spaces to its left, or one space and a built-in token to its    *
    * left that is not "." or ",".  (This should make chance alignments    *
    * unlikely.)                                                           *
    *                                                                      *
    * Note that this would be a fine opportunity to use tabular            *
    * alignment, but we won't do that unless it seems worth doing.         *
    * Instead, we just mark the first n-1 as single-paragraph lines, and   *
    * the n-th as well if it ends a paragraph.                             *
    *                                                                      *
    * Note: requiring that the aligned tokens all have the same item       *
    * number may be too strong.  However, I think I've reached the point   *
    * of diminishing returns in this kind of tinkering.  If we want to do  *
    * better, we need to re-design the whole paragraph shaping algorithm.  *
    ***********************************************************************/
    line = 0;
    while (line < com.length)    
     { int itemNo = 1 ;
       int maxUnalignedLine = line + 1;
       while (    (itemNo <= 5)
               && (itemNo < com[line].length))
        { 
          if (PossibleAlignment(com, line, itemNo))
           { int col = com[line][itemNo].column ;
             int nextLine = line + 1 ;
             while (   (nextLine < com.length)
                    && (itemNo < com[nextLine].length)
                    && PossibleAlignment(com, nextLine, itemNo)
                    && (com[nextLine][itemNo].column == col))
              { nextLine = nextLine + 1;}
             if (nextLine > maxUnalignedLine)
               {maxUnalignedLine = nextLine ;}
           } ;
          itemNo = itemNo + 1;
        }
       if (maxUnalignedLine - line >= 3)
         { int kk = line;
           while (kk < maxUnalignedLine - 1)
            { oneLine[kk] = true ;
              kk = kk + 1;
            }
          if (    (maxUnalignedLine == com.length)
               || (com[maxUnalignedLine].length == 0))
             { oneLine[maxUnalignedLine - 1] = true ; }
         };
       line = line + 1;
     } ;

    /***********************************************************************
    * We also turn any line consisting only of REP_CHAR tokens into a      *
    * one-line paragraph.                                                  *
    ***********************************************************************/
    line = 0;
    while (line < com.length)    
     { if (com[line].length != 0)
         { int item = 0 ;
           while (   (item < com[line].length)
                  && (com[line][item].type == CToken.REP_CHAR))
             { item = item + 1; } 
           if (item == com[line].length)
             { oneLine[line] = true ; } 
         }
       line = line + 1;
     } ;
      
    
    /***********************************************************************
    * Compute lineType and parStart.                                       *
    ***********************************************************************/
    int marginDepth = 0 ;
      /*********************************************************************
      * The depth of the current prevailing margin.                        *
      *********************************************************************/
    int[] margin = new int[200] ;
      /*********************************************************************
      * for 0 \leq i \leq parDepth, margin[i] is the depth i prevailing    *
      * left margin (a column number)                                      *
      *********************************************************************/

    /***********************************************************************
    * Set margin[0] to left-most token column.                             *
    ***********************************************************************/
    line = 0 ;
    margin[0] = 999;
    while (line < com.length)
      { if (   (com[line].length > 0)
            && (com[line][0].column < margin[0]))
          {margin[0] = com[line][0].column ;}
        line = line + 1;
      };

    /***********************************************************************
    * startNewPar is true if the next non-blank line starts a new          *
    * paragraph.                                                           *
    ***********************************************************************/
    boolean startNewPar = false ;
    if (IsParType(commentType))
     {                           // BEGIN then OF if (IsParType(commentType))
      startNewPar = true ; 
      line = 0 ;
      while (line < com.length)
       {                // BEGIN while (line < com.length)
        if (com[line].length == 0)
         { lineType[line] = -2 ; 
           line = line + 1;
         }
        else
         {                // BEGIN else of if (com[line].length == 0)
          /***************************************************************
          * A new paragraph starts at this line.                         *
          ***************************************************************/
          int nextParLine = line + 1;
            /**************************************************************
            * The line after the end of this paragraph                    *
            **************************************************************/
          int newMargin = com[line][0].column ;
            /**************************************************************
            * The new prevailing margin.                                  *
            **************************************************************/
          int labelItem = 0 ;
            /**************************************************************
            * The number of the item on this line with which the next     *
            * line is aligned, if this is a labeled paragraph; otherwise  *
            * zero.                                                       *
            **************************************************************/
          int popArg = 0 ;
          boolean nest  = false ;
          String nestArg  = "F" ;
          boolean isLabel = false ;
          String isLabelArg  = "F" ;
          int dim1Cols = 0 ;
          int dim2Cols = 0 ;
            /**************************************************************
            * The arguments or values that determine the arguments of     *
            * the LaTeXCommentPar environment.                            *
            **************************************************************/
          if (   (com[line][0].type == CToken.VERB)
              || (   (com[line][0].type == CToken.TEX) )
                  && (com[line].length == 1))
           {    // BEGIN then OF if ((com[line][0].type == CToken.VERB)...)
            /***************************************************************
            * This is a VERB or TEX line.                                  *
            *                                                              *
            * A VERB line is one that begins with a VERB token.  A VERB    *
            * token that does not appear at the beginning of a line will   *
            * be TeXify'ed and typeset as is.  A sequence of VERB lines    *
            * is typeset verbatim, with the prevailing margin reset to     *
            * the left edge.                                               *
            *                                                              *
            * A TEX line is one consisting of a single TEX token.  A TEX   *
            * token that doesn't form a TEX line will be typeset in situ   *
            * as TeX input.  A sequence of lines beginning with a TEX      *
            * line and followed by lines beginning with a TEX token is     *
            * typeset in a new paragraph, whose left margin is determined  *
            * by the column of the "`^" token.  (If the "`^" token         *
            * appeared on a previous line, then we act as if the "`^"      *
            * appeared in column 0.)                                       *
            ***************************************************************/
            int tokType = com[line][0].type ;            
             
            if (tokType == CToken.VERB)
              /*************************************************************
              * For a sequence of VERB lines, the margin is reset to the   *
              * left edge.                                                 *
              *************************************************************/
              { newMargin = 0 ;
                popArg = marginDepth ;
                marginDepth = 0 ;
              }
            else
              /*************************************************************
              * For a sequence of TEX lines, the margin is determined by   *
              * the column of the first token.                             *
              *************************************************************/
              { /***********************************************************
                * Set newMargin to the first token's column, set           *
                * marginDepth to the depth of the prevailing margin for    *
                * this paragraph, and set popArg.                          *
                ***********************************************************/
                newMargin = com[line][0].column ;

                while (margin[marginDepth] > newMargin)
                 { marginDepth = marginDepth - 1;
                   popArg = popArg + 1;
                 }
                /***********************************************************
                * Set dim1Cols to number of columns from the prevailing    *
                * margin to newMargin of first line.                       *
                ***********************************************************/
                dim1Cols = com[line][0].column - margin[marginDepth];
            
              } ;
            /***************************************************************
            * All immediately following VERB/TEX lines get lineType = -1.  *
            ***************************************************************/
            while (   (nextParLine < com.length)
                   && (com[nextParLine].length > 0)
                   && (com[nextParLine][0].type == tokType))
             { nextParLine = nextParLine + 1; } ;
           }      // END then OF ((com[line][0].type == CToken.VERB)...)
          else
           {     // BEGIN else OF if ((com[line][0].type == CToken.VERB)...)


            if (   (! oneLine[line])
                && (line + 1 < com.length)
                && (com[line + 1].length != 0)
                && ! oneLine[line + 1] 
                && (com[line + 1][0].column >= com[line][0].column))
                   /********************************************************
                   * This is a one-line paragraph if the following line    *
                   * is outdented from this one.                           *
                   ********************************************************/
              { /***********************************************************
                * This paragraph has at least two lines.                   *
                ***********************************************************/
                newMargin = com[line + 1][0].column ;
                nextParLine = line + 2 ;
                
                /***********************************************************
                * Add new lines to the paragraph as long as they are       *
                * aligned with the second line.                            *
                ***********************************************************/
                while (   (nextParLine < com.length)
                       && (com[nextParLine].length != 0)
                       && ! oneLine[nextParLine]
                       && (com[nextParLine][0].column == newMargin))
                 { nextParLine = nextParLine + 1; } ;
              };           
  
            /***************************************************************
            * Set leftMargin to the left margin of the paragraph, which    *
            * is the leftmost of the first two lines.                      *
            ***************************************************************/
            int leftMargin = com[line][0].column;
            if (leftMargin > newMargin )
              { leftMargin = newMargin; }
            /****************************************************************
            * Set marginDepth to the depth of the prevailing margin for     *
            * this paragraph, and set popArg.                               *
            ****************************************************************/
            while (margin[marginDepth] > leftMargin)
              { marginDepth = marginDepth - 1;
                popArg = popArg + 1;
              }
  
            /****************************************************************
            * Set dim1Cols to number of columns from the prevailing margin  *
            * to newMargin of first line.                                   *
            ****************************************************************/
            dim1Cols = com[line][0].column - margin[marginDepth];
  
            /****************************************************************
            * Set nest and nestArg.                                         *
            ****************************************************************/
            nest = (margin[marginDepth] != newMargin);
            if (nest) {nestArg = "T";};
  
            /****************************************************************
            * Determine if this is a labeled paragraph.                     *
            ****************************************************************/
            if (com[line][0].column < newMargin)
              { int i = 0 ;
                while (   (i+1 < com[line].length)
                       && (com[line][i+1].column <= newMargin))
                 {i = i+1;};
                isLabel = (com[line][i].column == newMargin) ;
                if (isLabel) {labelItem = i;
                              isLabelArg = "T";
                             };
              };
  
            /*****************************************************************
            * Determine dim2Cols.                                            *
            *****************************************************************/
            if (isLabel)
              { dim2Cols = com[line][labelItem].column 
                              - com[line][labelItem - 1].column 
                              - com[line][labelItem - 1].getWidth();
              }
            else
              { dim2Cols = newMargin - com[line][0].column;
              } ;
  
            /*****************************************************************
            * Update marginDepth and margin, if necessary.                   *
            *****************************************************************/
            if (nest){ marginDepth = marginDepth + 1;
                       margin[marginDepth] = newMargin ;
                     } ;
           };    // END else OF if ((com[line][0].type == CToken.VERB)...)
  
          /*****************************************************************
          * Set lineType[line] and parStart[line].                         *
          *****************************************************************/
          lineType[line] = labelItem ;
          String temp =    
             "\\begin{" + Parameters.LaTeXCommentPar 
            + "}{" + popArg + "}{" + nestArg + "}{" + isLabelArg + "}{"
            + Misc.floatToString(Parameters.LaTeXCommentLeftSpace(dim1Cols),2)
            + "}{"
            + Misc.floatToString(Parameters.LaTeXCommentLeftSpace(dim2Cols),2)
            +"}{" ;
          if (isLabel)
           { parStart[line] = temp + "%"; }
          else
           { parStart[line] = temp + "}%"; };
            
          /*****************************************************************
          * Set lineType for the rest of the lines of the paragraph, and   *
          * set line to nextParLine.                                       *
          *****************************************************************/
          line = line + 1;
          while (line < nextParLine)
           { lineType[line] = -1 ;
             line = line + 1;
           } ;
        };                    // END else OF if (com[line].length == 0);
      }                      // END while (line < com.length)
     }                          // END then OF if (IsParType(commentType))
    else
     {                           // BEGIN else OF if (IsParType(commentType))
      if (com.length != 0)
        { lineType[0]   = -1;
        } ;
     }                           // END else OF if (IsParType(commentType))


    line = 0;
    /***********************************************************************
    * Set line to the first non-null line (or com.length if there is       *
    * none).                                                               *
    ***********************************************************************/
    while (   (line < com.length)
           && (lineType[line] == -2))
     { line = line + 1;
     };

    /***********************************************************************
    * Set endLine to the line after the last non-null line, or to (or to   *
    * com.length if there is none).                                        *
    ***********************************************************************/
    int endLine = com.length ;
      /*********************************************************************
      * The line after the last non-null line.                             *
      *********************************************************************/
    while (   (endLine > line)
           && (lineType[endLine - 1] == -2))
     { endLine = endLine - 1;
     };

    if (   (line == endLine)
        || (   !IsParType(commentType)
            && (com[0].length == 0)))
     /**********************************************************************
     * This is the null comment.  We write nothing except for commentType  *
     * ONE_LINE, in which case we write a null comment.                    *
     **********************************************************************/
     { if (commentType == ONE_LINE)
         { writer.putLine(Parameters.LaTeXOneLineCommentCommand + "{}%");};
       return ;
     }     

    /***********************************************************************
    * Write out the opening of the comment.                                *
    ***********************************************************************/
    String tempStr = "";
    switch (commentType)
      {
       case ONE_LINE :
         tempStr = Parameters.LaTeXOneLineCommentCommand + "{" ;
         if (   (com[0].length > 0)
             && (com[0][0].column > 0))
           { tempStr = tempStr + 
                  Parameters.LaTeXSpaceCommand + "{" 
                + Misc.floatToString(Parameters.LaTeXCommentLeftSpace(
                   com[0][0].column - 1), 2)
                + "}" ;
           } ;
         writer.putLine(tempStr + "%");
         break ;

       case ZERO_WIDTH :
         tempStr = Parameters.LaTeXZeroWidthCommentCommand + "{" ;
         if (   (com[0].length > 0)
             && (com[0][0].column > 0))
           { tempStr = tempStr + 
                  Parameters.LaTeXSpaceCommand + "{" 
                + Misc.floatToString(Parameters.LaTeXCommentLeftSpace(
                   com[0][0].column - 1), 2)
                + "}" ;
           } ;
         writer.putLine(tempStr + "%");
         break ;

       case PAR :
         float indent = indentOrWidth ;

         if (indent < -1)
           { indent = Parameters.LaTeXCommentLeftSpace(margin[0]);
           } ;
         writer.putLine("\\begin{" 
                             + Parameters.LaTeXLeftMultiLineComment
                             + "}{" + Misc.floatToString(indent,2) 
                             + "}%");
         break ;

       case RIGHT_MULTI :
         writer.putLine("\\begin{" 
                             + Parameters.LaTeXRightMultiLineComment
                             + "}{" + Misc.floatToString(indentOrWidth,2) 
                             + "}%");
         break ;
       default :
         Debug.ReportBug(
           "The impossible has happened in FormatComments.InnerWriteComment");
      }

    /***********************************************************************
    * Write out the body of the comment.                                   *
    ***********************************************************************/
    String curOutput = "" ;
      /*********************************************************************
      * The current output line.                                           *
      * Invariant: ~openPar => (curOutput = "")                            *
      *********************************************************************/
    boolean openPar = false ;
      /*********************************************************************
      * True if we are writing tokens inside a LaTeXCommentPar.            *
      *********************************************************************/
    boolean openVerb = false ;
      /*********************************************************************
      * True if currently writing tokens inside a verbatim environment.    *
      * Invariant: openVerb => openPar                                     *
      *********************************************************************/
    boolean openMath = false ;
      /*********************************************************************
      * True if we are writing tokens inside an \ensuremath argument.      *
      * Invariant: openMath => openPar                                     *
      *********************************************************************/
    boolean openLabel = false ;
      /*********************************************************************
      * openLabel is true iff we are writing tokens inside the label       *
      * argument of a LaTeXCommentPar environment.  In that case,          *
      * curOutput is the output for the label constructed thus far.        *
      *********************************************************************/
    int item = 0;
     /**********************************************************************
     * The next token to process is com[line][item].                       *
     **********************************************************************/
    while (line < endLine)
     { // BEGIN while (line < endLine)
      /*********************************************************************
      * Writing out next line.                                             *
      *                                                                    *
      * Invariant: curOutput = "".                                         *
      *********************************************************************/
      if (lineType[line] == -2)
       {                  // BEGIN then OF if ((lineType[line] == -2)...)
        /*******************************************************************
        * This is a blank line.  Close the current paragraph and write     *
        * out a LaTeXCommentVSpaceCmd command.                             *
        *******************************************************************/
         if (openPar)
           /****************************************************************
           * Close an open paragraph.                                      *
           ****************************************************************/
          { CloseParagraph(writer, curOutput, openMath, openVerb) ;
            openPar   = false ;
            openMath  = false ;
            openVerb  = false ;
            curOutput = "" ;
          } ;

         /******************************************************************
         * Set numOfBlankLines to the number of blank lines before the     *
         * next paragraph, and increment line by numOfBlankLines - 1.      *
         ******************************************************************/
         int numOfBlankLines = 0 ;
         while (lineType[line] == -2)
          { numOfBlankLines = numOfBlankLines + 1 ;
            line = line + 1 ;
          }
         line = line - 1;

         /******************************************************************
         * Write out a LaTeXCommentVSpaceCmd command.                      *
         ******************************************************************/
         writer.putLine(
           Parameters.LaTeXCommentVSpaceCmd +"{" + 
           Misc.floatToString(Parameters.LaTeXCommentVSpace(numOfBlankLines),
                              2)
           + "}%");
       }                   // END then OF if ((lineType[line] == -2)...)

      else
       {                   // BEGIN else OF if ((lineType[line] == -2)...)
         /******************************************************************
         * This is a non-blank line.                                       *
         ******************************************************************/
         if (lineType[line] != -1) 
          {                             // BEGIN if (lineType[line] != -1)
           /****************************************************************
           * This line begins a new paragraph, so write parStart[line].    *
           ****************************************************************/
           if (openPar)
            { /*************************************************************
              * Need to start new paragraph, but old one is still open.    *
              * So, need to close it.                                      *
              *************************************************************/
              CloseParagraph(writer, curOutput, openMath, openVerb) ;
              openMath  = false ;
              openVerb  = false ;
              curOutput = "" ;
            } ;

           writer.putLine(parStart[line]);
           openPar = true ;
           Debug.Assert(!(openVerb || openMath),
             "FormatComments.InnerWriteComment: Invariant "
           + "(openMath \\/ openVerb) => openPar  violated") ;
          
           /****************************************************************
           * Set openLabel true iff this is a labeled paragraph.           *
           ****************************************************************/
           openLabel = false ;
           if (lineType[line] > 0)
             { openLabel = true; }
         }                              // END if (lineType[line] != -1) 
        /*******************************************************************
        * Now, process the tokens on this line, which should be non-blank. *
        *******************************************************************/
        Debug.Assert(curOutput.equals(""),
                     "FormatComments.InnerWriteComment: Output not processed\n"
                     + "    when it should have been");

        item = 0 ;
        while (item < com[line].length)
         {                         // BEGIN while (item < com[item].length)

          /*****************************************************************
          * Loop Invariant: openLabel => item \leq offSet                  *
          *****************************************************************/
          if (openLabel && (item == lineType[line]))
           { if (openMath)
               { /**********************************************************
                 * Have to close the \ensuremath.                          *
                 **********************************************************/
                 curOutput = curOutput + "}";
                 openMath = false;
               } ;
             Misc.BreakStringOut (writer, curOutput + "}%") ;
             curOutput = "";
             openLabel = false;
           }

          if (com[line][item].type == CToken.VERB)
           { /**************************************************************
             * This is a VERB token.                                       *
             **************************************************************/
             if (openMath)
              { curOutput = curOutput + "}" ;
                openMath = false; } ;

             if (IsParType(commentType) && (! openLabel) && (item == 0))
              /*************************************************************
              * We write a verbatim command only if this is not a          *
              * one-line comment, we're not inside a label, and this is    *
              * the first item on the line.  Otherwise, we just TeXify     *
              * the string and write it out.  (A \verb command won't work  *
              * because TeX may process the string inside a command        *
              * argument.)                                                 *
              *************************************************************/
              { Debug.Assert(curOutput.equals(""),
                  "FormatComments.InnerWriteComment: "
                   + "failed to write curOutput");
                if (! openVerb)
                  {writer.putLine("\\begin{minipage}[t]{\\linewidth}");
                     /******************************************************
                     * A verbatim environment is put inside a minipage     *
                     * environment so it won't be broken across pages.     *
                     ******************************************************/
                   writer.putLine("\\begin{verbatim}") ;

                   openVerb = true;
                   /********************************************************
                   * Set curOutput to a number of spaces equal to the      *
                   * number of spaces to the left of the "`.", if this     *
                   * token begins a VERB.                                  *
                   ********************************************************/
                   int w = com[line][item].column;
                   while (w > 0)
                    { curOutput = curOutput + " ";
                      w = w - 1;
                    }
                  } ;

                writer.putLine(curOutput + com[line][0].string) ;
                curOutput = "";
              }
             else
              { curOutput = curOutput + Misc.TeXify(com[line][item].string) ;
              }
           }       
          else
           {       // BEGIN else OF if (com[line][item].type == CToken.VERB)
             /**************************************************************
             * This is not a VERB token.                                   *
             *                                                             *
             * Check if need to close a verbatim environment.              *
             **************************************************************/
             if (openVerb)
              { writer.putLine("\\end{verbatim}%") ;
                writer.putLine("\\end{minipage}");
                openVerb = false;
              } ;

             CToken tok  = com[line][item] ;
             CToken ptok = previousCToken(com, line, item) ;
               /************************************************************
               * tok is the current token, and ptok is the preceding one.  *
               ************************************************************/

             /**************************************************************
             * Check if need to close \ensuremath command.                 *
             **************************************************************/
             if (   openMath 
                 && (   !tok.isTLA
                     || (tok.type == CToken.TEX)))
                        /***************************************************
                        * We close \ensuremath for a TEX token that        *
                        * somehow mangaged to get marked as a TLA token.   *
                        * (For example, it might have been inside a        *
                        * "`...'".)                                        *
                        ***************************************************/
               { curOutput = curOutput + "}" ;
                 openMath = false;}

             /**************************************************************
             * Output a space if this there is a space between this token  *
             * and the preceding one--and this token doesn't either begin  *
             * a paragraph or come right after the label in a labeled      *
             * paragraph.                                                  *
             *                                                             *
             * If both tokens are on the same line and there are at least  *
             * 5 spaces between them, then leave a fair amount of extra    *
             * space between them, based on how many spaces apart they     *
             * are.  (I chose 4 spaces because "`foo'  bar" winds up with  *
             * 5 apparent spaces between the "`foo'" and the "bar".        *
             *                                                             *
             * If both tokens are in in math mode and their types          *
             * indicate that they probably shouldn't be printed right      *
             * next to one another, so we add a space.  (In this case,     *
             * either we've made a mistake in identifying TLA tokens, or   *
             * the input is strange.  Adding a space in the output seems   *
             * like the best thing to do here.)  Outputing a "\ " doesn't  *
             * work because that doesn't seem to permit a line break in    *
             * math mode.  So, we add "} \ensuremath{".                    *
             **************************************************************/
             if (   !isPreviousAdjacent(com, line, item)
                 && !(   (lineType[line] >= 0)
                      && (   (item == 0)
                          || (item == lineType[line]))))
               { 

                if (   (item > 0)
                    && (ptok.column + ptok.getWidth() <= tok.column - 5))
                 { curOutput = 
                    curOutput + Parameters.LaTeXSpaceCommand
                     + "{" 
                     + Misc.floatToString(
                           Parameters.LaTeXCommentLeftSpace(
                               tok.column - (ptok.column + ptok.getWidth())),
                           2) + "}";
                 }
                else
                 {
                  if(   (tok.isTLA) && (ptok.isTLA)
                     && (   (tok.type  != CToken.BUILTIN)
                         || (BuiltInSymbols.GetBuiltInSymbol(
                              tok.string, true).symbolType == Symbol.PREFIX)
                         || (BuiltInSymbols.GetBuiltInSymbol(
                              tok.string, true).symbolType == Symbol.KEYWORD))
                     && (tok.type  != CToken.RIGHT_DQUOTE)
                     && (   (ptok.type != CToken.BUILTIN)
                         || (BuiltInSymbols.GetBuiltInSymbol(
                              ptok.string, true).symbolType == Symbol.POSTFIX)
                         || (BuiltInSymbols.GetBuiltInSymbol(
                              ptok.string, true).symbolType == Symbol.KEYWORD))
                     && (ptok.type != CToken.LEFT_DQUOTE))
                   { curOutput = curOutput + "} \\ensuremath{"; 
                   }
                  else
                   { curOutput = curOutput + " "; 
                   } ;
                 }
               } ;
             /**************************************************************
             * Check if need to start an \ensuremath argument.             *
             **************************************************************/
             if ( (!openMath) && tok.isTLA)
               { curOutput = curOutput + "\\ensuremath{" ;
                 openMath  = true;}

             /**************************************************************
             * Output the token.                                           *
             **************************************************************/
             switch (tok.type)
              {
               case CToken.BUILTIN :
                 if (tok.isTLA)
                  { curOutput = curOutput + 
                     BuiltInSymbols.GetBuiltInSymbol(tok.string, true).TeXString;
                   /********************************************************
                   * For subscripted BUILINs like WF_, we don't do         *
                   * subscripting in comments, so we must print the "_".   *
                   ********************************************************/
                   if (   (tok.string.charAt(tok.string.length()-1) == '_')      
                       && (tok.string.length() != 1))
                    { curOutput = curOutput + "\\_"; } ;
                  }
                 else
                  { curOutput = curOutput + 
                      getAmbiguous(tok.string);
                  } ;
                 break ;

               case CToken.NUMBER :
                 curOutput = curOutput + Misc.TeXify(tok.string);
                                /*******************************************
                                * Need to TeXify because of numbers like   *
                                * "\O777".                                 *
                                *******************************************/
                 break ;        

               case CToken.STRING :
                 curOutput = curOutput + Parameters.LaTeXStringCommand 
                             + "{" + Misc.TeXify(tok.string) + "}" ;
                 break ;

               case CToken.PF_STEP :
                 curOutput = curOutput + LaTeXOutput.PfStepString(tok.string) ;
                 break ;

               case CToken.IDENT :
                 curOutput = curOutput + Misc.TeXifyIdent(tok.string);
                 break ;

               case CToken.OTHER :
                 curOutput = curOutput + Misc.TeXify(tok.string);
                 break ;

               case CToken.REP_CHAR :
                 /**********************************************************
                 * Set outS to the command to produce the token.           *
                 **********************************************************/
                 String outS = getRepeatCharCommand(tok.string.charAt(0));
                 if (outS.equals(""))
                  { outS = Misc.TeXify(tok.string);
                  }
                 else
                  { outS = outS + "{" + tok.getWidth() + "}";
                  } ;
                 /**********************************************************
                 * If this token is on a line by itself, then typeset it   *
                 * on a line by itself.                                    *
                 **********************************************************/
                 if (com[line].length == 1)
                  { if (lineType[line] == -1)
                      /*****************************************************
                      * If this isn't the first line of the paragraph,     *
                      * must output a \par command first.                  *
                      *****************************************************/
                      { outS = "{\\par}" + outS ;
                      } ;
                   if (   (line + 1 < lineType.length)
                       && (lineType[line + 1] == -1) )
                      /*****************************************************
                      * If this isn't the last line of the paragraph,      *
                      * must output a \par command afterwards.             *
                      *****************************************************/
                      { outS = outS + "{\\par}" ; 
                      } ;
                  } ;
                 curOutput = curOutput + outS ;
                break ;

               case CToken.LEFT_DQUOTE :
                 if (tok.isTLA)
                   {curOutput = curOutput + "\\mbox{``}" ; }
                 else
                   {curOutput = curOutput + "``" ; }
                 break ;

               case CToken.RIGHT_DQUOTE :
                 if (tok.isTLA)
                   {curOutput = curOutput + "\\mbox{''}" ; }
                 else
                   {curOutput = curOutput + "''" ; }
                 break ;

               case CToken.TEX :
                 curOutput = curOutput + tok.string;
                 break ;

               default :
                 Debug.ReportBug(
                   "Bad CToken type found in FormatComments.InnerWriteComment");
                 break ;
              }
        
           }       // END else OF if (com[line][item].type == CToken.VERB)

          item = item + 1;
         }                        // END while (item < com[item].length)
       };                      // END else OF if ((lineType[line] == -2)...)
     
      Misc.WriteIfNonNull(writer, curOutput);
      curOutput = "" ;
      line = line + 1;
     }; // END while (line < endLine)

    /***********************************************************************
    * Write out the end of the comment.                                    *
    *                                                                      *
    * Start by closing any open \ensuremath command or verbatim            *
    * environment.                                                         *
    ***********************************************************************/
    if (IsParType(commentType) && openPar)
      { CloseParagraph(writer, curOutput, openMath, openVerb) ;
        curOutput = ""; }
    else
      { if (openMath)
          { curOutput = curOutput + "}" ; 
          } ;
      } ;
    switch (commentType)
      {
       case ONE_LINE :
       case ZERO_WIDTH :
         Misc.BreakStringOut(writer, curOutput + "}%");
         break ;
       case PAR :
         Misc.WriteIfNonNull(writer, curOutput);
         writer.putLine("\\end{" + Parameters.LaTeXLeftMultiLineComment + "}%");
         break ;
       case RIGHT_MULTI :
         Misc.WriteIfNonNull(writer, curOutput);
         writer.putLine("\\end{" + Parameters.LaTeXRightMultiLineComment
                                    + "}%");
         break ;
       default :
         Debug.ReportBug(
           "The impossible happened in FormatComments.InnerWriteComment");
      };
      
   } // END InnerWriteComment(...)

  public static final int ONE_LINE    = 1;
  public static final int ZERO_WIDTH  = 2;
  public static final int PAR         = 3;
  public static final int RIGHT_MULTI = 4;
    /***********************************************************************
    * The possible commentType arguments to writeComment.                  *
    ***********************************************************************/
    
  private static boolean IsParType(int type)
    /***********************************************************************
    * True if type is PAR or RIGHT_MULTI.                                  *
    ***********************************************************************/
    { return (type == PAR) || (type == RIGHT_MULTI) ;
    }    

  private static void CloseParagraph
                      (OutputFileWriter writer, 
                       String  curOutput, 
                       boolean openMath, 
                       boolean openVerb)
    /***********************************************************************
    * A procedure for InnerWriteComments that closes the current           *
    * paragraph.  After this is called, the caller should execute:         *
    *                                                                      *
    *    openPar   = false ;                                               *
    *    openMath  = false ;                                               *
    *    openVerb  = false ;                                               *
    *    curOutput = "" ;                                                  *
    ***********************************************************************/
    { String curOut = curOutput ;
      if (openMath)
       { curOut = curOut + "}%" ; } ;
      if (openVerb)
       { Misc.WriteIfNonNull(writer, curOut);
         curOut = "" ;
         writer.putLine("\\end{verbatim}");
         writer.putLine("\\end{minipage}");
           /****************************************************************
           * Note: a verbatim environment is put inside a minipage         *
           * environment so it won't be broken across pages.               *
           ****************************************************************/
       } ; 
      Misc.WriteIfNonNull(writer, curOut);
      writer.putLine("\\end{" + Parameters.LaTeXCommentPar + "}%");
    } ;
    

  private static boolean HasDigit(String str)
   { int i = 0 ;
     boolean result = false ;
     while ((!result) && (i < str.length()))
      { result = Misc.IsDigit(str.charAt(i));
        i = i + 1;
      } ;
     return result;
   }

} // END Class

/* Last modified on Wed 19 Sep 2007 at  5:26:37 PST by lamport */ 
/*      modified on Tue Dec 12 14:39:45 PT 2000 by unknown */ 


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/src/org/lamport/tla/toolbox/doc/handler/HelpURLHandler.java<|end_filename|>
package org.lamport.tla.toolbox.doc.handler;

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

public class HelpURLHandler extends AbstractHandler implements IHandler {

	public Object execute(final ExecutionEvent event) throws ExecutionException {
		try {
			final URL url = new URL(event.getParameter("org.lamport.tla.toolbox.doc.url.name"));
			PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(url);
		} catch (final MalformedURLException e) {
			e.printStackTrace();
		} catch (final PartInitException e) {
			e.printStackTrace();
		}
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/data/StateSpaceInformationItemTest.java<|end_filename|>
// Copyright (c) Dec 12, 2011 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import junit.framework.TestCase;

/**
 * @author <NAME>
 */
public class StateSpaceInformationItemTest extends TestCase {

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
	}

	/**
	 * Test method for
	 * {@link org.lamport.tla.toolbox.tool.tlc.output.data.StateSpaceInformationItem#parse(java.lang.String)}
	 * .
	 */
	public void testParse() {
		String outputMessage = "Progress(10) at 2011-12-12 17:16:45: 36114 states generated (658832 s/min)," +
				" 9392 distinct states found (9127 ds/min), 4232 states left on queue. is in wrong format";
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parse(outputMessage);
		assertEquals(10, parsed.getDiameter());
		assertEquals(9392, parsed.getDistinctStates());
		assertEquals(36114, parsed.getFoundStates());
		assertEquals(4232, parsed.getLeftStates());
		assertEquals(658832, parsed.getSpm());
		assertEquals(9127, parsed.getDistinctSPM());
	}
	
	/**
	 * Test method for
	 * {@link org.lamport.tla.toolbox.tool.tlc.output.data.StateSpaceInformationItem#parseInit(java.lang.String)}
	 * .
	 */
	public void testParseInit() {
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parseInit("Finished computing initial states: 123456789 distinct states generated.");
		assertEquals(0, parsed.getDiameter());
		assertEquals(123456789, parsed.getDistinctStates());
		assertEquals(123456789, parsed.getFoundStates());
		assertEquals(123456789, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}
	
	public void testParseInit2() {
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parseInit("Finished computing initial states: 1 distinct state generated.");
		assertEquals(0, parsed.getDiameter());
		assertEquals(1, parsed.getDistinctStates());
		assertEquals(1, parsed.getFoundStates());
		assertEquals(1, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}

	public void testParseInit3() {
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parseInit("Finished computing initial states: 123456789 states generated, with 123 of them distinct.");
		assertEquals(0, parsed.getDiameter());
		assertEquals(123, parsed.getDistinctStates());
		assertEquals(123456789, parsed.getFoundStates());
		assertEquals(123, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}

	public void testParseInit4() {
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parseInit("Finished computing initial states: 2 states generated, with 1 of them distinct.");
		assertEquals(0, parsed.getDiameter());
		assertEquals(1, parsed.getDistinctStates());
		assertEquals(2, parsed.getFoundStates());
		assertEquals(1, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}

	public void testParseInit5() throws ParseException {
		StateSpaceInformationItem parsed = StateSpaceInformationItem
				.parseInit("Finished computing initial states: 2 distinct states generated at 2018-07-03 16:10:44.");

		assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-07-03 16:10:44"), parsed.getTime());
		assertEquals(0, parsed.getDiameter());
		assertEquals(2, parsed.getDistinctStates());
		assertEquals(2, parsed.getFoundStates());
		assertEquals(2, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}

	public void testParseInit6() throws ParseException {
		StateSpaceInformationItem parsed = StateSpaceInformationItem.parseInit(
				"Finished computing initial states: 2 states generated, with 1 of them distinct at 2018-07-03 16:10:44.");

		assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-07-03 16:10:44"), parsed.getTime());
		assertEquals(0, parsed.getDiameter());
		assertEquals(1, parsed.getDistinctStates());
		assertEquals(2, parsed.getFoundStates());
		assertEquals(1, parsed.getLeftStates());
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}
	
	public void testParseOldComma() throws ParseException {
		StateSpaceInformationItem parsed = StateSpaceInformationItem.parseOld(
				"Progress(57) at 2019-03-21 10:20:20: 48,613 states generated, 25,188 distinct states found, 556,000 states left on queue.");
		
		assertEquals(57, parsed.getDiameter());
		assertEquals(48613, parsed.getFoundStates());
		assertEquals(25188, parsed.getDistinctStates());
		assertEquals(556000, parsed.getLeftStates());
		
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}
	
	public void testParseOldDot() throws ParseException {
		StateSpaceInformationItem parsed = StateSpaceInformationItem.parseOld(
				"Progress(57) at 2019-03-21 10:20:20: 48.613 states generated, 25.188 distinct states found, 556.000 states left on queue.");
		
		assertEquals(57, parsed.getDiameter());
		assertEquals(48613, parsed.getFoundStates());
		assertEquals(25188, parsed.getDistinctStates());
		assertEquals(556000, parsed.getLeftStates());
		
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}
	
	public void testParseOld() throws ParseException {
		StateSpaceInformationItem parsed = StateSpaceInformationItem.parseOld(
				"Progress(57) at 2019-03-21 10:20:20: 48613 states generated, 25188 distinct states found, 556000 states left on queue.");
		
		assertEquals(57, parsed.getDiameter());
		assertEquals(48613, parsed.getFoundStates());
		assertEquals(25188, parsed.getDistinctStates());
		assertEquals(556000, parsed.getLeftStates());
		
		assertEquals(0, parsed.getSpm());
		assertEquals(0, parsed.getDistinctSPM());
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/pref/PreferenceInitializer.java<|end_filename|>
package org.lamport.tla.toolbox.util.pref;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.lamport.tla.toolbox.ui.preference.EditorPreferencePage;
import org.lamport.tla.toolbox.ui.preference.GeneralPreferencePage;

/**
 * Class used to initialize default preference values.
 */
public class PreferenceInitializer extends AbstractPreferenceInitializer {
    /**
     * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
     */
	public void initializeDefaultPreferences() {
        final IPreferenceStore store = PreferenceStoreHelper.getInstancePreferenceStore();
        store.setDefault(IPreferenceConstants.I_PARSER_POPUP_ERRORS, true); // set to true by LL on 22 Sep 2009

        // instance based properties
        store.setDefault(IPreferenceConstants.I_RESTORE_LAST_SPEC, true);
        store.setDefault(IPreferenceConstants.I_MIN_DISPLAYED_SIZE, GeneralPreferencePage.MIN_DISPLAYED_SIZE_DEFAULT);

        store.setDefault(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY, true);
        // store.setDefault(IPreferenceConstants.I_PARSE_FILES_ON_MODIFY, true);
        store.setDefault(IPreferenceConstants.I_PARSE_SPEC_ON_MODIFY, true);
        
        /*
         * Set default (and only) option for PlusCal translator.  (Added by LL on 13 May 2016.)
         */
        store.setDefault(IPreferenceConstants.PCAL_CAL_PARAMS, "-nocfg"); 
        
        // set editor page preference defaults
        store.setDefault(EditorPreferencePage.EDITOR_RIGHT_MARGIN, 
                EditorPreferencePage.EDITOR_RIGHT_MARGIN_DEFAULT);
        
        store.setDefault(EditorPreferencePage.CLEAR_DECLARATION_USE_MARKERS_ON_PARSE, 
                EditorPreferencePage.CLEAR_DECLARATION_USE_MARKERS_ON_PARSE_DEFAULT);

        store.setDefault(EditorPreferencePage.EDITOR_ADD_MODIFICATION_HISTORY,
                EditorPreferencePage.EDITOR_ADD_MODIFICATION_HISTORY_DEFAULT);

        /*
         * Set default for Renumber Proof command option.
         */
        store.setDefault(EditorPreferencePage.RENUMBER_KEY,  
        		EditorPreferencePage.ALL_NAMES);
        store.setDefault(EditorPreferencePage.SAVE_MODULE, true);
        
        store.setDefault(IPreferenceConstants.I_FOLDING_BLOCK_COMMENTS, false);
        store.setDefault(IPreferenceConstants.I_FOLDING_PCAL_ALGORITHM, false);
        store.setDefault(IPreferenceConstants.I_FOLDING_PCAL_TRANSLATED, false);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCSingleLineRule.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.SingleLineRule;

public class TLCSingleLineRule extends SingleLineRule {

	public TLCSingleLineRule(String startSequence, String endSequence, IToken token) {
		super(startSequence, endSequence, token);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.rules.PatternRule#endSequenceDetected(org.eclipse.jface.text.rules.ICharacterScanner)
	 */
	@Override
	protected boolean endSequenceDetected(ICharacterScanner scanner) {
		while(true) {
			scanner.read();
			if(TLCCharScanner.isEOF(scanner)) {
				break;
			} else if (TLCCharScanner.isEOL(scanner)) {
				// EOL has to be consumed
				scanner.read();
				break;
			}
		}
		return true;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalSymTab.java<|end_filename|>
/***************************************************************************
* CLASS PcalSymTab                                                         *
* last modified on Fri 31 Aug 2007 at 15:44:54 PST by lamport               *
*      modified on Tue 30 Aug 2005 at 18:30:10 UT by keith                 *
*                                                                          *
* This class implements the symbol table corresponding with an AST object. *
*                                                                          *
* symtab is the generated symbol table and is a vector of SymTableEntry.   *
* procs is the generated vector of ProcedureEntry (which includes the      *
*   entry point label),  and processes is the generated vector of          *
*   ProcessEntry.                                                          *
* If the algorithm is a uniprocess, then iPC is the initial label.         *
*                                                                          *
* The string disambiguateReport are TLA comments that describe how         *
* variables and labels were renamed.                                       *
*                                                                          *
* The string errorreport are errors that were generated while creating     *
* the symbol table.                                                        *
*                                                                          *
* The public methods of this class are the following.  Except as noted,    *
* they are not called from outside this file.                              *
*                                                                          *
*     boolean InsertSym (char type, String id, String context, int line,   *
*                             int col)                                     *
*          Inserts the values into the symbol table. Returns true if the   *
*          value was not in the symbol table before the insert.            *
*                                                                          *
*     int FindSym (char type, String id, String context)                   *
*          Returns the index of this symbol in the symbol table.           *
*                                                                          *
*     boolean InsertProc (AST.Procedure ast)                               *
*          Inserts ast.params and ast.decls into the procedure table.      *
*          Returns true if value was not in  table before the insert.      *
*                                                                          *
*     boolean InsertProcess (AST.Process p)                                *
*          Inserts an entry into the process table vector. Returns true    *
*          is the value was not in the  table before the insert.           *
*                                                                          *
*     int FindSym (char type, String id, String context)                   *
*          Returns the index of this symbol in the symbol table.           *
*     (there are other versions of this method too).                       *
*                                                                          *
*     String UseThis (char type, String id, String context)                * 
*          Returns the disambiguated id of this symbol.                    *
*     (there are other versions of this method too).                       *
*          Called from PcalFixIDs and PcalTranslate.                       *
*                                                                          *
*     void Disambiguate ( )                                                *
*          Generates the disambiguated names in the symbol table.          *
*          Called from NotYetImplemented                                   *
*                                                                          *
*     String toString ( )                                                  *
*          The symbol table represented as a string; useful for debugging  *
*          Impossible to figure out which of the zillions of invocations   *
*          of toString are calling this method.                            *
*                                                                          *
*     void CheckForDefaultInitValue ( )                                    *
*          Reports an error if "defaultInitValue" appears in the symbol    *
*          table.  Added by LL on 31 Aug 2007.                             *
*                                                                          *
* This method does not save the complete AST of the algorithm, which gives *
* some clue to what the methods do.                                        *
*                                                                          *
* TO REVISE: The mapping of id to symbol, via UseThis, is sloppy.          *
****************************************************************************/

package pcal;

import java.util.Vector;

import pcal.exception.PcalSymTabException;

public class PcalSymTab {
    public Vector symtab;             // Vector of SymTabEntry
    public Vector procs;              // Vector of ProcedureEntry
    public Vector processes;          // Vector of ProcessEntry
    public Vector disambiguateReport; // Vector of String (comments)
    public String errorReport;        // Accumulated errors
    public String iPC;                // initial pc value for unip algorithm

    // Symbol types. The order  determines priority in terms of constructing a
    // disambiguous name.
    public static final int num_vtypes = 7;
    public static final int GLOBAL = 0;   
    public static final int LABEL = 1;
    public static final int PROCEDURE = 2;
    public static final int PROCESS = 3;
    public static final int PROCESSVAR = 4;
    public static final int PROCEDUREVAR = 5;
    public static final int PARAMETER = 6;

    // The following two arrays need to be ordered wrt the constants above.

    // Prepend this type-specific string to name before disambiguation.
    private static String typePrefix[ ] = { "", "", "", "", "", "", "" };

    // For toString method.
    public static String vtypeName[ ] = {
        "Global variable", "Label", "Procedure", "Process", 
        "Process variable", "Procedure variable", "Parameter"};

    /* NESTED CLASS: Symbol table entries */
    public class SymTabEntry {
        public int type;       // variable type
                               // can be GLOBAL, LABEL, PROCEDURE, PROCESS, PROCESSVAR,
                               // PROCEDUREVAR, or PARAMETER, declared above.
        public String id;      // original name
        public String context; // where defined
                               // experimentation shows that context is:
                               //    "" if cType = ""
                               //    the name of a process if cType = "process"
                               //    the name of a procedure if cType = "procedure"
        public String cType;   // procedure, process or empty
        public int line;       // line where defined
        public int col;        // column where defined
        public String useThis; // Disambiguated name

        public SymTabEntry(int type,
                           String id,
                           String context,
                           String cType,
                           int line,
                           int col) {
            this.type = type;
            this.id = id;
            this.context = context;
            this.cType = cType;
            this.line = line;
            this.col = col;
            this.useThis = id;
        }
        
        /**
         * For debugging:
         */
        public String toString() {
        	return "[id: " + this.id + ", usethis: " + this.useThis + 
        			", line: " + this.line + ", col:" + this.col +
        			", type: " + this.type + ", context: " + this.context + "]";
        }
    } /* End of SymTabEntry */

    /* NESTED CLASS: Procedure table entries */
    public class ProcedureEntry {
        public String name;    // Procedure name
        public Vector params;  // of PVarDecl
        public Vector decls;   // of PVarDecl
        public String iPC;     // initial label of procedure
        public AST.Procedure ast; // AST of the procedure
                                  // Added 13 Jan 2011 by LL 
        
        public ProcedureEntry(AST.Procedure p) {
            this.name = p.name;
            this.params = p.params;
            this.decls = p.decls;
            this.ast = p;
            if (p.body.size() == 0) this.iPC = null;
            else {
                AST.LabeledStmt ls = (AST.LabeledStmt) p.body.elementAt(0);
                this.iPC = ls.label;
            }
        }
    } /* End of ProcedureEntry */

    /* NESTED CLASS: Process table entries */
    public class ProcessEntry {
        public String name;      // Process name
        public boolean isEq;     // true means "=", false means "\\in"
        public TLAExpr id;       // set of identifiers or identifier
        public Vector decls;     // of ParDecl
        public String iPC;       // Initial pc of this process
        public AST.Process ast; // AST of the procedure
        // Added 13 Jan 2011 by LL 

        public ProcessEntry(AST.Process p) {
            this.name = p.name;
            this.isEq = p.isEq;
            this.id = p.id;
            this.decls = p.decls;
            this.ast = p;
            if (p.body.size() == 0) this.iPC = null;
            else {
                AST.LabeledStmt ls = (AST.LabeledStmt) p.body.elementAt(0);
                this.iPC = ls.label;
            }
        }
    } /* End of ProcessEntry */

    /**
     * As should be perfectly obvious from the name, this method constructs
     * the symbol table for the AST ast, which I presume contains all things
     * whose name must be looked up, which includes labels, variables, and
     * probably process and procedure names.
     * 
     * @param ast
     * @throws PcalSymTabException
     */
    public PcalSymTab (AST ast) throws PcalSymTabException {

        symtab = new Vector();
        iPC = null;
        disambiguateReport = new Vector();
        procs = new Vector();
        processes = new Vector();
        errorReport = "";
// Following line removed by LL on 3 Feb 2006
//        InsertSym(LABEL, "Done", "", "", 0, 0);

        InsertSym(GLOBAL, "pc", "", "", 0, 0);
        ExtractSym(ast, "");
        if (errorReport.length() > 0) throw new PcalSymTabException(errorReport);
    }

    /***************************************************
     * TRUE if inserted; false if was already in table *
     * Can not insert a variable of name x if there is *
     * a global with name x or another variable in the *
     * same context with name x.                       *
    /***************************************************/
    public boolean InsertSym (int type,
                              String id,
                              String context,
                              String cType,
                              int line, int col) {
        int i;
        if (type == PROCEDUREVAR || type == PROCESSVAR || type == PARAMETER) {
            i = FindSym(GLOBAL, id, "");
            if (i < symtab.size()) return false; /* GLOBAL with same id exists */
            i = FindSym(id, context);
            if (i < symtab.size()) return false; /* id in same context exists */
        }
        else {
            i = FindSym(type, id, context);
            if (i < symtab.size()) return false;
        }
        SymTabEntry se = new SymTabEntry(type, id, context, cType, line, col);
        symtab.addElement(se);
        return true;
    }

    /***************************************************
     * Insert procedure table entry.                   *
     * TRUE if inserted; false if was already in table *
     ***************************************************/
    public boolean InsertProc (AST.Procedure proc) {
        int i = FindProc(proc.name);
        if (i < procs.size()) return false;
        ProcedureEntry pe = new ProcedureEntry(proc);
        procs.addElement(pe);
        return true;
    }

    /***************************************************
     * Insert process table entry.                     *
     * TRUE if inserted; false if was already in table *
     ***************************************************/
    public boolean InsertProcess(AST.Process p) {
        int i = FindProcess(p.name);
        if (i < processes.size()) return false;
        ProcessEntry pe = new ProcessEntry(p);
        processes.addElement(pe);
        return true;
    }

    /*********************************************************
     * Various ways to look up something in the symbol table.*
     * Returns the index in the table. If the index equals   *
     * symtab.size() (which makes no sense), then it isn't   *
     * in the symbol table.                                  *
     *********************************************************/
    public int FindSym (int type, String id, String context) {
        int i = 0;
        while (i < symtab.size()) {
            SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
            if (se.id.equals(id) && se.context.equals(context)
                && se.type == type) return i;
            i = i + 1;
        }
        return i;
   }

    /*********************************************************
     * Returns first it finds with id and context, no matter *
     * what type it is.                                      *
     *********************************************************/
    public int FindSym (String id, String context) {
        int i = 0;
        while (i < symtab.size()) {
            SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
            if (se.id.equals(id) && se.context.equals(context))
                return i;
            i = i + 1;
        }
        return i;
   }

    /*********************************************************
     * Returns index of entry in procedure table. If it isn't*
     * in the table, then returns procs.size().              *
     *********************************************************/
    public int FindProc (String id) {
        int i = 0;
        while (i < procs.size()) {
            ProcedureEntry pe = (ProcedureEntry) procs.elementAt(i);
            if (pe.name.equals(id)) return i;
            i = i + 1;
        }
        return i;
   }

    /*********************************************************
     * Returns index of entry in process table. If it isn't  *
     * in the table, then returns procs.size().              *
     *********************************************************/
    public int FindProcess (String id) {
        int i = 0;
        while (i < processes.size()) {
            ProcessEntry pe = (ProcessEntry) processes.elementAt(i);
            if (pe.name.equals(id)) return i;
            i = i + 1;
        }
        return i;
   }

    /*********************************************************
     * Routines for returning disambiguated names.           *
     *********************************************************/
    
    /* Return the disambiguated name for a type X id X context */
    public String UseThis (int type, String id, String context) {
        int i = FindSym(type, id, context);
        if (i == symtab.size()) return id;
        else return ((SymTabEntry) symtab.elementAt(i)).useThis;
    }

    /* Return the disambiguated name for a label in a context */
    public String UseThisLab(String id, String context) {
        return UseThis(LABEL, id, context);
    }

    /*********************************************************
     * Given a variable referenced in a context. First get   *
     * the entry in the context. If no such variable, then   *
     * see if a global one exists. If not, then use it       *
     * undisambiguated.                                      *
     * NOTE: Stop using FindSym; it's a bad hack.            *
     *********************************************************/
    public String UseThisVar (String id, String context) {
        SymTabEntry se = null;
        int i = FindSym(id, context);
        if (i == symtab.size()) return id;
        se = (SymTabEntry) symtab.elementAt(i);
        if (se.type == GLOBAL || se.type == PROCESSVAR
            || se.type == PROCEDUREVAR || se.type == PARAMETER)
            return se.useThis;
        i = FindSym(id, "");
        if (se.type == GLOBAL) return se.useThis;
        return id;
    }

    /*********************************************************
     * Return first variable in this context.                *
     *********************************************************/
    public String UseThis (String id, String context) {
        int i = 0;
        while (i < symtab.size()) {
            SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
            if (se.id.equals(id) && se.context.equals(context)
                && (se.type == GLOBAL || se.type == PROCESSVAR 
                    || se.type == PROCEDUREVAR || se.type == PARAMETER)) break;
            i = i + 1;
        }
        if (i == symtab.size()) return id;
        else return ((SymTabEntry) symtab.elementAt(i)).useThis;
    }

    /*********************************************************
     * TRUE if id is ambiguous.                              *
     *********************************************************/
    private boolean Ambiguous (String id) {
        int i = 0;
        boolean found = false;
        while (i < symtab.size()) {
            SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
            if (se.useThis.equals(id)) {
                if (! found) found = true;
                else return true;
            }
            i = i + 1;
        }
        return false;
    }

    /**************************************************************************
     * Disambiguating names. First, names are prepended with a type specific  *
     * string, defined in the array typePrefix. Then, the names are           *
     * considered in increasing type order. The first type in this order      *
     * are left unchanged. Then, each other order has a suffix appended to it *
     * until it is unique from all the current symbol names (both renamed and *
     * not yet renamed). The suffix is a prefix of "_context" where "context" *
     * is the context in which the name is defined (which is the empty string *
     * for the global context). If it is still not unique after all of the    *
     * context is appended, then the decimal representation of the name type  *
     * is added repeatedly until it is unambiguous.                           *
     **************************************************************************/
    public void Disambiguate ( ) {
        for (int vtype = 0; vtype <= num_vtypes; vtype++)
            for (int i = 0; i < symtab.size(); i++) {
                SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
                if (se.type == vtype) {
                    se.useThis = typePrefix[vtype] + se.id;
                    int suffixLength = 0;
                    while (vtype > 0 && Ambiguous(se.useThis)) {
                        suffixLength = suffixLength + 1;
                        if (suffixLength == 1) se.useThis = se.useThis + "_";
                        else if (suffixLength > se.context.length() + 1)
                            se.useThis = se.useThis + vtype;
                        else se.useThis = se.useThis
                            + se.context.charAt(suffixLength - 2);
                    }
                    if (! se.id.equals(se.useThis))
                        disambiguateReport.addElement(
                        "\\* " +
                        vtypeName[se.type] +
                        " " +
                        se.id +
                        ((se.context.length() == 0)
                         ? "" 
                         : (" of " + se.cType + " " + se.context)) +
                        " at line " + se.line + " col " + se.col +
                        " changed to " +
                        se.useThis);
                }
            }
    }

    public String toString ( ) {
        int i = 0;
        String result = "[";
        while (i < symtab.size()) {
           SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
            if (i > 0) result = result + ", ";
            result = result + vtypeName[se.type] + " " + se.context
                + ':' + se.id + " line " + se.line + " col " +
                se.col + " (" + se.useThis + ")";
            i = i + 1;
        }
        return result + "]";
    }

    /********************************
     * Type generic extract routine *
     ********************************/
    private void ExtractSym (AST ast, String context) {
        if (ast.getClass().equals(AST.UniprocessObj.getClass()))
            ExtractUniprocess((AST.Uniprocess) ast, context);
        else if (ast.getClass().equals(AST.MultiprocessObj.getClass()))
            ExtractMultiprocess((AST.Multiprocess) ast, context);
        else PcalDebug.ReportBug("Unexpected AST type.");
    }

    private void ExtractStmt (AST ast, String context, String cType) {
         if (ast.getClass().equals(AST.WhileObj.getClass()))
            ExtractWhile((AST.While) ast, context, cType);
        else if (ast.getClass().equals(AST.AssignObj.getClass()))
            ExtractAssign((AST.Assign) ast, context, cType);
        else if (ast.getClass().equals(AST.IfObj.getClass()))
            ExtractIf((AST.If) ast, context, cType);
        else if (ast.getClass().equals(AST.WithObj.getClass()))
            ExtractWith((AST.With) ast, context, cType);
        else if (ast.getClass().equals(AST.WhenObj.getClass()))
            ExtractWhen((AST.When) ast, context, cType);
        else if (ast.getClass().equals(AST.PrintSObj.getClass()))
            ExtractPrintS((AST.PrintS) ast, context, cType);
        else if (ast.getClass().equals(AST.AssertObj.getClass()))
            ExtractAssert((AST.Assert) ast, context, cType);
        else if (ast.getClass().equals(AST.SkipObj.getClass()))
            ExtractSkip((AST.Skip) ast, context, cType);
        else if (ast.getClass().equals(AST.LabelIfObj.getClass()))
            ExtractLabelIf((AST.LabelIf) ast, context, cType);
        else if (ast.getClass().equals(AST.CallObj.getClass()))
            ExtractCall((AST.Call) ast, context, cType);
        else if (ast.getClass().equals(AST.ReturnObj.getClass()))
            ExtractReturn((AST.Return) ast, context, cType);
        else if (ast.getClass().equals(AST.CallReturnObj.getClass()))
            ExtractCallReturn((AST.CallReturn) ast, context, cType);
        else if (ast.getClass().equals(AST.CallGotoObj.getClass()))
            ExtractCallGoto((AST.CallGoto) ast, context, cType);
        else if (ast.getClass().equals(AST.GotoObj.getClass()))
            ExtractGoto((AST.Goto) ast, context, cType);

        /*******************************************************************
        * Handling of Either and LabelEither added by LL on 24 Jan 2006.   *
        *******************************************************************/
        else if (ast.getClass().equals(AST.EitherObj.getClass()))
            ExtractEither((AST.Either) ast, context, cType);
        else if (ast.getClass().equals(AST.LabelEitherObj.getClass()))
            ExtractLabelEither((AST.LabelEither) ast, context, cType);
        else PcalDebug.ReportBug("Unexpected AST type " + ast.toString());
    }


    /**********************************************
     * Type specific extraction routines.         *
     **********************************************/

    private void ExtractUniprocess (AST.Uniprocess ast, String context) {
// On 3 Feb 2006, LL moved insertion of "stack" before extraction of 
// global variable decls, so use of "stack" as a global variable would be 
// detected.
        if (ast.prcds.size() > 0) InsertSym(GLOBAL, "stack", "", "", 0, 0);
        for (int i = 0; i < ast.decls.size(); i++)
            ExtractVarDecl((AST.VarDecl) ast.decls.elementAt(i), "");
        for (int i = 0; i < ast.prcds.size(); i++)
            ExtractProcedure((AST.Procedure) ast.prcds.elementAt(i), "");
        if (ast.body.size() > 0) {
            AST.LabeledStmt ls = (AST.LabeledStmt) ast.body.elementAt(0);
            iPC = ls.label;
        }
        for (int i = 0; i < ast.body.size(); i++) {
            ExtractLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i), "", "");
        }
    }
        
    private void ExtractMultiprocess (AST.Multiprocess ast, String context) {
// On 3 Feb 2006, LL moved insertion of "stack" before extraction of 
// global variable decls, so use of "stack" as a global variable would be 
// detected.
        if (ast.prcds.size() > 0) InsertSym(GLOBAL, "stack", "", "", 0, 0);
        for (int i = 0; i < ast.decls.size(); i++)
            ExtractVarDecl((AST.VarDecl) ast.decls.elementAt(i), "");
        for (int  i = 0; i < ast.prcds.size(); i++)
            ExtractProcedure((AST.Procedure) ast.prcds.elementAt(i), "");
        for (int i = 0; i < ast.procs.size(); i++)
            ExtractProcess((AST.Process) ast.procs.elementAt(i), "");
    }

    private void ExtractProcedure (AST.Procedure ast, String context) {
        
        if (! InsertProc(ast))
            errorReport = errorReport + "\nProcedure " + ast.name +
            		" redefined at line " + ast.line + ", column " + ast.col;
        boolean b = InsertSym(PROCEDURE,
                      ast.name,
                      context,
                      "procedure",
                      ast.line,
                      ast.col);
        for (int i = 0; i < ast.decls.size(); i++)
            ExtractPVarDecl((AST.PVarDecl) ast.decls.elementAt(i), ast.name);
        for (int i = 0; i < ast.params.size(); i++)
            ExtractParamDecl((AST.PVarDecl) ast.params.elementAt(i), ast.name);
        for (int i = 0; i < ast.body.size(); i++)
            ExtractLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i),
                               ast.name,
                               "procedure");
    }
        
    private void ExtractProcess(AST.Process ast, String context) {
        boolean b;
        if (! InsertProcess(ast))
            errorReport = errorReport + "\nProcess " + ast.name +
            		" redefined at line " + ast.line + ", column " + ast.col;
        b = InsertSym(PROCESS, ast.name, context, "process", ast.line, ast.col);
        for (int i = 0; i < ast.decls.size(); i++)
            ExtractVarDecl((AST.VarDecl) ast.decls.elementAt(i), ast.name);
        for (int i = 0; i < ast.body.size(); i++)
            ExtractLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i),
                               ast.name,
                               "process");
    }
        
    private void ExtractVarDecl(AST.VarDecl ast, String context) {
        int vtype = (context == "") ? GLOBAL : PROCESSVAR;
        if (! InsertSym(vtype, ast.var, context, "process", ast.line, ast.col))
            errorReport = errorReport + "\n" + vtypeName[vtype] + " " + ast.var +
            " redefined at line " + ast.line + ", column " + ast.col;
    }

    private void ExtractPVarDecl(AST.PVarDecl ast, String context) {
        if (! InsertSym(PROCEDUREVAR,
                        ast.var,
                        context,
                        "procedure",
                        ast.line,
                        ast.col))
            errorReport = errorReport + "\nProcedure variable " + ast.var +
            " redefined at line " + ast.line + ", column " + ast.col;
    }

    private void ExtractParamDecl(AST.PVarDecl ast, String context) {
        if (! InsertSym(PARAMETER,
                        ast.var,
                        context,
                        "procedure",
                        ast.line,
                        ast.col))
            errorReport = errorReport + "\nParameter " + ast.var +
            " redefined at line " + ast.line + ", column " + ast.col;
    }

    private void ExtractLabeledStmt(AST.LabeledStmt ast,
                                    String context,
                                    String cType) {
        if (! InsertSym(LABEL, ast.label, context, cType, ast.line, ast.col))
            errorReport = errorReport + "\nLabel " + ast.label +
                " redefined at line " + ast.line + ", column " + ast.col;
        for (int i = 0; i < ast.stmts.size(); i++)
            ExtractStmt((AST) ast.stmts.elementAt(i), context, cType);
    }

    private void ExtractWhile(AST.While ast, String context, String cType) {
        for (int i = 0; i < ast.unlabDo.size(); i++)
            ExtractStmt((AST) ast.unlabDo.elementAt(i), context, cType);
        for (int  i = 0; i < ast.labDo.size(); i++)
            ExtractLabeledStmt((AST.LabeledStmt) ast.labDo.elementAt(i),
                               context,
                               cType);
    }

    private void ExtractAssign(AST.Assign ast, String context, String cType) {
    }

    private void ExtractIf(AST.If ast, String context, String cType) {
        for (int i = 0; i < ast.Then.size(); i++)
            ExtractStmt((AST) ast.Then.elementAt(i), context, cType);
        for (int i = 0; i < ast.Else.size(); i++)
            ExtractStmt((AST) ast.Else.elementAt(i), context, cType);
    }

    private void ExtractWith(AST.With ast, String context, String cType) {
        for (int i = 0; i < ast.Do.size(); i++)
            ExtractStmt((AST) ast.Do.elementAt(i), context, cType);
    }

    private void ExtractWhen(AST.When ast, String context, String cType) {
    }

    private void ExtractPrintS(AST.PrintS ast, String context, String cType) {
    }

    private void ExtractAssert(AST.Assert ast, String context, String cType) {
    }

    private void ExtractSkip(AST.Skip ast, String context, String cType) {
    }

    private void ExtractLabelIf(AST.LabelIf ast, String context, String cType) {
        for (int i = 0; i < ast.unlabThen.size(); i++) 
            ExtractStmt((AST) ast.unlabThen.elementAt(i), context, cType);
        for (int i = 0; i < ast.labThen.size(); i++)
            ExtractLabeledStmt((AST.LabeledStmt) ast.labThen.elementAt(i),
                               context,
                               cType);
        for (int i = 0;  i < ast.unlabElse.size(); i++)
            ExtractStmt((AST) ast.unlabElse.elementAt(i), context, cType);
        for (int i = 0; i < ast.labElse.size(); i++)
            ExtractLabeledStmt((AST.LabeledStmt) ast.labElse.elementAt(i),
                               context,
                               cType);
    }

    private void ExtractCall(AST.Call ast, String context, String cType) {
    }

    private void ExtractReturn(AST.Return ast, String context, String cType) {
    }

    private void ExtractCallReturn(AST.CallReturn ast,
                                   String context,
                                   String cType) {
    }

    private void ExtractCallGoto(AST.CallGoto ast,
                                 String context,
                                 String cType) {
    }

    private void ExtractGoto(AST.Goto ast, String context, String cType) {
    }

    /***********************************************************************
    * Handling of Either and LabelEither added by LL on 24 Jan 2006.       *
    ***********************************************************************/
    private void ExtractEither(AST.Either ast, String context, String cType) {
        for (int i = 0; i < ast.ors.size(); i++)
              { Vector orClause = (Vector) ast.ors.elementAt(i) ;
                for (int j = 0; j < orClause.size(); j++)
                  ExtractStmt((AST) orClause.elementAt(j), context, cType);
               } ;
   }

    private void ExtractLabelEither(AST.LabelEither ast, String context, 
                                    String cType) {
        for (int i = 0; i < ast.clauses.size(); i++)
              { AST.Clause orClause = (AST.Clause) ast.clauses.elementAt(i) ;
                for (int j = 0; j < orClause.unlabOr.size(); j++)
                  ExtractStmt((AST) orClause.unlabOr.elementAt(j), 
                                 context, cType);
                 for (int j = 0; j < orClause.labOr.size(); j++)
                   ExtractLabeledStmt((AST.LabeledStmt) 
                                          orClause.labOr.elementAt(j), 
                                       context, cType);
               } ;
    }

   /************************************************************************
   * Reports an error if "defaultInitValue" appears in the symbol table.   *
   * Added by LL on 31 Aug 2007.                                           *
   ************************************************************************/
   public void CheckForDefaultInitValue() throws PcalSymTabException {
     String errors = "" ;
     for (int i = 0 ; i < symtab.size() ; i++) 
       { SymTabEntry se = (SymTabEntry) symtab.elementAt(i);
         if (se.id.equals("defaultInitValue")) 
           { if (errors.equals(""))
               { errors = "Cannot use `defaultInitValue' as " ;}
             else {errors = errors + " or " ;} ;
             errors = errors + vtypeName[se.type] + " name";
           } ;
       } ;
     if (! errors.equals(""))
       { throw new PcalSymTabException(errors) ; } ;
     return ;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/handler/CheckProofHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.handler;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;

/**
 * Launches TLAPM on the proof step currently containing the caret or on the
 * entire module if the caret is not at a proof step. See 
 * {@link ProverHelper#runProverForActiveSelection(boolean, boolean)} to see how it works.
 * 
 * @author <NAME>
 */
public class CheckProofHandler extends AbstractProverHandler implements IHandler {
	public Object execute(ExecutionEvent event) throws ExecutionException {
		/*
		 * See the comments for the following method for its effect and implementation.
		 */
		ProverHelper.runProverForActiveSelection(false, true);

		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/preference/TLA2TeXPreferenceInitializer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.preference;

import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.lamport.tla.toolbox.tool.tla2tex.TLA2TeXActivator;

/**
 * Gives default preferences for TLA2TeX
 * 
 * @author <NAME>
 */
public class TLA2TeXPreferenceInitializer extends AbstractPreferenceInitializer {

	public void initializeDefaultPreferences() {
		IPreferenceStore store = TLA2TeXActivator.getDefault()
				.getPreferenceStore();
		store.setDefault(ITLA2TeXPreferenceConstants.SHADE_COMMENTS, true);
		store.setDefault(ITLA2TeXPreferenceConstants.NO_PCAL_SHADE, false);
        store.setDefault(ITLA2TeXPreferenceConstants.NUMBER_LINES, false);
		store.setDefault(ITLA2TeXPreferenceConstants.DOT_COMMAND, "dot");
		store.setDefault(ITLA2TeXPreferenceConstants.LATEX_COMMAND, "pdflatex");
		store.setDefault(ITLA2TeXPreferenceConstants.GRAY_LEVEL, "0.85");
		store.setDefault(ITLA2TeXPreferenceConstants.HAVE_OS_OPEN_PDF, false);
		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			// Support for the built-in viewer has ended on MACOSX, thus disable
			// even if user enabled it in an earlier Toolbox release.
			store.setValue(ITLA2TeXPreferenceConstants.EMBEDDED_VIEWER, false);
		} else {
			store.setDefault(ITLA2TeXPreferenceConstants.EMBEDDED_VIEWER, true);
			store.setValue(ITLA2TeXPreferenceConstants.HAVE_OS_OPEN_PDF, false);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/util/ProverSpecLifecycleParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.util;

import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;

/**
 * This class listens to changes in specs in order to update information
 * about prover obligations. In particular, it does two things:
 * 
 * 1.) When a spec is closed, it cancels all running prover jobs
 *     and then removes all obligation markers on that spec.
 * 
 * 2.) When a spec is opened, it refreshes the obligation view so that if the view
 *     is currently open, it does not continue to display information about
 *     obligations from the previously opened spec.
 *     
 * @author <NAME>
 */
public class ProverSpecLifecycleParticipant extends SpecLifecycleParticipant {

	public boolean eventOccured(SpecEvent event) {
		/*
		 * If a spec if being closed remove all obligation markers on that spec
		 * and cancel any running prover jobs.
		 * 
		 * If a spec is being opened, refresh the obligation view.
		 */
		if (event.getType() == SpecEvent.TYPE_CLOSE) {
			try {
				/*
				 * Running provers must be killed before clearing obligations
				 * markers because the running jobs can continue to contribute
				 * new obligation markers.
				 * 
				 * The following two invocations don't access the UI and can
				 * thus be safely run from this Extension Point created
				 * ProverSpecLifecycleParticipant.
				 */
				ProverHelper.cancelProverJobs(true);
				ProverHelper.clearObligationMarkers(event.getSpec().getProject());
			} catch (CoreException e) {
				ProverUIActivator.getDefault().logError(
						"Error removing obligation markers from spec " + event.getSpec().getName()
								+ " when it was closed.", e);
			}
		}
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/management/StateMonitor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.management;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

import tlc2.tool.distributed.management.TLCStatisticsMXBean;

/*
 * This class does not compile in the Eclipse IDE on Ubuntu 18.04 with JaveSE1.8 linked to the
 * 8u201-1~webupd8~1 JVM installed from webupd8 and probably fails to compile elsewhere too,
 * because Eclipse fails to find the com.sun.tools.attach classes.  The fix is to add the JDK's
 * tools.jar to the Java installation.  On Java 11 this doesn't seem to be an issue.
 */
public class StateMonitor {

	private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$ 

	public static void main(String[] args) throws IOException, MalformedObjectNameException, InterruptedException, AttachNotSupportedException {
		int interval = 10; // 10sec interval by default
		if (args.length == 1) {
			interval = Integer.valueOf(args[0]);
		}
		
		JMXServiceURL url = null;
		try {
			final List<VirtualMachineDescriptor> vmds = com.sun.tools.attach.VirtualMachine.list();
			vmds.sort(new Comparator<VirtualMachineDescriptor>() {
				@Override
				public int compare(VirtualMachineDescriptor o1, VirtualMachineDescriptor o2) {
					// Sort those vms higher whose display name contains TLC.
					final boolean c1 = o1.displayName().contains("TLC");
					final boolean c2 = o2.displayName().contains("TLC");
					if (c1 ^ c2) {
						if (c1) {
							return -1;
						}
						return 1;
					}
					return 0;
				}
			});
			
			int index = 1;
			try (Scanner scanner = new Scanner(System.in)) {
				rd: while (true) {
					index = 1;
					System.out.printf("============\n");
					for (VirtualMachineDescriptor vmd : vmds) {
						System.out.printf("[%s]: pid=%s, name=%s\n", index++, vmd.id(), vmd.displayName());
					}
					System.out.printf("Please select the number of the Java VM running TLC to connect to:\n");
					if (scanner.hasNextInt()) {
						index = scanner.nextInt();
						
						// Check index is within bounds.
						if (index >= 1 && index <= vmds.size()) {
							break rd;
						}
					}
					System.err.printf("Invalid selection %s\n", index);
				}
			}
			final VirtualMachineDescriptor tlcVMD = vmds.get(index - 1);
			final VirtualMachine vm = tlcVMD.provider().attachVirtualMachine(tlcVMD);
			final String address = vm.startLocalManagementAgent();
			url = new JMXServiceURL(address);
			System.out.printf("Connecting to TLC running at %s.\n(Hit Ctrl+c to terminate)\n", url);
		} catch (NumberFormatException nfe) {
			// If monitored VM has been launched with explicit port, use service url instead
			// of CAL:
			// -Dcom.sun.management.jmxremote
			// -Dcom.sun.management.jmxremote.port=10995
			// -Dcom.sun.management.jmxremote.ssl=false
			// -Dcom.sun.management.jmxremote.authenticate=false
			// => "service:jmx:rmi:///jndi/rmi://localhost:10995/jmxrmi".
			url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + "/jmxrmi");
			System.out.printf("Connecting to TLC running at %s.\n(Hit Ctrl+c to terminate)\n", url);
		}
		
		final JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
		final MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
		// ObjectName should be same as your MBean name
		final ObjectName mbeanName = new ObjectName(ModelCheckerMXWrapper.OBJ_NAME);

		// Get MBean proxy instance that will be used to make calls to registered MBean
		final TLCStatisticsMXBean mbeanProxy = (TLCStatisticsMXBean) MBeanServerInvocationHandler
				.newProxyInstance(mbeanServerConnection, mbeanName, TLCStatisticsMXBean.class, true);

		while (true) {
			System.out.printf("############ %s ############\n%s", SDF.format(new Date()), mbeanProxy.getCurrentState());
			Thread.sleep(interval * 1000L);
		}
		
		// No need to close the connection because JVM itself terminates.
		//jmxConnector.close();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/other/CheckFP.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

package tlc2.tool.other;

import java.io.IOException;

import tlc2.util.BufferedRandomAccessFile;

/**
 * <NAME> told us that
 *  1. We are probably in trouble if any two fingerprints have the
 *     same high order 56 bits.
 *  2. With a lot of hand waving, the probability of collision is
 *     about the max of 1/|fi - fj|.
 * This program does these sanity checkings.
 * @deprecated (SZ February 19, 2009)
 */
public class CheckFP {
  public static void main(String args[]) {
    try {
      @SuppressWarnings("resource")
	  BufferedRandomAccessFile raf = new BufferedRandomAccessFile(args[0], "r");
      long fileLen = raf.length();
      long dis = Long.MAX_VALUE;
      int cnt = 0;
      long x = raf.readLong();
      while (raf.getFilePointer() < fileLen) {
	long y = raf.readLong();
	if ((x >> 8) == (y >> 8))
	  System.err.println("bad: " + x + " and " + y);
	dis = Math.min(dis, y-x);
	x = y;
	cnt++;
	if ((cnt & 0xFFFF) == 0)
	  System.err.println("the number of states checked: " + cnt);
      }
      System.err.println("the number of states checked: " + cnt);
      System.err.println("the probability of collision: " + 1.0/dis);
    }
    catch (IOException e) {
      System.err.println("Error: " + e.getMessage());
      System.exit(1);
    }
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jclouds/src/org/lamport/tla/toolbox/jcloud/PacketNetCloudTLCInstanceParameters.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.jcloud;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jclouds.compute.domain.TemplateBuilder;

public class PacketNetCloudTLCInstanceParameters extends CloudTLCInstanceParameters {

	public PacketNetCloudTLCInstanceParameters(final String tlcParams, int numberOfWorkers) {
		super(tlcParams.trim(), numberOfWorkers);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaVMArgs()
	 */
	@Override
	public String getJavaVMArgs() {
		return System.getProperty("packetnet.vmargs", super.getJavaVMArgs("-Xmx6G -Xms6G"));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaWorkerVMArgs()
	 */
	@Override
	public String getJavaWorkerVMArgs() {
		return System.getProperty("packetnet.vmworkerargs",
				super.getJavaWorkerVMArgs("-Xmx4G -Xms4G -XX:MaxDirectMemorySize=2g"));
	}
	
	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getTLCParameters()
	 */
	@Override
	public String getTLCParameters() {
		return System.getProperty("packetnet.tlcparams", super.getTLCParameters(4));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getCloudProvier()
	 */
	@Override
	public String getCloudProvider() {
		return "packet"; // as defined by jclouds.
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getRegion()
	 */
	@Override
	public String getRegion() {
		return System.getProperty("packetnet.region", "sjc1");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getImageId()
	 */
	@Override
	public String getImageId() {
		return System.getProperty("packetnet.image", "ubuntu_18_04");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getHardwareId()
	 */
	@Override
	public String getHardwareId() {
		return System.getProperty("packetnet.instanceType", "baremetal_0"); // t1.small.x86 whose "slug" is baremetal_0.
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getIdentity()
	 */
	@Override
	public String getIdentity() {
		final String identity = System.getenv("PACKET_NET_PROJECT_ID");
		Assert.isNotNull(identity);
		return identity;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getCredentials()
	 */
	@Override
	public String getCredentials() {
		final String credential = System.getenv("PACKET_NET_APIKEY");
		Assert.isNotNull(credential);
		return credential;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#validateCredentials()
	 */
	@Override
	public IStatus validateCredentials() {
		final String credential = System.getenv("PACKET_NET_PROJECT_ID");
		final String identity = System.getenv("PACKET_NET_APIKEY");
		if (credential == null || identity == null) {
			return new Status(Status.ERROR, "org.lamport.tla.toolbox.jcloud",
					"Invalid credentials, please check the environment variables "
							+ "(PACKET_NET_PROJECT_ID "
							+ "and PACKET_NET_APIKEY) are correctly "
							+ "set up and picked up by the Toolbox."
							+ "\n\nPlease visit the Toolbox help and read section 4 "
							+ "of \"Cloud based distributed TLC\" on how to setup authentication.");
		}
		return Status.OK_STATUS;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#mungeTemplateBuilder(org.jclouds.compute.domain.TemplateBuilder)
	 */
	@Override
	public void mungeTemplateBuilder(TemplateBuilder templateBuilder) {
        templateBuilder.locationId(getRegion());
	}

	@Override
	public String getCloudAPIShutdown(final String credentials, String groupName) {
		// One might think we could simply invoke curl and terminate the instance right
		// away. That doesn't work because we want the instance to idle until the
		// scheduled shutdown call executes in case the Toolbox reuses the instance to
		// run another model.
//		return String.format("/usr/bin/curl -X DELETE -H X-Auth-Token:%s https://api.packet.net/devices/%s", credentials, nodeId);
		return String.format(
				"printf \"#!/bin/bash\\n"
				+ "if /usr/bin/curl https://metadata.packet.net/metadata 2>/dev/null | jq -e -r '.tags | index(\\\"power_off\\\")' > /dev/null; then\\n"
				+ " /usr/bin/curl -X POST -H X-Auth-Token:%s https://api.packet.net/devices/$(curl https://metadata.packet.net/metadata 2>/dev/null | jq -r '.id')/actions?type=power_off\\n"
				+ "else\\n"
				+ " /usr/bin/curl -X DELETE -H X-Auth-Token:%s https://api.packet.net/devices/$(curl https://metadata.packet.net/metadata 2>/dev/null | jq -r '.id')\\n"
				+ "fi\\n\" | sudo tee /usr/local/bin/packetnet.sh"
				+ " && sudo chmod +x /usr/local/bin/packetnet.sh"
				+ " && "
				+ "printf \"[Unit]\\nDescription=Delete instance via packetnet api on shutdown\\n"
				+ "Requires=network.target\\n"
				+ "After=network.target\\n"
				+ "DefaultDependencies=no\\n"
				+ "Before=shutdown.target\\n"
				+ "[Service]\\n"
				+ "Type=oneshot\\n"
				+ "RemainAfterExit=true\\n"
				+ "ExecStart=/bin/true\\n"
				+ "ExecStop=/usr/local/bin/packetnet.sh\\n"
				+ "[Install]\\n"
				+ "WantedBy=multi-user.target\\n\" | sudo tee /lib/systemd/system/delete-on-shutdown.service"
				+ " && systemctl enable delete-on-shutdown" // restart delete-on-shutdown service after a reboot.
				+ " && service delete-on-shutdown start",
				credentials, credentials);
		
		/*
			@packethost Can I somehow set (upon creation) servers to be automatically be deleted on an OS shutdown?
			@lemmster Not at the moment - you can control that from your automation / etc but we're not in the habit (in our API or otherwise) of deleting things on the behalf of clients.  Make sense?
			@packethost Others (Azure & AWS) do support automatic deletion. Why not make it a flag on instance creation?
			@lemmster Actually I lied, we do revoke in our spot market. We actually have the ability but always found that the risk (why did you delete my database) was more than the benefit.  Sorry!
			@packethost Me: Why did you delete my database? You: Because you told us to (by setting the delete-upon-shutdown flag during instance creation)!
			@lemmster For Ubuntu pass this userdata to create the delete-on-shutdown service for Packet's API. Not quite a flag but works!  gist.github.com/nathangoulding…
			@NathanGoulding Thanks! Just slightly worried about the security implications of having API token on the instance.
			@lemmster For sure, best to pull from an envvar or something like Vault vs. embedding (and certainly not passing via https userdata).
			@NathanGoulding I don't understand how an envvar or a vault - for which I need another secret to unlock, no? - solves the fundamental problem of having the API token on the instance?
			@lemmster You can limit the blast radius significantly with certs/keys that are single-use, tied to that specific instance, and/or revocable. If you can't trust the instance at all then yes you're stuck.
			@NathanGoulding Can I generate a single-use API subkey which is possibly even restricted to a specific instance?
			@NathanGoulding Could even be part of the response to the instance creation API call.
			@NathanGoulding Generally though, an instance creation flag is both simple and secure.
			@lemmster Agreed, unfortunately we don't have a hypervisor present to intercept the system shutdown call.
			@lemmster 'Unfortunately' in this one case at least ;)
			@NathanGoulding I assume that the same reason why servers show up as running in the admin frontend when shutdown locally?
			@lemmster Exactly, and I think our API calls them "active" to avoid "on/off" verbiage, but that green circle does look a lot like "on"
			
			https://twitter.com/NathanGoulding/status/1089990444287696897
			
			https://gist.github.com/nathangoulding/6a69b3fd7023bf3f558acfc7bb9ba645
		 */
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/Validator.java<|end_filename|>
package pcal;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;

import pcal.exception.ParseAlgorithmException;
import pcal.exception.RemoveNameConflictsException;
import tla2sany.modanalyzer.ParseUnit;
import tla2sany.st.Location;
import util.TLAConstants;

/**
 * This class validates the recorded checksums generated from an input specification's PlusCal and translated PlusCal
 * blocks.
 */
public class Validator {

	public enum ValidationResult {
		/** No PlusCal algorithm exists in the specification */
		NO_PLUSCAL_EXISTS,
		
		/** No translation exists - BUT THERE IS PLUSCAL IN THE SPECIFICATION! */
		NO_TRANSLATION_EXISTS,
		
		NO_TLA_CHECKSUMS_EXIST,
		NO_PCAL_CHECKSUMS_EXIST,
		
		TLA_DIVERGENCE_EXISTS,
		PCAL_DIVERGENCE_EXISTS,
		
		/** A Java error was encountered while attempting to validate. */
		ERROR_ENCOUNTERED,
		
		/** Everything checks out. */
		NO_DIVERGENCE;
	}
	
	static final String PCAL_CHECKSUM = "pcalchecksum";
	static final String TLA_CHECKSUM = "tlachecksum";
	
	static final String FAIR = "fair";
	
	static final String CHECKSUM_TEMPLATE_IGNORE = "(chksum(pcal) \\in STRING /\\ chksum(tla) \\in STRING)";
	static final String CHECKSUM_TEMPLATE = "(chksum(pcal) = \"%s\" /\\ chksum(tla) = \"%s\")";
	
	static final Pattern CHECKSUM_PATTERN = Pattern
			.compile("\\\\\\* BEGIN TRANSLATION\\s+\\(\\s*((?i)ch(ec)?ksum\\(p(lus)?cal\\)(?-i))\\s*(=\\s*\\\"(?<"
					+ PCAL_CHECKSUM + ">[0-9A-Fa-f]*)\\\"|\\\\in\\s*"
					+ "STRING)\\s*\\/\\\\\\s*((?i)ch(ec)?ksum\\(tla\\+?\\)(?-i))\\s*(=\\s*\\\"(?<" + TLA_CHECKSUM
					+ ">[0-9A-Fa-f]*)\\\"|\\\\in\\s*STRING)\\s*\\)");

	private static final Pattern MODULE_CLOSING_PATTERN = Pattern.compile(TLAConstants.MODULE_CLOSING_REGEX);

	public static Set<ValidationResult> validate(ParseUnit parseUnit, InputStream inputStream)
			throws IOException {
		final BufferedReader reader = new BufferedReader(
				new InputStreamReader((inputStream instanceof BufferedInputStream) ? (BufferedInputStream) inputStream
						: new BufferedInputStream(inputStream)));
		return validate(parseUnit, reader);
	}
	
	public static Set<ValidationResult> validate(final ParseUnit parseUnit, final BufferedReader reader) throws IOException {
		// Instead of matching the module start and end markers, whe while loop use SANY's
		// parse tree that has the location of the start and end markers.
		final Location loc = parseUnit.getParseTree().getLocation();
		
		// Pre-allocate the number of lines we will read below.
		final List<String> lines = new ArrayList<>(loc.endLine() - loc.beginLine());
		
		// TODO It would be faster to let SANY look for a PlusCal algorithm when it
		// parses the TLA+ spec (although SANY probably doesn't parse comments, it
		// could look for the "--algorithm" or "--fair algorithm" tokens).
		boolean seenAlgo = false;
		int cnt = 1; // Location is 1-indexed.
		String line;
		while ((line = reader.readLine()) != null) {
			// Skip lines that are not within the range given by location.
			// This implies that this loop will miss "pluscal options" before
			// or after the module's start and end markers.  While it is legal to
			// put options there, I've decided we don't want to pay the price
			// of parsing the lines preceding or after a module.  Users can
			// put the options into a comment inside the module, which I
			// believe to be the choice for most users anyway.
			if (loc.beginLine() <= cnt && cnt <= loc.endLine()) {
				if (line.indexOf(PcalParams.BeginAlg.substring(2)) > 0) {
					seenAlgo = true;
				}
				lines.add(line);
			} else if (cnt >= loc.endLine()) {
				break;
			}
			cnt++;
		}
		
		if (!seenAlgo) {
			// No "algorithm" string in the input => No PlusCal algorithm.
			// The appearance of "algorithm", however, might be a false
			// positive of which validate will take care of (I don't have
			// time to move the logic up here).
			return setOf(ValidationResult.NO_PLUSCAL_EXISTS);
		}
		return validate(lines);
	}
	
	/**
	 * There is some redundancy between this and {@link trans#performTranslation(List)} - it would be nice to make a
	 * 	common method, extended by each.
	 * 
	 * @param specificationText the entire specification, line by line - for historical reasons.
	 * @return the result of the validation, as enumerated by the inner enum of this class.
	 */
	private static Set<ValidationResult>  validate(final List<String> specificationText) {
        final Vector<String> deTabbedSpecification = trans.removeTabs(specificationText);
		
        final IntPair searchLoc = new IntPair(0, 0);
        boolean notDone = true;
		while (notDone) {
			try {
				/*
				 * As mentioned in #413, this is a performance bottleneck point; unfortunately we need process the
				 *		options as it affects the production of the AST and we base the checksum on the AST.
				 * We have addressed a use case in which there is a long run of line prefacing the module specification
				 * 		in the {@link #validate(InputStream)} method, but that doesn't address a long spec.
				 * If we wanted to devote more time to this, we should examine the performance difference between
				 * 		the character-by-character marching done in the ParseAlgorithm code versus using a
				 * 		regex matcher to split apart lines.
				 */
                ParseAlgorithm.FindToken("PlusCal", deTabbedSpecification, searchLoc, "");
                final String line = ParseAlgorithm.GotoNextNonSpace(deTabbedSpecification, searchLoc);
                final String restOfLine = line.substring(searchLoc.two);
				if (restOfLine.startsWith("options")) {
                    // The first string after "PlusCal" not starting with a
                    // space character is "options"
					if (ParseAlgorithm.NextNonIdChar(restOfLine, 0) == 7) {
                        // The "options" should begin an options line
                        PcalParams.optionsInFile = true;
                        ParseAlgorithm.ProcessOptions(deTabbedSpecification, searchLoc);
                        notDone = false;
                    }
                }
			} catch (ParseAlgorithmException e) {
                // The token "PlusCal" not found.
                notDone = false;
            }
        }
        
        int algLine = 0;
        int algCol = -1;
        // Search for "--algorithm" or "--fair".
        // If found set algLine and algCol right after the last char,
        // set foundBegin true, and set foundFairBegin true iff it
        // was "--fair".  Otherwise, set foundBegin false.
        boolean foundBegin = false;
        boolean foundFairBegin = false;
		while ((algLine < deTabbedSpecification.size()) && !foundBegin) {
			final String line = deTabbedSpecification.elementAt(algLine);
			final Matcher m = MODULE_CLOSING_PATTERN.matcher(line);
			if (m.matches()) {
				break;
			}
			
			algCol = line.indexOf(PcalParams.BeginAlg);
			if (algCol != -1) {
				algCol = algCol + PcalParams.BeginAlg.length();
				foundBegin = true;
			} else {
            	algCol = line.indexOf(PcalParams.BeginFairAlg);
            	if (algCol != -1) {
            		// Found the "--fair".  The more structurally nice thing to
            		// do here would be to move past the following "algorithm".
            		// However, it's easier to pass a parameter to the ParseAlgorithm
            		// class's GetAlgorithm method that tells it to go past the
            		// "algorithm" token.
            		 algCol = algCol + PcalParams.BeginFairAlg.length();
                     foundBegin = true;
                     foundFairBegin = true;
            		
            	} else {
            		algLine = algLine + 1;
            	} 
            }
        }
	       
		final Set<ValidationResult> res = new HashSet<>();

		
		// TLA+ translation
		final int translationLine = trans.findTokenPair(deTabbedSpecification, 0,
														PcalParams.BeginXlation1, PcalParams.BeginXlation2);
		if (translationLine == -1) {
			res.add(ValidationResult.NO_TRANSLATION_EXISTS);
		}
		
		final int endTranslationLine = trans.findTokenPair(deTabbedSpecification, translationLine + 1,
				PcalParams.EndXlation1, PcalParams.EndXlation2);
		if (endTranslationLine == -1) {
			res.add(ValidationResult.NO_TRANSLATION_EXISTS);
		}
		if (translationLine == -1 && endTranslationLine == -1) {
			return res;
		}

		// PlusCal algorithm
		if (!foundBegin) {
			res.add(ValidationResult.NO_PLUSCAL_EXISTS);
		} else {

	    	// Get the PlusCal AST by parsing it.
			try {
				ParseAlgorithm.uncomment(deTabbedSpecification, algLine, algCol);
			} catch (ParseAlgorithmException e) {
	            PcalDebug.reportError(e);
	            return setOf(ValidationResult.ERROR_ENCOUNTERED);
	        }
			
	        final TLAtoPCalMapping mapping = new TLAtoPCalMapping() ;
	        mapping.algColumn = algCol;
	        mapping.algLine = algLine;
	        PcalParams.tlaPcalMapping = mapping;
			
			AST ast = new AST();
			try {
				final PcalCharReader reader = new PcalCharReader(deTabbedSpecification, algLine, algCol,
						specificationText.size(), 0);
				ast = ParseAlgorithm.getAlgorithm(reader, foundFairBegin);
				
				// The call translate mutates the ast in pcal.PcalTranslate.Explode(AST, PcalSymTab).
				// I'm ignoring the PcalParams.tlcTranslation() alternative in trans.java
				// because I doubt the "-spec" feature is used widely (if at all).
		        final PCalTLAGenerator pcalTLAGenerator = new PCalTLAGenerator(ast);
	            pcalTLAGenerator.removeNameConflicts();
                pcalTLAGenerator.translate();
			} catch (ParseAlgorithmException | RemoveNameConflictsException e) {
				PcalDebug.reportError(e);
				// The PlusCal algorithm doesn't parse because of a syntax error. This indicates
				// that the algorithm has been modified since it wouldn't have been possible to
				// calculate a checksum earlier. ast will be empty string and, thus, not match below.
			}
	        
			// Calculate the checksum value for the PlusCal's AST and compare unless no
			// checksum to compare it with is given (or it has been disabled).
			final Matcher m = Validator.CHECKSUM_PATTERN.matcher(deTabbedSpecification.get(translationLine));
	    	if (m.find()) {
	    		if (m.group(Validator.PCAL_CHECKSUM) != null) {

	    			final String chksumPCalAST = Validator.checksum(foundFairBegin ? FAIR : "" + ast.toString());
	    			if (!m.group(Validator.PCAL_CHECKSUM).equals(chksumPCalAST)) {
	    				// Mismatch between the PlusCal algorithm and its checksum.
	    				res.add(ValidationResult.PCAL_DIVERGENCE_EXISTS);
	    			}
	    		}
	    		if (m.group(Validator.TLA_CHECKSUM) != null) {
					final Vector<String> translation = new Vector<>(
							specificationText.subList((translationLine + 1), endTranslationLine));
					final String chksumTLATranslation = Validator.checksum(translation);
	    			
	    			if (!m.group(Validator.TLA_CHECKSUM).equals(chksumTLATranslation)) {
	    				// Mismatch between the TLA+ translation and its checksum.
	    				res.add(ValidationResult.TLA_DIVERGENCE_EXISTS);
	    			}
	    		}
	    	} else {
	    		res.add(ValidationResult.NO_PCAL_CHECKSUMS_EXIST);
	    	}
		}
		return res.isEmpty() ? setOf(ValidationResult.NO_DIVERGENCE) : res;
	}
    
    public static String checksum(final Vector<String> lines) {
    	final StringBuilder sb = new StringBuilder();
    	for (final String str : lines) {
    		sb.append(str);
    	}
    	
    	return checksum(sb.toString());
    }
    
    static String checksum(final String string) {
    	final CRC32 crc32 = new CRC32();
    	crc32.update(string.getBytes());
    	return Long.toHexString(crc32.getValue());
    }

    private static Set<ValidationResult> setOf(ValidationResult... res) {
    	return new HashSet<>(Arrays.asList(res));
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/part/EmptyPart.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.part;

import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.forms.AbstractFormPart;

/**
 * Empty part
 * @author <NAME>
 * @version $Id: EmptyPart.java 589 2009-03-18 16:53:13Z simonzam $
 * @deprecated (not used)
 */
public class EmptyPart extends AbstractFormPart
{
    private Vector controls = new Vector();

    public boolean addControl(Control control)
    {
        Assert.isNotNull(control);
        return controls.add(control);
    }

    public boolean removeControl(Control control)
    {
        Assert.isNotNull(control);
        return controls.remove(control);
    }

    /**
     * Tests if the control belongs to the part, providing a deep search 
     * for SWT composites
     * @param control
     * @return
     */
    public boolean isControlledBy(Control control)
    {
        Assert.isNotNull(control);
        boolean contains = controls.contains(control);

        if (!contains && control instanceof Composite)
        {
            Control[] children = ((Composite) control).getChildren();
            for (int i = 0; i < children.length; i++)
            {
                contains = isControlledBy(children[i]);
                if (contains)
                {
                    return true;
                }
            }
        }

        return contains;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/TLCRuntime.java<|end_filename|>
// Copyright (c) Dec 26, 2011 Microsoft Corporation.  All rights reserved.

package util;

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import tlc2.tool.fp.FPSet;

/**
 * @author <NAME>
 */
public class TLCRuntime {
	/**
	 * Absolute lower hard limit for {@link FPSet} memory
	 */
	public static final long MinFpMemSize = 20 * (1 << 19);

	private static TLCRuntime runtime;

	/**
	 * @return a {@link TLCRuntime} instance
	 */
	public synchronized static TLCRuntime getInstance() {
		if (runtime == null) {
			runtime = new TLCRuntime();
		}
		return runtime;
	}
	

	private long physicalSystemMemory = -1;
	
	/**
	 * @return the total amount of memory, measured in bytes.
	 */
	private long getPhysicalSystemMemory() {
		final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
		try {
			return (Long) mBeanServer.getAttribute(new ObjectName("java.lang", "type", "OperatingSystem"),
					"TotalPhysicalMemorySize");
		} catch (InstanceNotFoundException | AttributeNotFoundException | MalformedObjectNameException
				| ReflectionException | MBeanException | ClassCastException e) {
			// as a safeguard default to the total memory available to this JVM
			return Runtime.getRuntime().totalMemory();
		}
	}

	/**
	 * @param fraction
	 *            The percentage of physical memory required
	 * @return the absolute amount of physical memory in MB
	 */
	public long getAbsolutePhysicalSystemMemory(double fraction) {
		if (physicalSystemMemory == -1) {
			physicalSystemMemory = getPhysicalSystemMemory();
		}
		final double d = physicalSystemMemory * fraction;
		return (long) (d / 1024d / 1024d);
	}
	
	/**
	 * @return The non-heap memory JVM memory set with -XX:MaxDirectMemorySize in Bytes
	 */
	public long getNonHeapPhysicalMemory() {
		// 64MB by default. This happens to be the JVM default for
		// XX:MaxDirectMemorySize if no other value is given.
		long l = (64L * 1024L * 1024L);
		
		final RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
		final List<String> arguments = RuntimemxBean.getInputArguments();
		for (String arg : arguments) {
			if (arg.toLowerCase().startsWith("-xx:maxdirectmemorysize")) {
				String[] strings = arg.split("=");
				String mem = strings[1].toLowerCase();
				if (mem.endsWith("g")) {
					l = Long.parseLong(mem.substring(0, mem.length() -1));
					l = l << 30;
					break;
				} else if (mem.endsWith("m")) {
					l = Long.parseLong(mem.substring(0, mem.length() -1));
					l = l << 20;
					break;
				} else if (mem.endsWith("k")) {
					l = Long.parseLong(mem.substring(0, mem.length() -1));
					l = l << 10;
					break;
				} else {
					l = Long.parseLong(mem.substring(0, mem.length()));
					break;
				}
			}
		}
		return l;
	}

	/**
	 * @param fpMemSize
	 *            can be used in two ways:
	 *            <ul>
	 *            <li>to set the relative memory to be used for fingerprints
	 *            (being machine independent)</li>
	 *            <li>to set the absolute memory to be used for fingerprints.
	 *            </li>
	 *            </ul>
	 * 	<p>
	 *            In order to set memory relatively, a value in the domain [0.0,
	 *            1.0] is interpreted as a fraction. A value in the [2,
	 *            Double.MaxValue] domain allocates memory absolutely.
	 * </p>
	 *            Independently of relative or absolute mem allocation, a user
	 *            cannot allocate more than JVM heap space available. Conversely
	 *            there is the lower hard limit {@link TLCRuntime#MinFpMemSize}.
	 * @return a long value that indicates the absolute amount of fingerprints that can potentially fit into VM heap memory
	 */
	//TODO rename to non-fp specific
	public long getFPMemSize(double fpMemSize) {
		// determine amount of memory to be used for fingerprints
		final long maxMemory = Runtime.getRuntime().maxMemory();
		// -fpmem is given
		if (fpMemSize == -1) {
			// .25 * maxMemory
			fpMemSize = maxMemory >> 2;
		}
		// -fpmemratio is given
		if (0 <= fpMemSize && fpMemSize <= 1) {
			fpMemSize = maxMemory * fpMemSize;
		}
		if (fpMemSize < MinFpMemSize) {
			fpMemSize = MinFpMemSize;
		}
		if (fpMemSize >= maxMemory) {
			// .75*maxMemory
			fpMemSize = maxMemory - (maxMemory >> 2);
		}
		return (long) fpMemSize;
	}

	public enum ARCH {
		x86,
		x86_64;
	}
	
	public ARCH getArchitecture() {
		if (System.getProperty("sun.arch.data.model") != null
				&& System.getProperty("sun.arch.data.model").equals("64")) {
			return ARCH.x86_64;
		}
		if (System.getProperty("com.ibm.vm.bitmode") != null 
				&& System.getProperty("com.ibm.vm.bitmode").equals("64")) {
			return ARCH.x86_64;
		}
		if (System.getProperty("java.vm.version") != null 
				&& System.getProperty("java.vm.version").contains("_64")) {
			return ARCH.x86_64;
		}
		return ARCH.x86;
	}

	// See java.lang.ProcessHandle.current().pid() or -1 when Java version -lt 9.
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public long pid() {
		// Once Java9 is minimum BREE, change to:
        // return java.lang.ProcessHandle.current().pid();
		try {
			// Get class.
			final ClassLoader classLoader = getClass().getClassLoader();
	        final Class aClass = classLoader.loadClass("java.lang.ProcessHandle");
	        // Execute static current()
	        final Object o = aClass.getMethod("current").invoke(null, (Object[]) null);
	        // Execute instance method pid()
	        return (long) aClass.getMethod("pid").invoke(o, (Object[]) null);
	    } catch (Exception e) {
			return -1;
		}
	}

	public boolean isThroughputOptimizedGC() {
		final List<GarbageCollectorMXBean> gcs = ManagementFactory.getGarbageCollectorMXBeans();
		for (GarbageCollectorMXBean gc : gcs) {
			// This might not be a reliable way to identify the currently active GC.
			if ("PS Scavenge".equals(gc.getName())) {
				return true;
			}
		}
		return false;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/about-models.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/about-models.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Models</title>
</head>
<!-- a comment -->

<body>
<h1>Models</h1>

 <p> 
You run the TLC model checker on a <em>model</em> of your spec.&nbsp;  The model
tells TLC what it should do.&nbsp;  Here are the parts of the model
that you must explicitly choose:</p>
<ul>
<li>What the <a href="../spec/what-is.html">behavior spec</a> is.</li>

<li>What TLC should check.</li>

<li>What values to substitute for constant parameters.</li>
</ul>
 <p>
 The <em><a href="overview-page.html">Model Overview</a></em>,
 <em><a href="spec-options-page.html">Spec Options</a></em>,
 and <em><a href="tlc-options-page.html">TLC Options</a></em> 
 help pages describe all the things that can go into a model.
 </p>

<p>

A specification may contain multiple models.&nbsp; You can create a
new model, open an existing one, or create a clone (a copy with a new
name) of an existing model by clicking on the&nbsp; <samp>TLC Model
Checker</samp>&nbsp; menu.&nbsp;



Alternatively, you can use the <a
href="../spec/opening-closing.html">Spec Explorer</a>.&nbsp;

To create a new model, open the <a
href="../spec/opening-closing.html">Spec Explorer</a> and right-click
on the currently open spec.&nbsp;

To open an existing model, open the spec's menu item (by clicking on
the&nbsp; <samp>+</samp>&nbsp;) and double-clicking on the
model.&nbsp;

Right-clicking on the model also gives you the options of renaming it,
deleting it, and creating a clone.  </p>

<p>
A convenient way to examine all the spec's models
is by selecting <a name="quick-access"><em>Quick Access</em></a> on the <em>Window</em> menu
or typing <code>Control+Shift+A</code>.&nbsp;  This raises a window showing the models
and the beginning of their <em>Model Description</em> fields.&nbsp;  Double-clicking
on a model opens it.&nbsp;
You can also open
imported modules from that window.&nbsp;  Check out the window's <em>options</em> menu.
</p>

<p>
When you model check a spec, you should begin with a very small model--that is, a model for which the
values substituted for constants (and perhaps a <a href="spec-options-page.html#state">constraint</a>)
yield a small set of reachable states.&nbsp;  Before you've model checked it, your spec almost surely contains
quite a few errors.&nbsp;  Using a small model, TLC can find the trivial ones very quickly.&nbsp;  When it finds
no errors in a small model, you can then gradually increase the size of the model.
</p>

<p>

As you run your spec on larger and larger models, it's easy to forget
what you've done.&nbsp;

Instead of changing a model and running it again, create a new model
and keep the old one.&nbsp; (This is easy to do by cloning the model,
as described above.)&nbsp;

You can identify your models with the <em>Model Description</em> field,
which is shown
It will be easier to identify your models if you put the important
contents of the model in the model name--for example, you can name a
model </p> <pre>
   N=3,Proc={a1,a2,a3}
</pre>
<A name="locking">
The model is always locked while it is being run by TLC. This means that
you can't view information in sections of a running model that are closed.&nbsp;

It's therefore a good idea to open all sections of the model
that you might want to look at before starting a TLC run that will
take a significant amount of time.&nbsp;

If you forget to do this, you can clone the running model and examine
the clone.&nbsp;


<p>
The Toolbox saves a
copy of the version of the spec on which the model was run or checked, so you can look at it even after you
have changed the spec.&nbsp;
You can examine any modules in the saved version by clicking on the <i>Open Saved Module</i> command on the
<i>TLC Model Checker</i> menu when the model is selected.&nbsp;  (The model is selected when one of its pages has the focus.)&nbsp;   The
<a href="executing-tlc.html#MC">How TLC is Run</a>
help-page section tells you where
those saved modules are saved.
 </p>
<hr>
<!-- delete rest of line to comment out
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
-->
<!-- delete rest of line to comment out -->
<a href = "model.html">&uarr; Model Checking</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/test-long/tlc2/tool/fp/MSBDiskFPSetTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;

public class MSBDiskFPSetTest extends FPSetTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractFPSetTest#getFPSet(long)
	 */
	@Override
	protected FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws IOException {
		return new MSBDiskFPSet(fpSetConfig);
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/contribution/SpecListContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.ui.contribution;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Vector;

import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.handler.NewSpecHandler;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.compare.SpecComparator;

/**
 * A contribution item, that displays a list of specs, recently loaded by the spec manager
 *
 * @author <NAME>
 * @version $Id$
 */
public class SpecListContributionItem extends CompoundContributionItem
{
    private ImageDescriptor iconAddSpec = UIHelper.imageDescriptor("icons/full/newspec_wiz.gif");
    /**
     * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
     */
    protected IContributionItem[] getContributionItems()
    {

        Spec[] specs = Activator.getSpecManager().getRecentlyOpened();
        Vector specContributions = new Vector();

        HashMap parameters = new HashMap();
        
        // create the contribution item for add new spec
        CommandContributionItemParameter param = new CommandContributionItemParameter(UIHelper.getActiveWindow(),
                "toolbox.command.spec.new", NewSpecHandler.COMMAND_ID, parameters, iconAddSpec, null, null,
                "Add New Spec...", "n", "Adds new TLA+ Module to the specification",
                CommandContributionItem.STYLE_PUSH, IHelpConstants.M_NEW_SPEC, true);

        // add contribution item to the list
        specContributions.add(new CommandContributionItem(param));
        specContributions.add(new Separator());

        Arrays.sort(specs, new SpecComparator()) ;
        // iterate over recently opened specs
        // TODO: Need to sort the array specs using SpecComparator.compare
        // Or perhaps change SpecContentProvider.getRecentlyOpened() to
        // return the array sorted.
        for (int i = 0; i < specs.length; i++)
        {
            parameters = new HashMap();
            // fill the spec name for the handler
            parameters.put(OpenSpecHandler.PARAM_SPEC, specs[i].getName());

            // create the contribution item
            param = new CommandContributionItemParameter(UIHelper.getActiveWindow(),
                    "toolbox.command.spec.open." + specs[i].getName(), OpenSpecHandler.COMMAND_ID, parameters, null, null, null,
                    specs[i].getName(), null, "Opens " + specs[i].getName(), CommandContributionItem.STYLE_PUSH, null,
                    true);
            
            // add contribution item to the list
            specContributions.add(new CommandContributionItem(param));

        }
        return (IContributionItem[]) specContributions.toArray(new IContributionItem[specContributions.size()]);
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/util/EditorUtil.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.util;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.editor.basic.TLAEditorAndPDFViewer;
import org.lamport.tla.toolbox.editor.basic.util.DocumentHelper.WordRegion;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import pcal.TLAtoPCalMapping;
import tla2sany.modanalyzer.SpecObj;
import tla2sany.parser.Operators;
import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.AssumeProveNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.LetInNode;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.NewSymbNode;
import tla2sany.semantic.NonLeafProofNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.TheoremNode;
import tla2sany.semantic.ThmOrAssumpDefNode;
import tla2sany.st.Location;
import tla2sany.st.SyntaxTreeConstants;
import util.UniqueString;

/**
 * A collection of useful editor methods.
 * 
 * @author ricketts
 *
 */
public class EditorUtil
{

    /**
     * Type of the marker that contains a boolean attribute indicating if the module on which
     * the marker is placed should be read-only.
     */
    public static final String READ_ONLY_MODULE_MARKER = "org.lamport.tla.toolbox.editor.basic.readOnly";
    /**
     * ID for the boolean attribute for {@link EditorUtil#READ_ONLY_MODULE_MARKER} indicating if
     * the module should be read only.
     */
    public static final String IS_READ_ONLY_ATR = "org.lamport.tla.toolbox.editor.basic.isReadOnly";

    /**
     * Returns the {@link TLAEditor} with focus or null if
     * there is none.
     * 
     * This must be run in a a UI thread. See {@link UIHelper#runUIAsync(Runnable)}
     * and {@link UIHelper#runUISync(Runnable)}.
     * 
     * @return
     */
    public static TLAEditor getTLAEditorWithFocus()
    {
		IEditorPart activeEditor = UIHelper.getActiveEditor();
		if (activeEditor instanceof TLAEditorAndPDFViewer) {
			TLAEditor editor = ((TLAEditorAndPDFViewer) activeEditor).getTLAEditor();
			if (editor != null && editor.getViewer().getTextWidget().isFocusControl()) {
				return editor;
			}
		} else if (activeEditor != null && activeEditor.getAdapter(TLAEditor.class) != null) {
			TLAEditor editor = activeEditor.getAdapter(TLAEditor.class);
			if (editor != null && editor.getViewer().getTextWidget().isFocusControl()) {
				return editor;
			}
		}
        return null;
    }

    /**
     * Returns the currently active {@link TLAEditor}
     * in the toolbox. This {@link TLAEditor} may not have focus
     * or may not even be visible. If there is an editor showing
     * in the toolbox and the editor is a {@link TLAEditorAndPDFViewer},
     * then the {@link TLAEditor} from that multipage editor
     * will be returned. Else, this method returns null.
     * 
     * @return
     */
    public static TLAEditor getActiveTLAEditor()
    {
        IEditorPart activeEditor = UIHelper.getActiveEditor();
        // activeEditor.getAdapter(ITexto)
        if (activeEditor instanceof TLAEditorAndPDFViewer)
        {
            return ((TLAEditorAndPDFViewer) activeEditor).getTLAEditor();
		}

        return activeEditor.getAdapter(TLAEditor.class);
    }

    /**
     * returns true iff the location loc1 is contained within location loc2,
     * where the file names of the locations are ignored.
     * 
     * @param loc1
     * @param loc2
     * @return
     */
    public static boolean locationContainment(Location loc1, Location loc2)
    {
        if ((loc1.beginLine() < loc2.beginLine())
                || ((loc1.beginLine() == loc2.beginLine()) && (loc1.beginColumn() < loc2.beginColumn())))
        {
            return false;
        }
        return (loc1.endLine() < loc2.endLine())
                || ((loc1.endLine() == loc2.endLine()) && (loc1.endColumn() <= loc2.endColumn()));
    }
    
    /**
     * True iff the range of lines specified by loc1 is a subset of the range of lines
     * specified by loc2.
     * 
     * @param loc1
     * @param loc2
     * @return
     */
    public static boolean lineLocationContainment(Location loc1, Location loc2) {
    	return (loc1.beginLine() >= loc2.beginLine()) && (loc2.endLine() >= loc1.endLine()) ;
    }

    /**
     * Returns the TLA+ token in the document containing the region delimited
     * by the offset and length.  A token here means a TLA+ token except
     * that a name like Foo!bar!x is considered to be a single token.  It
     * returns null if the file is not parsed or the editor is dirty (so there
     * is no useful information in the parse tree) or if there is no token
     * contained within the indicated region.
     * 
     * Note: The reason the arguments are an offset and a length is because
     * Eclipse sometimes gives a region of a document as an IRegion and
     * sometimes as an ISelection.  And even though an ISelection implements
     * all the methods of an IRegion, the builders of Eclipse in their infinite
     * wisdom chose not to declare an ISelection to implement an IRegion,
     * and I didn't feel like creating an interface that implements both
     * of them.

     * 
     * @param document
     * @param offset
     * @param length
     * @return
     */
    public static StringAndLocation getTokenAt(IDocument document, int offset, int length)
    {
        Location location = getLocationAt(document, offset, length);
        return getTokenAtLocation(location);
    }

    /**
     * Returns the token containing the current selection, or null
     * if there is none.  A token here means a TLA+ token except
     * that a name like Foo!bar!x is considered to be a single token.  It
     * returns null if the file is not parsed or the editor is dirty (so there
     * is no useful information in the parse tree) or if there is no token
     * contained within the indicated region.
     * 
     * THIS METHOD DOES NOT SEEM TO BE USED.
     * @return
     */
    public static StringAndLocation getCurrentToken()
    {
        Location location = getCurrentLocation();
        if (location == null)
        {
            return null;
        }

        return getTokenAtLocation(location);
    }

    /**
     * On 21 June 2010 LL discovered the following bug.  For a proof-step number of the form "<2>3.", the token in the
     * syntax tree contains the ".".  This seems to be a reasonable place to fix it by returning just the "<2>3" and
     * its location.  Apparently, it has been fixed here.
     *  
     * @param location
     * @return
     */
    public static StringAndLocation getTokenAtLocation(Location location)
    {
        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();
        // This method is called only when there is a TLAEditor with
        // the focus, so I don't see how it could be null. However,
        // while debugging, that did happen in some unreproducible
        // fashion.
        if (editor == null)
        {
            return null;
        }
        IFile moduleFile = ((FileEditorInput) editor.getEditorInput()).getFile();

        if (editor.isDirty())
        {
        	TLAEditorActivator.getDefault().logDebug("Editor is dirty");
            return null;
        }

        // Return null if the file is not parsed.
        ParseResult parseResult = ResourceHelper.getValidParseResult(moduleFile);
        if ((parseResult == null) || (parseResult.getStatus() != IParseConstants.PARSED))
        {
            return null;
        }

        // get module node (code copied from
        // ResourceHelper.getPfStepOrUseHideFromMod)
        String moduleName = ResourceHelper.getModuleName(moduleFile);
        ModuleNode module = parseResult.getSpecObj().getExternalModuleTable().getModuleNode(
                UniqueString.uniqueStringOf(moduleName));
        if (module == null)
        {
            return null;
        }
        SyntaxTreeNode stn = (SyntaxTreeNode) module.stn;
        if (!locationContainment(location, stn.getLocation()))
        {
            return null;
        }

        StringAndLocation stl = innerGetCurrentToken(stn, location);
        if (stl == null)
        {
            return null;
        }
        if ((stl.string.charAt(0) == '<') && (stl.string.indexOf('.') != -1))
        {
            Location loc = stl.location;
            stl = new StringAndLocation(stl.string.substring(0, stl.string.indexOf('.')), new Location(UniqueString
                    .uniqueStringOf(loc.source()), loc.beginLine(), loc.beginColumn(), loc.endLine(), loc.beginColumn()
                    + stl.string.indexOf('.')));
        }
        return stl;
    }

    /**
     * The inner method of getCurrentToken.  It assumes that
     * location is contained within stn.location.
     * 
     * @param stn
     * @param location
     * @return
     */
    private static StringAndLocation innerGetCurrentToken(SyntaxTreeNode stn, Location location)
    {
        int kind = stn.getKind();
        if (kind == SyntaxTreeConstants.N_GeneralId
        // || kind == SyntaxTreeConstants.N_GenNonExpPrefixOp
        // || kind == SyntaxTreeConstants.N_GenPrefixOp || kind == SyntaxTreeConstants.N_GenPostfixOp
        )
        {
            // TLAEditorActivator.getDefault().logDebug("Returning concatenation of heirs: " + concatHeirTokens(stn));
            return new StringAndLocation(concatHeirTokens(stn), stn.getLocation());
        }
        // TLAEditorActivator.getDefault().logDebug("Called on node kind = " + stn.getKind() +
        // ", image = `" + stn.getImage() + "'");
        SyntaxTreeNode[] heirs = stn.getHeirs();
        if (heirs.length == 0)
        {
            // TLAEditorActivator.getDefault().logDebug("Hit bottom, returning " + stn.getImage());
            return new StringAndLocation(stn.getImage(), stn.getLocation());
        }
        for (int i = 0; i < heirs.length; i++)
        {
            if (locationContainment(location, heirs[i].getLocation()))
            {
                // TLAEditorActivator.getDefault().logDebug("Recursing");
                return innerGetCurrentToken(heirs[i], location);
            }
        }
        // TLAEditorActivator.getDefault().logDebug("Not found; return null");
        return null;
    }

    /**
     * Returns the concatenation of the images of all leaf nodes
     * of the node stn that correspond to actual tokens
     * 
     * @param stn
     * @return
     */
    private static String concatHeirTokens(SyntaxTreeNode stn)
    {
        SyntaxTreeNode[] heirs = stn.getHeirs();
        if (heirs.length == 0)
        {
            // A a node of kind >= NULL_ID with no heirs should
            // (I think) only be an empty N_IdPrefix.
            if (stn.getKind() < SyntaxTreeConstants.NULL_ID)
            {
                return stn.getImage();
            } else
            {
                return "";
            }
        }
        String val = "";
        for (int i = 0; i < heirs.length; i++)
        {
            val = val + concatHeirTokens(heirs[i]);
        }
        return val;
    }

    /**
     * Returns a Location corresponding to the current selection of the
     * {@link TLAEditor} that has the focus, except with a null file 
     * (module) name.  (To find the code for getting the name, see  
     * ProverHelper.runProverForActiveSelection.
     * 
     * Returns null if anything goes wrong when trying to compute the
     * location.
     * 
     * @return
     */
    public static Location getCurrentLocation()
    {
		return getCurrentLocation(0);
    }
    
    /**
     * Like getCurrentLocation, except it adds x to the result's endCol
     * field.  For some reason, computing the region of the PlusCal code 
     * corresponding to a region in the TLA+ translation calls this
     * method with x=1.
     * 
     * @param x
     * @return
     */
    public static Location getCurrentLocation(int x)
    {
        ITextSelection selection = getCurrentSelection();
		return getLocationAt(getCurrentDocument(), selection.getOffset(), selection.getLength(), x);
    }
    
    private static IDocument getCurrentDocument() {
        TLAEditor editor = getTLAEditorWithFocus();
        // editor shouldn't be null, but just in case...
        if (editor == null)
        {
            return null;
        }
        return editor.getDocumentProvider().getDocument(editor.getEditorInput());
    }
    
    private static ITextSelection getCurrentSelection() {
        TLAEditor editor = getTLAEditorWithFocus();
        return (ITextSelection) editor.getSelectionProvider().getSelection();
    }

    /**
     * This returns the region in <code>document</code> represented by the
     * <code>location</code>.  Note that a <code>Location</code> is a region
     * represented by the <row, column> coordinates of its first and last 
     * characters.
     * @param document
     * @param location
     * @return
     * @throws BadLocationException
     */
    public static IRegion getRegionOf(IDocument document, Location location)
               throws BadLocationException {
        int offset;
        int length;
        offset = document.getLineInformation(location.beginLine()-1).getOffset()
                            + location.beginColumn() -1;
        length = document.getLineInformation(location.endLine()-1).getOffset()
                          + location.endColumn() - offset;
        return new Region(offset, length) ;
    }
    
    public static Location getLocationAt(IDocument document, int offset, int length)
    {
    	return getLocationAt(document, offset, length, 0);
    }
    
    /**
     * Like getLocationAt, except it adds x to the endCol.
     * 
     * @param document
     * @param offset
     * @param length
     * @param x
     * @return
     */
    public static Location getLocationAt(IDocument document, int offset, int length, int x)
    {
        // I don't think document or selection can be null, but...
        if (document == null)
        {
            return null;
        }
        Location loc = null;
        try
        {
            // Compute the lines in Java coordinates and the columns
            // in human coordinates.
            int startOffset = offset;
            int startLine = document.getLineOfOffset(startOffset);
            int startCol = startOffset - document.getLineOffset(startLine) + 1;
            int endOffset = startOffset + length;
            int endLine = document.getLineOfOffset(endOffset);
            int endCol = endOffset - document.getLineOffset(endLine);
            // Because endCol points to the character to the right of
            // the selection, it now is in human coordinates for the
            // last character of the selection--except if the selection
            // has length 0.
            if (length == 0)
            {
                endCol++;
            }
            loc = new Location(startLine + 1, startCol, endLine + 1, endCol + x);
        } catch (BadLocationException e)
        {
            return null;
            // e.printStackTrace();
        }
        return loc;
    }
    
    /**
     * @see EditorUtil#lookupSymbol(UniqueString, SemanticNode, Location, SymbolNode)
     */
 	public static SymbolNode lookupSymbol(SpecObj specObj, IDocument document, WordRegion region) {
		final Location location = getLocationAt(document, region.getOffset(), region.getLength());
		final ModuleNode rootModule = specObj.getExternalModuleTable().getRootModule();
		return lookupSymbol(UniqueString.uniqueStringOf(region.getWord()), rootModule, location, null);
	}
    
 	/**
 	 * @see EditorUtil#lookupSymbol(UniqueString, SemanticNode, Location, SymbolNode)
 	 */
	public static SymbolNode lookupSymbol(String name, SymbolNode curNode, IDocument document, IRegion region,
			SymbolNode defaultResult) {
		final Location location = getLocationAt(document, region.getOffset(), region.getLength());
		return lookupSymbol(UniqueString.uniqueStringOf(name), curNode, location, defaultResult);
	}

    /**
     * This method is called externally with <code>curNode</code> equal to
     * a ModuleNode and <code>defaultResult</code> equal to <code>null</code>.
     * It then returns the SymbolNode that defines or declares the symbol
     * named <code>name</code> located at <code>location</code>.  For example,
     * in
     * <pre>
     *    foo == \A s \in {s \in T : Find(s)} : AnotherInstance(s)
     *    s == SomeDefinition
     * </pre>
     * if <code>name</code> is the UniqueString of "s" and <code>location</code>
     * is the position of the s in Find(s), then it returns the SymbolNode for
     * the s declared in the set constructor. <p>
     * <p>
     * If no declaration is found, it returns <code>null</code>.<p>
     * <p>
     * It is implemented by using the getChildren() method to walk down the semantic
     * tree towards the symbol's location.  In the recursive call, <code>curNode</code>
     * is the node within which we are looking, and <code>defaultResult</code> is the
     * lowest-level SymbolNode defining <code>name</code> that has been found.
     * 
     * @param name
     * @param curNode
     * @param location
     * @param defaultResult
     */
    public static SymbolNode lookupSymbol(UniqueString name, SemanticNode curNode, Location location,
            SymbolNode defaultResult)
    {
        SymbolNode foundSymbol = null;
        if (curNode instanceof ModuleNode)
        {
            foundSymbol = ((ModuleNode) curNode).getContext().getSymbol(name);
        } else if (curNode instanceof LetInNode)
        {
            foundSymbol = ((LetInNode) curNode).context.getSymbol(name);
        } else if (curNode instanceof NonLeafProofNode)
        {
            foundSymbol = ((NonLeafProofNode) curNode).getContext().getSymbol(name);
        } else if (curNode instanceof OpApplNode)
        {
            OpApplNode oan = (OpApplNode) curNode;
            FormalParamNode[] fpn = oan.getUnbdedQuantSymbols();
            if (fpn != null)
            {
                for (int i = 0; i < fpn.length; i++)
                {
                    if (fpn[i].getName() == name)
                    {
                        // return fpn[i];
                        foundSymbol = fpn[i];
                        break;
                    }
                }
            }

            FormalParamNode[][] fpnA = oan.getBdedQuantSymbolLists();
            if (fpnA != null)
            {
                for (int i = 0; i < fpnA.length; i++)
                {
                    for (int j = 0; j < fpnA[i].length; j++)
                    {
                        if (fpnA[i][j].getName() == name)
                        {
                            // return fpnA[i][j];
                            foundSymbol = fpnA[i][j];
                            i = fpnA.length;
                            break;
                        }
                    }
                }
            }
        } else if (curNode instanceof OpDefNode)
        {
            FormalParamNode[] params = ((OpDefNode) curNode).getParams();
            for (int i = 0; i < params.length; i++)
            {
                if (name == params[i].getName())
                {
                    // return params[i];
                    foundSymbol = params[i];
                    break;
                }
            }
        } else if (curNode instanceof TheoremNode)
        {
            TheoremNode thm = (TheoremNode) curNode;
            LevelNode assertion = thm.getTheorem();

            if (assertion instanceof AssumeProveNode)
            {
                AssumeProveNode apn = (AssumeProveNode) assertion;
                SemanticNode[] assumes = apn.getAssumes();
                if (!apn.getSuffices())
                {
                    for (int i = 0; i < assumes.length; i++)
                    {
                        if (assumes[i] instanceof NewSymbNode)
                        {
                            NewSymbNode newSymb = (NewSymbNode) assumes[i];
                            OpDeclNode opDecl = newSymb.getOpDeclNode();
                            if (name == opDecl.getName())
                            {
                                foundSymbol = opDecl;
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (foundSymbol == null)
        {
            foundSymbol = defaultResult;
        }
        SemanticNode[] children = curNode.getChildren();
        if (children == null)
        {
            return foundSymbol;
        }
        for (int i = 0; i < children.length; i++)
        {
            if (locationContainment(location, children[i].getLocation()))
            {
                foundSymbol = lookupSymbol(name, children[i], location, foundSymbol);
            }
        }
        return foundSymbol;
    }

    /**
     *  Like lookupSymbol except that for definitions that were obtained by instantiation
     *  from a definition in another module, it returns the definition from that other module.
     *  
     * @param name
     * @param curNode
     * @param location
     * @param defaultResult
     * @return
     */
    public static SymbolNode lookupOriginalSymbol(UniqueString name, SemanticNode curNode, Location location,
            SymbolNode defaultResult)
    {
        // In case this is a synonym for something else.
        name = Operators.resolveSynonym(name);

        SymbolNode resolvedSymbol = lookupSymbol(name, curNode, location, defaultResult);
        if (resolvedSymbol == null)
        {
            return null;
        }
        if (resolvedSymbol instanceof OpDefNode)
        {
            OpDefNode opdef = (OpDefNode) resolvedSymbol;
            if (opdef.getSource() != null)
            {
                resolvedSymbol = opdef.getSource();
            }
        } else if (resolvedSymbol instanceof ThmOrAssumpDefNode)
        {
            ThmOrAssumpDefNode opdef = (ThmOrAssumpDefNode) resolvedSymbol;
            if (opdef.getSource() != null)
            {
                resolvedSymbol = opdef.getSource();
            }
        }
        return resolvedSymbol;
    }

    /**
     * Returns a TLA editor on moduleFileName and opens it in a window if there isn't 
     * one already open.  It also gives the editor focus.
     * 
     * @param moduleFileName name of the module with .tla extension.
     * @return
     */
    public static TLAEditor openTLAEditor(final String moduleFileName)
    {
        final IResource module = ResourceHelper.getResourceByName(moduleFileName);
		if ((module != null) && (module instanceof IFile)) {
            final IEditorPart editor = UIHelper.openEditor(TLAEditor.ID, (IFile) module);
            
            if (editor instanceof TLAEditor) {
            	return (TLAEditor)editor;
			} else if (editor instanceof TLAEditorAndPDFViewer) {
                return ((TLAEditorAndPDFViewer) editor).getTLAEditor();
            }
        }

        return null;
    }

    /**
     * Tries to find and return a {@link TLAEditor} already open
     * on module. Returns null if one is not found. If there
     * are multiple editors open, this just returns one of them.
     * Which one is unspecified.
     * 
     * @param module
     * @return
     */
    public static TLAEditor findTLAEditor(IResource module)
    {
        if (module != null && module instanceof IFile)
        {
            IEditorPart editor = UIHelper.getActivePage().findEditor(new FileEditorInput((IFile) module));
            if (editor instanceof TLAEditorAndPDFViewer)
            {
                return ((TLAEditorAndPDFViewer) editor).getTLAEditor();
            }
        }

        return null;
    }

    /**
     * If there is currently a TLAEditor with focus, 
     * and that editor is unmodified and is currently parsed,
     * and its cursor is "at" a TheoremNode, then it returns
     * that TheoremNode.  Otherwise, it returns null.
     */
    public static TheoremNode getCurrentTheoremNode()
    {
        // get editor and return null if it doesn't exist or
        // is dirty.
        TLAEditor editor = getTLAEditorWithFocus();
        if ((editor == null) || (editor.isDirty()))
        {
            return null;
        }
        ISelectionProvider selectionProvider = editor.getSelectionProvider();
        Assert.isNotNull(selectionProvider, "Active editor does not have a selection provider. This is a bug.");
        ISelection selection = selectionProvider.getSelection();
        if (!(selection instanceof ITextSelection))
        {
            return null;
        }
        ITextSelection textSelection = (ITextSelection) selection;
        IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());

        // check if editor's file is currently parsed.
        
        if (editor.getEditorInput() instanceof FileEditorInput) {
        	IFile file = ((FileEditorInput) editor.getEditorInput()).getFile();
        	String moduleName = ResourceHelper.getModuleName(file);
        	
        	ParseResult parseResult = ResourceHelper.getValidParseResult(file);
        	
        	return ResourceHelper.getTheoremNodeWithCaret(parseResult, moduleName, textSelection, document);
        }
        return null;
    }

    /**
     *  Returns true iff editor with focus is modified
     */
    public static boolean editorWithFocusDirty()
    {
        return getTLAEditorWithFocus().isDirty();
    }

    /**
     * Returns the name of the module whose editor has focus.
     */
    public static String moduleWithFocus()
    {
        TLAEditor editor = getTLAEditorWithFocus();
        IFile file = ((FileEditorInput) editor.getEditorInput()).getFile();
        String name = ResourceHelper.getModuleName(file);
        return name;
    }

    /**
     * Signals using a marker that the module should be read-only
     * if isReadOnly is true or not read-only if isReadOnly is false.
     * 
     * @param module
     * @param isReadOnly
     * @throws CoreException 
     */
    public static void setReadOnly(IResource module, boolean isReadOnly)
    {
        try
        {

            if (module.exists())
            {
                IMarker marker;
                // Try to find any existing markers.
                IMarker[] foundMarkers = module.findMarkers(READ_ONLY_MODULE_MARKER, false, IResource.DEPTH_ZERO);

                // There should only be one such marker at most.
                // In case there is more than one existing marker,
                // remove extra markers.
                if (foundMarkers.length > 0)
                {
                    marker = foundMarkers[0];
                    // remove trash if any
                    for (int i = 1; i < foundMarkers.length; i++)
                    {
                        foundMarkers[i].delete();
                    }
                } else
                {
                    // Create a new marker if no existing ones.
                    marker = module.createMarker(READ_ONLY_MODULE_MARKER);
                }

                // Set the boolean attribute to indicate if the marker is running.
                marker.setAttribute(IS_READ_ONLY_ATR, isReadOnly);
            }
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error setting module " + module + " to read only.", e);
        }

    }

    /**
     *  Finds the current editor and calls 
     *  setReturnFromOpenDecl(TLAEditor)
     */
    public static void setReturnFromOpenDecl()
    {
        TLAEditor srcEditor = EditorUtil.getTLAEditorWithFocus();
        setReturnFromOpenDecl(srcEditor);
    }

    /**
     * Sets the location to which the ReturnFromOpenDeclaration command
     * should return to be the current selection of srcEditor.
     * 
     * @param srcEditor
     */
    public static void setReturnFromOpenDecl(TLAEditor srcEditor)
    {
        if (srcEditor != null)
        {
            Spec spec = ToolboxHandle.getCurrentSpec();
            spec.setOpenDeclModuleName(srcEditor);
        }
    }

    /**
     * Returns true iff the module has been set to read only using
     * the method {@link EditorUtil#setReadOnly(IResource, boolean)}.
     * 
     * @param module
     * @return
     * @throws CoreException 
     */
    public static boolean isReadOnly(IResource module)
    {

        try
        {
            if (module.exists())
            {
                IMarker marker;
                // Try to find any existing markers.
                IMarker[] foundMarkers = module.findMarkers(READ_ONLY_MODULE_MARKER, false, IResource.DEPTH_ZERO);

                // There should only be one such marker at most.
                // In case there is more than one existing marker,
                // remove extra markers.
                if (foundMarkers.length > 0)
                {
                    marker = foundMarkers[0];
                    // remove trash if any
                    for (int i = 1; i < foundMarkers.length; i++)
                    {
                        foundMarkers[i].delete();
                    }

                    return marker.getAttribute(IS_READ_ONLY_ATR, false);
                } else
                {
                    return false;
                }
            } else
            {
                return false;
            }
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error determining if module " + module + " is read only.", e);
        }
        return false;

    }

    /**
     * Gets the current {@link Position} of the marker in the
     * {@link TLAEditor} showing the module that contains the
     * marker. Returns null if there is no editor open on that module.
     * This method assumes that {@link TLAEditor}s are synchronized. That
     * is, multiple editors on the same module are synchronized. At the time
     * of writing this method (June 2010), they are synchronized.
     * 
     * @param marker
     * @return
     */
    public static Position getMarkerPosition(IMarker marker)
    {
        TLAEditor editor = findTLAEditor(marker.getResource());
        if (editor != null)
        {
            IAnnotationModel annotationModel = editor.getDocumentProvider().getAnnotationModel(editor.getEditorInput());
            /*
             * From exploration of eclipse's code, I've determined that this
             * should be an instance of ResourceMarkerAnnotationModel. If this is
             * not always true, then we need to figure out a way to get a hold of the
             * annotation model that manages positions of markers in the editor.
             */
            if (annotationModel instanceof ResourceMarkerAnnotationModel)
            {
                return ((ResourceMarkerAnnotationModel) annotationModel).getMarkerPosition(marker);
            } else
            {
                Activator.getDefault().logDebug("Cannot get the annotation model that manages marker positions for the marker on "
                        + marker.getResource());
            }
        }

        return null;
    }

    /**
     * A class that we use so a method can return both a string and a 
     * location.
     * 
     * @author lamport
     *
     */
    public static final class StringAndLocation
    {
        public String string;
        public Location location;

        public StringAndLocation(String string, Location location)
        {
            this.string = string;
            this.location = location;

        }

        public String toString()
        {
            return "[string |-> " + this.string + ", location |-> " + this.location.toString() + "]";
        }
    }

	/**
	 * @param mapping
	 * @return
	 * @throws BadLocationException
	 */
	public static boolean selectAndRevealPCalRegionFromCurrentTLARegion() throws BadLocationException {

		final TLAtoPCalMapping mapping = getTLAEditorWithFocus().getTpMapping();
		if (mapping == null) {
			UIHelper.setStatusLineMessage("No valid TLA to PCal mapping found for current selection");
			return false;
		}

		final IDocument document = getCurrentDocument();
		final pcal.Region sourceRegion = AdapterFactory.jumptToPCal(mapping,
				EditorUtil.getCurrentLocation(1), document);
		if (sourceRegion == null) {
			// Cannot find a valid mapping for current selection
			return false;
		}

		/*
		 * The following command makes executing ReturnFromOpenDecl (F4) return
		 * to the selected location.
		 */
		setReturnFromOpenDecl();

		// Reveal the PCal source in the editor
		getTLAEditorWithFocus().selectAndReveal(sourceRegion);
		
		return true;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/TLCModelFactory.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.model;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationListener;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchManager;
import org.lamport.tla.toolbox.tool.tlc.launch.TLCModelLaunchDelegate;

public class TLCModelFactory implements IAdapterFactory, ILaunchConfigurationListener {

	private final Map<IFile, Model> launch2model = new HashMap<IFile, Model>();
	
	public TLCModelFactory() {
        final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
        launchManager.addLaunchConfigurationListener(this);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
	 */
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
		if (IResource.class.equals(adapterType) && adaptableObject instanceof Model) {
			// Convert a Model instance to an IResource (to connect SpecExplorer with ShowInSystemExplorerHandler).
			final Model model = (Model) adaptableObject;
			if (model.getFolder().exists()) {
				// Before a model has been checked or validated, the model folder doesn't exist. If it exists,
				// a user is likely more interested to open the folder.
				return (T) model.getFolder();
			}
			return (T) model.getFile();
		}
		if (!Model.class.equals(adapterType)) {
			return null;
		}
		if (adaptableObject instanceof ILaunchConfiguration) {
			final ILaunchConfiguration launchConfiguration = (ILaunchConfiguration) adaptableObject;
			// The ILC instances change all the time due to working copies being
			// created dynamically upon save. Thus, map the various ILC's to one
			// model by using the canonical IFile that all ILC instances are
			// technically represented by.
			final IFile key = launchConfiguration.getFile();
			Assert.isNotNull(key);
			if (!launch2model.containsKey(key)) {
				launch2model.put(key, new Model(launchConfiguration));
			}
			return (T) launch2model.get(key);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
	 */
	public Class<?>[] getAdapterList() {
		return new Class[] {ILaunchConfiguration.class, IResource.class};
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationAdded(org.eclipse.debug.core.ILaunchConfiguration)
	 */
	public void launchConfigurationAdded(final ILaunchConfiguration configuration) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationChanged(org.eclipse.debug.core.ILaunchConfiguration)
	 */
	public void launchConfigurationChanged(final ILaunchConfiguration configuration) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationRemoved(org.eclipse.debug.core.ILaunchConfiguration)
	 */
	public void launchConfigurationRemoved(final ILaunchConfiguration configuration) {
		// If the launch2model mapping has an entry for the removed launch
		// config, also dispose the corresponding Model instance. For example
		// Model#rename(String) internally creates a new ILaunchConfiguration
		// making the old obsolete.
		final IFile key = configuration.getFile();
		Assert.isNotNull(key);
		launch2model.remove(key);
	}

	/**
	 * @see Model#getByName(String)
	 */
	public static Model getByName(final String fullQualifiedModelName) {
		Assert.isNotNull(fullQualifiedModelName);
		Assert.isLegal(fullQualifiedModelName.contains(Model.SPEC_MODEL_DELIM), "Not a full-qualified model name.");
		
        final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
        final ILaunchConfigurationType launchConfigurationType = launchManager
                .getLaunchConfigurationType(TLCModelLaunchDelegate.LAUNCH_CONFIGURATION_TYPE);

		try {
			final ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations(launchConfigurationType);
			for (int i = 0; i < launchConfigurations.length; i++) {
				// Can do equals here because of full qualified name.
				final ILaunchConfiguration launchConfiguration = launchConfigurations[i];
				if (fullQualifiedModelName.equals(launchConfiguration.getName())) {
					return launchConfiguration.getAdapter(Model.class);
				}
			}
		} catch (CoreException shouldNeverHappen) {
			shouldNeverHappen.printStackTrace();
		}
		
		return null;
	}
	
	public static Model getBy(final IFile aFile) {
		Assert.isNotNull(aFile);
		
        final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
        final ILaunchConfigurationType launchConfigurationType = launchManager
                .getLaunchConfigurationType(TLCModelLaunchDelegate.LAUNCH_CONFIGURATION_TYPE);

		try {
			final ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations(launchConfigurationType);
			for (int i = 0; i < launchConfigurations.length; i++) {
				final ILaunchConfiguration launchConfiguration = launchConfigurations[i];
				if (aFile.equals(launchConfiguration.getFile())) {
					return launchConfiguration.getAdapter(Model.class);
				}
			}
		} catch (CoreException shouldNeverHappen) {
			shouldNeverHappen.printStackTrace();
		}
		
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/pcal/PCalHover.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic.pcal;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.text.IDocument;
import org.lamport.tla.toolbox.editor.basic.ToolboxHover;
import org.lamport.tla.toolbox.editor.basic.util.DocumentHelper.WordRegion;

public class PCalHover extends ToolboxHover implements IPCalReservedWords {
	
	private final Map<String, String> keywordHover = new HashMap<String, String>();

	public PCalHover() {
		keywordHover.put(ALGORITHM, ALGORITHM_HELP);
		keywordHover.put("algorithm", ALGORITHM_HELP);
		keywordHover.put(DEFINE, DEFINE_HELP);
		keywordHover.put(MACRO, MACRO_HELP);
		keywordHover.put(PROCEDURE, PROCEDURE_HELP);
		keywordHover.put(RETURN, RETURN_HELP);
		keywordHover.put(CALL, CALL_HELP);
		keywordHover.put(PROCESS, PROCESS_HELP);
		keywordHover.put(WHILE, WHILE_HELP);
		keywordHover.put("variable", VARIABLE_HELP);
		keywordHover.put("variables", VARIABLE_HELP);
		keywordHover.put(IF, IFTHENELSE_HELP);
		keywordHover.put(THEN, IFTHENELSE_HELP);
		keywordHover.put(ELSE, IFTHENELSE_HELP);
		keywordHover.put(ELSEIF, IFTHENELSE_HELP);
		keywordHover.put(EITHER, EITHEROR_HELP);
		keywordHover.put(OR, EITHEROR_HELP);
		keywordHover.put(WITH, WITH_HELP);
		keywordHover.put(AWAIT, AWAIT_HELP);
		keywordHover.put(PRINT, PRINT_HELP);
		keywordHover.put(ASSERT, ASSERT_HELP);
		keywordHover.put(SKIP, SKIP_HELP);
		keywordHover.put(GOTO, GOTO_HELP);
		keywordHover.put(":=", ASSIGN_HELP);
		keywordHover.put("||", MULTI_ASSIGN_HELP);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.editor.basic.ToolboxHover#getHoverInfo(org.eclipse.jface.text.IDocument, org.lamport.tla.toolbox.editor.basic.util.DocumentHelper.WordRegion)
	 */
	@Override
	protected String getHoverInfo(final IDocument document, final WordRegion wordRegion) {
		// Check if word matches any keywords.
		if (keywordHover.containsKey(wordRegion.getWord())) {
			return keywordHover.get(wordRegion.getWord());
		}
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/profiling.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/profiling.html  -->

 
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Profiling</title>
</head>
<!-- a comment here -->

<body>
<h1>Profiling</h1>

<pre>
Contents
  <a href="#how-it-works">What can the profiler do?</a>
  <a href="#modes">Profiling Modes</a>
  <a href="#ui">Profiler UI</a>
  <a href="#limitations">Limitations</a>
</pre>


<a name="how-it-works"></a><h2>What can the profiler do?</h2>

<p>
Profiling a  specification is similar to profiling implementation 
code: During model checking, the profiler collects evaluation 
metrics about the invocation of expressions, their costs, as well 
as  action metrics. The number of invocations equals the number 
of times an expression has been evaluated by the model checker. 
Assuming an identical, fixed cost for all expressions allows to 
identify the biggest contributor to overall model checking time 
by looking at the number of invocations. This assumption however 
does not hold for expressions that require the model checker to 
explicitly enumerate data structures as part of their evaluation. 
For example, let S be a set of natural numbers from N to M such 
that N << M and \A s \in SUBSET S : s \subseteq S be a  
expression. This expression will clearly be a major contributor 
to model checking time even if its number of invocations is low. 
More concretely, its cost equals the number of operations 
required by the model checker to enumerate the powerset of S. 
Users can override such  operators with more efficient variants. 
Specifically, TLC allows  operators to be overridden with Java 
code which can often be evaluated orders of magnitudes faster.
</p>
<p>
Evaluation metrics are captured globally and at the call-chain 
level. In other words, the metrics for an expression such as a  
operator, that occurs in two or more expressions, will be 
reported individually for each occurrence. Metrics are 
furthermore sensitive to constants such that the change of a 
constant value - across model checker runs - will be detectable 
in the metrics unless the constant has no influence at all.
</p>
<p>
Action metrics, which are orthogonal to evaluation metrics and 
are not found in an implementation profiler, are the total number 
of states and distinct states found which are reported at the  
action level.
</p>

<p>
The profiler neither requires the specification nor the model to 
be modified in order to collect metrics.
</p>

<a name="modes"></a><h2>Profiling modes</h2>

The profiler can be turned On to collect evaluation and action metrics, restricted to
action metrics only to debug action enablement, or switched off completely.  Overhead 
of profiling suggests to turn it off when checking large models. The control is located
on the TLC Options page of the Model.

<a name="ui"></a><h2>Profiling tab of the Model</h2>

The Toolbox overlays the evaluation and action metrics onto a module by coloring the 
exact locations of the corresponding expressions or  actions in the Spec Editor. Users 
can interactively drill into the call-chain scope by selecting individual expressions. 
Heatmaps allow to quickly navigate to the dominant contributors of model checking time 
as well as total states and distinct states found. Expressions with zero invocations 
and actions whose enablement predicate is never true - which are considered spec errors - 
are highlighted specifically.
<p>
<img src="profiler.png" alt="Action and evaluation metrics for the global scope overlayed 
onto the Spec Editor. Red boxes indicate action that are never enabled and dead expressions. 
The hover help displays detailed metrics for action a. Clicking the 1D heatmap at the bottom 
selects the corresponding expression." height="600" width="700" class="center"> 
<p>

<a name="limitations"></a><h2>Limitations</h2>

<ul>
  <li>Profiling only for the Spec and its invariants but not for liveness properties</li>
  <li>No support for distributed TLC</li>
  <li>Just profiling which incurs overhead, no sampling yet</li>
</ul>

<hr> 
<a href = "tlc-options-page.html">&uarr; TLC Options Page</a>
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/CommentToken.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS CommentToken                                                       *
* EXTENDS Token                                                            *
*                                                                          *
* A subclass of Token for a comment (a Token of type COMMENT).  In this    *
* subclass, the superclass's string field does not contain the "(*", "*)"  *
* or "\*" token.  Also, inner comments are stripped out.  This means       *
* that, if there are inner comments, the getWidth method returns the       *
* number of characters in the original comment that are not part of an     *
* inner comment.                                                           *
*                                                                          *
* The additional fields of the subclass are:                               *
*                                                                          *
*   rsubtype   : A "raw" subtype set by TokenizeSpec.Tokenize when         *
*                the token is created.                                     *
*                                                                          *
*   subtype    : A subtype for use in formatting the comment.  This        *
*                field is set by the ProcessComments method.               *
*                                                                          *
*   delimiters : Used to compute the width of the comment in the           *
*                original input.                                           *
***************************************************************************/
package tla2tex;

public class CommentToken extends Token
  { public int rsubtype ;
      /*********************************************************************
      * The "raw" subtype of the Token, set by the TokenizeSpec.Tokenize   *
      * method.  Below are its possible values, and their meanings.        *
      *********************************************************************/

      public static final int NORMAL = 1 ;
        /*******************************************************************
        * This is a "(* ... *)" comment on a single line.                  *
        *******************************************************************/

      public static final int LINE = 2 ;
        /*******************************************************************
        * This is a "\*" comment.                                          *
        *******************************************************************/

      public static final int BEGIN_OVERRUN = 3 ;
        /*******************************************************************
        * The first line of an overrun comment.                            *
        *******************************************************************/

      public static final int END_OVERRUN = 4 ;
        /*******************************************************************
        * The last line of an overrun comment.                             *
        *******************************************************************/
        
      public static final int OVERRUN = 5 ;
        /*******************************************************************
        * After tokenizing, this is a line in the middle of an overrun     *
        * comment.  With further processing, this subtype may be changed.  *
        *******************************************************************/

   public int subtype ;
      /*********************************************************************
      * The interpreted subtype, set by the ProcessComments method.        *
      * Below are its possible values, and their meanings.                 *
      *********************************************************************/
        public static final int ONE_LINE    = 6 ;
          /*****************************************************************
          * A comment that is typeset on a single line.                    *
          *****************************************************************/
          
        public static final int BEGIN_MULTI = 7 ;
          /*****************************************************************
          * The beginning of a multi-line end comment.                     *
          *****************************************************************/

        public static final int MULTI = 8 ;
          /*****************************************************************
          * A line of the body of a multi-line end comment.                *
          *****************************************************************/

        public static final int NULL = 9 ;
          /*****************************************************************
          * A line of "*"s that ends a multi-line comment, and is thus     *
          * not to be printed.                                             *
          *****************************************************************/
          
        public static final int PAR = 10 ;
          /*****************************************************************
          * A line of a paragraph comment--that is, one begun with a (*    *
          * that covers multiple lines before the *).  If the first or     *
          * last line of a paragraph comment is not the only token on the  *
          * line, then that line is turned into a one-line comment.        *
          *****************************************************************/
          
   private int delimiters = 0;
     /**********************************************************************
     * This is the number of comment delimiter characters deleted from     *
     * the string.  It is 4 for a "(* ... *)" comment, etc.                *
     **********************************************************************/
     
   public CommentToken(String str, int col, int sub, boolean pseudo)
     /**********************************************************************
     * The constructor for this class.  The third argument specifies the   *
     * rsubtype.  The fourth argument is true iff this comment is ended    *
     * by the beginning of a PlusCal algorithm or begun by the end of a    *
     * PlusCal algorithm.  In either case, two delimiter characters that   *
     * normally would have been deleted weren't.                           *
     **********************************************************************/
     { type    = Token.COMMENT; 
       column = col ;
       string  = str;
       rsubtype = sub;
       subtype = 0 ;
       switch (rsubtype)
         { case NORMAL :         delimiters = pseudo?2:4;
                                 break;
           case LINE :
           case BEGIN_OVERRUN :
           case END_OVERRUN :    delimiters = pseudo?0:2;
                                 break ;

           case OVERRUN :        break ;
           default : Debug.ReportBug(
                      "CommentToken constructor called with illegal subtype"
                      );
         } ;

     };     

   public int getWidth()
     /**********************************************************************
     * Returns the number of columns occupied by the token in the input.   *
     **********************************************************************/
     { if (string == null) {return 0;} ;
       return string.length() + delimiters ;
     }

   public static void ProcessComments(Token[][] spec)
      /*********************************************************************
      * This computes the subtype of each token, based on the rsubtypes.   *
      *                                                                    *
      * OVERRUN :                                                          *
      *    Set to PAR.                                                     *
      *                                                                    *
      * BEGIN_OVERRUN or END_OVERRUN :                                     *
      *    Set to PAR, and its column field set to 0, if it is the         *
      *    only token on the line.  Otherwise, it is changed to ONE_LINE.  *
      *                                                                    *
      * NORMAL or LINE :                                                   *
      *    If not part of a multiline comment, set to ONE_LINE.            *
      *                                                                    *
      *    If part of a multiline comment at least one of whose            *
      *    lines contains another token (which must be to the left),       *
      *    then set to BEGIN_MULTI, MULTI, or NULL depending               *
      *    on whether it is the first line, an inner line, or the          *
      *    (optional) end line.                                            *
      *                                                                    *
      *    If part of a multiline comment all of whose lines contain       *
      *    only this comment, then the first and (optional) end line       *
      *    are set to NULL and the inner lines are set to PAR.             *
      *                                                                    *
      *    Note: The first or end line of a multi-line comment is one      *
      *    that consists of all *'s or -'s for a NORMAL comment, and       *
      *    consists of at least 3 *'s or -'s followed by spaces and or     *
      *    *'s or -'s for a                                                *
      *    LINE comment.                                                   *
      *********************************************************************/
     { int line = 0 ;       
         /******************************************************************
         * The current line.                                               *
         ******************************************************************/

       int beginLine = -1 ; 
         /******************************************************************
         * The line beginning the current multi-line comment.              *
         ******************************************************************/

       while (line < spec.length)
        /*******************************************************************
        * Loop Invariant:                                                  *
        *   /\ 0 \leq item \leq = spec[line].length                        *
        *   /\ (beginLine # -1) <=>                                        *
        *        /\ beginLine is largest i < line s.t.                     *
        *               Last token of spec[beginLine] is a "******"        *
        *               comment.                                           *
        *        /\ \A i \in beginLine .. (line - 1) :                     *
        *             /\ Last token of spec[beginLine] is a comment.       *
        *             /\ spec[i].column =                                  *
        *                 spec[beginLine][spec[beginLine].length-1].column *
        *******************************************************************/
        { int item = 0;

          boolean beginMultiLine = false ;
               /************************************************************
               * Set to true if this should begin the next multi-line      *
               * comment.                                                  *
               ************************************************************/

          boolean endMultiLine = false ;
               /************************************************************
               * Set to true if this should end the previous multi-line    *
               * comment.                                                  *
               ************************************************************/
             
          while (item < spec[line].length)
           { 
             if (spec[line][item].type == COMMENT)
               { /**********************************************************
                 *                  This is a comment token.               *
                 **********************************************************/
                 boolean starLine = true ;
                   /********************************************************
                   * For the last token on the line, this is set false     *
                   * iff this is not a star comment.                       *
                   ********************************************************/
                 CommentToken tok = (CommentToken) spec[line][item] ;
                 if (item == spec[line].length - 1)
                   { /******************************************************
                     * This is the last token on the line.                 *
                     ******************************************************/

                     /******************************************************
                     * Set starLine to false if this is not a LINE or      *
                     * NORMAL "****" comment.                              *
                     ******************************************************/
                     if (   (   (tok.rsubtype != LINE)
                             && (tok.rsubtype != NORMAL))
                         || (tok.string.length() == 0))
                            /***********************************************
                            * A "\*" or "(**)" comment is not considered   *
                            * a star line.                                 *
                            ***********************************************/
                       { starLine = false; } ;
                     int ch = 0;
                     while (   starLine
                            && (ch < tok.string.length())
                            && (ch <= 3) )
                      { if (   (tok.string.charAt(ch) != '*')
                            && (tok.string.charAt(ch) != '-'))
                          { starLine = false; } ;
                        ch = ch+1 ;
                      } // end while
                     ch = 4;
                     while (   starLine
                            && (ch < tok.string.length()))
                      { if (   (tok.string.charAt(ch) != '*')
                            && (tok.string.charAt(ch) != '-')
                            && (tok.string.charAt(ch) != ' '))
                          { starLine = false; };
                        ch = ch+1 ;
                      } // end while

                     /******************************************************
                     * Set endMultiLine for a COMMENT token.               *
                     ******************************************************/
                     if (   (beginLine != -1)
                         && (   (   (tok.rsubtype != LINE)
                                 && (tok.rsubtype != NORMAL))
                             || (tok.column  != 
                                   spec[beginLine][
                                             spec[beginLine].length - 1].column)
                             || starLine ))
                        { endMultiLine = true ;}

                     /******************************************************
                     * Set beginMultiLine (only done for a COMMENT token). *
                     ******************************************************/
                     if (   starLine
                         && (   (beginLine == -1) 
                             || (tok.column  != 
                                   spec[beginLine][
                                      spec[beginLine].length - 1].column)))
                        /***************************************************
                        * Note: A non-aligned star line both ends and      *
                        * begins a multi-line comment.                     *
                        ***************************************************/
                        { beginMultiLine = true;} ;

                   }  // END then OF if (item == spec[line].length - 1)
                 else 
                   { /******************************************************
                     * This is not the last token on the line .            *
                     ******************************************************/
                     
                   }; // END else OF if (item == spec[line].length - 1)
                 /**********************************************************
                 * Set the subtype of the COMMENT token.                   *
                 **********************************************************/
                 switch (tok.rsubtype)
                   { case NORMAL :
                     case LINE   :
                       if (beginMultiLine)
                         { tok.subtype = BEGIN_MULTI ; }
                       else
                         { if (endMultiLine)
                            { 
                              if (starLine)
                                { tok.subtype = NULL ; }
                              else 
                                { tok.subtype = ONE_LINE ;} ; 
                            }
                          else
                            { if (   (beginLine != -1)
                                  && (item == spec[line].length - 1))
                                { tok.subtype = MULTI ;}
                              else
                                { tok.subtype = ONE_LINE ;} ; 
                            }
                         };
                       break ;

                     case BEGIN_OVERRUN :
                       if (item == 0)
                         { tok.subtype = PAR ;}
                       else
                         { tok.subtype = ONE_LINE ;} ;
                       break ;

                     case END_OVERRUN   :
                       if (item == spec[line].length - 1)
                         { tok.subtype = PAR ;}
                       else
                         { tok.subtype = ONE_LINE ;} ;
                       break ;

                     case OVERRUN :
                       tok.subtype = PAR ;
                       break ;

                     default :
                       Debug.ReportBug(
                        "Bad token rsubtype in CommentToken.ProcessComments");
                   } ; // END switch (tok.rsubtype)                 

                 /**********************************************************
                 * Set aboveAlign for NULL or MULTI comments.              *
                 **********************************************************/
                 if (   (tok.subtype == MULTI)
                     || (tok.subtype == NULL))
                   { tok.aboveAlign = 
                       new Position(beginLine, spec[beginLine].length - 1);
                   } ;


               } // END then OF if (spec[line][item].type == COMMENT)
             else
               { /**********************************************************
                 * This is not a comment token.                            *
                 *                                                         *
                 * Set endMultiLine true if a multi-line comment has       *
                 * been started and this is the last token on the line.    *
                 **********************************************************/
                 if (   (beginLine != -1)
                     && (item == spec[line].length - 1))
                   { endMultiLine = true ;}

               } ;  // END else OF if (spec[line][item].type == COMMENT)

             item = item + 1 ;
           }; // END while (item < spec[line].length)

          /**************************************************************
          * Set or reset beginLine if necessary.                        *
          **************************************************************/
          if (endMultiLine || (spec[line].length == 0))
            {beginLine = -1;} ;
          if (beginMultiLine) {beginLine = line;} ;

          line = line + 1 ;
        }; // END while (line < spec.length)
     }; // END ProcessComments(Token[][] spec)


   public String toString()
      /*********************************************************************
      * For debugging output.                                              *
      *********************************************************************/
      { String rstypeName = "";
        String stypeName = "";
        switch (rsubtype) 
          { case NORMAL        : rstypeName = "NORMAL"        ; break ;
            case LINE          : rstypeName = "LINE"          ; break ;
            case BEGIN_OVERRUN : rstypeName = "BEGIN_OVERRUN" ; break ;
            case END_OVERRUN   : rstypeName = "END_OVERRUN"   ; break ;
            case OVERRUN       : rstypeName = "OVERRUN"       ; break ;
          } ;
        switch (subtype) 
          { case ONE_LINE      : stypeName = "ONE_LINE"      ; break ;
            case BEGIN_MULTI   : stypeName = "BEGIN_MULTI"   ; break ;
            case MULTI         : stypeName = "MULTI"         ; break ;
            case NULL          : stypeName = "NULL"          ; break ;
            case PAR           : stypeName = "PAR"           ; break ;
          } ;
        return Misc.BreakLine( mostOfString() + 
                          ",\t subtype |-> " + stypeName + 
                          ",\t rsubtype |-> " + rstypeName + 
                          ",\t delim |-> " + delimiters + "]");
      };  

  }

/* last modified on Tue 18 Sep 2007 at  6:44:14 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/OpValue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:21:02 PST by lamport
//      modified on Fri Sep 22 13:18:45 PDT 2000 by yuanyu

package tlc2.value.impl;

import tla2sany.semantic.ExprOrOpArgNode;
import tlc2.tool.TLCState;
import tlc2.tool.coverage.CostModel;
import tlc2.tool.impl.Tool;
import tlc2.util.Context;

public abstract class OpValue extends Value implements Applicable {

	// Allow sub-classes to override.
	public Value eval(final Tool tool, final ExprOrOpArgNode[] args, final Context c, final TLCState s0,
			final TLCState s1, final int control, final CostModel cm) {
		final Value[] argVals = new Value[args.length];
		// evaluate the operator's arguments:
		for (int i = 0; i < args.length; i++) {
			argVals[i] = tool.eval(args[i], c, s0, s1, control, cm);
		}
		// evaluate the operator:
		return this.apply(argVals, control);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/Enumerable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:20:54 PST by lamport
//      modified on Thu Mar 11 21:25:20 PST 1999 by yuanyu

package tlc2.value.impl;

import tlc2.value.IValue;

public interface Enumerable extends IValue {

	enum Ordering {
		UNDEFINED,
		/**
		 * The normalized order is the order of elements when a Value gets
		 * fingerprinted (@see {@link Value#fingerPrint(long)}.
		 */
		NORMALIZED,
		/**
		 * A randomized ordering of the elements returned by this enumerator. Contrary
		 * to the other orderings, the enumerator is *not* guaranteed to enumerate all
		 * elements but only enumerates all of them with increasing probability
		 * eventually.
		 */
		RANDOMIZED
    }
	
  @Override
  int size();
  boolean member(Value elem);
  /**
   * Semantics or Enumerable#elements(Ordering#UNDEFINED) 
   */
  ValueEnumeration elements();
  ValueEnumeration elements(final Ordering ordering);
  /**
   * Returns a {@link ValueEnumeration} which returns k 
   * {@link IValue}s of all {@link IValue}s returned by 
   * {@link Enumerable#elements()}. In other words, it returns
   * a randomly chosen subset of all {@link IValue} members of
   * this {@link Enumerable}.
   */
  ValueEnumeration elements(final int k);
  EnumerableValue getRandomSubset(final int k);
  Value isSubsetEq(Value other);
}



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/coverage/CostModelNode.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import java.util.LinkedHashMap;
import java.util.Map;

import tla2sany.semantic.SemanticNode;
import tla2sany.st.Location;
import tlc2.TLCGlobals;
import tlc2.util.statistics.CounterStatistic;

public abstract class CostModelNode implements CostModel {
	
	// children has to preserve order to later traverse tree in the module location
	// order when reporting coverage. Thus, use LinkedHashMap here.
	protected final Map<SemanticNode, CostModelNode> children = new LinkedHashMap<>();

	protected final CounterStatistic stats = CounterStatistic.getInstance(() -> TLCGlobals.isCoverageEnabled());
	protected final CounterStatistic secondary = CounterStatistic.getInstance(() -> TLCGlobals.isCoverageEnabled());
	
	// ---------------- Statistics ---------------- //

	protected long getEvalCount() {
		return this.stats.getCount();
	}

	protected long getSecondary() {
		return this.secondary.getCount();
	}

	protected abstract Location getLocation();

	// -- --//
	
	void addChild(final CostModelNode child) {
		final boolean newlyInserted = this.children.put(child.getNode(), child) == null;
		assert newlyInserted;
	}

	abstract SemanticNode getNode();
	
	@Override
	public abstract CostModelNode getRoot();
	
	boolean isRoot() {
		return false;
	}

	int getLevel() {
		return 0;
	}
	
	// -- -- //
	
	@Override
	public final CostModel getAndIncrement(final SemanticNode eon) {
		return get(eon).incInvocations();
	}

	@Override
	public final CostModel incInvocations(long size) {
		this.stats.add(size);
		return this;
	}

	@Override
	public final CostModel incInvocations() {
		this.stats.increment();
		return this;
	}

	public final CostModel incSecondary() {
		this.secondary.increment();
		return this;
	}

	@Override
	public final CostModel incSecondary(final long value) {
		this.secondary.add(value);
		return this;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ModuleRelationships.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.modanalyzer;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Each instance of this class basically is a map from ModulePointer objects to
 * ModuleRelatives objects.
 *
 * It is primarily a wrapper for a Hashtable, with the added benefit of type checking
 */

class ModuleRelationships {

  // Maps ModulePointer objects to ModuleRelatives objects
  private Hashtable modRelHashtable = new Hashtable();

/*
  ModuleRelatives getRelatives(ModulePointer modulePointer) { 
    return modulePointer.getRelatives(); //(ModuleRelatives)modRelHashtable.get(modulePointer); 
  }
*/

  void putRelatives (ModulePointer modulePointer, ModuleRelatives relatives) {
    modRelHashtable.put(modulePointer, relatives);
  } // end putRelatives()


  ModuleContext getContext(ModulePointer module) {
    return module.getRelatives().context;
  } // end getContext()


  Enumeration<ModulePointer> getKeys() { return modRelHashtable.keys(); }  


  // Add the entries from otherMR into THIS; they are assumed not to overlap.
  void union(ModuleRelationships otherMR) {

    Enumeration otherKeys = otherMR.getKeys();

    while ( otherKeys.hasMoreElements() ) {
      ModulePointer key = (ModulePointer)otherKeys.nextElement();

      if (key.getRelatives() == null ) { 
        this.putRelatives( key, key.getRelatives() );
      }
    }

  } // end union()


  public String toString() {

    String ret = "";

    Enumeration e = modRelHashtable.keys();
    while ( e.hasMoreElements()) {

      ModulePointer   modPtr    = (ModulePointer)e.nextElement();

      ret = ret + "\n----------- Module '" + modPtr.getName() + "'\n";
      ret = ret + modPtr.getRelatives().toString(); 
      ret = ret + "-----------" + "\n";  

    } // end while 

    return ret;

  } // end toString()

} // end class


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/TLCStates.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.OpDeclNode;
import tlc2.value.impl.IntValue;
import util.UniqueString;

public abstract class TLCStates {

	public static TLCState createDummyState() {
		return createDummyState(1);
	}

	public static TLCState createDummyState(final int numVars) {
		UniqueString.setVariableCount(numVars);

		// Create variable declarations (no values yet).
		final OpDeclNode[] variables = new OpDeclNode[numVars];
		for (int i = 0; i < numVars; i++) {
			UniqueString us = UniqueString.uniqueStringOf("v" + Integer.toString(i));
			us.setLoc(i);
			variables[i] = new OpDeclNode(us, ASTConstants.VariableDeclKind, 1, 0, null, null, null);
		}

		// Initialize the empty state (variable declarations are static/final per TLC
		// run).
		TLCStateMut.setVariables(variables);
		final TLCState state = TLCState.Empty.createEmpty();
		state.uid = 0;

		// Assign values to variables.
		for (int i = 0; i < numVars; i++) {
			state.bind(variables[i].getName(), IntValue.gen(i));
		}

		return state;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/suite/Test213.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.suite;

import static org.junit.Assert.assertFalse;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;

public class Test213 extends SuiteETestCase {

	public Test213() {
		super(ExitStatus.ERROR_SPEC_PARSE);
	}
	
	@Test
	public void testSpec() {
		assertFalse(recorder.recorded(EC.GENERAL));
		assertSubstring("Semantic errors:\n" + 
				"\n" + 
				"*** Errors: 5\n" + 
				"\n" + 
				"line 13, col 1 to line 13, col 52 of module test213\n" + 
				"\n" + 
				"Level error in instantiating module 'test213b':\n" + 
				"The level of the expression or operator substituted for 'C' \n" + 
				"must be at most 2.\n" + 
				"\n" + 
				"\n" + 
				"line 14, col 1 to line 14, col 52 of module test213\n" + 
				"\n" + 
				"Level error in instantiating module 'test213b':\n" + 
				"The level of the expression or operator substituted for 'D' \n" + 
				"must be at most 2.\n" + 
				"\n" + 
				"\n" + 
				"line 29, col 8 to line 29, col 15 of module test213\n" + 
				"\n" + 
				"Non-constant CASE for temporal goal.\n" + 
				"\n" + 
				"\n" + 
				"line 31, col 8 to line 31, col 15 of module test213\n" + 
				"\n" + 
				"Non-constant TAKE, WITNESS, or HAVE for temporal goal.\n" + 
				"\n" + 
				"\n" + 
				"line 33, col 8 to line 33, col 22 of module test213\n" + 
				"\n" + 
				"Non-constant TAKE, WITNESS, or HAVE for temporal goal.\n" + 
				"\n" + 
				"\n" + 
				"");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/SBBTest_TTraceTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;
import tlc2.tool.liveness.TTraceModelCheckerTestCase;

public class SBBTest_TTraceTest extends TTraceModelCheckerTestCase {

	public SBBTest_TTraceTest() {
		super(SBBTest.class, "pcal", ExitStatus.VIOLATION_SAFETY);
	}

    @Test
	public void testSpec() {
		assertTrue(recorder.recordedWithStringValue(EC.TLC_INIT_GENERATED1, "1"));
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertFalse(recorder.recorded(EC.GENERAL));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "15", "15", "0"));
		assertEquals(15, recorder.getRecordAsInt(EC.TLC_SEARCH_DEPTH));

		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT2));
		final List<String> expectedTrace = new ArrayList<String>();
		expectedTrace.add("/\\ availablebuffers = {b1, b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> NoBuf @@ p1 :> NoBuf)\n" + 
				"/\\ op = (p0 :> {} @@ p1 :> {})\n" + 
				"/\\ pc = (p0 :> \"Loop\" @@ p1 :> \"Loop\")");
		expectedTrace.add("/\\ availablebuffers = {b1, b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> NoBuf)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> {})\n" + 
				"/\\ pc = (p0 :> \"Publish1\" @@ p1 :> \"Loop\")");
		expectedTrace.add("/\\ availablebuffers = {b1, b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> NoBuf)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> {})\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Loop\")");
		expectedTrace.add("/\\ availablebuffers = {b1, b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b0)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify1\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b0, owner |-> p1]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify3\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> p1]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Loop\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> p1]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify1\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> p1]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish3\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {b0}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b0 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Loop\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {b0}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b1 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish1\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {b0}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b1 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish2\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {b0}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b1 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Publish3\" @@ p1 :> \"Modify2\")");
		expectedTrace.add("/\\ availablebuffers = {b2, b3}\n" + 
				"/\\ publishedbuffers = {b0, b1}\n" + 
				"/\\ sb = [buf |-> b1, owner |-> NoPid]\n" + 
				"/\\ buf = (p0 :> b1 @@ p1 :> b1)\n" + 
				"/\\ op = (p0 :> \"Publish\" @@ p1 :> \"Modify\")\n" + 
				"/\\ pc = (p0 :> \"Loop\" @@ p1 :> \"Modify2\")");
		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);

		assertZeroUncovered();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/output/IProverProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.output;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;

/**
 * An interface for sinks which receive output from the TLAPM.
 * The sinks receive output through the method {@link #appendText(String)}.
 * They are given a chance to initialize prior to any text being sent
 * through the method {@link #initializeSink(IFile, ProverJob, IProgressMonitor)}.
 * The method {@link #processFinished()} indicates that no more text will be
 * sent.
 * 
 * @author <NAME>
 *
 */
public interface IProverProcessOutputSink
{
    /**
     * Indicates that the sink is receiving output from a launch
     * of the prover in which proving but not checking is done.
     */
    public final static int TYPE_PROVE = 1;
    /**
     * Indicates that the sink is receiving output from a launch
     * of the prover in which checking is done.
     */
    public final static int TYPE_CHECK = 2;

    /**
     * Appends text to the sink.
     * 
     * @param text 
     */
    public void appendText(String text);

    /**
     * Called prior to appending text. Allows the sink to perform any
     * necessary initialization before receiving output from the prover.
     * 
     * The {@link IFile} is a handle on the module on which the prover was launched
     * 
     * @param moduleFile the file handle on the module
     * @param proverJob job contains a description of the prover launch. Contains information about
     * the parameters used to launch the prover.
     * @param monitor a progress monitor that can be used to report progress
     */
    public void initializeSink(IFile moduleFile, ProverJob proverJob, IProgressMonitor monitor);

    /**
     * Signal to the sink that the prover process has terminated and no data will be sent.
     */
    public void processFinished();

}


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/generator/BatchedFingerPrintGenerator.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp.generator;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

import org.junit.Assert;

import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.MultiThreadedFPSetTest;

public class BatchedFingerPrintGenerator extends FingerPrintGenerator {

	private static final int batch = 1024;
	
	public BatchedFingerPrintGenerator(MultiThreadedFPSetTest test, int id, int numThreads, FPSet fpSet, CountDownLatch latch, long seed, long insertions, final CyclicBarrier barrier) {
		super(test, id, numThreads, fpSet, latch, seed, insertions, barrier);
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		waitForAllThreadsStarted();
		
		long predecessors[] = new long[batch];
		boolean initialized = false;
		// Reduce number of FPSet#size invocation by counting puts/collisions.
		// FPSet#size can cause an FPSet to synchronize all its writers slowing
		// down execution.
		while (puts + collisions < perThreadInsertions || fpSet.size() < totalInsertions) {
			try {
				// Make sure set still contains predecessors
				if (initialized) {
					for (int i = 0; i < predecessors.length; i++) {
						long predecessor = predecessors[i];
						Assert.assertTrue(fpSet.contains(predecessor));
					}
				}

				// Fill new fingerprints and sort them
				for (int i = 0; i < predecessors.length; i++) {
					predecessors[i] = rnd.nextLong();
				}
				initialized = true;
				Arrays.sort(predecessors);

				// Add sorted batch to fpset
				for (int i = 0; i < predecessors.length; i++) {
					long predecessor = predecessors[i];
					boolean put = fpSet.put(predecessor);
					if (put == false) {
						puts++;
					} else {
						collisions++;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
				Assert.fail("Unexpected");
			}
		}
		latch.countDown();
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/AST.java<|end_filename|>

/***************************************************************************
* CLASS AST                                                                *
*                                                                          *
* This class defines AST objects, which represent non-terminals of the     *
* +CAL grammar, to be subclasses of the AST class.                         *
*                                                                          *
* Each subclass has a toString() method that prints the object as the      *
* TLA+ record that represents that node in the representation of the       *
* abstract syntax tree used in the PlusCal TLA+ specification.             *
*                                                                          *
* There are no explicit classes corresponding to the following             *
* non-terminals.                                                           *
*                                                                          *
*    Algorithm   AlgorithmBody LabelSeq   SimpleStmt   Finalstmt  VarDecls *
*                                                                          *
* However, there are the following classes that do not represent explicit  *
* non-terminals of the +CAL grammar.                                       *
*                                                                          *
* Uniprocess   MultiProcess   SingleAssign   CallReturn   CallGoto         *
*                                                                          *
* Every AST has col and line fields that contain the position of the       *
* first character of the corresponding portion of the algorithm text (as   *
* human ordinals, numbered starting from 1).                               *
*                                                                          *
*                                                                          *
* Since the only way Java has of defining record (struct) type is by       *
* making it a class, all the different AST node subtypes had to be         *
* subclasses.  I didn't want to put each of them in a separate file, so I  *
* made them all nested inner static classes in this file.  (I presume it   *
* doesn't make sense to make them dynamic classes, since that would imply  *
* that each instance of an AST node has its own separate instance of       *
* those classes.  Anyway, we Java produces a runtime NoSuchMethodError     *
* unless I make the inner classes static.)                                 *
*                                                                          *
* To enable a method to figure out what subclass an AST object is, I       *
* initially gave the class a type field and tried to use that field to     *
* determine the type.  However, this didn't work right at all.  The        *
* problem is that when an element of the subtype gets obtained as an       *
* object of the superclass AST--for example, when it's pulled out of a     *
* vector of AST objects, the type field of the resulting object is set to  *
* the value set by the supertype's constructor.  So, I need to actually    *
* find out what Java thinks the class of the object is.  The following     *
* hack seems to work.  To determine if the subclass of an AST object obj   *
* is Skip, one can test                                                    *
*                                                                          *
*    obj.getClass().toString().equals("class pcal.AST$Skip")               *
*                                                                          *
* However, this seems unlikely to work for all versions of all Java        *
* implementations.  So, for each subclass like AST.Skip, we define an      *
* object SkipObj of that class.  We then test if obj is of class AST.Skip  *
* by                                                                       *
*                                                                          *
*    obj.getClass().equals(AST.SkipObj.getClass())                         *
*                                                                          *
* The object SkipObj cannot be declared with an initial value, because     *
* that leads the initialization of the AST class to go into an infinite    *
* loop.  So, the method AST.ASTInit() assign a new AST.Skip node to        *
* AST.SkipObj.                                                             *
*                                                                          *
* I'm sure there's a better way, but I can't find anything about           *
* it in the Java Reference Manual.                                         *
***************************************************************************/
package pcal;
import java.util.Vector;

public class AST
  { public static AST.Uniprocess   UniprocessObj   ;
    public static AST.Multiprocess MultiprocessObj ;
    public static AST.Procedure    ProcedureObj    ;
    public static AST.Process      ProcessObj      ;
    public static AST.VarDecl      VarDeclObj      ;
    public static AST.PVarDecl     PVarDeclObj     ;
    public static AST.LabeledStmt  LabeledStmtObj  ;
    public static AST.While        WhileObj        ;
    public static AST.Assign       AssignObj       ;
    public static AST.SingleAssign SingleAssignObj ;
      /*********************************************************************
      * We added an explicit SINGLEASSIGN type to represent a single       *
      * assignment within a multi-assignment.  We did this because Java    *
      * doesn't allow a record (struct) to be constructed as anything      *
      * other than an object of some class.                                *
      *********************************************************************/
    public static AST.Lhs          LhsObj          ;
    public static AST.If           IfObj           ;
    public static AST.Either       EitherObj       ;
    public static AST.With         WithObj         ;
    public static AST.When         WhenObj         ;
    public static AST.PrintS       PrintSObj       ;
    public static AST.Assert       AssertObj       ;
    public static AST.Skip         SkipObj         ;
    public static AST.LabelIf      LabelIfObj      ;
    public static AST.LabelEither  LabelEitherObj  ;
    public static AST.Clause       ClauseObj       ;
      /*********************************************************************
      * Because Java doesn't have records, only objects, we we add an      *
      * explicit Clause object to be a record such that the `clauses'      *
      * field of a LabelEither object is a sequence of Clause objects.     *
      *********************************************************************/
    public static AST.Call         CallObj         ;
    public static AST.Return       ReturnObj       ;
    public static AST.CallReturn   CallReturnObj   ;
    public static AST.CallGoto     CallGotoObj     ;
    public static AST.Goto         GotoObj         ;
    public static AST.Macro        MacroObj        ;
    public static AST.MacroCall    MacroCallObj    ;

    public int col ;
    public int line ;
      /*********************************************************************
      * These are the column and line numbers of the first token in the    *
      * algorithm text that corresponds to the AST. (They are human        *
      * ordinals, counting from 1.)                                        *
      *********************************************************************/
    public int macroCol  = 0 ;
    public int macroLine = -1 ;  
      /*********************************************************************
      * If this is an object that was inserted into the AST as the result  *
      * of macro expansion, then this is the column and line number of     *
      * the MacroCall object that was expanded.  The col and line values   *
      * give the position of the object in the macro definition that       *
      * yielded the current object when the macro was expanded.            *
      *                                                                    *
      * If the object was not inserted by macro expansion, then macroLine  *
      * equals -1.                                                         *
      *********************************************************************/
    
    /**
     * If this AST is a statement that is the first statement resulting from
     * expansion of a macro call , then macroOriginBegin is set to the  
     * origin.begin value of the macro call.  It is set by 
     * ParseAlgorithm.ExpandMacroCall and is used by PcalTLAGen.GenLabeledStmt 
     * to set the MappingObject.LeftParen that marks the beginning of the 
     * labeled statement's translation.
     * 
     * macroOriginEnd is similarly set for the last statement resulting from
     * the expansion of a mapping call and used to set the labeled statement's
     * translation's MappingObject.RightParen.
     * 
     * This is a Kludge to correct a bug in the TLA+ translation to
     * PlusCal mapping.  These kludges are the result of implementing
     * that mapping on top of the existing translator, rather than rewriting
     * the translation. 
     */
    public PCalLocation macroOriginBegin = null;
    public PCalLocation macroOriginEnd = null;

    public String lbl = "" ;
      /*********************************************************************
      * Added by LL on 3 Mar 2006.  Used to hold a statement's label       *
      * during the parsing process, but irrelevant once the final AST has  *
      * been constructed.                                                  *
      *********************************************************************/
    
    /**
     * If the lbl field is not the empty string "", then lblLocation is
     * the location of the beginning of the label that provided the string
     * if it came from a label written by the user.  It will be null if the
     * label was added by the translator.
     */
    public PCalLocation lblLocation = null ;
    
    /**
     * The region of the PlusCal code from which the object was created.
     */
    private Region origin = null ;
    
    public Region getOrigin() {
        return origin;
    }

    public void setOrigin(Region origin) {
        this.origin = origin;
    }

    public String location()
      /*********************************************************************
      * The string that describes the location in the algorithm of the     *
      * first token that represents the AST object.  Should be used in     *
      * error messages.                                                    *
      *********************************************************************/
      { if (macroLine < 0)
          { return "line " + line + ", column " + col ; }
        else
          { return "line " + line + ", column " + col +
                   " of macro called at line " + macroLine + 
                   ", column " + macroCol ; }
      }
      
    public static void ASTInit()
      /*********************************************************************
      * An initializing method that creates the ...Obj objects used to     *
      * test the class of an AST object.                                   *
      *********************************************************************/
      { UniprocessObj   = new AST.Uniprocess() ;
        MultiprocessObj = new AST.Multiprocess() ;
        ProcedureObj    = new AST.Procedure() ;
        ProcessObj      = new AST.Process() ;
        VarDeclObj      = new AST.VarDecl() ;
        PVarDeclObj     = new AST.PVarDecl() ;
        LabeledStmtObj  = new AST.LabeledStmt() ;
        WhileObj        = new AST.While() ;
        AssignObj       = new AST.Assign() ;
        SingleAssignObj = new AST.SingleAssign() ;
        LhsObj          = new AST.Lhs() ;
        IfObj           = new AST.If() ;
        EitherObj       = new AST.Either() ;
        WithObj         = new AST.With() ;
        WhenObj         = new AST.When() ;
        PrintSObj       = new AST.PrintS() ;
        AssertObj       = new AST.Assert() ;
        SkipObj         = new AST.Skip() ;
        LabelIfObj      = new AST.LabelIf() ;
        LabelEitherObj  = new AST.LabelEither() ;
        CallObj         = new AST.Call() ;
        ReturnObj       = new AST.Return() ;
        CallReturnObj   = new AST.CallReturn() ;
        CallGotoObj     = new AST.CallGoto() ;
        GotoObj         = new AST.Goto() ;
        MacroObj        = new AST.Macro() ;
        MacroCallObj    = new AST.MacroCall() ;
      }


    public static class Uniprocess extends AST
      { public String  name   = "" ;
        public Vector  decls  = null ; // of VarDecl 
        public TLAExpr defs   = null ;
        public Vector  macros = null ; // of Macro
        public Vector  prcds  = null ; // of Procedure
        public Vector  body   = null ; // of LabeledStmt
        public Uniprocess() {};
        public String toString() 
          { return
             Indent(lineCol()) +  
               "[type     |-> \"uniprocess\", " + NewLine() +
               " name  |-> \"" + name + "\", " + NewLine() +
               Indent(" decls  |-> ") + VectorToSeqString(decls) + ","
                                           + 
               EndIndent() + NewLine() +
               Indent(" defs   |-> ") + defs.toString() + ","
                                           + 
               EndIndent() + NewLine() +

              /*************************************************************
              * Uncomment the following to print the macros field.  It is  *
              * commented out so the printed result is what PlusCal.tla    *
              * considers a Uniprocess object to be.                       *
              *************************************************************/
              // Indent(" macros |-> ") + VectorToSeqString(macros) + ","
              //                             + 
              //  EndIndent() + NewLine() +

               Indent(" prcds  |-> ") + VectorToSeqString(prcds) + ","
                                           + 
               EndIndent() + NewLine() +
               Indent(" body  |-> ") + VectorToSeqString(body) + "]" +
               EndIndent() +
            EndIndent() ;
          }
      }

    public static class Multiprocess extends AST
      { public String  name   = "" ;
        public Vector  decls  = null ; // of VarDecl 
        public TLAExpr defs   = null ;
        public Vector  macros = null ; // of Macro
        public Vector  prcds  = null ; // of Procedure
        public Vector  procs  = null ; // of Process
        public Multiprocess() {} ;
        public String  toString() 
          { return
             Indent(lineCol()) +
               "[type    |-> \"multiprocess\", " + NewLine() +
               " name  |-> \"" + name + "\", " + NewLine() +
               Indent(" decls |-> ") + VectorToSeqString(decls) + ","
                                           + 
               EndIndent() + NewLine() +
               Indent(" defs  |-> ") + defs.toString() + ","
                                           + 
               EndIndent() + NewLine() +
              /*************************************************************
              * Uncomment the following to print the macros field.  It is  *
              * commented out so the printed result is what PlusCal.tla    *
              * considers a Multiprocess object to be.                     *
              *************************************************************/
              // Indent(" macros |-> ") + VectorToSeqString(macros) + ","
              //                             + 
              // EndIndent() + NewLine() +

               Indent(" prcds |-> ") + VectorToSeqString(prcds) + ","
                                           + 
               EndIndent() + NewLine() +
               Indent(" procs |-> ") + VectorToSeqString(procs) + "]" +
               EndIndent() +
             EndIndent() ;
          }
      }

    /**
     * The minusLabels and plusLabels fields were added by LL in 
     * January 2011 to implement the Version 1.5 enhancement that allows
     * fairness modifiers on labels.  These Vectors contain the labels
     * in the process that have the indicated modifier.  They are initially
     * set in the GetProcedure method of ParseAlgorithm, with the help of 
     * the GetLabel method.  They are then fixed to correct for label
     * conflicts by the FixProcedure method of PcalFixIDs.
     * 
     * The proceduresCalled field was added later in Jan 2011 by LL because,
     * since procedures can call other procedures, a transitive closure
     * is required to compute the procedures called by a process.  (Those
     * procedures need to be known to compute the fairness conditions, since
     * a fairness requirement on a process implies a fairness requirement on
     * all the procedures that the process calls.)
     * 
     * Note added 2 Apr 2013 by LL.  Also, it should be noted
     * that the transitive closure is computed by the call to PcalFixIDs.Fix,
     * not during the initial parsing phase. 
     * 
     * @author lamport
     *
     */
    public static class Procedure extends AST
      { public String name   = "" ;
        public Vector minusLabels = new Vector();
        public Vector plusLabels = new Vector();
        public Vector proceduresCalled = new Vector();
        public Vector params = null ; // of PVarDecl
        public Vector decls  = null ; // of PVarDecl 
        public Vector body   = null ; // of LabeledStmt
        public Procedure() {} ;
        public String toString() 
          { 
            // For versions earlier than 1.5 need to return those versions'
            // value since toString() is used to generate the AST module
            // used when TLC is doing the translation.
            if (PcalParams.inputVersionNumber < PcalParams.VersionToNumber("1.5")){
              return
                Indent(lineCol()) +
                  "[name   |-> \"" + name + "\", " + NewLine() +
                  Indent(" params |-> ") + VectorToSeqString(params) + "," + 
                  EndIndent() + NewLine() +
                  Indent(" decls  |-> ") + VectorToSeqString(decls) + "," + 
                  EndIndent() + NewLine() +
                  Indent(" body   |-> ") + VectorToSeqString(body) + "]" +
                  EndIndent() + 
                EndIndent() ;
            } 
            return
             Indent(lineCol()) +
               "[name   |-> \"" + name + "\", " + NewLine() +
               "minusLabels |-> "
               + VectorToSeqQuotedString(minusLabels) + ", plusLabels |->"
               + VectorToSeqQuotedString(plusLabels) + ", proceduresCalled |->"
               + VectorToSeqQuotedString(proceduresCalled) + ","
             + NewLine() +
               Indent(" params |-> ") + VectorToSeqString(params) + "," + 
               EndIndent() + NewLine() +
               Indent(" decls  |-> ") + VectorToSeqString(decls) + "," + 
               EndIndent() + NewLine() +
               Indent(" body   |-> ") + VectorToSeqString(body) + "]" +
               EndIndent() + 
             EndIndent() ;
          }
      }
    
    /***********************************************************************
    * Constants used to describe a process's fairness assumption.          *
    ***********************************************************************/
    public static final int UNFAIR_PROC = 0;
    public static final int WF_PROC = 1;
    public static final int SF_PROC = 2;
    public static final String[] FairnessString = {"unfair", "wf", "sf"} ;
    
    /**
     * The minusLabels and plusLabels fields were added by LL in 
     * January 2011 to implement the Version 1.5 enhancement that allows
     * fairness modifiers on labels.  They are set much like the corresponding
     * fields of an AST.Procedure object, as described above.
     * The proceduresCalled field was also added then.  
     * 
     * Note added by LL on 2 April 2013.  The genius LL never noticed that 
     * the proceduresCalled field only contains the procedures directly called,
     * and he used that in generating the fairness conditions without finding
     * the procedures that are called indirectly.
     * 
     * @author lamport
     *
     */
    public static class Process extends AST
      { public String    name  = "" ;
        public int fairness = UNFAIR_PROC ;
        public Vector  minusLabels = new Vector();
        public Vector  plusLabels = new Vector();
        public Vector  proceduresCalled = new Vector();
        public boolean   isEq  = true ; // true means "=", false means "\\in"
        public TLAExpr   id    = null ;
        public Vector    decls = null ; // of VarDecl
        public Vector    body  = null ; // of LabeledStmt
        public Process() { };
        public String toString() 
          { 
            // For versions earlier than 1.5 need to return those versions'
            // value since toString() is used to generate the AST module
            // used when TLC is doing the translation.
            if (PcalParams.inputVersionNumber < PcalParams.VersionToNumber("1.5")){
              return
               Indent(lineCol()) +
                 "[name   |-> \"" + name + "\", " + NewLine() +
                 " eqOrIn |-> " + boolToEqOrIn(isEq) + "," + NewLine() +
                 " id     |-> " + id.toString() + "," + NewLine() +
                 Indent(" decls  |-> ") + 
                    VectorToSeqString(decls) + "," + 
                 EndIndent() + NewLine() +
                 Indent(" body   |-> ") + 
                    VectorToSeqString(body) + "]" +
                 EndIndent() + 
              EndIndent() ;
            } 
            
            return
             Indent(lineCol()) +
               "[name   |-> \"" + name + "\"," 
               + NewLine() +
               " fairness |-> \"" 
                 + FairnessString[fairness] + "\", minusLabels |-> "
                 + VectorToSeqQuotedString(minusLabels) + ", plusLabels |->"
                 + VectorToSeqQuotedString(plusLabels) + ", proceduresCalled |->"
                 + VectorToSeqQuotedString(proceduresCalled) + ","
               + NewLine() +
               " eqOrIn |-> " + boolToEqOrIn(isEq) + "," + NewLine() +
               " id     |-> " + id.toString() + "," + NewLine() +
               Indent(" decls  |-> ") + 
                  VectorToSeqString(decls) + "," + 
               EndIndent() + NewLine() +
               Indent(" body   |-> ") + 
                  VectorToSeqString(body) + "]" +
               EndIndent() + 
             EndIndent() ;
          }
     }

    public static class VarDecl extends AST
      { public String    var  = null ;
        public boolean   isEq = true ; // true means "=", false means "\\in"
        public TLAExpr   val  = PcalParams.DefaultVarInit();
        public VarDecl() {};
        public String toString() 
          { return 
             Indent(lineCol()) + 
                    "[var |-> \"" + var + "\", " + 
                    "eqOrIn |-> " + boolToEqOrIn(isEq) + ", " +
                    "val |-> " + val.toString() + "]" + 
             EndIndent() ;
          }
      }

    public static class PVarDecl extends AST
      { public final boolean isEq = true    ;  // true means "="
        public String        var  = null ;
        public TLAExpr       val  = PcalParams.DefaultVarInit();
        public PVarDecl() {};
        
        /**
         * Converts the PVarDecl object to an equivalent VarDecl
         * object.  (I don't know why I bothered introducing a separate
         * PVarDecl object in the first place.)
         * @return
         */
        public VarDecl toVarDecl() {
            VarDecl result = new VarDecl() ;
            result.var = this.var ;
            result.val = this.val ;
            result.setOrigin(this.getOrigin());
            result.isEq = true ;
            return result ;
        }
        
        public String toString() 
          { return 
             Indent(lineCol()) + 
                    "[var |-> \"" + var + "\", " + 
                    "eqOrIn |-> \"=\", " +
                    "val |-> " + val.toString() + "]"  + 
             EndIndent() ;
          }
      }

    public static class LabeledStmt extends AST
      { public String    label = null ;
        public Vector    stmts = null ;  
          /*****************************************************************
          * An optional While prepended to a LabelSeq.                     *
          *****************************************************************/

        public LabeledStmt() { } ;
        public String toString() 
          {return 
             Indent(lineCol()) + 
                    "[label |-> \"" + label + "\"," + NewLine() +
                    Indent(" stmts |-> ") + 
                     VectorToSeqString(stmts) + "]" +  
                    EndIndent() +
             EndIndent() ;
          }
     }   


    public static class While extends AST
      { public TLAExpr   test    = null ;
        public Vector    unlabDo = null ; // a LabelSeq
        public Vector    labDo   = null ; // of LabeledStmt 
        public While() { };
        public String toString() 
          { return 
             Indent(lineCol()) + 
                "[type    |-> \"while\", " + NewLine() +
                " test    |-> " + test.toString()  +  "," + NewLine() +
                Indent(" labDo   |-> ") +
                    VectorToSeqString(labDo) + ","  + 
                EndIndent() + NewLine() +
                
                Indent(" unlabDo |-> ") +
                    VectorToSeqString(unlabDo) + "]" +
                EndIndent() + 
             EndIndent() ;
          }
      }


    public static class Assign extends AST
      { public Vector    ass  = null ; // of SingleAssign
        public Assign() { } ;
        public String toString()
          { return 
              Indent(lineCol()) +
                "[type |-> \"assignment\"," + NewLine() +
                Indent(" ass  |-> ") +
                     VectorToSeqString(ass) + "]" +
                EndIndent() +
              EndIndent() ;
          }
      }

    public static class SingleAssign extends AST
      { public Lhs       lhs  = new Lhs() ; 
        public TLAExpr   rhs  = null ; 
        public SingleAssign() { };
        public String toString()
          { return 
            Indent(lineCol()) + 
              "[lhs |-> " + lhs.toString() + "," + NewLine() +
              " rhs |-> " + rhs.toString() + "]"  +
            EndIndent() ;
          }
      }

    public static class Lhs extends AST
      /*********************************************************************
      * Note use of Lhs as name rather than LHS, which is the type         *
      * constant.                                                          *
      *********************************************************************/
      { public String    var  = "" ;
        public TLAExpr   sub  = null ; 
        public Lhs() { };
        public String toString()
          { return lineCol() + 
                   "[var |-> \"" + var + "\", sub |-> " 
                    + sub.toString() + "]"; }
      }

    /**
     * An AST.If object is created from an AST.LabelIf or AST.While object.
     * For a LabelIf containing no labeled statements, it is created inside
     * the CheckLabeledStmtSeq method when executing ParseAlgorithm.runMe(String[]).
     * Otherwise, it is created by exploding the original AST inside the
     * call of  PcalFixIDs.Fix.  Its origin is set to that of the original AST.
     * 
     * @author lamport
     *
     */
    public static class If extends AST
      { public TLAExpr   test = null ;
        public Vector    Then = null ; // of SimpleStmt
          /*****************************************************************
          * Could use "then", but use "Then" to avoid confusion since we   *
          * can't use "else".                                              *
          *****************************************************************/
        public Vector    Else = null ; // of SimpleStmt
          /*****************************************************************
          * Can't use "else" because that's a Java keyword.                *
          *****************************************************************/
        
        public static final int UNBROKEN     = 0 ;
        public static final int BROKEN_WHILE = 1;
        public static final int BROKEN_THEN  = 2;
        public static final int BROKEN_ELSE  = 4;
        /**
         * The source field records the information about where the If came
         * from that is useful for the TLA+ to PlusCal translation.  The values
         * are:
         * 
         *   UNBROKEN : Contains the entire contents of the original AST.
         *   BROKEN_WHILE : Came from a While containing a labeled statement.
         *   BROKEN_THEN : Came from an IfThen that contained a labeled statement
         *      in the Then clause, but not the Else clausew.
         *   BROKEN_ELSE : Came from an IfThen that contained a labeled statement
         *      in the Else clause but not the Then clause.
         *   BROKEN_THEN + BROKEN_ELSE : Came from an IfThen with labeled statements
         *      in both clauses.     
         */
        private int source = UNBROKEN ;
        public int getSource() {
            return source;
        }
        public void setSource(int source) {
            this.source = source;
        }

        public If() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
                "[type    |-> \"if\", " + NewLine() +  
                " test    |-> " + test.toString() + "," + NewLine() +
                Indent(" then |-> ") + VectorToSeqString(Then) + "," 
                                          + 
                EndIndent() + NewLine() +
                Indent(" else |-> ") + VectorToSeqString(Else) + "]" + 
                EndIndent() +
             EndIndent() ; 
           }
      }     

    public static class Either extends AST
      { public Vector ors = null ; // of Seq(SimpleStmt)
        public Either() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
                "[type |-> \"either\", " + NewLine() +  
                Indent(" ors  |-> ") + VectorOfVectorsToSeqString(ors) + "]" + 
                EndIndent() +
             EndIndent() ; 
          }
      }

    public static class With extends AST
      { public String    var  = "" ;
        public boolean   isEq = true ; // true means "=", false "\\in"
        public TLAExpr   exp  = null ;
        public Vector    Do   = null ; // of SimpleStmt
          /*****************************************************************
          * Can't use "do" because that's a Java keyword.                  *
          *****************************************************************/
        public With() { };
        public String toString()
          { return
             Indent(lineCol()) + 
               "[type   |-> \"with\", " + NewLine() + 
               " var    |-> \"" + var + "\"," + NewLine() + 
               " eqOrIn |-> " + boolToEqOrIn(isEq) + ","  + NewLine() + 
               " exp    |-> " + exp.toString() + "," + NewLine() +          
               Indent(" do     |-> ") + VectorToSeqString(Do) + "]" + 
               EndIndent() +
             EndIndent() ;
          }
      }

    public static class When extends AST
      { public TLAExpr   exp  = null ;
        public When() {};
        public String toString()
          { return 
             Indent(lineCol()) + 
              "[type |-> \"when\", " + NewLine() + 
              " exp |-> " + exp.toString() + "]" +
             EndIndent() ;
          }
      }

    public static class PrintS extends AST
      { public TLAExpr   exp  = null ;
        public PrintS() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
              "[type |-> \"print\", " + NewLine() + 
              " exp |-> " + exp.toString() + "]" +
             EndIndent() ;
          }
      }

    public static class Assert extends AST
      { public TLAExpr   exp  = null ;
        public Assert() {};
        public String toString()
          { return 
             Indent(lineCol()) + 
              "[type |-> \"assert\", " + NewLine() + 
              " exp |-> " + exp.toString() + "]" +
             EndIndent() ;
          }
      }

    public static class Skip extends AST
      { 
        public Skip() {};
        public String toString()
          { return lineCol() + "[type |-> \"skip\"]";
          }
      }


    /**
     * A LabelIf represents an if statement whose then and/or
     * else clause has a label.
     * 
     * @author lamport
     *
     */
    public static class LabelIf extends AST
      { public TLAExpr   test      = null ;
        public Vector    unlabThen = null ; // a LabelSeq
        public Vector    labThen   = null ; // of LabeledStmt 
        public Vector    unlabElse = null ; // a LabelSeq
        public Vector    labElse   = null ; // of LabeledStmt 
        public LabelIf() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type      |-> \"labelIf\"," + NewLine() +
               " test      |-> " + test.toString() + "," + NewLine() +
               Indent(" unlabThen |-> ") + VectorToSeqString(unlabThen) 
                                           + "," + 
               EndIndent() + NewLine() +
               Indent(" labThen   |-> ") + VectorToSeqString(labThen) 
                                            + "," + 
               EndIndent() + NewLine() +
               Indent(" unlabElse |-> ") + VectorToSeqString(unlabElse) 
                                             + "," + 
               EndIndent() + NewLine() +
               Indent(" labElse   |-> ") + VectorToSeqString(labElse) 
                                             + "]" + 
               EndIndent() + NewLine() +
             EndIndent() ;
          }
      }

    public static class LabelEither extends AST
      { public Vector    clauses = null ; // of Clause
        public LabelEither() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type    |-> \"labelEither\"," + NewLine() +
               Indent(" clauses |-> ") + VectorToSeqString(clauses) 
                                             + "]" + 
               EndIndent() + NewLine() +
             EndIndent() ;
          }
      }

    public static class Clause extends AST
      { public Vector    unlabOr = null ; // a LabelSeq
        public Vector    labOr   = null ; // LabeledStmt

        public Clause() {   
        }
        
        /**
         * The broken field is true iff the Clause object came from
         * a LabelEither object for which the corresponding clause
         * contained a labeled statement. 
         */
        private boolean broken = false ;
        public boolean isBroken() {
            return broken;
        }

        public void setBroken(boolean broken) {
            this.broken = broken;
        }

        public String toString()
          { return 
             Indent(lineCol()) +
               Indent("[unlabOr |-> ") + VectorToSeqString(unlabOr) 
                                           + "," + 
               EndIndent() + NewLine() +
               Indent(" labOr   |-> ") + VectorToSeqString(labOr) 
                                            + "]" + 
               EndIndent() + NewLine() +
             EndIndent() ;
          }
      }

    public static class Call extends AST
      { public String    returnTo = "" ;
        public String    to       = "" ;
        public Vector    args     = null ; // of TLAExpr
        public Call() {};
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type     |-> \"call\"," + NewLine() +
               " returnTo |-> \"" + returnTo + "\"," + NewLine() +
               " to       |-> \"" + to + "\"," + NewLine() +
               Indent(" args     |-> ") + VectorToSeqString(args) + "]" +
               EndIndent() +
             EndIndent() ;
          }
      }

    public static class Return extends AST
      { public String    from = "" ;
        public Return() {};
        public String toString()
          { return 
              lineCol() + 
               "[type |-> \"return\", from |-> \"" + from + "\"]" ;
          }
      }

    /**
     * A CallReturn object represents a call immediately followed
     * by a return.
     * 
     * @author lamport
     *
     */
    public static class CallReturn extends AST
      { public String    from = "" ;
        public String    to       = "" ;
        public Vector    args     = null ; // of TLAExpr
        public CallReturn() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type     |-> \"callReturn\"," + NewLine() +
               " from     |-> \"" + from + "\"," + NewLine() +
               " to       |-> \"" + to + "\"," + NewLine() +
               Indent("args     |-> ") + VectorToSeqString(args) 
                                             + "]" + NewLine() +
               EndIndent() +
             EndIndent() ;
          }
      }

    public static class CallGoto extends AST
      { public String    after = "" ;
        public String    to       = "" ;
        public Vector    args     = null ; // of TLAExpr
        public CallGoto() { };
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type     |-> \"callGoto\"," + NewLine() +
               " after    |-> \"" + after + "\"," + NewLine() +
               " to       |-> \"" + to + "\"," + NewLine() +
               Indent("args     |-> ") + VectorToSeqString(args) 
                                             + "]" + NewLine() +
               EndIndent() +
             EndIndent() ;
          }
      }

    public static class Goto extends AST
      { public String    to       = "" ;
        public Goto() {};
        public String toString()
          { return 
             lineCol() + 
               "[type |-> \"goto\", " + 
               " to |-> \"" + to + "\"]" ;
          }
      }

    public static class Macro extends AST
      { public String name   = "" ;
        public Vector params = null ; // of Strings
        public Vector body   = null ; // of Stmt
        public Macro() {};
        public String toString()
          { return 
             Indent(lineCol()) +
               "[name   |-> \"" + name + "\", " + NewLine() +
               Indent(" params |-> ") + VectorToSeqString(params) + "," + 
               EndIndent() + NewLine() +
               Indent(" body   |-> ") + VectorToSeqString(body) + "]" +
               EndIndent() + 
             EndIndent() ;
          }
      }

    public static class MacroCall extends AST
      { public String name   = "" ;
        public Vector args     = null ; // of TLAExpr
        public MacroCall() {};
        public String toString()
          { return 
             Indent(lineCol()) + 
               "[type |-> \"macrocall\"," + NewLine() +
               " name |-> \"" + name + "\"," + NewLine() +
               Indent(" args     |-> ") + VectorToSeqString(args) + "]" +
               EndIndent() +
             EndIndent() ;
          }
      }

/***************************** UTILITY METHODS ****************************/

   public String boolToEqOrIn(boolean iseq)
     { if (iseq)
         { return "\"=\"" ;}
       else
         { return "\"\\\\in\"" ;} 
     }

   public String lineCol() 
     /**********************************************************************
     * Equals "(*line, col*)" if pcal.trans called in debugging mode,      *
     * otherwise the empty string.                                         *
     **********************************************************************/
     { if (PcalParams.Debug)
         { return "(*" + line + ", " + col +"*)" ;
         }
       else 
         { return "" ;}
     }

   /************************************************************************
   * Methods for getting the toString() methods to indent the              *
   * representation nicely so it's readable.  They are used as follows.    *
   * Suppose we are printing a record with fields foo, foobar, elf, and    *
   * we want it to be output as:                                           *
   *                                                                       *
   *    [foo |-> XXXXXX                                                    *
   *             XXXXXX                                                    *
   *             XXXXX ,                                                   *
   *     elf    |-> "elf",                                                 *
   *     foobar |-> YYYY                                                   *
   *                YYY ]                                                  *
   *                                                                       *
   * where XX...XXX is produced by XXX.toString and YY...YYY by            *
   * YYY.toString().  We would produce the string as follows:              *
   *                                                                       *
   *    Indent("[foo |-> ") +                                              *
   *           XXX.toString() + "," +                                      *
   *    EndIndent() + NewLine() +                                          *
   *    "[elf    |-> \"elf\"," + NewLine()                                 *
   *    NewLine() +                                                        *
   *    Indent(" foobar |-> ") +                                           *
   *             XXX.toString() + "]" +                                    *
   *    EndIndent()                                                        *
   ************************************************************************/
   public static int indentDepth = 0 ;
   public static int[] curIndent = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
     /**********************************************************************
     * There must be an easier way.                                        *
     **********************************************************************/
     
   public static String Indent(String str)
     { curIndent[indentDepth + 1] = curIndent[indentDepth] + str.length() ;
       indentDepth = indentDepth + 1 ;
       return str ;
     }

   public static String EndIndent()
     { indentDepth = indentDepth - 1 ;
       return "" ;
     }


   public static String NewLine()
     { String result = "\n" ;
       int i = 0 ;
       while (i < curIndent[indentDepth])
         { result = result + " " ;
           i = i + 1 ;
         } ;
       return result ;
     }     

     
   public static String VectorToSeqString(Vector vec)
     /**********************************************************************
     * Returns the TLA+ representation of vec as a sequence of its         *
     * elements, where toString() is used to produce the elements'         *
     * representation.                                                     *
     **********************************************************************/
     { if (vec == null) {return "null" ;} ;
       String result = Indent("<<") ;
       int i = 0 ;
       while (i < vec.size())
         { if (i > 0)
             { result = result + ", " + NewLine() ; } ;
           result = result + vec.elementAt(i).toString() ;
           i = i + 1 ;
         } ;
       return result + ">>" + EndIndent();
     }
   
   public static String VectorToSeqQuotedString(Vector vec)
   /**********************************************************************
   * Returns the TLA+ representation of vec as a sequence of quoted      *
   * elements, where toString() is used to produce the elements'         *
   * representation to be quoted.                                        *
   **********************************************************************/
   { if (vec == null) {return "null" ;} ;
     String result = Indent("<<") ;
     int i = 0 ;
     while (i < vec.size())
       { if (i > 0)
           { result = result + ", " /* + NewLine() */ ; } ;
         result = result + "\"" + vec.elementAt(i).toString() + "\"" ;
         i = i + 1 ;
       } ;
     return result + ">>" + EndIndent();
   }

   public static String VectorOfVectorsToSeqString(Vector vecvec)
     /**********************************************************************
     * Returns the TLA+ representation of vec as a sequence of its         *
     * elements, where each of its elements is a vector of objects whose   *
     * representation is obtained by calling toString().                   *
     **********************************************************************/
     { String result = Indent("<< ") ;
       int i = 0 ;
       while (i < vecvec.size())
         { if (i > 0)
             { result = result + ", " + NewLine() ; } ;
           result = result + VectorToSeqString((Vector) vecvec.elementAt(i));
           i = i + 1 ;
         } ;
       return result + " >>" + EndIndent();
     }

 }


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/util/FlightRecorderProfiler.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

import org.openjdk.jmh.infra.BenchmarkParams;
import org.openjdk.jmh.profile.ExternalProfiler;
import org.openjdk.jmh.results.BenchmarkResult;
import org.openjdk.jmh.results.Result;

public class FlightRecorderProfiler implements ExternalProfiler {

	// Inspired by https://github.com/nicoulaj/jmh-utils
	
	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.Profiler#getDescription()
	 */
	@Override
	public String getDescription() {
		return FlightRecorderProfiler.class.getSimpleName();
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#addJVMInvokeOptions(org.openjdk.jmh.infra.BenchmarkParams)
	 */
	@Override
	public Collection<String> addJVMInvokeOptions(BenchmarkParams arg0) {
		return new ArrayList<String>();
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#allowPrintErr()
	 */
	@Override
	public boolean allowPrintErr() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#allowPrintOut()
	 */
	@Override
	public boolean allowPrintOut() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#beforeTrial(org.openjdk.jmh.infra.BenchmarkParams)
	 */
	@Override
	public void beforeTrial(BenchmarkParams arg0) {
		//noop
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#afterTrial(org.openjdk.jmh.results.BenchmarkResult, long, java.io.File, java.io.File)
	 */
	@Override
	public Collection<? extends Result> afterTrial(BenchmarkResult arg0, long arg1, File arg2, File arg3) {
        return new ArrayList<>();
	}

	/* (non-Javadoc)
	 * @see org.openjdk.jmh.profile.ExternalProfiler#addJVMOptions(org.openjdk.jmh.infra.BenchmarkParams)
	 */
	@Override
	public Collection<String> addJVMOptions(BenchmarkParams bp) {
		// Create the jfr file in the current directory named after the benchmark.
		return Arrays.asList("-XX:StartFlightRecording=settings=default,disk=true,dumponexit=true,filename=./" + bp.id() + ".jfr");
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/view/ErrorTraceTreeViewer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.view;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ILazyTreeContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationConstants;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationDefaults;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError.Order;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCFcnElementVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCFunctionVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCModelLaunchDataProvider;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCMultiVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCNamedVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCRecordVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCSequenceVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCSetVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCSimpleVariableValue;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariable;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.page.MainModelPage;
import org.lamport.tla.toolbox.tool.tlc.ui.preference.ITLCPreferenceConstants;
import org.lamport.tla.toolbox.tool.tlc.ui.util.RecordToSourceCoupler;
import org.lamport.tla.toolbox.tool.tlc.ui.util.RecordToSourceCoupler.LoaderTLCState;

import tla2sany.st.Location;

/**
 * {@link TLCErrorView} was becoming a bit of a behemoth, so we're spinning out this chunk into its own class and inner
 * 	classes.
 */
class ErrorTraceTreeViewer {
    private static final int[] COLUMN_WIDTH = { 200, 200 };
    private static final String[] COLUMN_TEXTS = { "Name", "Value" };

	private static final String LOADER_TOOL_TIP
			= "Double-click to load more states.\nIf the number of states is large, this might take a few seconds.";

    
	private final TreeViewer treeViewer;
	
    // listener on changes to the error trace font preference
    private final IPropertyChangeListener errorTraceFontChangeListener;
    
    private ModelEditor modelEditor;
	
	ErrorTraceTreeViewer(final Tree parent, final ModelEditor associatedModelEditor) {
		treeViewer = new TreeViewer(parent);
		treeViewer.setUseHashlookup(true);
		treeViewer.setContentProvider(new StateContentProvider());
		ColumnViewerToolTipSupport.enableFor(treeViewer);

		final TraceDisplayResizer resizer = new TraceDisplayResizer(parent);
		final StateLabelProvider labelProvider = new StateLabelProvider();
		for (int i = 0; i < COLUMN_TEXTS.length; i++) {
			final TreeViewerColumn column = new TreeViewerColumn(treeViewer, i);
			column.getColumn().setText(COLUMN_TEXTS[i]);
			column.getColumn().setWidth(COLUMN_WIDTH[i]);
			column.setLabelProvider(labelProvider);
			resizer.setColumnForIndex(column, i);
			column.getColumn().addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(final SelectionEvent e) {
					// reverse the current trace
					final TLCError error = (TLCError) treeViewer.getInput();
					error.reverseTrace();
					
					treeViewer.getTree().setSortDirection(error.getOrder() == Order.OneToN ? SWT.UP : SWT.DOWN);
					
					// Reset the viewer's selection to the empty selection. With empty
					// selection, the subsequent refresh call does *not* invalidate the
					// StateContentProvider's lazy policy.
					// We know that the user clicked on the tree's column header
					// and the real selection is of little importance.
					treeViewer.setSelection(new ISelection() {
						public boolean isEmpty() {
							return true;
						}
					});
					treeViewer.refresh(false);
					
					// remember the order for next trace shown
					final IDialogSettings dialogSettings = Activator.getDefault().getDialogSettings();
					dialogSettings.put(TLCModelLaunchDataProvider.STATESORTORDER,
							!dialogSettings.getBoolean(TLCModelLaunchDataProvider.STATESORTORDER));
				}
			});
		}
		// We consider the "Value" column of the tree to be the one that shows a state's
		// number. In order to reverse the direction in which the trace is shown, a user
		// can click the "Value" or the "Name" column (the latter for convenience).
		// The convention on Win, macOS, and Linux is to place an arrow on the column to
		// indicate the current direction. We place this indicator on the "Value" column,
		// not just because https://bugs.eclipse.org/133154 prevents us from placing an 
		// indicator on both columns, but because the tree is sorted on the value, ie.
		// the state number.
		treeViewer.getTree().setSortColumn(treeViewer.getTree().getColumn(1));
		
        parent.addControlListener(resizer);
		
		errorTraceFontChangeListener = (event) -> {
			if ((event == null) || event.getProperty().equals(ITLCPreferenceConstants.I_TLC_ERROR_TRACE_FONT)) {
				final Font f = JFaceResources.getFont(ITLCPreferenceConstants.I_TLC_ERROR_TRACE_FONT);
				
				JFaceResources.getFontRegistry().put(TLCErrorView.JFACE_ERROR_TRACE_ID, f.getFontData());

				if (treeViewer != null) {
					treeViewer.refresh(true);
				}
			}
		};
		errorTraceFontChangeListener.propertyChange(null);
        JFaceResources.getFontRegistry().addListener(errorTraceFontChangeListener);
        
        createContextMenu();
        
        setModelEditor(associatedModelEditor);
	}
	
	void dispose() {
		final FontRegistry fr = JFaceResources.getFontRegistry();
		
        fr.removeListener(errorTraceFontChangeListener);
	}
	
	void setModelEditor(final ModelEditor associatedModelEditor) {
		modelEditor = associatedModelEditor;
	}
	
	/**
	 * @return the {@link TreeViewer} instance wrapped by this class
	 */
	TreeViewer getTreeViewer() {
		return treeViewer;
	}
	
	TLCError getCurrentTrace() {
		return (TLCError)treeViewer.getInput();
	}
	
	private void createContextMenu() {
	    final MenuManager contextMenu = new MenuManager("#ViewerMenu"); //$NON-NLS-1$
	    contextMenu.setRemoveAllWhenShown(true);
	    contextMenu.addMenuListener(new IMenuListener() {
	        @Override
	        public void menuAboutToShow(final IMenuManager menuManager) {
				final Object selection = ((IStructuredSelection)treeViewer.getSelection()).getFirstElement();
				if (selection instanceof TLCState) {
		        	menuManager.add(new Action("Run model from this point") {
		    	        @Override
		    	        public void run() {
		    	        	if (modelEditor != null) {
		    	        		final Model m = modelEditor.getModel();
		    	        		
		    	        		if (m != null) {
									try {
										final int specType = m.getAttribute(
												IModelConfigurationConstants.MODEL_BEHAVIOR_SPEC_TYPE,
												IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_DEFAULT);

										if (specType == IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_NO_SPEC) {
											return;
										}
										
										final MainModelPage page = (MainModelPage)modelEditor.findPage(MainModelPage.ID);
										final String init = ((TLCState) selection).getConjunctiveDescription(false);
										if (specType == IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_SPEC_CLOSED) {
											page.setInitNextBehavior(init, "");
											modelEditor.setActivePage(MainModelPage.ID);
											
											Display.getDefault().asyncExec(() -> {
												MessageDialog.openInformation(null, "Model Reconfigured",
														"The model has been set up to begin checking from the selected "
																+ "state; please enter the next-state relation (usually Next), review the model parameters and run the checker.");
											});
										} else {
											page.setInitNextBehavior(init, null);
											modelEditor.setActivePage(MainModelPage.ID);
											
											Display.getDefault().asyncExec(() -> {
												MessageDialog.openInformation(null, "Model Reconfigured",
														"The model has been set up to begin checking from the selected "
															+ "state; please review the model parameters and run the checker.");
											});										
										}

		// We previously handled the config alteration and model check launch behind the
		//	scenes but have since stopped doing that. I'm leaving a portion of this here,
		//	commented out, in case we decide to return to that workflow.
//										final StringBuilder constraint = new StringBuilder();
//										if (specType == IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_SPEC_CLOSED) {
//											final String temporalSpecification = m.getAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_CLOSED_SPECIFICATION, "");
//										}
//										
//										constraint.append(((TLCState) selection).getConjunctiveDescription(false));
//
//										m.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_INIT, constraint.toString());
//										m.save(null);
//
//										modelEditor.launchModel(TLCModelLaunchDelegate.MODE_MODELCHECK, true);
		    	        			} catch (final CoreException e) {
		    	        				TLCActivator.logError("Problem encountered attempting to launch checker.", e);
		    	        			}
		    	        		}
		    	        	} else {
		    	        		TLCActivator.logInfo(
		    	        				"Were not able to launch ammended model because we have no model editor.");
		    	        	}
		    	        }
		    	    });
				}
	        	/*
	        	  In earlier versions of the Toolbox, we also provided:
	        	  		Collapse All (treeViewer.collapseAll())
	        	  		Expand to default level (treeViewer.collapseAll(); treeViewer.expandToLevel(2);)
	        	  		Expand All (treeViewer.expandAll())
	        	  But we now provide expand and collapse through the parent section's toolbar
	        	 */
	        }
	    });

	    final Control c = treeViewer.getControl();
	    final Menu menu = contextMenu.createContextMenu(c);
	    c.setMenu(menu);
	}

	
    private class StateContentProvider implements ILazyTreeContentProvider {
		private List<TLCState> states;
		private final int numberOfStatesToShow;

		StateContentProvider() {
			states = new ArrayList<>(0);
			
			numberOfStatesToShow = TLCUIActivator.getDefault().getPreferenceStore()
					.getInt(ITLCPreferenceConstants.I_TLC_TRACE_MAX_SHOW_ERRORS);
    	}

		@Override
		public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
			// Eagerly cache the list of states as it can be a sublist of the
			// complete trace. Getting the sublist in the updateElement method
			// means we obtain it over and over again for each top-level tree
			// item.
			if (newInput instanceof TLCError) {
				this.states = ((TLCError) newInput).getStates();
			} else if (newInput == null) {
				this.states = new ArrayList<TLCState>(0);
			} else {
				throw new IllegalArgumentException();
			}
		}

		@Override
		public void updateElement(final Object parent, final int viewerIndex) {
			if (parent instanceof TLCError) {
				final TLCError error = (TLCError) parent;
				if (error.isTraceRestricted() && (viewerIndex == 0)) {
					// If only a subset of the trace is shown, show a dummy item
					// at the top which can be double-clicked to load more.
					treeViewer.replace(parent, viewerIndex, new RecordToSourceCoupler.LoaderTLCState(treeViewer,
							Math.min(numberOfStatesToShow, error.getNumberOfRestrictedTraceStates()), error));
					return;
				}
				
				// decrease index into states by one if the viewers first element is a dummy item
				final int statesIndex = viewerIndex - (error.isTraceRestricted() ? 1 : 0);
				final TLCState child = states.get(statesIndex);
				// Diffing is supposed to be lazy and thus is done here when
				// the state is first used by the viewer. The reason why it
				// has to be lazy is to be able to efficiently handle traces
				// with hundreds or thousands of states where it would be a
				// waste to diff all state pairs even if the user is never
				// going to look at all states anyway.
				// TODO If ever comes up as a performance problem again, the
				// nested TLCVariableValues could also be diffed lazily.
           		if (statesIndex > 0) {
           			if (error.isOrder(Order.OneToN)) {
           				final TLCState predecessor = states.get(statesIndex - 1);
           				predecessor.diff(child);
           			} else {
						// With Order NtoOne, the previous state is logically the child's successor.
           				final TLCState successor = states.get(statesIndex - 1);
           				child.diff(successor);
           			}
           		}
				treeViewer.replace(parent, viewerIndex, child);
				// Always setHashChildren even if child has no children: This is
				// a virtual table here meaning that it reduces the number of
				// table items at the OS level by recycling them (the OS only
				// creates a many items that fit into the visible area). If an
				// item showing a regular state, is later recycled by a "back to
				// state" or "stuttering" indicator (neither has children),
				// the OS still incorrectly assumes the item has children. This
				// crashes hard on Linux and results in erratic behavior on
				// Windows and Mac.
				treeViewer.setHasChildren(child, child.getVariablesAsList().size() > 0);
				// Lazily expand the children
				if (child.isExpandable()){
					treeViewer.expandToLevel(child, 1);
				}
			} else if (parent instanceof TLCState) {
				final TLCState state = (TLCState) parent;
                if ((state.isStuttering() || state.isBackToState())) {
                	treeViewer.setChildCount(state, 0);
                } else {
                	final List<TLCVariable> variablesAsList = state.getVariablesAsList();
                	if (variablesAsList.size() > viewerIndex) {
                		final TLCVariable child = variablesAsList.get(viewerIndex);
                		treeViewer.replace(parent, viewerIndex, child);
                		treeViewer.setHasChildren(child, child.getChildCount() > 0);
                	}
                }
			} else if (parent instanceof TLCVariable
					&& ((TLCVariable) parent).getValue() instanceof TLCMultiVariableValue) {
				final TLCMultiVariableValue multiValue = (TLCMultiVariableValue) ((TLCVariable) parent).getValue();
				final TLCVariableValue child = multiValue.asList().get(viewerIndex);
				treeViewer.replace(parent, viewerIndex, child);
				treeViewer.setHasChildren(child, child.getChildCount() > 0);
			} else if (parent instanceof TLCVariable) {
				final TLCVariable variable = (TLCVariable) parent;
				final TLCVariableValue child = variable.getValue();
				treeViewer.replace(parent, viewerIndex, child);
				treeViewer.setChildCount(child, child.getChildCount());
			} else if (parent instanceof TLCMultiVariableValue) {
				final TLCMultiVariableValue multiValue = (TLCMultiVariableValue) parent;
				final TLCVariableValue child = multiValue.asList().get(viewerIndex);
				treeViewer.replace(parent, viewerIndex, child);
				treeViewer.setHasChildren(child, child.getChildCount() > 0);
			} else if (parent instanceof TLCVariableValue
					&& ((TLCVariableValue) parent).getValue() instanceof TLCMultiVariableValue) {
				final TLCMultiVariableValue multiValue = (TLCMultiVariableValue) ((TLCVariableValue) parent).getValue();
				final TLCVariableValue child = multiValue.asList().get(viewerIndex);
				treeViewer.replace(parent, viewerIndex, child);
				treeViewer.setHasChildren(child, child.getChildCount() > 0);
			} else {
				throw new IllegalArgumentException();
			}
		}

		@Override
		public void updateChildCount(Object element, int currentChildCount) {
			if (element instanceof TLCError) {
				final TLCError error = (TLCError) element;
				int traceSize = error.getTraceSize();
				if (traceSize != currentChildCount) {
					if (error.isTraceRestricted()) {
						treeViewer.setChildCount(element, traceSize + 1);
					} else {
						treeViewer.setChildCount(element, traceSize);
					}
				}
			} else if (element instanceof TLCState) {
				final TLCState state = (TLCState) element;
				if (((state.isStuttering() || state.isBackToState()) && currentChildCount != 0)) {
					treeViewer.setChildCount(element, 0);
				} else if (currentChildCount != state.getVariablesAsList().size()) {
					treeViewer.setChildCount(element, state.getVariablesAsList().size());
				}
			} else if (element instanceof TLCVariable) {
				final TLCVariable variable = (TLCVariable) element;
				if (currentChildCount != variable.getChildCount()) {
					treeViewer.setChildCount(element, variable.getChildCount());
				}
			} else if (element instanceof TLCVariableValue) {
				final TLCVariableValue value = (TLCVariableValue) element;
				if (currentChildCount != value.getChildCount()) {
					treeViewer.setChildCount(element, value.getChildCount());
				}
			} else {
				throw new IllegalArgumentException();
			}
		}

		@Override
		public Object getParent(Object element) {
			return null;
		}
    }
    
    /**
	 * Label provider for the tree table. Modified on 30 Aug 2009 by LL to implement
	 * ITableColorProvider instead of IColorProvider. This allows coloring of
	 * individual columns, not just of entire rows.
	 */
	static class StateLabelProvider extends CellLabelProvider {
        private static final int NAME_COLUMN_INDEX = 0;
        private static final int VALUE_COLUMN_INDEX = 1;

		private static final Map<String, Color> LOCATION_COLOR_MAP = new ConcurrentHashMap<String, Color>();
		//TODO Convert to Toolbox preference once this features proves useful.
		private static final boolean COLORING_SYSTEM_PROPERTY = Boolean.getBoolean(TLCErrorView.class.getName() + ".coloring");

    	
        private final Image stateImage;
        private final Image varImage;
        private final Image recordImage;
        private final Image setImage;
        private final Image loadMoreImage;
        
		public StateLabelProvider() {
            stateImage = TLCUIActivator.getImageDescriptor("/icons/full/default_co.gif").createImage();
            varImage = TLCUIActivator.getImageDescriptor("/icons/full/private_co.gif").createImage();
            recordImage = TLCUIActivator.getImageDescriptor("/icons/full/brkpi_obj.gif").createImage();
            // setImage = TLCUIActivator.getImageDescriptor("/icons/full/over_co.gif").createImage();
            setImage = TLCUIActivator.getImageDescriptor("/icons/full/compare_method.gif").createImage();
            loadMoreImage = TLCUIActivator.getImageDescriptor("/icons/full/add.gif").createImage();
            // other candidates are newstream_wiz.gif, nav_go.gif, debugt_obj.gif
        }

		@Override
		public void dispose() {
			stateImage.dispose();
			varImage.dispose();
			recordImage.dispose();
			setImage.dispose();
			loadMoreImage.dispose();
			
			super.dispose();
		}

		@Override
		public String getToolTipText(final Object element) {
			if (element instanceof LoaderTLCState) {
				return LOADER_TOOL_TIP;
			}
			
			return null;
		}

		@Override
		public void update(final ViewerCell cell) {
			// labels
			cell.setText(getColumnText(cell.getElement(), cell.getColumnIndex()));
			
			// images
			cell.setImage(getColumnImage(cell.getElement(), cell.getColumnIndex()));
			
			// font
			cell.setFont(getFont(cell.getElement(), cell.getColumnIndex()));

			
			final Color bg = getBackground(cell.getElement(), cell.getColumnIndex());
			cell.setBackground(bg);

			if (TLAEditorActivator.getDefault().isCurrentThemeDark()) {
				cell.setForeground((bg == null) ? null : Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
			} else {
				cell.setForeground(null);
			}
		}

		private Image getColumnImage(Object element, int columnIndex) {
			if (columnIndex == NAME_COLUMN_INDEX) {
				if (element instanceof LoaderTLCState) {
					return loadMoreImage;
				}
				if (element instanceof TLCState) {
					return stateImage;
				} else if (element instanceof TLCVariable) {
					return varImage;
				} else if (element instanceof TLCNamedVariableValue) {
					return recordImage;
				} else if (element instanceof TLCFcnElementVariableValue) {
					return recordImage;
				}
				return setImage; // other things appear in unordered collections
			}
			return null;
		}

		private String getColumnText(final Object element, final int columnIndex) {
			if (element instanceof TLCState) {
				final TLCState state = (TLCState) element;

				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						if (state.isStuttering()) {
							return "<Stuttering>";
						} else if (state.isBackToState()) {
							return "<Back to state " + state.getStateNumber() + ">";
						}
						return state.getLabel();
					case VALUE_COLUMN_INDEX:
						if (state instanceof RecordToSourceCoupler.LoaderTLCState) {
							return "";
						} else {
							return "State (num = " + state.getStateNumber() + ")";
						}
						// state.toString();
					default:
						break;
				}
			} else if (element instanceof TLCVariable) {
				final TLCVariable var = (TLCVariable) element;
				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						if (var.isTraceExplorerVar()) {
							return var.getSingleLineName();
						} else {
							return var.getName();
						}
					case VALUE_COLUMN_INDEX:
						return var.getValue().toSimpleString();
					// Changed from toString by LL on 30 Aug 2009
					default:
						break;
				}
			} else if ((element instanceof TLCSetVariableValue)
						|| (element instanceof TLCSequenceVariableValue)
						|| (element instanceof TLCSimpleVariableValue)) {
				final TLCVariableValue varValue = (TLCVariableValue) element;
				switch (columnIndex) {
					case VALUE_COLUMN_INDEX:
						return varValue.toString();
					case NAME_COLUMN_INDEX:
						return ""; // added by LL on 5 Nov 2009
					default:
						break;
				}
			} else if (element instanceof TLCNamedVariableValue) {
				final TLCNamedVariableValue namedValue = (TLCNamedVariableValue) element;
				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						return namedValue.getName();
					case VALUE_COLUMN_INDEX:
						return ((TLCVariableValue) namedValue.getValue()).toSimpleString();
					// Changed from toString by LL on 30 Aug 2009
					default:
						break;
				}
			} else if (element instanceof TLCFcnElementVariableValue) {
				final TLCFcnElementVariableValue fcnElementValue = (TLCFcnElementVariableValue) element;
				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						return fcnElementValue.getFrom().toSimpleString();
					// Changed from toString by LL on 30 Aug 2009
					case VALUE_COLUMN_INDEX:
						return ((TLCVariableValue) fcnElementValue.getValue()).toSimpleString();
					// Changed from toString by LL on 30 Aug 2009
					default:
						break;
				}
			} else if (element instanceof TLCRecordVariableValue) {
				final TLCRecordVariableValue recordValue = (TLCRecordVariableValue) element;
				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						return "";
					case VALUE_COLUMN_INDEX:
						return recordValue.toSimpleString();
					default:
						break;
				}
			} else if (element instanceof TLCFunctionVariableValue) {
				final TLCFunctionVariableValue fcnValue = (TLCFunctionVariableValue) element;
				switch (columnIndex) {
					case NAME_COLUMN_INDEX:
						return "";
					case VALUE_COLUMN_INDEX:
						return fcnValue.toSimpleString();
					default:
						break;
				}
			}

			return null;
		}

        /**
         * The following method sets the background color of a row or column of
         * the table. It highlights the entire row for an added or deleted item.
         * For a changed value, only the value is highlighted.
         */
		private Color getBackground(final Object element, final int column) {
            if (element instanceof TLCVariable) {
				final TLCVariable var = (TLCVariable) element;
				if (var.isChanged() && (column == VALUE_COLUMN_INDEX)) {
					return TLCUIActivator.getDefault().getChangedColor();
				}
			} else if (element instanceof TLCVariableValue) {
				final TLCVariableValue value = (TLCVariableValue) element;
				if (value.isChanged()) {
					if (column == VALUE_COLUMN_INDEX) {
						return TLCUIActivator.getDefault().getChangedColor();
					}
				} else if (value.isAdded()) {
					// Added takes precedence over deleted. E.g. a value can be
					// added to a set in this state and be removed in the next
					// state.
					return TLCUIActivator.getDefault().getAddedColor();
				} else if (value.isDeleted()) {
					return TLCUIActivator.getDefault().getDeletedColor();
				}
			} else if (COLORING_SYSTEM_PROPERTY && (element instanceof TLCState)) {
				// Assign a color to each location to make actions in the error
				// viewer more easily distinguishable.
				final TLCState state = (TLCState) element;
				final Location moduleLocation = state.getModuleLocation();
				if (moduleLocation == null) {
					return null;
				}
				Color c = LOCATION_COLOR_MAP.get(moduleLocation.toString());
				if (c == null) {
					final int color = SWT.COLOR_WHITE + (2 * LOCATION_COLOR_MAP.size());
					c = TLCUIActivator.getColor(color);
					LOCATION_COLOR_MAP.put(state.getModuleLocation().toString(), c);
				}
				return c;
			}
			return null;
		}

		private Font getFont(final Object element, final int columnIndex) {
			boolean returnBoldVersion = false;
			
			if (element instanceof TLCVariable) {
				if (((TLCVariable) element).isTraceExplorerVar()) {
					returnBoldVersion = true;
				}
			} else if (element instanceof RecordToSourceCoupler.LoaderTLCState) {
				returnBoldVersion = true;
			}

			final FontRegistry fr = JFaceResources.getFontRegistry();
			return returnBoldVersion ? fr.getBold(TLCErrorView.JFACE_ERROR_TRACE_ID)
									 : fr.get(TLCErrorView.JFACE_ERROR_TRACE_ID);
		}
    }
	
	
    /**
     * A control listener for the Provides method for resizing the columns of
     * the error trace viewer. This is to solve the problem of a bogus
     * "third column" being displayed when the window is made wider than the two
     * real columns.
     * 
     * There are two listener methods in this class: controlResized - called
     * when the tree is resized. handleEvent - called when column[0] is resized.
     * The controlResized command can change the size of column[0], which
     * triggers the calling of the handleEvent. Experimentation indicates that
     * this call of handleEvent occurs in the middle of executing the call of
     * controlResized. The boolean flag inControlResized is used to tell the
     * handleEvent method whether it was called this way or by the user resizing
     * the colulmn.
     * 
     * Note: I [N.B. no idea who "I" is] am assuming that the call of handleEvent that happens when
     * controlResized is resizing column[0] happens during the execution of
     * column[0].setWidth, and no funny races are possible.
     * 
     * Note that all the code here assumes that there are two columns. It needs
     * to be modified if the number of columns is changed.
     */
	private static class TraceDisplayResizer extends ControlAdapter implements Listener {
        private double firstColumnPercentageWidth = 0.5;

        // See comments above for meaning of the following flag.
        private boolean inControlResized = false;
        
        private final Tree tree;
        private final TreeColumn[] columns;
        private final Scrollable treeParentComponent;

        TraceDisplayResizer(final Tree resizingTree) {
        	tree = resizingTree;
        	treeParentComponent = (Scrollable)tree.getParent();
        	columns = new TreeColumn[COLUMN_TEXTS.length];
        }
        
        @Override
		public void controlResized(final ControlEvent e) {
            inControlResized = true;

            final int treeWidth = computeMaximumWidthOfAllColumns();
            final int firstColWidth = Math.round(Math.round(firstColumnPercentageWidth * treeWidth));
            final int secondColWidth = treeWidth - firstColWidth;
            columns[0].setWidth(firstColWidth);
            columns[1].setWidth(secondColWidth);
            
            inControlResized = false;
        }

        @Override
		public void handleEvent(final Event event) {
			if (inControlResized) {
				return;
			}

			final int treeWidth = computeMaximumWidthOfAllColumns();
			if (treeWidth == 0) {
				return;
			}

			// the percentage that the first column will occupy
			// until controlResized is called
			// We do not want the width of either column
			// to be less than 10% of the total width
			// of the tree. Currently, the user
			// can make a column smaller than 10%, but
			// when controlResized is called, the column
			// will be enlarged to 10%. It is not very nice
			// to do the enlarging in this method. It creates
			// very choppy performance.
			int firstColWidth = columns[0].getWidth();
			final double tentativefirstColPercentageWidth = (double) firstColWidth / (double) treeWidth;
			if ((tentativefirstColPercentageWidth > 0.1) && (tentativefirstColPercentageWidth < 0.9)) {
				firstColumnPercentageWidth = (double) firstColWidth / (double) treeWidth;
			} else if (tentativefirstColPercentageWidth <= .1) {
				firstColumnPercentageWidth = 0.1;
			} else {
				firstColumnPercentageWidth = 0.9;
			}
			firstColWidth = Math.round(Math.round(tentativefirstColPercentageWidth * treeWidth));
			columns[1].setWidth(treeWidth - firstColWidth);
		}
        
        void setColumnForIndex(final TreeViewerColumn column, final int index) {
        	columns[index] = column.getColumn();
        	
        	if (index == 0) {
                // I [N.B. no idea who "I" is] need to add a listener for size changes to column[0] to
                // detect when the user has tried to resize the individual columns. The following might work,
        		// if I can figure out the real event type to use.
                columns[0].addListener(SWT.Resize, this);
        	}
        }

        /*
         * Computes the maximum width that columns of the tree can occupy
         * without having a horizontal scrollbar.
         * 
         * This is not equal to the sash form's client area. From the client
         * area we must subtract the tree's border width. We must also subtract
         * the width of the grid lines used in the tree times the number of
         * columns because there is one grid line per column. We must subtract
         * the width of the vertical scroll bar if it is visible.
         */
		private int computeMaximumWidthOfAllColumns() {
			final ScrollBar vBar = tree.getVerticalBar();
			final boolean scrollBarShown = vBar.isVisible();
			
			return treeParentComponent.getClientArea().width
							- tree.getBorderWidth()
							- (tree.getColumnCount() * tree.getGridLineWidth())
							- ((scrollBarShown) ? vBar.getSize().x : 0);
		}
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/provider/FormulaContentProvider.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.provider;

import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;

import tlc2.model.Formula;

/**
 * @author <NAME>
 */
public class FormulaContentProvider implements IStructuredContentProvider
{
    private static final Object[] EMPTY = new Object[0];

    public FormulaContentProvider()
    {
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IContentProvider#dispose()
     */
    public void dispose()
    {
        // formulaList = null;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
     */
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
    {
        Assert.isNotNull(viewer);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
     */
    public Object[] getElements(Object inputElement)
    {
        if (inputElement != null && inputElement instanceof Vector)
        {
            @SuppressWarnings("unchecked")
			Vector<Formula> formulaList = (Vector<Formula>) inputElement;
            return formulaList.toArray(new Formula[formulaList.size()]);
        }
        return EMPTY;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/IntStack.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

public interface IntStack {

	/**
	 * Return the number of items on the stack.
	 */
	long size();

	/**
	 * Push an integer onto the stack.
	 */
	void pushInt(final int x);

	/**
	 * Push a long integer onto the stack.
	 */
	void pushLong(final long x);

	/**
	 * Pop the integer from the top of the stack.
	 */
	int popInt();

	/**
	 * Pop the long integer from the top of the stack.
	 */
	long popLong();
	
	/**
	 * Removes all elements from the stack
	 */
	void reset();

	// Some implementors support peak operations.
	default long peakLong() {
		throw new UnsupportedOperationException("Not implemented");
	}
	
	default int peakInt() {
		throw new UnsupportedOperationException("Not implemented");
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/gettingstarted/gettingstarted.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/gettingstarted/main.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

	<title>Getting Started</title>
</head>
<!-- a comment -->

<body>
<h1>Getting Started</h1>

 <P> 
The first thing you see when you start the Toolbox for the first
time is the 

<!-- <a href="../../../../org.lamport.tla.toolbox/welcome/welcomeView.html">
 Welcome View</a>.&nbsp;  -->
 Welcome View.&nbsp; 
 If you are new to the Toolbox, you should
read the <A href="help.html"><em>Using Help</em></A> and <A
href="views.html"><em>Managing Views</em></A> help pages.&nbsp;
If  you're new to TLA+, try opening an example specification in the Toolbox by
clicking on one of the the buttons at the bottom of the Welcome Page.
 </P>

 <P> 
From the welcome view, you will usually open a specification.&nbsp;  See the <A
href="../spec/spec.html"><em>Managing Your Specifications</em></A> page.&nbsp;  You can also set
the Toolbox <A href="preferences.html"><em>Preferences</em></A>. 
</P>

<p>

</p>
<p>For further information about TLA<sup>+</sup> and the TLA<sup>+</sup> tools, see
the <A href="resources.html"><em>TLA+ Resources</em></A> help page.&nbsp;

<!--
When using the Toolbox, TLA<sup>+</sup> means TLA<sup>+2</sup>, the revised version
of the language; see the 
<a href="http://research.microsoft.com/en-us/um/people/lamport/tla/tla2.html"
    target="_blank">TLA+2 web page</a>.
-->             
</p>

<p> 
<b>Your specs should not contain tab characters.</b>  See the <i>General</i> section of the <A href="preferences.html"><i>Preferences</i></A> help page.
</p>

<p> <b> Important:</b>  The <i><a href="../trouble/trouble.html">In
Case of Trouble</a></i> help page tells you what to do if you encounter a
Toolbox bug. 
In the unlikely event that a bug prevents you from reading the help pages,
these  pages are available on the Web
at <code><a 
href="http://tla.msr-inria.inria.fr/tlatoolbox/doc/contents.html"
  target="_blank">http://tla.msr-inria.inria.fr/tlatoolbox/doc/contents.html</a></code>.&nbsp; 
Bookmark this URL in your browser for emergency use.

</p> 

<dl> <hr>

<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href="help.html">Using Help</A></dd>
<dd> <A href="views.html">Managing Views</A></dd>
<dd> <A href="preferences.html">Preferences</A></dd>
<dd> <A href="resources.html">TLA+ Resources</A></dd>

</dl>
<a href = "../contents.html">&uarr; TLA+ Toolbox User's Guide</a>
</hr>

</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/prover/decompose.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/prover/prover.html -->
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

    <title>The Decompose Proof Command</title>
</head>
<!-- a comment -->

<body>


<h1>The Decompose Proof Command</h1>

The Decompose Proof command is executed by placing the cursor in a proof obligation, either a proof step or
a theorem, and either typing <code>Ctl+G&nbsp;Ctl+D</code> or right-clicking and selecting
the command.&nbsp;  Clicking on the button labeled &nbsp;<font size=+1><b>?</b></font>&nbsp; in the upper right corner of the command's
pop-up window displays this page.

<p>
The command provides two basic ways to decompose a proof obligation
into simpler obligations:
<DL> <DT> <b><code>/\</code> decomposition</b> </DT>
<DD>If formula &nbsp;<code>P</code>&nbsp; equals 
   &nbsp;<code>P1 /\ ... /\ Pn</code>&nbsp;,
then the proof of &nbsp;<code>P</code>&nbsp; can be broken into the
proof of the &nbsp;<code>n</code>&nbsp; formulas 
  &nbsp;<code>P1, ... , Pn</code>&nbsp;.
</DD>

<BR> </BR>
 <DT><b><code>\/</code> decomposition &nbsp; (case split) </b>
 </DT>
<DD> 
If formula &nbsp;<code>P</code>&nbsp; equals 
   &nbsp;<code>P1&nbsp;\/ ... \/&nbsp;Pn</code>&nbsp;,
then the proof of &nbsp;<code>ASSUME&nbsp;P&nbsp;PROVE&nbsp;Q</code>&nbsp;
can be broken into the
proof of the &nbsp;<code>n</code>&nbsp; obligations
  &nbsp;<code>ASSUME&nbsp;P1&nbsp;PROVE&nbsp;Q,&nbsp;...,&nbsp;ASSUME&nbsp;Pn&nbsp;PROVE&nbsp;Q</code>&nbsp;
   (or the equivalent <code>CASE</code> steps).
</DD>
</DL>
</p>

<p>

Often, a proof obligation must be transformed into a different one in order to be decomposed into simpler
obligations, where the decomposition may be done manually or by the Decompose Proof command.&nbsp;  The command
provides the following two such transformations that can be
applied to the goal of an obligation.  The goal is the <code>PROVE</code> formula of an <code>ASSUME</code>/<code>PROVE</code>
obligation or the entire obligation, if it is a single formula.  For a <code>CASE</code> or <code>QED</code> step, it is the 
proof's current goal.

<DL> <DT> <b><code>=></code> splitting</b> </DT>
<DD>A goal &nbsp;<code>P => Q</code>&nbsp; is transformed to the assumption &nbsp;<code>P</code>&nbsp;
and the goal &nbsp;<code>Q</code>&nbsp;.
</DD>

<BR> </BR>
 <DT><b><code>\A</code> splitting</b>
 </DT>
<DD>A goal &nbsp;<code>\A x \in S : P</code>&nbsp; is transformed to the assumption &nbsp;<code>NEW&nbsp;x&nbsp;\in&nbsp;S</code>&nbsp;
and the goal &nbsp;<code>P</code>&nbsp;.&nbsp;  The goal &nbsp;<code>\A x&nbsp;:&nbsp;P</code>&nbsp; is similarly split.

</DD>
</DL>

There are two such transformations that can be applied to an assumption of an <code>ASSUME</code>/<code>PROVE</code> obligation:


<BR> </BR>
<DL> <DT><b><code>\E</code> splitting</b>
 </DT>
<DD>An assumption &nbsp;<code>\E x \in S : P</code>&nbsp; is transformed to the two assumptions 
 &nbsp;<code>NEW&nbsp;x&nbsp;\in&nbsp;S,&nbsp;P</code>&nbsp;.

</DD>

<BR> </BR>

<DT> <b><code>/\</code> splitting</b> </DT>
<DD>An assumption &nbsp;<code>P1 /\ ... /\ Pn</code>&nbsp;, is transformed to the &nbsp;<code>n</code>&nbsp; assumptions
&nbsp;<code>P1,&nbsp;...,&nbsp;Pn</code>&nbsp;.&nbsp;  This transformation can be performed by the Decompose Proof command only
if at least one of the conjuncts <code>Pi</code> can be further decomposed by the command.   
</DD>

</DL>


These transformations (decompositions and splittings) are effected by clicking on the appropriately labeled buttons.&nbsp;  
You can perform multiple transformations  before generating the proof.&nbsp; The <code>\/</code> 
decomposition and <code>\E</code>
splitting transformations can be combined hierarchically.&nbsp;  Clicking on the &nbsp;<font size=+1>&larr;</font>&nbsp; button undoes 
the last transformation that has not been undone.
</P>

<p>
The proof is generated by clicking a button that is either labeled by <font size=+1><b>P</b></font> or (for an <code>/\</code>
decomposition) by a button with <font size=+1><b>P</b></font> next to it.&nbsp;
</p>

<p>
Instead of generating an <code>/\</code> or <code>\/</code> decomposition, the button labeled <font size=+1><b>P</b></font>
at the top of the command's dialog window generates a proof consisting of only a 
  &nbsp;<code>SUFFICES&nbsp;ASSUME&nbsp;...&nbsp;PROVE</code>&nbsp;
step, constructed by splitting the original obligation, and a &nbsp;<code>QED</code>&nbsp; step.

For example, starting from the obligation &nbsp;<code>P&nbsp;=>&nbsp;\A&nbsp;x&nbsp;\in&nbsp;S&nbsp;:&nbsp;Q</code>&nbsp;, performing
a &nbsp;<code>=></code>&nbsp; split followed by a &nbsp;<code>\A</code> split on the goal and then clicking on this
button produces a proof like this:
<pre>
   <3> SUFFICES ASSUME P, NEW x \in S
                PROVE  Q
     OBVIOUS
   <3> QED
</pre>
</p>

<p>  The obligation to which you apply the Decompose Proof command must have either no proof or else a 
leaf proof, such as a &nbsp;<code>BY</code>&nbsp; proof or the proof &nbsp;<code>OBVIOUS</code>&nbsp;.&nbsp;  If it has a leaf proof, that proof
is made the proof of each of the simpler obligations into which the proof is decomposed.&nbsp;  For a proof generated by
the top  <font size=+1><b>P</b></font> button (which does no decomposing), the obligation's leaf proof becomes the 
<code>QED</code> step's proof.
</p>

<p>
You can use the command to transform the goal and/or usable assumptions that come  from the 
statement's <code>ASSUME</code> formulas and/or
from previous statements.&nbsp;  The formula to be transformed must either have  the appropriate form
or else consist of a single occurrence of a user-defined operator whose definition has that form.&nbsp;  

The command displays
only  assumptions that can be transformed and new assumptions that have been created so far 
by the current use of the command--the latter being
displayed below a dashed line.
</p>

<h2>Options</h2>

There are three options that you can select.

<DL> <DT> <b>Show Context</b> </DT>
<DD>A context assumption is a usable assumption that comes from the theorem or from a previous step.&nbsp;  Context
assumptions are displayed (and can thus be transformed) if and only if this option is chosen.
</DD>

<BR></BR>
<DT> <b>Use <code>SUFFICES</code></b> </DT>
<DD>Splitting the goal or a <code>\E</code> assumption generates new assumptions.&nbsp;
Selecting this option causes those assumptions to be asserted by a 
  &nbsp;<code>SUFFICES&nbsp;ASSUME/PROVE</code>&nbsp;
step.&nbsp;  Otherwise, these assumptions are added to each step of the decomposed proof to which they apply.&nbsp;
</DD>

<BR> </BR>
 <DT><b>Use <code>CASE</code></b>
 </DT>
<DD>This selection determines whether, in the created substeps of the proof of an <code>\/</code>
decomposition, <code>CASE</code> steps should be used instead of <code>ASSUME/PROVE</code>
steps when possible.&nbsp;  
</DD>

<!-- COMMENT
<BR> </BR>
 <DT><b>Use subexpression names</b>
 </DT>
<DD>The command looks at the expansions of definitions when looking for splittings and decompositions.&nbsp;
For example, you can do an <code>/\</code> decomposition if the goal is    &nbsp;<code>P</code>&nbsp;, where
&nbsp;<code>P</code>&nbsp; is defined to equal a conjunction of formulas.&nbsp;  Normally, this decomposition
will produce steps that prove each of the conjuncts as they appear in the definition of &nbsp;<code>P</code>&nbsp;.
However, if you select this option, the generated steps will contain the goals &nbsp;<code>P!1,&nbsp;P!2,&nbsp;...</code>&nbsp;.
</DD>
END COMMENT -->
</DL>

<h2>Limitations</h2>

The following are the known problems and limitations of the command.
<ul>

<li> The command will not expand definitions that are imported into the current module by parametrized instantiation--that
is, via a statement such as.
<pre>      Foo(x) == INSTANCE M WITH ... 
</pre>
</li>


<li> Decomposing a proof step may require renaming of bound identifiers
to avoid name clashes.&nbsp; This renaming is not done for clashes with identifiers
introduced by a <code>LET</code> definition within the step or by an expression in an argument
of a user-defined operator whose definition is being expanded.&nbsp; 
This failure to avoid name clashes will cause parsing
errors in the decomposed proof that must be fixed by hand.

</li>
</ul>
<hr>
<a href = "reading.html">&uarr; Viewing and Editing Structured Proofs</a>
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/Github358.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.tool.CommonTestCase;
import util.ToolIO;

public class Github358 extends PCalTest {
	
	@Test
	public void test() {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS,
				trans.runMe(new String[] {"-nocfg", CommonTestCase.BASE_PATH + "Github358.tla"}));
		
		final String[] messages = ToolIO.getAllMessages();
		assertTrue(messages.length == 1);
		
		final String msg = messages[0];
		assertEquals("Unrecoverable error:\n" + 
				" -- Expected \":=\" but found \"skip\"\n" + 
				"    line 5, column 7.", msg.trim());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LiveException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:44 PST by lamport
//      modified on Tue Jun 13 17:16:21 PDT 2000 by yuanyu

package tlc2.tool.liveness;

public class LiveException extends RuntimeException {

	public final int errorCode;

	public LiveException(int errorCode) {
		super();
		this.errorCode = errorCode;
	}

	public LiveException(int errorCode, String msg) {
		super(msg);
		this.errorCode = errorCode;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TagBasedTLCOutputTokenScanner.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.Vector;

import org.eclipse.jface.text.rules.IPredicateRule;
import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
import org.eclipse.jface.text.rules.Token;

/**
 * Partitioning of the TLC output
 * @author <NAME>
 * @version $Id$
 */
public class TagBasedTLCOutputTokenScanner extends RuleBasedPartitionScanner
{
    public final static String HEAD_DELIM = "@!@!@";
    private final static String TAIL_DELIM = "";
    private final static String RULE_START = HEAD_DELIM + "STARTMSG";
    private final static String RULE_END = HEAD_DELIM + "ENDMSG";

    public static final String TAG_OPEN = "__tlc_tag_open";
    public static final String TAG_CLOSED = "__tlc_tag_closed";
    public static final String DEFAULT_CONTENT_TYPE = "__tlc_output";

    public static final String[] CONTENT_TYPES = new String[] { TAG_OPEN, TAG_CLOSED, DEFAULT_CONTENT_TYPE };

    public TagBasedTLCOutputTokenScanner()
    {
        Vector<IPredicateRule> rules = new Vector<IPredicateRule>();

        rules.add(new TLCSingleLineRule(RULE_START, TAIL_DELIM + "\n", new Token(TAG_OPEN)));
        rules.add(new TLCSingleLineRule(RULE_END, TAIL_DELIM + "\n", new Token(TAG_CLOSED)));
        rules.add(new TLCMultiLineRule(new Token(DEFAULT_CONTENT_TYPE)));
        
        // add the rules
        setPredicateRules((IPredicateRule[]) rules.toArray(new IPredicateRule[rules.size()]));
    }
 }


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/perspective/SpecLoadedPerspective.java<|end_filename|>
package org.lamport.tla.toolbox.ui.perspective;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

/**
 * Spec loaded perspective containing the editor and spec actions
 * @version $Id$
 * @author <NAME>
 */
public class SpecLoadedPerspective implements IPerspectiveFactory
{

    public final static String ID = "org.lamport.tla.toolbox.ui.perspective.specLoaded";

    public void createInitialLayout(IPageLayout layout)
    {
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Token.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Token                                                              *
*                                                                          *
* A Token object represents a single token of the specification, where a   *
* token is either a single token of a TLA spec, a line of comment, or a    *
* line of the prolog or epilog.                                            *
*                                                                          *
* A Token object has the following fields:                                 *
*                                                                          *
*   String string : The actual input.                                      *
*   int column    : The column in the input line of its first              *
*                   character (counting from 0).                           *
*   int type      : The type of the token.  Possibilities are:             *
*                      BUILTIN, NUMBER, STRING, IDENT, COMMENT,            *
*                      DASHES, END_MODULE, PROLOG, EPILOG,                 *
*                      PF_STEP                                             *
*   Position aboveAlign                                                    *
*   Position belowAlign                                                    *
*   float preSpace                                                         *
*   boolean isAlignmentPoint                                               *
*   float distFromMargin     : See the FindAlignments class.               *
*                                                                          *
* The constructors are Token() and Token(string, column, type).            *
*                                                                          *
* The methods are                                                          *
*                                                                          *
*   getWidth() : returns width of token in input.                          *
*   toString() : for debugging                                             *
*                                                                          *
* Every token of type COMMENT should belong to the subclass CommentToken.  *
***************************************************************************/
package tla2tex;
import java.util.Vector;

public class Token
  /*************************************************************************
  * This class defines the Token object, which is an element of a          *
  * tokenized specification.  It is expected that some token types may be  *
  * subclassed.  In particular, there will be a CommentToken class that    *
  * is a subclass of Token.  Every token of type COMMENT should belong to  *
  * this class.                                                            *
  *************************************************************************/
  { public String string ;
      /*********************************************************************
      * The string of the token.  This is usually what the user has        *
      * typed, but it may also be something else.                          *
      *********************************************************************/

    public int column ;
      /*********************************************************************
      * The column in which the first character of the token appears in    *
      * the input.                                                         *
      *********************************************************************/
      
    public int type ;
       /********************************************************************
       * The type of the token.  Here are the possibilities:               *
       ********************************************************************/

       public static final int BUILTIN = 1 ;
         /******************************************************************
         * A built-in token.                                               *
         ******************************************************************/

       public static final int NUMBER = 2 ;
         /******************************************************************
         * A number like "2" or "\O777".                                   *
         ******************************************************************/

       public static final int STRING = 3 ;
         /******************************************************************
         * A string like "foo".  In this type, the string field does not   *
         * contain the enclosing quotes.                                   *
         ******************************************************************/

       public static final int IDENT = 4 ;
         /******************************************************************
         * An identifier, such as foo_Bar.                                 *
         ******************************************************************/

       public static final int COMMENT = 5 ;
         /******************************************************************
         * A comment.  This will be subclassed to include an additional    *
         * field containing the tokenization of the comment.               *
         ******************************************************************/
         
       public static final int DASHES = 6 ;
         /******************************************************************
         * At least four "-"s.  May be either a separator or part of       *
         * "----- MODULE foo ------"                                       *
         ******************************************************************/

       public static final int END_MODULE = 7 ;
         /******************************************************************
         * A "========" string that ends a module.                         *
         ******************************************************************/

       public static final int PROLOG = 8 ;
         /******************************************************************
         * This is a string (usually a complete line) that appeared        *
         * before the beginning of the module.                             *
         ******************************************************************/

       public static final int EPILOG = 9 ;
         /******************************************************************
         * This is a line that appeared after the end of the module.       *
         ******************************************************************/

       public static final int PF_STEP = 12;
         /******************************************************************
         * This is a proof-step number, such as "<42>" or "<37>2a.".       *
         * It shouldn't make any difference, but the definitions of        *
         * PF_STEP in Token and CToken are made the same just in case.     *
         ******************************************************************/

       public static final int PCAL_LABEL = 13;
         /******************************************************************
         * This is a  label.  The string contains the label, the following *
         * ":" and perhaps a following "+" or "-".                         *
         ******************************************************************/

    /***********************************************************************
    * The following fields are specific to TLATeX. They are set to         *
    * non-default values only after the object has been created.           *
    ***********************************************************************/
    public Position aboveAlign  = new Position() ;
      /*********************************************************************
      * The position of the token in the tokenized spec with which         *
      * this token is to be left-aligned.  The specified item is always    *
      * in a line above the current token.  For a MULT or NULL comment     *
      * subtype, it points to the token that begins the multi-line         *
      * comment If aboveAlign.line = -1, then the token is to be           *
      * left-aligned with respect to the left margin.                      *
      *********************************************************************/
    public float preSpace =  0 ;
      /*********************************************************************
      * The amount of space to be added just before this token in the      *
      * final output.                                                      *
      *********************************************************************/
      
    public boolean subscript = false ;
      /*********************************************************************
      * Set true by FindAlignments.FindAlignments if this is token is part *
      * of a subscript or superscript.                                     *
      *********************************************************************/
      
    public Position belowAlign = new Position() ;
      /*********************************************************************
      * If belowAlign.line != -1, then belowAlign is the position of a     *
      * token on a lower line with which this token is to be aligned.      *
      * See the FindAlignments class for an explanation of the meaning of  *
      * this field.                                                        *
      *********************************************************************/

    /***********************************************************************
    * The aboveAlign and belowAlign fields of a spec maintain the          *
    * following invariant, which asserts that, for all tokens in a path    *
    * traced by belowAlign pointers, the aboveAlign field points to the    *
    * first token in the path.                                             *
    *                                                                      *
    *   \A pos : LET t == pos.toToken(spec)                                *
    *            IN  (t.belowAlign.line # -1) =>                           *
    *                  (t.belowAlign.toToken(spec).aboveAlign =            *
    *                     IF t.aboveAlign.line # -1 THEN t.aboveAlign      *
    *                                               ELSE pos               *
    ***********************************************************************/
    
    public boolean isAlignmentPoint = false ;
      /*********************************************************************
      * True iff some token is being aligned on this token, so we need to  *
      * find the distance from the left margin of this token.  The value   *
      * is true iff this token is the target of an aboveAlign or           *
      * belowAlign "pointer", or it is a multi-line comment that is not    *
      * the first token on its line.                                       *
      *********************************************************************/

    public float distFromMargin  =  0 ;
      /*********************************************************************
      * If isAlignmentPoint = true, then this is the distance in points    *
      * from the left-margin of the left-hand character in the token, as   *
      * reported by the alignment file's log output file.  The distance    *
      * from the margin in the final output of a token will be its         *
      * distFromMargin plus the sum of the preSpace for it and all         *
      * non-left-comment tokens to its left.                               *
      *********************************************************************/
      
    /***********************************************************************
    * Below are the methods for this object class, including the           *
    * constructor.                                                         *
    ***********************************************************************/
    public Token(String str, int col, int typ)
      /*********************************************************************
      * A Token constructor                                                *
      *********************************************************************/
      { string = str ;
        column = col ;
        type   = typ ;
      }

    public Token()
      /*********************************************************************
      * A default Token constructor, apparently needed for subclasses.     *
      *********************************************************************/
      { string = "" ;
        column = 0 ;
        type   = 0 ;
      } ;

    public int getWidth() 
      /*********************************************************************
      * Returns a width, which is the number of columns the token spans    *
      * in the original input stream.                                      *
      *********************************************************************/
      { if (string == null) 
          {return 0;}
        else if (type == STRING)
          {/****************************************************************
           * Have to compensate for the removal of the quotes.            **
           ****************************************************************/
            return string.length() + 2;}
        else
          {return string.length();}
      };      

    /***********************************************************************
    * The method FindPfStepTokens replaces each sequence of three to five  *
    * tokens created by TokenizeSpec for something like "<42>" or          *
    * "<42>1a." into a single token of type PF_STEP.                       *
    ***********************************************************************/
    static void FindPfStepTokens(Token[][] toks) {
      for (int k = 0 ; k < toks.length ; k++) 
        { Token[] input = toks[k] ;
          Vector outputVec = new Vector(input.length) ;
          int i = 0 ;
          while (i < input.length)
           { if (   (i < input.length - 2)
                 && (input[i].string.equals("<"))
                 && (input[i+1].column == input[i].column + 1)
                 && (input[i+1].type == NUMBER)
                 && (input[i+2].string.equals(">"))
                 && (input[i+2].column == 
                         input[i+1].column + input[i+1].getWidth()) )
               { int numOfToks = 3 ;
                 boolean needsSpace = true ;
                 String str = "<" + input[i+1].string + ">" ;
                 if (   (i < input.length - 3)
                     && (input[i+3].column == input[i+2].column + 1)
                     && (   (input[i+3].type == NUMBER)
                         || (input[i+3].type == IDENT)))
                   { str = str + input[i+3].string ;
                     numOfToks = 4;
                     if (   (i < input.length - 4)
                         && (input[i+4].column == 
                               input[i+3].column + input[i+3].getWidth())
                         && (input[i+4].string.equals(".")))
                       { str = str + "." ;
                         numOfToks = 5;
                       } ;
                   };

                 if (   (i < input.length - numOfToks)
                     && (input[i + numOfToks].type == BUILTIN)
                     && (   (BuiltInSymbols.GetBuiltInSymbol(
                                 input[i + numOfToks].string, true).symbolType
                              == Symbol.INFIX)
                         ||  (BuiltInSymbols.GetBuiltInSymbol(
                                 input[i + numOfToks].string, true).symbolType
                              == Symbol.PUNCTUATION)))
                   { needsSpace = false ; } ;
                 outputVec.addElement(new Token.PfStepToken
                                        (str,
                                         input[i].column,
                                         needsSpace) );
                 i = i + numOfToks;
               } // if
             else { outputVec.addElement(input[i]) ;
                    i = i+1 ;
                  } // else
           } ; // while
          if (outputVec.size() != input.length)
            { toks[k] = new Token[outputVec.size()] ;
              for (i = 0; i < outputVec.size(); i++) 
                 { toks[k][i] = (Token) outputVec.elementAt(i) ;
                 } ;
            }
        } // for k
      } 
    
    /***********************************************************************
    * The following defines a toString() method for printing a Token for   *
    * debugging.  To do a decent job, it splits it into reasonably-sized   *
    * lines, using the BreakLine method.                                   *
    ***********************************************************************/

    public String mostOfString()
      /*********************************************************************
      * This returns everything in toString() except the final "]", so it  *
      * can be used by the toString() method of subclasses.                *
      *********************************************************************/
      { String typeName = "";
        switch (type) 
          { case BUILTIN    : typeName = "BUILTIN"    ; break ;
            case NUMBER     : typeName = "NUMBER"     ; break ;
            case STRING     : typeName = "STRING"     ; break ;
            case PF_STEP    : typeName = "PF_STEP"    ; break ;
            case IDENT      : typeName = "IDENT"      ; break ;
            case COMMENT    : typeName = "COMMENT"    ; break ;
            case DASHES     : typeName = "DASHES"     ; break ;
            case END_MODULE : typeName = "END_MODULE" ; break ;
            case PROLOG     : typeName = "PROLOG"     ; break ;
            case EPILOG     : typeName = "EPILOG"     ; break ;
            case PCAL_LABEL : typeName = "PCAL_LABEL" ; break ;
          } ;
        String str = "\"" + string + "\"" ;
        if (string == null) {str = "null";};

        String result =    "[str |-> "    + str
                         + ",\t type |-> "  + typeName
                         + ",\t col |-> "   + column
                         + ",\t width |-> " + getWidth() ;
        if (aboveAlign.line != -1)
             {result = result + ",\t above |-> " + aboveAlign.toString();} ;
        if (belowAlign.line  != -1)
             {result = result + ",\t below |-> " + belowAlign.toString();} ;
        if (preSpace != 0)
             {result = result + ", space |-> " + preSpace; } ;
        if (isAlignmentPoint)
             {result = result + ", align |-> true"; } ;
        if (distFromMargin != 0)
             {result = result + ", dist |-> " + distFromMargin; } ;
        if (subscript) 
             {result = result + ", sub |-> true";};
        return result; 
      };
      

    public String toString()
      /*********************************************************************
      * For debugging.                                                     *
      *********************************************************************/
      {  return Misc.BreakLine(mostOfString() + "]") ; };  


    /***********************************************************************
    * We define a subclass to add a needsSpace field to PF_STEP tokens.    *
    ***********************************************************************/
    public static class PfStepToken extends Token { 
      public boolean needsSpace ;
        /*******************************************************************
        * This will be false iff the token is immediately followed by an   *
        * infix operator.                                                  *
        *******************************************************************/
        
      /*********************************************************************
      * The constructor.                                                   *
      *********************************************************************/
      public PfStepToken(String str, int col, boolean space) {
        super(str, col, PF_STEP) ;
        needsSpace = space ;
       }
     }

  }

/* last modified on Wed 19 Sep 2007 at  6:25:02 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/NextStateResult.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package tlc2.tool.distributed;

import java.io.Serializable;

import tlc2.tool.TLCStateVec;
import tlc2.util.LongVec;

@SuppressWarnings("serial")
public class NextStateResult implements Serializable {

	private final long computationTime;
	private final long statesComputed;
	private final TLCStateVec[] nextStates;
	private final LongVec[] nextFingerprints;
	
	public NextStateResult(TLCStateVec[] nextStates, LongVec[] nextFingerprints, 
			long computationTime, long statesComputed) {
		this.nextStates = nextStates;
		this.nextFingerprints = nextFingerprints;
		this.computationTime = computationTime;
		this.statesComputed = statesComputed;
	}
	
	public long getStatesComputedDelta() {
		return statesComputed - nextStates.length;
	}

	public long getComputationTime() {
		return computationTime;
	}

	public LongVec[] getNextFingerprints() {
		return nextFingerprints;
	}

	public TLCStateVec[] getNextStates() {
		return nextStates;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/TLCStateVec.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:40 PST by lamport
//      modified on Sun Dec  3 17:47:37 PST 2000 by yuanyu

package tlc2.tool;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TLCStateVec implements Cloneable, Serializable {
  private TLCState[] elementData;
  private int elementCount;
         
  public TLCStateVec() { this(10); }

  public TLCStateVec(int initialCapacity) {
    this.elementCount = 0;
    this.elementData = new TLCState[initialCapacity];
  }

  public final void addElement(TLCState x) {
    if (this.elementCount == this.elementData.length) {
      ensureCapacity(this.elementCount+1);
    }
    this.elementData[this.elementCount++] = x;
  }

  public final TLCState elementAt(int index) {
    return this.elementData[index];
  }

  public final int size() { return this.elementCount; }

  public final void ensureCapacity(int minCapacity) { 
    if (elementData.length < minCapacity) {
      int newCapacity = elementData.length + elementData.length;
      if (newCapacity < minCapacity) {
	newCapacity = minCapacity;
      }
      TLCState oldBuffer[] = this.elementData;
      this.elementData = new TLCState[newCapacity];

      System.arraycopy(oldBuffer, 0, elementData, 0, elementCount);
    }
  }

  private void readObject(ObjectInputStream ois)
  throws IOException, ClassNotFoundException {
    this.elementCount = ois.readInt();
    this.elementData = new TLCState[this.elementCount];
    for (int i = 0; i < this.elementCount; i++) {
      this.elementData[i] = (TLCState)ois.readObject();
    }
  }

  private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.writeInt(this.elementCount);
    for (int i = 0; i < this.elementCount; i++) {
      oos.writeObject(this.elementData[i]);
    }
  }

}




<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TLAAnnotationHover.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationHover;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.ui.texteditor.MarkerAnnotation;

/**
 * @author <NAME>
 * @version $Id$
 */
public class TLAAnnotationHover implements IAnnotationHover {
    /**
     * {@inheritDoc}
     */
	public String getHoverInfo(final ISourceViewer sourceViewer, final int lineNumber) {
		final String[] messages = getMessagesForLine(sourceViewer, lineNumber);

		if (messages.length == 0) {
			return null;
		}

		final StringBuilder sb = new StringBuilder();
		final String lineSeparator = System.getProperty("line.separator");
		for (int i = 0; i < messages.length; i++) {
			sb.append(messages[i]);
			if (i < (messages.length - 1)) {
				sb.append(lineSeparator);
			}
		}
		
		return sb.toString();
	}

	private String[] getMessagesForLine(final ISourceViewer viewer, final int line) {
		final IAnnotationModel model = viewer.getAnnotationModel();

		if (model == null) {
			return new String[0];
		}

		final Iterator<Annotation> it = model.getAnnotationIterator();
		final IDocument document = viewer.getDocument();
		final ArrayList<String> messages = new ArrayList<>();
		final HashMap<Position, Set<String>> placeMessagesMap = new HashMap<>();
		while (it.hasNext()) {
			final Annotation annotation = it.next();
			if (annotation instanceof MarkerAnnotation) {
				final MarkerAnnotation ma = (MarkerAnnotation) annotation;
				final Position p = model.getPosition(ma);
				if (compareRulerLine(p, document, line)) {
					final IMarker marker = ma.getMarker();
					final String message = marker.getAttribute(IMarker.MESSAGE, null);
					if ((message != null) && (message.trim().length() > 0)) {
						Set<String> priorMessages = placeMessagesMap.get(p);
						if (priorMessages == null) {
							priorMessages = new HashSet<>();
							placeMessagesMap.put(p, priorMessages);
						}
						
						if (!priorMessages.contains(message)) {
							messages.add(message);
							priorMessages.add(message);
						}
					}
				}
			}
		}
		return (String[]) messages.toArray(new String[messages.size()]);
	}

	private boolean compareRulerLine(final Position position, final IDocument document, final int line) {
		try {
			if ((position.getOffset() > -1) && (position.getLength() > -1)) {
				return (document.getLineOfOffset(position.getOffset()) == line);
			}
		} catch (final BadLocationException e) { }
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/model/Utils.java<|end_filename|>
package tlc2.model;

import java.util.ArrayList;
import java.util.List;

import tla2sany.st.Location;

/**
 * Some helper functions for dealing with various TLC model class types.
 */
public class Utils {

	public static MCState buildState(
			final int ordinal,
			final String name,
			final String location,
			final String ...assignments)
	{
		MCVariable[] variables = new MCVariable[assignments.length];
		for (int i = 0; i < assignments.length; i++)
		{
			String assignment = assignments[i];
			String[] split = assignment.split("=");
			variables[i] = new MCVariable(split[0].trim(), split[1].trim());
		}
		
		return new MCState(
				variables,
				name,
				Utils.toLabelFormat(name, location),
				Location.parseLocation(location),
				false,
				false,
				ordinal);
	}
	
	public static String toLabelFormat(String name, String location)
	{
		String label = String.format("%s %s", name, location).trim();
		return String.format("<%s>", label);
	}
	
	public static List<String> toTlcOutputFormat(final MCState state)
	{
		List<String> inputLines = new ArrayList<String>();
		inputLines.add(String.format("%d: %s", state.getStateNumber(), state.getLabel()));
		for (MCVariable variable : state.getVariables())
		{
			inputLines.add(String.format("/\\ %s = %s", variable.getName(), variable.getValueAsString()));
		}

		return inputLines;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/SyntaxTreePrinter.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.modanalyzer;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.st.Location;
import tla2sany.st.ParseTree;
import tla2sany.st.TreeNode;

public class SyntaxTreePrinter {

  /** 
   *  This method is used in only one place--in the ParseUnit class--to write a copy
   *  of the syntax tree to a file in case that option is invoked.
   */
  static public final void print( ParseTree pt, java.io.PrintWriter output ) {
    output.println("%% Output of parse tree for module " + pt.moduleName() );
    String[] dependencies = pt.dependencies();
    if (dependencies.length == 0) {
      output.println("%% no dependencies");
    } else {
      output.print("%% dependends on:");
      for (int lvi = 0; lvi < dependencies.length; lvi++) {
        output.print(" " + dependencies[lvi]);
      }
      output.println(".");
    }
    printSubTree(output, "", pt.rootNode() );
  }

  /*
  static public final void print( TreeNode tn, java.io.PrintWriter output ) {
    output.println("%% Output of syntax tree" ); 
    printSubTree(output, "", tn);
  }
  */
   
  private static void printSubTree(java.io.PrintWriter o, String offset, TreeNode node ) {
    StringBuffer outS = new StringBuffer( offset );
    Location l = node.getLocation();
    String image = node.getImage();
    if (image != null ) {
      outS.append(image);
    } else {
      outS.append("-- no name --");
    }
    outS.append(" [" ).append(l.beginLine()).append(" ").append(l.beginColumn()).append("] ");  
    TreeNode[] h = node.heirs();
// ADDED BY LL
// if (h == null) {
  outS.append(" (kind: " + ((SyntaxTreeNode) node).getKind() + ") ");
// } ;
// END ADDED BY LL
    if (h != null) {
      if (h.length == 0 ) {
        int length = node.getPreComments().length;
        outS.append(length); outS.append(" pre-comments ");
// Commented out on 21 Aug 2007 by LL
//        length = node.getPostComments().length;
//        outS.append(length); outS.append(" post-comments ");
      }
      outS.append(" {");
      o.println(outS);
      for (int i=0; i<h.length; i++) {
        printSubTree(o, offset + ".", h[i] );
      }
      o.print(offset); o.println( "}");
    } else {
      outS.append(" ***WARNING***  null array reference ");
      o.println(outS);
    }
  }

}



<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/org/eclipse/ui/dialogs/FilteredItemsSelectionDialog.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation 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:
 *  IBM Corporation - initial API and implementation
 *  <NAME> <<EMAIL>>
 *     - Fix for bug 196553 - [Dialogs] Support IColorProvider/IFontProvider in FilteredItemsSelectionDialog
 *  <NAME> <<EMAIL>>
 *     - Fix for bug 208602 - [Dialogs] Open Type dialog needs accessible labels
 *  <NAME> <<EMAIL>> - bug 258493
 *  <NAME> <<EMAIL>> - Bug 440810
 *  <NAME> <<EMAIL>> 
 *     - bug 482482 - Allow subclasses of FilteredItemsSelectionDialog to nest list and extended area inside SashForm
 *******************************************************************************/
package org.lamport.org.eclipse.ui.dialogs;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.ProgressMonitorWrapper;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.LegacyActionTools;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.ContentViewer;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ILazyContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.SearchPattern;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.statushandlers.StatusManager;

/**
 * Shows a list of items to the user with a text entry field for a string
 * pattern used to filter the list of items.
 *
 * @since 3.3
 */
public abstract class FilteredItemsSelectionDialog extends
		SelectionStatusDialog {

	private static final String DIALOG_BOUNDS_SETTINGS = "DialogBoundsSettings"; //$NON-NLS-1$

	private static final String SHOW_STATUS_LINE = "ShowStatusLine"; //$NON-NLS-1$

	private static final String HISTORY_SETTINGS = "History"; //$NON-NLS-1$

	private static final String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$

	private static final String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$

	/**
	 * Represents an empty selection in the pattern input field (used only for
	 * initial pattern).
	 */
	public static final int NONE = 0;

	/**
	 * Pattern input field selection where caret is at the beginning (used only
	 * for initial pattern).
	 */
	public static final int CARET_BEGINNING = 1;

	/**
	 * Represents a full selection in the pattern input field (used only for
	 * initial pattern).
	 */
	public static final int FULL_SELECTION = 2;

	private Text pattern;

	private TableViewer list;

	private DetailsContentViewer details;

	/**
	 * It is a duplicate of a field in the CLabel class in DetailsContentViewer.
	 * It is maintained, because the <code>setDetailsLabelProvider()</code>
	 * could be called before content area is created.
	 */
	private ILabelProvider detailsLabelProvider;

	private ItemsListLabelProvider itemsListLabelProvider;

	private MenuManager menuManager;

	private MenuManager contextMenuManager;

	private boolean multi;

	private ToolBar toolBar;

	private ToolItem toolItem;

	private Label progressLabel;

	private ToggleStatusLineAction toggleStatusLineAction;

	private RemoveHistoryItemAction removeHistoryItemAction;

	private ActionContributionItem removeHistoryActionContributionItem;

	private IStatus status;

	private RefreshCacheJob refreshCacheJob;

	private RefreshProgressMessageJob refreshProgressMessageJob = new RefreshProgressMessageJob();

	private Object[] currentSelection;

	private ContentProvider contentProvider;

	private FilterHistoryJob filterHistoryJob;

	private FilterJob filterJob;

	private ItemsFilter filter;

	private List lastCompletedResult;

	private ItemsFilter lastCompletedFilter;

	private String initialPatternText;

	private int selectionMode;

	private ItemsListSeparator itemsListSeparator;

	private static final String EMPTY_STRING = ""; //$NON-NLS-1$

	private boolean refreshWithLastSelection = false;

	private IHandlerActivation showViewHandler;

	/**
	 * Creates a new instance of the class.
	 *
	 * @param shell
	 *            shell to parent the dialog on
	 * @param multi
	 *            indicates whether dialog allows to select more than one
	 *            position in its list of items
	 */
	public FilteredItemsSelectionDialog(Shell shell, boolean multi) {
		super(shell);
		this.multi = multi;
		filterHistoryJob = new FilterHistoryJob();
		filterJob = new FilterJob();
		contentProvider = new ContentProvider();
		refreshCacheJob = new RefreshCacheJob();
		itemsListSeparator = new ItemsListSeparator(
				WorkbenchMessages.FilteredItemsSelectionDialog_separatorLabel);
		selectionMode = NONE;
	}

	/**
	 * Creates a new instance of the class. Created dialog won't allow to select
	 * more than one item.
	 *
	 * @param shell
	 *            shell to parent the dialog on
	 */
	public FilteredItemsSelectionDialog(Shell shell) {
		this(shell, false);
	}

	/**
	 * Adds viewer filter to the dialog items list.
	 *
	 * @param filter
	 *            the new filter
	 */
	protected void addListFilter(ViewerFilter filter) {
		contentProvider.addFilter(filter);
	}

	/**
	 * Sets a new label provider for items in the list. If the label provider
	 * also implements {@link
	 * org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider
	 * .IStyledLabelProvider}, the style text labels provided by it will be used
	 * provided that the corresponding preference is set.
	 *
	 * @see IWorkbenchPreferenceConstants#USE_COLORED_LABELS
	 *
	 * @param listLabelProvider
	 * 		the label provider for items in the list
	 */
	public void setListLabelProvider(ILabelProvider listLabelProvider) {
		getItemsListLabelProvider().setProvider(listLabelProvider);
	}

	/**
	 * Returns the label decorator for selected items in the list.
	 *
	 * @return the label decorator for selected items in the list
	 */
	private ILabelDecorator getListSelectionLabelDecorator() {
		return getItemsListLabelProvider().getSelectionDecorator();
	}

	/**
	 * Sets the label decorator for selected items in the list.
	 *
	 * @param listSelectionLabelDecorator
	 *            the label decorator for selected items in the list
	 */
	public void setListSelectionLabelDecorator(
			ILabelDecorator listSelectionLabelDecorator) {
		getItemsListLabelProvider().setSelectionDecorator(
				listSelectionLabelDecorator);
	}

	/**
	 * Returns the item list label provider.
	 *
	 * @return the item list label provider
	 */
	private ItemsListLabelProvider getItemsListLabelProvider() {
		if (itemsListLabelProvider == null) {
			itemsListLabelProvider = new ItemsListLabelProvider(
					new LabelProvider(), null);
		}
		return itemsListLabelProvider;
	}

	/**
	 * Sets label provider for the details field.
	 *
	 * For a single selection, the element sent to
	 * {@link ILabelProvider#getImage(Object)} and
	 * {@link ILabelProvider#getText(Object)} is the selected object, for
	 * multiple selection a {@link String} with amount of selected items is the
	 * element.
	 *
	 * @see #getSelectedItems() getSelectedItems() can be used to retrieve
	 *      selected items and get the items count.
	 *
	 * @param detailsLabelProvider
	 *            the label provider for the details field
	 */
	public void setDetailsLabelProvider(ILabelProvider detailsLabelProvider) {
		this.detailsLabelProvider = detailsLabelProvider;
		if (details != null) {
			details.setLabelProvider(detailsLabelProvider);
		}
	}

	private ILabelProvider getDetailsLabelProvider() {
		if (detailsLabelProvider == null) {
			detailsLabelProvider = new LabelProvider();
		}
		return detailsLabelProvider;
	}

	
	public void create() {
		super.create();
		pattern.setFocus();
	}

	/**
	 * Restores dialog using persisted settings. The default implementation
	 * restores the status of the details line and the selection history.
	 *
	 * @param settings
	 *            settings used to restore dialog
	 */
	protected void restoreDialog(IDialogSettings settings) {
		boolean toggleStatusLine = true;

		if (settings.get(SHOW_STATUS_LINE) != null) {
			toggleStatusLine = settings.getBoolean(SHOW_STATUS_LINE);
		}

		toggleStatusLineAction.setChecked(toggleStatusLine);

		details.setVisible(toggleStatusLine);

		String setting = settings.get(HISTORY_SETTINGS);
		if (setting != null) {
			try {
				IMemento memento = XMLMemento.createReadRoot(new StringReader(
						setting));
				this.contentProvider.loadHistory(memento);
			} catch (WorkbenchException e) {
				// Simply don't restore the settings
				StatusManager
						.getManager()
						.handle(
								new Status(
										IStatus.ERROR,
										PlatformUI.PLUGIN_ID,
										IStatus.ERROR,
										WorkbenchMessages.FilteredItemsSelectionDialog_restoreError,
										e));
			}
		}
	}

	
	public boolean close() {
		this.filterJob.cancel();
		this.refreshCacheJob.cancel();
		this.refreshProgressMessageJob.cancel();
		if (showViewHandler != null) {
			IHandlerService service = PlatformUI
					.getWorkbench().getService(IHandlerService.class);
			service.deactivateHandler(showViewHandler);
			showViewHandler.getHandler().dispose();
			showViewHandler = null;
		}
		if (menuManager != null)
			menuManager.dispose();
		if (contextMenuManager != null)
			contextMenuManager.dispose();
		storeDialog(getDialogSettings());
		return super.close();
	}

	/**
	 * Stores dialog settings.
	 *
	 * @param settings
	 *            settings used to store dialog
	 */
	protected void storeDialog(IDialogSettings settings) {
		settings.put(SHOW_STATUS_LINE, toggleStatusLineAction.isChecked());

		XMLMemento memento = XMLMemento.createWriteRoot(HISTORY_SETTINGS);
		this.contentProvider.saveHistory(memento);
		StringWriter writer = new StringWriter();
		try {
			memento.save(writer);
			settings.put(HISTORY_SETTINGS, writer.getBuffer().toString());
		} catch (IOException e) {
			// Simply don't store the settings
			StatusManager
					.getManager()
					.handle(
							new Status(
									IStatus.ERROR,
									PlatformUI.PLUGIN_ID,
									IStatus.ERROR,
									WorkbenchMessages.FilteredItemsSelectionDialog_storeError,
									e));
		}
	}

	/**
	 * Create a new header which is labelled by headerLabel.
	 *
	 * @param parent
	 * @return Label the label of the header
	 */
	private Label createHeader(Composite parent) {
		Composite header = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		header.setLayout(layout);

		Label headerLabel = new Label(header, SWT.NONE);
		headerLabel.setText((getMessage() != null && getMessage().trim()
				.length() > 0) ? getMessage()
				: WorkbenchMessages.FilteredItemsSelectionDialog_patternLabel);
		headerLabel.addTraverseListener(new TraverseListener() {
			
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
					e.detail = SWT.TRAVERSE_NONE;
					pattern.setFocus();
				}
			}
		});

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		headerLabel.setLayoutData(gd);

		createViewMenu(header);
		header.setLayoutData(gd);
		return headerLabel;
	}

	/**
	 * Create the labels for the list and the progress. Return the list label.
	 *
	 * @param parent
	 * @return Label
	 */
	private Label createLabels(Composite parent) {
		Composite labels = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		labels.setLayout(layout);

		Label listLabel = new Label(labels, SWT.NONE);
		listLabel
				.setText(WorkbenchMessages.FilteredItemsSelectionDialog_listLabel);

		listLabel.addTraverseListener(new TraverseListener() {
			
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_MNEMONIC && e.doit) {
					e.detail = SWT.TRAVERSE_NONE;
					list.getTable().setFocus();
				}
			}
		});

		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		listLabel.setLayoutData(gd);

		progressLabel = new Label(labels, SWT.RIGHT);
		progressLabel.setLayoutData(gd);

		labels.setLayoutData(gd);
		return listLabel;
	}

	private void createViewMenu(Composite parent) {
		toolBar = new ToolBar(parent, SWT.FLAT);
		toolItem = new ToolItem(toolBar, SWT.PUSH, 0);

		GridData data = new GridData();
		data.horizontalAlignment = GridData.END;
		toolBar.setLayoutData(data);

		toolBar.addMouseListener(new MouseAdapter() {
			
			public void mouseDown(MouseEvent e) {
				showViewMenu();
			}
		});

		// Just the image is easily missed. Thus, add an additional label.
		toolItem.setText("Options");
		toolItem.setImage(WorkbenchImages
				.getImage(IWorkbenchGraphicConstants.IMG_LCL_VIEW_MENU));
		toolItem
				.setToolTipText(WorkbenchMessages.FilteredItemsSelectionDialog_menu);
		toolItem.addSelectionListener(new SelectionAdapter() {
			
			public void widgetSelected(SelectionEvent e) {
				showViewMenu();
			}
		});

		menuManager = new MenuManager();

		fillViewMenu(menuManager);

		IHandlerService service = PlatformUI.getWorkbench()
				.getService(IHandlerService.class);
		IHandler handler = new AbstractHandler() {
			
			public Object execute(ExecutionEvent event) {
				showViewMenu();
				return null;
			}
		};
		showViewHandler = service.activateHandler(
				IWorkbenchCommandConstants.WINDOW_SHOW_VIEW_MENU, handler,
				new ActiveShellExpression(getShell()));
	}

	/**
	 * Fills the menu of the dialog.
	 *
	 * @param menuManager
	 *            the menu manager
	 */
	protected void fillViewMenu(IMenuManager menuManager) {
		toggleStatusLineAction = new ToggleStatusLineAction();
		menuManager.add(toggleStatusLineAction);
	}

	private void showViewMenu() {
		Menu menu = menuManager.createContextMenu(getShell());
		Rectangle bounds = toolItem.getBounds();
		Point topLeft = new Point(bounds.x, bounds.y + bounds.height);
		topLeft = toolBar.toDisplay(topLeft);
		menu.setLocation(topLeft.x, topLeft.y);
		menu.setVisible(true);
	}

    /**
     * Hook that allows to add actions to the context menu.
	 * <p>
	 * Subclasses may extend in order to add other actions.</p>
     *
     * @param menuManager the context menu manager
     * @since 3.5
     */
	protected void fillContextMenu(IMenuManager menuManager) {
		List selectedElements= ((StructuredSelection)list.getSelection()).toList();

		Object item= null;

		for (Iterator it= selectedElements.iterator(); it.hasNext();) {
			item= it.next();
			if (item instanceof ItemsListSeparator || !isHistoryElement(item)) {
				return;
			}
		}

		if (selectedElements.size() > 0) {
			removeHistoryItemAction.setText(WorkbenchMessages.FilteredItemsSelectionDialog_removeItemsFromHistoryAction);

			menuManager.add(removeHistoryActionContributionItem);

		}
	}

	private void createPopupMenu() {
		removeHistoryItemAction = new RemoveHistoryItemAction();
		removeHistoryActionContributionItem = new ActionContributionItem(
				removeHistoryItemAction);

		contextMenuManager = new MenuManager();
		contextMenuManager.setRemoveAllWhenShown(true);
		contextMenuManager.addMenuListener(new IMenuListener() {
			
			public void menuAboutToShow(IMenuManager manager) {
				fillContextMenu(manager);
			}
		});

		final Table table = list.getTable();
		Menu menu= contextMenuManager.createContextMenu(table);
		table.setMenu(menu);
	}

	/**
	 * Creates an extra content area, which will be located above the details.
	 *
	 * @param parent
	 *            parent to create the dialog widgets in
	 * @return an extra content area
	 */
	protected abstract Control createExtendedContentArea(Composite parent);

	/**
	 * Creates the {@link Composite} into which the dialog area's TableViewer
	 * will be nested.
	 * 
	 * @param parent
	 *            parent to create the TableViewer in
	 * @return a Composite to hold the TableViewer.
	 */
	protected Composite createContentComposite(final Composite parent) {
		final Composite comp = new Composite(parent, SWT.NONE);
		comp.setLayoutData(new GridData(GridData.FILL_BOTH));

		final GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		comp.setLayout(layout);

		return comp;
	}

	
	protected Control createDialogArea(Composite parent) {
		Composite dialogArea = (Composite) super.createDialogArea(parent);

		Composite content = new Composite(dialogArea, SWT.NONE);
		GridData gd = new GridData(GridData.FILL_BOTH);
		content.setLayoutData(gd);

		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		content.setLayout(layout);

		final Label headerLabel = createHeader(content);

		pattern = new Text(content, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL);
		pattern.getAccessible().addAccessibleListener(new AccessibleAdapter() {
			
			public void getName(AccessibleEvent e) {
				e.result = LegacyActionTools.removeMnemonics(headerLabel
						.getText());
			}
		});
		gd = new GridData(GridData.FILL_HORIZONTAL);
		pattern.setLayoutData(gd);

		final Label listLabel = createLabels(content);

		final Composite comp = createContentComposite(content);

		list = new TableViewer(comp,
				(multi ? SWT.MULTI : SWT.SINGLE)
				| SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL);
		list.getTable().getAccessible().addAccessibleListener(
				new AccessibleAdapter() {
					
					public void getName(AccessibleEvent e) {
						if (e.childID == ACC.CHILDID_SELF) {
							e.result = LegacyActionTools
									.removeMnemonics(listLabel.getText());
						}
					}
				});
		list.setContentProvider(contentProvider);
		list.setLabelProvider(getItemsListLabelProvider());
		list.setInput(new Object[0]);
		list.setItemCount(contentProvider.getNumberOfElements());
		gd = new GridData(GridData.FILL_BOTH);
		applyDialogFont(list.getTable());
		gd.heightHint= list.getTable().getItemHeight() * 15;
		list.getTable().setLayoutData(gd);

		createPopupMenu();

		pattern.addModifyListener(new ModifyListener() {
			
			public void modifyText(ModifyEvent e) {
				applyFilter();
			}
		});

		pattern.addKeyListener(new KeyAdapter() {
			
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.ARROW_DOWN) {
					if (list.getTable().getItemCount() > 0) {
						list.getTable().setFocus();
					}
				}
			}
		});

		list.addSelectionChangedListener(new ISelectionChangedListener() {
			
			public void selectionChanged(SelectionChangedEvent event) {
				StructuredSelection selection = (StructuredSelection) event
						.getSelection();
				handleSelected(selection);
			}
		});

		list.addDoubleClickListener(new IDoubleClickListener() {
			
			public void doubleClick(DoubleClickEvent event) {
				handleDoubleClick();
			}
		});

		list.getTable().addKeyListener(new KeyAdapter() {
			
			public void keyPressed(KeyEvent e) {

				if (e.keyCode == SWT.DEL) {

					List selectedElements = ((StructuredSelection) list
							.getSelection()).toList();

					Object item = null;
					boolean isSelectedHistory = true;

					for (Iterator it = selectedElements.iterator(); it
							.hasNext();) {
						item = it.next();
						if (item instanceof ItemsListSeparator
								|| !isHistoryElement(item)) {
							isSelectedHistory = false;
							break;
						}
					}
					if (isSelectedHistory)
						removeSelectedItems(selectedElements);

				}

				if (e.keyCode == SWT.ARROW_UP && (e.stateMask & SWT.SHIFT) != 0
						&& (e.stateMask & SWT.CTRL) != 0) {
					StructuredSelection selection = (StructuredSelection) list
							.getSelection();

					if (selection.size() == 1) {
						Object element = selection.getFirstElement();
						if (element.equals(list.getElementAt(0))) {
							pattern.setFocus();
						}
						if (list.getElementAt(list.getTable()
								.getSelectionIndex() - 1) instanceof ItemsListSeparator)
							list.getTable().setSelection(
									list.getTable().getSelectionIndex() - 1);
						list.getTable().notifyListeners(SWT.Selection,
								new Event());

					}
				}

				if (e.keyCode == SWT.ARROW_DOWN
						&& (e.stateMask & SWT.SHIFT) != 0
						&& (e.stateMask & SWT.CTRL) != 0) {

					if (list
							.getElementAt(list.getTable().getSelectionIndex() + 1) instanceof ItemsListSeparator)
						list.getTable().setSelection(
								list.getTable().getSelectionIndex() + 1);
					list.getTable().notifyListeners(SWT.Selection, new Event());
				}

			}
		});

		createExtendedContentArea(comp);

		details = new DetailsContentViewer(content, SWT.BORDER | SWT.FLAT);
		details.setVisible(toggleStatusLineAction.isChecked());
		details.setContentProvider(new NullContentProvider());
		details.setLabelProvider(getDetailsLabelProvider());

		applyDialogFont(content);

		restoreDialog(getDialogSettings());

		if (initialPatternText != null) {
			pattern.setText(initialPatternText);
		}

		switch (selectionMode) {
		case CARET_BEGINNING:
			pattern.setSelection(0, 0);
			break;
		case FULL_SELECTION:
			pattern.setSelection(0, initialPatternText.length());
			break;
		}

		// apply filter even if pattern is empty (display history)
		applyFilter();

		return dialogArea;
	}

	/**
	 * This method is a hook for subclasses to override default dialog behavior.
	 * The <code>handleDoubleClick()</code> method handles double clicks on
	 * the list of filtered elements.
	 * <p>
	 * Current implementation makes double-clicking on the list do the same as
	 * pressing <code>OK</code> button on the dialog.
	 */
	protected void handleDoubleClick() {
		okPressed();
	}

	/**
	 * Refreshes the details field according to the current selection in the
	 * items list.
	 */
	private void refreshDetails() {
		StructuredSelection selection = getSelectedItems();

		switch (selection.size()) {
		case 0:
			details.setInput(null);
			break;
		case 1:
			details.setInput(selection.getFirstElement());
			break;
		default:
			details
					.setInput(NLS
							.bind(
									WorkbenchMessages.FilteredItemsSelectionDialog_nItemsSelected,
									new Integer(selection.size())));
			break;
		}

	}

	/**
	 * Handle selection in the items list by updating labels of selected and
	 * unselected items and refresh the details field using the selection.
	 *
	 * @param selection
	 *            the new selection
	 */
	protected void handleSelected(StructuredSelection selection) {
		IStatus status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
				IStatus.OK, EMPTY_STRING, null);

		Object[] lastSelection = currentSelection;

		currentSelection = selection.toArray();

		if (selection.size() == 0) {
			status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
					IStatus.ERROR, EMPTY_STRING, null);

			if (lastSelection != null
					&& getListSelectionLabelDecorator() != null) {
				list.update(lastSelection, null);
			}

			currentSelection = null;

		} else {
			status = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
					IStatus.ERROR, EMPTY_STRING, null);

			List items = selection.toList();

			Object item = null;
			IStatus tempStatus = null;

			for (Iterator it = items.iterator(); it.hasNext();) {
				Object o = it.next();

				if (o instanceof ItemsListSeparator) {
					continue;
				}

				item = o;
				tempStatus = validateItem(item);

				if (tempStatus.isOK()) {
					status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
							IStatus.OK, EMPTY_STRING, null);
				} else {
					status = tempStatus;
					// if any selected element is not valid status is set to
					// ERROR
					break;
				}
			}

			if (lastSelection != null
					&& getListSelectionLabelDecorator() != null) {
				list.update(lastSelection, null);
			}

			if (getListSelectionLabelDecorator() != null) {
				list.update(currentSelection, null);
			}
		}

		refreshDetails();
		updateStatus(status);
	}

	
	protected IDialogSettings getDialogBoundsSettings() {
		IDialogSettings settings = getDialogSettings();
		IDialogSettings section = settings.getSection(DIALOG_BOUNDS_SETTINGS);
		if (section == null) {
			section = settings.addNewSection(DIALOG_BOUNDS_SETTINGS);
			section.put(DIALOG_HEIGHT, 500);
			section.put(DIALOG_WIDTH, 600);
		}
		return section;
	}

	/**
	 * Returns the dialog settings. Returned object can't be null.
	 *
	 * @return return dialog settings for this dialog
	 */
	protected abstract IDialogSettings getDialogSettings();

	/**
	 * Refreshes the dialog - has to be called in UI thread.
	 */
	public void refresh() {
		if (list != null && !list.getTable().isDisposed()) {

			List lastRefreshSelection = ((StructuredSelection) list
					.getSelection()).toList();
			list.getTable().deselectAll();

			list.setItemCount(contentProvider.getNumberOfElements());
			list.refresh();

			if (list.getTable().getItemCount() > 0) {
				// preserve previous selection
				if (refreshWithLastSelection && lastRefreshSelection != null
						&& lastRefreshSelection.size() > 0) {
					list.setSelection(new StructuredSelection(
							lastRefreshSelection));
				} else {
					refreshWithLastSelection = true;
					list.getTable().setSelection(0);
					list.getTable().notifyListeners(SWT.Selection, new Event());
				}
			} else {
				list.setSelection(StructuredSelection.EMPTY);
			}

		}

		scheduleProgressMessageRefresh();
	}

	/**
	 * Updates the progress label.
	 *
	 * @deprecated
	 */
	@Deprecated
	public void updateProgressLabel() {
		scheduleProgressMessageRefresh();
	}

	/**
	 * Notifies the content provider - fires filtering of content provider
	 * elements. During the filtering, a separator between history and workspace
	 * matches is added.
	 * <p>
	 * This is a long running operation and should be called in a job.
	 *
	 * @param checkDuplicates
	 *            <code>true</code> if data concerning elements duplication
	 *            should be computed - it takes much more time than the standard
	 *            filtering
	 * @param monitor
	 *            a progress monitor or <code>null</code> if no monitor is
	 *            available
	 */
	public void reloadCache(boolean checkDuplicates, IProgressMonitor monitor) {
		if (list != null && !list.getTable().isDisposed()
				&& contentProvider != null) {
			contentProvider.reloadCache(checkDuplicates, monitor);
		}
	}

	/**
	 * Schedule refresh job.
	 */
	public void scheduleRefresh() {
		refreshCacheJob.cancelAll();
		refreshCacheJob.schedule();
	}

	/**
	 * Schedules progress message refresh.
	 */
	public void scheduleProgressMessageRefresh() {
		if (filterJob.getState() != Job.RUNNING
				&& refreshProgressMessageJob.getState() != Job.RUNNING)
			refreshProgressMessageJob.scheduleProgressRefresh(null);
	}

	
	protected void computeResult() {

		List selectedElements = ((StructuredSelection) list.getSelection())
				.toList();

		List objectsToReturn = new ArrayList();

		Object item = null;

		for (Iterator it = selectedElements.iterator(); it.hasNext();) {
			item = it.next();

			if (!(item instanceof ItemsListSeparator)) {
				accessedHistoryItem(item);
				objectsToReturn.add(item);
			}
		}

		setResult(objectsToReturn);
	}

	/*
	 * @see org.eclipse.ui.dialogs.SelectionStatusDialog#updateStatus(org.eclipse.core.runtime.IStatus)
	 */
	
	protected void updateStatus(IStatus status) {
		this.status = status;
		super.updateStatus(status);
	}

	/*
	 * @see Dialog#okPressed()
	 */
	
	protected void okPressed() {
		if (status != null
				&& (status.isOK() || status.getCode() == IStatus.INFO)) {
			super.okPressed();
		}
	}

	/**
	 * Sets the initial pattern used by the filter. This text is copied into the
	 * selection input on the dialog. A full selection is used in the pattern
	 * input field.
	 *
	 * @param text
	 *            initial pattern for the filter
	 * @see FilteredItemsSelectionDialog#FULL_SELECTION
	 */
	public void setInitialPattern(String text) {
		setInitialPattern(text, FULL_SELECTION);
	}

	/**
	 * Sets the initial pattern used by the filter. This text is copied into the
	 * selection input on the dialog. The <code>selectionMode</code> is used
	 * to choose selection type for the input field.
	 *
	 * @param text
	 *            initial pattern for the filter
	 * @param selectionMode
	 *            one of: {@link FilteredItemsSelectionDialog#NONE},
	 *            {@link FilteredItemsSelectionDialog#CARET_BEGINNING},
	 *            {@link FilteredItemsSelectionDialog#FULL_SELECTION}
	 */
	public void setInitialPattern(String text, int selectionMode) {
		this.initialPatternText = text;
		this.selectionMode = selectionMode;
	}

	/**
	 * Gets initial pattern.
	 *
	 * @return initial pattern, or <code>null</code> if initial pattern is not
	 *         set
	 */
	protected String getInitialPattern() {
		return this.initialPatternText;
	}

	/**
	 * Returns the current selection.
	 *
	 * @return the current selection
	 */
	protected StructuredSelection getSelectedItems() {

		StructuredSelection selection = (StructuredSelection) list
				.getSelection();

		List selectedItems = selection.toList();
		Object itemToRemove = null;

		for (Iterator it = selection.iterator(); it.hasNext();) {
			Object item = it.next();
			if (item instanceof ItemsListSeparator) {
				itemToRemove = item;
				break;
			}
		}

		if (itemToRemove == null)
			return new StructuredSelection(selectedItems);
		// Create a new selection without the collision
		List newItems = new ArrayList(selectedItems);
		newItems.remove(itemToRemove);
		return new StructuredSelection(newItems);

	}

	/**
	 * Validates the item. When items on the items list are selected or
	 * deselected, it validates each item in the selection and the dialog status
	 * depends on all validations.
	 *
	 * @param item
	 *            an item to be checked
	 * @return status of the dialog to be set
	 */
	protected abstract IStatus validateItem(Object item);

	/**
	 * Creates an instance of a filter.
	 *
	 * @return a filter for items on the items list. Can be <code>null</code>,
	 *         no filtering will be applied then, causing no item to be shown in
	 *         the list.
	 */
	protected abstract ItemsFilter createFilter();

	/**
	 * Applies the filter created by <code>createFilter()</code> method to the
	 * items list. When new filter is different than previous one it will cause
	 * refiltering.
	 */
	protected void applyFilter() {

		ItemsFilter newFilter = createFilter();

		// don't apply filtering for patterns which mean the same, for example:
		// *a**b and ***a*b
		if (filter != null && filter.equalsFilter(newFilter)) {
			return;
		}

		filterHistoryJob.cancel();
		filterJob.cancel();

		this.filter = newFilter;

		if (this.filter != null) {
			filterHistoryJob.schedule();
		}
	}

	/**
	 * Returns comparator to sort items inside content provider. Returned object
	 * will be probably created as an anonymous class. Parameters passed to the
	 * <code>compare(java.lang.Object, java.lang.Object)</code> are going to
	 * be the same type as the one used in the content provider.
	 *
	 * @return comparator to sort items content provider
	 */
	protected abstract Comparator getItemsComparator();

	/**
	 * Fills the content provider with matching items.
	 *
	 * @param contentProvider
	 *            collector to add items to.
	 *            {@link FilteredItemsSelectionDialog.AbstractContentProvider#add(Object, FilteredItemsSelectionDialog.ItemsFilter)}
	 *            only adds items that pass the given <code>itemsFilter</code>.
	 * @param itemsFilter
	 *            the items filter
	 * @param progressMonitor
	 *            must be used to report search progress. The state of this
	 *            progress monitor reflects the state of the filtering process.
	 * @throws CoreException
	 */
	protected abstract void fillContentProvider(
			AbstractContentProvider contentProvider, ItemsFilter itemsFilter,
			IProgressMonitor progressMonitor) throws CoreException;

	/**
	 * Removes selected items from history.
	 *
	 * @param items
	 *            items to be removed
	 */
	private void removeSelectedItems(List items) {
		for (Iterator iter = items.iterator(); iter.hasNext();) {
			Object item = iter.next();
			removeHistoryItem(item);
		}
		refreshWithLastSelection = false;
		contentProvider.refresh();
	}

	/**
	 * Removes an item from history.
	 *
	 * @param item
	 *            an item to remove
	 * @return removed item
	 */
	protected Object removeHistoryItem(Object item) {
		return contentProvider.removeHistoryElement(item);
	}

	/**
	 * Adds item to history.
	 *
	 * @param item
	 *            the item to be added
	 */
	protected void accessedHistoryItem(Object item) {
		contentProvider.addHistoryElement(item);
	}

	/**
	 * Returns a history comparator.
	 *
	 * @return decorated comparator
	 */
	private Comparator getHistoryComparator() {
		return new HistoryComparator();
	}

	/**
	 * Returns the history of selected elements.
	 *
	 * @return history of selected elements, or <code>null</code> if it is not
	 *         set
	 */
	protected SelectionHistory getSelectionHistory() {
		return this.contentProvider.getSelectionHistory();
	}

	/**
	 * Sets new history.
	 *
	 * @param selectionHistory
	 *            the history
	 */
	protected void setSelectionHistory(SelectionHistory selectionHistory) {
		if (this.contentProvider != null)
			this.contentProvider.setSelectionHistory(selectionHistory);
	}

	/**
	 * Indicates whether the given item is a history item.
	 *
	 * @param item
	 *            the item to be investigated
	 * @return <code>true</code> if the given item exists in history,
	 *         <code>false</code> otherwise
	 */
	public boolean isHistoryElement(Object item) {
		return this.contentProvider.isHistoryElement(item);
	}

	/**
	 * Indicates whether the given item is a duplicate.
	 *
	 * @param item
	 *            the item to be investigated
	 * @return <code>true</code> if the item is duplicate, <code>false</code>
	 *         otherwise
	 */
	public boolean isDuplicateElement(Object item) {
		return this.contentProvider.isDuplicateElement(item);
	}

	/**
	 * Sets separator label
	 *
	 * @param separatorLabel
	 *            the label showed on separator
	 */
	public void setSeparatorLabel(String separatorLabel) {
		this.itemsListSeparator = new ItemsListSeparator(separatorLabel);
	}

	/**
	 * Returns name for then given object.
	 *
	 * @param item
	 *            an object from the content provider. Subclasses should pay
	 *            attention to the passed argument. They should either only pass
	 *            objects of a known type (one used in content provider) or make
	 *            sure that passed parameter is the expected one (by type
	 *            checking like <code>instanceof</code> inside the method).
	 * @return name of the given item
	 */
	public abstract String getElementName(Object item);

	private class ToggleStatusLineAction extends Action {

		/**
		 * Creates a new instance of the class.
		 */
		public ToggleStatusLineAction() {
			super(
					WorkbenchMessages.FilteredItemsSelectionDialog_toggleStatusAction,
					IAction.AS_CHECK_BOX);
		}

		
		public void run() {
			details.setVisible(isChecked());
		}
	}

	/**
	 * Only refreshes UI on the basis of an already sorted and filtered set of
	 * items.
	 * <p>
	 * Standard invocation scenario:
	 * <ol>
	 * <li>filtering job (<code>FilterJob</code> class extending
	 * <code>Job</code> class)</li>
	 * <li>cache refresh without checking for duplicates (<code>RefreshCacheJob</code>
	 * class extending <code>Job</code> class)</li>
	 * <li>UI refresh (<code>RefreshJob</code> class extending
	 * <code>UIJob</code> class)</li>
	 * <li>cache refresh with checking for duplicates (<cod>CacheRefreshJob</code>
	 * class extending <code>Job</code> class)</li>
	 * <li>UI refresh (<code>RefreshJob</code> class extending <code>UIJob</code>
	 * class)</li>
	 * </ol>
	 * The scenario is rather complicated, but it had to be applied, because:
	 * <ul>
	 * <li> refreshing cache is rather a long action and cannot be run in the UI -
	 * cannot be run in a UIJob</li>
	 * <li> refreshing cache checking for duplicates is twice as long as
	 * refreshing cache without checking for duplicates; results of the search
	 * could be displayed earlier</li>
	 * <li> refreshing the UI have to be run in a UIJob</li>
	 * </ul>
	 *
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.FilterJob
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshJob
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.RefreshCacheJob
	 */
	private class RefreshJob extends UIJob {

		/**
		 * Creates a new instance of the class.
		 */
		public RefreshJob() {
			super(FilteredItemsSelectionDialog.this.getParentShell()
					.getDisplay(),
					WorkbenchMessages.FilteredItemsSelectionDialog_refreshJob);
			setSystem(true);
		}

		
		public IStatus runInUIThread(IProgressMonitor monitor) {
			if (monitor.isCanceled())
				return new Status(IStatus.OK, WorkbenchPlugin.PI_WORKBENCH,
						IStatus.OK, EMPTY_STRING, null);

			if (FilteredItemsSelectionDialog.this != null) {
				FilteredItemsSelectionDialog.this.refresh();
			}

			return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
					EMPTY_STRING, null);
		}

	}

	/**
	 * Refreshes the progress message cyclically with 500 milliseconds delay.
	 * <code>RefreshProgressMessageJob</code> is strictly connected with
	 * <code>GranualProgressMonitor</code> and use it to to get progress
	 * message and to decide about break of cyclical refresh.
	 */
	private class RefreshProgressMessageJob extends UIJob {

		private GranualProgressMonitor progressMonitor;

		/**
		 * Creates a new instance of the class.
		 */
		public RefreshProgressMessageJob() {
			super(
					FilteredItemsSelectionDialog.this.getParentShell()
							.getDisplay(),
					WorkbenchMessages.FilteredItemsSelectionDialog_progressRefreshJob);
			setSystem(true);
		}

		
		public IStatus runInUIThread(IProgressMonitor monitor) {

			if (!progressLabel.isDisposed())
				progressLabel.setText(progressMonitor != null ? progressMonitor
						.getMessage() : EMPTY_STRING);

			if (progressMonitor == null || progressMonitor.isDone()) {
				return new Status(IStatus.CANCEL, PlatformUI.PLUGIN_ID,
						IStatus.CANCEL, EMPTY_STRING, null);
			}

			// Schedule cyclical with 500 milliseconds delay
			schedule(500);

			return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
					EMPTY_STRING, null);
		}

		/**
		 * Schedule progress refresh job.
		 *
		 * @param progressMonitor
		 *            used during refresh progress label
		 */
		public void scheduleProgressRefresh(
				GranualProgressMonitor progressMonitor) {
			this.progressMonitor = progressMonitor;
			// Schedule with initial delay to avoid flickering when the user
			// types quickly
			schedule(200);
		}

	}

	/**
	 * A job responsible for computing filtered items list presented using
	 * <code>RefreshJob</code>.
	 *
	 * @see FilteredItemsSelectionDialog.RefreshJob
	 *
	 */
	private class RefreshCacheJob extends Job {

		private RefreshJob refreshJob = new RefreshJob();

		/**
		 * Creates a new instance of the class.
		 */
		public RefreshCacheJob() {
			super(
					WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob);
			setSystem(true);
		}

		/**
		 * Stops the job and all sub-jobs.
		 */
		public void cancelAll() {
			cancel();
			refreshJob.cancel();
		}

		
		protected IStatus run(IProgressMonitor monitor) {
			if (monitor.isCanceled()) {
				return new Status(IStatus.CANCEL, WorkbenchPlugin.PI_WORKBENCH,
						IStatus.CANCEL, EMPTY_STRING, null);
			}

			if (FilteredItemsSelectionDialog.this != null) {
				GranualProgressMonitor wrappedMonitor = new GranualProgressMonitor(
						monitor);
				FilteredItemsSelectionDialog.this.reloadCache(true,
						wrappedMonitor);
			}

			if (!monitor.isCanceled()) {
				refreshJob.schedule();
			}

			return new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK,
					EMPTY_STRING, null);

		}

		
		protected void canceling() {
			super.canceling();
			contentProvider.stopReloadingCache();
		}

	}

	private class RemoveHistoryItemAction extends Action {

		/**
		 * Creates a new instance of the class.
		 */
		public RemoveHistoryItemAction() {
			super(
					WorkbenchMessages.FilteredItemsSelectionDialog_removeItemsFromHistoryAction);
		}

		
		public void run() {
			List selectedElements = ((StructuredSelection) list.getSelection())
					.toList();
			removeSelectedItems(selectedElements);
		}
	}

	private static boolean showColoredLabels() {
		return PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS);
	}

	private class ItemsListLabelProvider extends StyledCellLabelProvider
			implements ILabelProviderListener {
		private ILabelProvider provider;

		private ILabelDecorator selectionDecorator;

		// Need to keep our own list of listeners
		private ListenerList listeners = new ListenerList();

		/**
		 * Creates a new instance of the class.
		 *
		 * @param provider
		 *            the label provider for all items, not <code>null</code>
		 * @param selectionDecorator
		 *            the decorator for selected items, can be <code>null</code>
		 */
		public ItemsListLabelProvider(ILabelProvider provider,
				ILabelDecorator selectionDecorator) {
			Assert.isNotNull(provider);
			this.provider = provider;
			this.selectionDecorator = selectionDecorator;

			setOwnerDrawEnabled(showColoredLabels() && provider instanceof IStyledLabelProvider);

			provider.addListener(this);

			if (selectionDecorator != null) {
				selectionDecorator.addListener(this);
			}
		}

		/**
		 * Sets new selection decorator.
		 *
		 * @param newSelectionDecorator
		 *            new label decorator for selected items in the list
		 */
		public void setSelectionDecorator(ILabelDecorator newSelectionDecorator) {
			if (selectionDecorator != null) {
				selectionDecorator.removeListener(this);
				selectionDecorator.dispose();
			}

			selectionDecorator = newSelectionDecorator;

			if (selectionDecorator != null) {
				selectionDecorator.addListener(this);
			}
		}

		/**
		 * Gets selection decorator.
		 *
		 * @return the label decorator for selected items in the list
		 */
		public ILabelDecorator getSelectionDecorator() {
			return selectionDecorator;
		}

		/**
		 * Sets new label provider.
		 *
		 * @param newProvider
		 *            new label provider for items in the list, not
		 *            <code>null</code>
		 */
		public void setProvider(ILabelProvider newProvider) {
			Assert.isNotNull(newProvider);
			provider.removeListener(this);
			provider.dispose();

			provider = newProvider;

			if (provider != null) {
				provider.addListener(this);
			}

			setOwnerDrawEnabled(showColoredLabels() && provider instanceof IStyledLabelProvider);
		}

		private Image getImage(Object element) {
			if (element instanceof ItemsListSeparator) {
				return WorkbenchImages
						.getImage(IWorkbenchGraphicConstants.IMG_OBJ_SEPARATOR);
			}

			return provider.getImage(element);
		}

		private boolean isSelected(Object element) {
			if (element != null && currentSelection != null) {
				for (int i = 0; i < currentSelection.length; i++) {
					if (element.equals(currentSelection[i]))
						return true;
				}
			}
			return false;
		}

		private String getText(Object element) {
			if (element instanceof ItemsListSeparator) {
				return getSeparatorLabel(((ItemsListSeparator) element)
						.getName());
			}

			String str = provider.getText(element);
			if (selectionDecorator != null && isSelected(element)) {
				return selectionDecorator.decorateText(str.toString(), element);
			}

			return str;
		}

		private StyledString getStyledText(Object element,
				IStyledLabelProvider provider) {
			StyledString string = provider.getStyledText(element);

			if (selectionDecorator != null && isSelected(element)) {
				String decorated = selectionDecorator.decorateText(string
						.getString(), element);
				return StyledCellLabelProvider.styleDecoratedString(decorated, null, string);
				// no need to add colors when element is selected
			}
			return string;
		}

		
		public void update(ViewerCell cell) {
			Object element = cell.getElement();

			if (!(element instanceof ItemsListSeparator)
					&& provider instanceof IStyledLabelProvider) {
				IStyledLabelProvider styledLabelProvider = (IStyledLabelProvider) provider;
				StyledString styledString = getStyledText(element,
						styledLabelProvider);

				cell.setText(styledString.getString());
				cell.setStyleRanges(styledString.getStyleRanges());
				cell.setImage(styledLabelProvider.getImage(element));
			} else {
				cell.setText(getText(element));
				cell.setImage(getImage(element));
			}
			cell.setFont(getFont(element));
			cell.setForeground(getForeground(element));
			cell.setBackground(getBackground(element));

			super.update(cell);
		}

		private String getSeparatorLabel(String separatorLabel) {
			Rectangle rect = list.getTable().getBounds();

			int borderWidth = list.getTable().computeTrim(0, 0, 0, 0).width;

			int imageWidth = WorkbenchImages.getImage(
					IWorkbenchGraphicConstants.IMG_OBJ_SEPARATOR).getBounds().width;

			int width = rect.width - borderWidth - imageWidth;

			GC gc = new GC(list.getTable());
			gc.setFont(list.getTable().getFont());

			int fSeparatorWidth = gc.getAdvanceWidth('-');
			int fMessageLength = gc.textExtent(separatorLabel).x;

			gc.dispose();

			StringBuffer dashes = new StringBuffer();
			int chars = (((width - fMessageLength) / fSeparatorWidth) / 2) - 2;
			for (int i = 0; i < chars; i++) {
				dashes.append('-');
			}

			StringBuffer result = new StringBuffer();
			result.append(dashes);
			result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$
			result.append(dashes);
			return result.toString().trim();
		}

		
		public void addListener(ILabelProviderListener listener) {
			listeners.add(listener);
		}

		
		public void dispose() {
			provider.removeListener(this);
			provider.dispose();

			if (selectionDecorator != null) {
				selectionDecorator.removeListener(this);
				selectionDecorator.dispose();
			}

			super.dispose();
		}

		
		public boolean isLabelProperty(Object element, String property) {
			if (provider.isLabelProperty(element, property)) {
				return true;
			}
			if (selectionDecorator != null
					&& selectionDecorator.isLabelProperty(element, property)) {
				return true;
			}
			return false;
		}

		
		public void removeListener(ILabelProviderListener listener) {
			listeners.remove(listener);
		}

		private Color getBackground(Object element) {
			if (element instanceof ItemsListSeparator) {
				return null;
			}
			if (provider instanceof IColorProvider) {
				return ((IColorProvider) provider).getBackground(element);
			}
			return null;
		}

		private Color getForeground(Object element) {
			if (element instanceof ItemsListSeparator) {
				return Display.getCurrent().getSystemColor(
						SWT.COLOR_WIDGET_NORMAL_SHADOW);
			}
			if (provider instanceof IColorProvider) {
				return ((IColorProvider) provider).getForeground(element);
			}
			return null;
		}

		private Font getFont(Object element) {
			if (element instanceof ItemsListSeparator) {
				return null;
			}
			if (provider instanceof IFontProvider) {
				return ((IFontProvider) provider).getFont(element);
			}
			return null;
		}

		
		public void labelProviderChanged(LabelProviderChangedEvent event) {
			Object[] l = listeners.getListeners();
			for (int i = 0; i < listeners.size(); i++) {
				((ILabelProviderListener) l[i]).labelProviderChanged(event);
			}
		}
	}

	/**
	 * Used in ItemsListContentProvider, separates history and non-history
	 * items.
	 */
	public class ItemsListSeparator {

		private String name;

		/**
		 * Creates a new instance of the class.
		 *
		 * @param name
		 *            the name of the separator
		 */
		public ItemsListSeparator(String name) {
			this.name = name;
		}

		/**
		 * Returns the name of this separator.
		 *
		 * @return the name of the separator
		 */
		public String getName() {
			return name;
		}
	}

	/**
	 * GranualProgressMonitor is used for monitoring progress of filtering
	 * process. It is used by <code>RefreshProgressMessageJob</code> to
	 * refresh progress message. State of this monitor illustrates state of
	 * filtering or cache refreshing process.
	 *
	 */
	private class GranualProgressMonitor extends ProgressMonitorWrapper {

		private String name;

		private String subName;

		private int totalWork;

		private double worked;

		private boolean done;

		/**
		 * Creates instance of <code>GranualProgressMonitor</code>.
		 *
		 * @param monitor
		 *            progress to be wrapped
		 */
		public GranualProgressMonitor(IProgressMonitor monitor) {
			super(monitor);
		}

		/**
		 * Checks if filtering has been done
		 *
		 * @return true if filtering work has been done false in other way
		 */
		public boolean isDone() {
			return done;
		}

		
		public void setTaskName(String name) {
			super.setTaskName(name);
			this.name = name;
			this.subName = null;
		}

		
		public void subTask(String name) {
			super.subTask(name);
			this.subName = name;
		}

		
		public void beginTask(String name, int totalWork) {
			super.beginTask(name, totalWork);
			if (this.name == null)
				this.name = name;
			this.totalWork = totalWork;
			refreshProgressMessageJob.scheduleProgressRefresh(this);
		}

		
		public void worked(int work) {
			super.worked(work);
			internalWorked(work);
		}

		
		public void done() {
			done = true;
			super.done();
		}

		
		public void setCanceled(boolean b) {
			done = b;
			super.setCanceled(b);
		}

		
		public void internalWorked(double work) {
			worked = worked + work;
		}

		private String getMessage() {
			if (done)
				return ""; //$NON-NLS-1$

			String message;

			if (name == null) {
				message = subName == null ? "" : subName; //$NON-NLS-1$
			} else {
				message = subName == null ? name
						: NLS
								.bind(
										WorkbenchMessages.FilteredItemsSelectionDialog_subtaskProgressMessage,
										new Object[] { name, subName });
			}
			if (totalWork == 0)
				return message;

			return NLS
					.bind(
							WorkbenchMessages.FilteredItemsSelectionDialog_taskProgressMessage,
							new Object[] {
									message,
									new Integer(
											(int) ((worked * 100) / totalWork)) });

		}

	}

	/**
	 * Filters items history and schedule filter job.
	 */
	private class FilterHistoryJob extends Job {

		/**
		 * Filter used during the filtering process.
		 */
		private ItemsFilter itemsFilter;

		/**
		 * Creates new instance of receiver.
		 */
		public FilterHistoryJob() {
			super(WorkbenchMessages.FilteredItemsSelectionDialog_jobLabel);
			setSystem(true);
		}

		
		protected IStatus run(IProgressMonitor monitor) {

			this.itemsFilter = filter;

			contentProvider.reset();

			refreshWithLastSelection = false;

			contentProvider.addHistoryItems(itemsFilter);

			if (!(lastCompletedFilter != null && lastCompletedFilter
					.isSubFilter(this.itemsFilter)))
				contentProvider.refresh();

			filterJob.schedule();

			return Status.OK_STATUS;
		}

	}

	/**
	 * Filters items in indicated set and history. During filtering, it
	 * refreshes the dialog (progress monitor and elements list).
	 *
	 * Depending on the filter, <code>FilterJob</code> decides which kind of
	 * search will be run inside <code>filterContent</code>. If the last
	 * filtering is done (last completed filter), is not null, and the new
	 * filter is a sub-filter ({@link FilteredItemsSelectionDialog.ItemsFilter#isSubFilter(FilteredItemsSelectionDialog.ItemsFilter)})
	 * of the last, then <code>FilterJob</code> only filters in the cache. If
	 * it is the first filtering or the new filter isn't a sub-filter of the
	 * last one, a full search is run.
	 */
	private class FilterJob extends Job {

		/**
		 * Filter used during the filtering process.
		 */
		protected ItemsFilter itemsFilter;

		/**
		 * Creates new instance of FilterJob
		 */
		public FilterJob() {
			super(WorkbenchMessages.FilteredItemsSelectionDialog_jobLabel);
			setSystem(true);
		}

		
		protected final IStatus run(IProgressMonitor parent) {
			GranualProgressMonitor monitor = new GranualProgressMonitor(parent);
			return doRun(monitor);
		}

		/**
		 * Executes job using the given filtering progress monitor. A hook for
		 * subclasses.
		 *
		 * @param monitor
		 *            progress monitor
		 * @return result of the execution
		 */
		protected IStatus doRun(GranualProgressMonitor monitor) {
			try {
				internalRun(monitor);
			} catch (CoreException e) {
				cancel();
				return new Status(
						IStatus.ERROR,
						PlatformUI.PLUGIN_ID,
						IStatus.ERROR,
						WorkbenchMessages.FilteredItemsSelectionDialog_jobError,
						e);
			}
			return Status.OK_STATUS;
		}

		/**
		 * Main method for the job.
		 *
		 * @param monitor
		 * @throws CoreException
		 */
		private void internalRun(GranualProgressMonitor monitor)
				throws CoreException {
			try {
				if (monitor.isCanceled())
					return;

				this.itemsFilter = filter;

				if (filter.getPattern().length() != 0) {
					filterContent(monitor);
				}

				if (monitor.isCanceled())
					return;

				contentProvider.refresh();
			} finally {
				monitor.done();
			}
		}

		/**
		 * Filters items.
		 *
		 * @param monitor
		 *            for monitoring progress
		 * @throws CoreException
		 */
		protected void filterContent(GranualProgressMonitor monitor)
				throws CoreException {

			if (lastCompletedFilter != null
					&& lastCompletedFilter.isSubFilter(this.itemsFilter)) {

				int length = lastCompletedResult.size() / 500;
				monitor
						.beginTask(
								WorkbenchMessages.FilteredItemsSelectionDialog_cacheSearchJob_taskName,
								length);

				for (int pos = 0; pos < lastCompletedResult.size(); pos++) {

					Object item = lastCompletedResult.get(pos);
					if (monitor.isCanceled())
						break;
					contentProvider.add(item, itemsFilter);

					if ((pos % 500) == 0) {
						monitor.worked(1);
					}
				}

			} else {

				lastCompletedFilter = null;
				lastCompletedResult = null;

				SubProgressMonitor subMonitor = null;
				if (monitor != null) {
					monitor
							.beginTask(
									WorkbenchMessages.FilteredItemsSelectionDialog_searchJob_taskName,
									100);
					subMonitor = new SubProgressMonitor(monitor, 95);

				}

				fillContentProvider(contentProvider, itemsFilter, subMonitor);

				if (monitor != null && !monitor.isCanceled()) {
					monitor.worked(2);
					contentProvider.rememberResult(itemsFilter);
					monitor.worked(3);
				}
			}

		}

	}

	/**
	 * History stores a list of key, object pairs. The list is bounded at a
	 * certain size. If the list exceeds this size the oldest element is removed
	 * from the list. An element can be added/renewed with a call to
	 * <code>accessed(Object)</code>.
	 * <p>
	 * The history can be stored to/loaded from an XML file.
	 */
	protected static abstract class SelectionHistory {

		private static final String DEFAULT_ROOT_NODE_NAME = "historyRootNode"; //$NON-NLS-1$

		private static final String DEFAULT_INFO_NODE_NAME = "infoNode"; //$NON-NLS-1$

		private static final int MAX_HISTORY_SIZE = 60;

		private final Set historyList;

		private final String rootNodeName;

		private final String infoNodeName;

		private SelectionHistory(String rootNodeName, String infoNodeName) {

			historyList = Collections.synchronizedSet(new LinkedHashSet() {

				private static final long serialVersionUID = 0L;

				
				public boolean add(Object arg0) {
					if (this.size() >= MAX_HISTORY_SIZE) {
						Iterator iterator = this.iterator();
						iterator.next();
						iterator.remove();
					}
					return super.add(arg0);
				}

			});

			this.rootNodeName = rootNodeName;
			this.infoNodeName = infoNodeName;
		}

		/**
		 * Creates new instance of <code>SelectionHistory</code>.
		 */
		public SelectionHistory() {
			this(DEFAULT_ROOT_NODE_NAME, DEFAULT_INFO_NODE_NAME);
		}

		/**
		 * Adds object to history.
		 *
		 * @param object
		 *            the item to be added to the history
		 */
		public synchronized void accessed(Object object) {
			historyList.remove(object);
			historyList.add(object);
		}

		/**
		 * Returns <code>true</code> if history contains object.
		 *
		 * @param object
		 *            the item for which check will be executed
		 * @return <code>true</code> if history contains object
		 *         <code>false</code> in other way
		 */
		public synchronized boolean contains(Object object) {
			return historyList.contains(object);
		}

		/**
		 * Returns <code>true</code> if history is empty.
		 *
		 * @return <code>true</code> if history is empty
		 */
		public synchronized boolean isEmpty() {
			return historyList.isEmpty();
		}

		/**
		 * Remove element from history.
		 *
		 * @param element
		 *            to remove form the history
		 * @return <code>true</code> if this list contained the specified
		 *         element
		 */
		public synchronized boolean remove(Object element) {
			return historyList.remove(element);
		}

		/**
		 * Load history elements from memento.
		 *
		 * @param memento
		 *            memento from which the history will be retrieved
		 */
		public void load(IMemento memento) {

			XMLMemento historyMemento = (XMLMemento) memento
					.getChild(rootNodeName);

			if (historyMemento == null) {
				return;
			}

			IMemento[] mementoElements = historyMemento
					.getChildren(infoNodeName);
			for (int i = 0; i < mementoElements.length; ++i) {
				IMemento mementoElement = mementoElements[i];
				Object object = restoreItemFromMemento(mementoElement);
				if (object != null) {
					historyList.add(object);
				}
			}
		}

		/**
		 * Save history elements to memento.
		 *
		 * @param memento
		 *            memento to which the history will be added
		 */
		public void save(IMemento memento) {

			IMemento historyMemento = memento.createChild(rootNodeName);

			Object[] items = getHistoryItems();
			for (int i = 0; i < items.length; i++) {
				Object item = items[i];
				IMemento elementMemento = historyMemento
						.createChild(infoNodeName);
				storeItemToMemento(item, elementMemento);
			}

		}

		/**
		 * Gets array of history items.
		 *
		 * @return array of history elements
		 */
		public synchronized Object[] getHistoryItems() {
			return historyList.toArray();
		}

		/**
		 * Creates an object using given memento.
		 *
		 * @param memento
		 *            memento used for creating new object
		 *
		 * @return the restored object
		 */
		protected abstract Object restoreItemFromMemento(IMemento memento);

		/**
		 * Store object in <code>IMemento</code>.
		 *
		 * @param item
		 *            the item to store
		 * @param memento
		 *            the memento to store to
		 */
		protected abstract void storeItemToMemento(Object item, IMemento memento);

	}

	/**
	 * Filters elements using SearchPattern by comparing the names of items with
	 * the filter pattern.
	 */
	protected abstract class ItemsFilter {

		protected SearchPattern patternMatcher;

		/**
		 * Creates new instance of ItemsFilter.
		 */
		public ItemsFilter() {
			this(new SearchPattern());
		}

		/**
		 * Creates new instance of ItemsFilter.
		 *
		 * @param searchPattern
		 *            the pattern to be used when filtering
		 */
		public ItemsFilter(SearchPattern searchPattern) {
			patternMatcher = searchPattern;
			String stringPattern = ""; //$NON-NLS-1$
			if (pattern != null && !pattern.getText().equals("*")) { //$NON-NLS-1$
				stringPattern = pattern.getText();
			}
			patternMatcher.setPattern(stringPattern);
		}

		/**
		 * Check if the given filter is a sub-filter of this filter. The default
		 * implementation checks if the <code>SearchPattern</code> from the
		 * given filter is a sub-pattern of the one from this filter.
		 * <p>
		 * <i>WARNING: This method is <b>not</b> defined in reading order, i.e.
		 * <code>a.isSubFilter(b)</code> is <code>true</code> iff
		 * <code>b</code> is a sub-filter of <code>a</code>, and not
		 * vice-versa. </i>
		 * </p>
		 *
		 * @param filter
		 *            the filter to be checked, or <code>null</code>
		 * @return <code>true</code> if the given filter is sub-filter of this
		 *         filter, <code>false</code> if the given filter isn't a
		 *         sub-filter or is <code>null</code>
		 *
		 * @see org.eclipse.ui.dialogs.SearchPattern#isSubPattern(org.eclipse.ui.dialogs.SearchPattern)
		 */
		public boolean isSubFilter(ItemsFilter filter) {
			if (filter != null) {
				return this.patternMatcher.isSubPattern(filter.patternMatcher);
			}
			return false;
		}

		/**
		 * Checks whether the provided filter is equal to the current filter.
		 * The default implementation checks if <code>SearchPattern</code>
		 * from current filter is equal to the one from provided filter.
		 *
		 * @param filter
		 *            filter to be checked, or <code>null</code>
		 * @return <code>true</code> if the given filter is equal to current
		 *         filter, <code>false</code> if given filter isn't equal to
		 *         current one or if it is <code>null</code>
		 *
		 * @see org.eclipse.ui.dialogs.SearchPattern#equalsPattern(org.eclipse.ui.dialogs.SearchPattern)
		 */
		public boolean equalsFilter(ItemsFilter filter) {
			if (filter != null
					&& filter.patternMatcher.equalsPattern(this.patternMatcher)) {
				return true;
			}
			return false;
		}

		/**
		 * Checks whether the pattern's match rule is camel case.
		 *
		 * @return <code>true</code> if pattern's match rule is camel case,
		 *         <code>false</code> otherwise
		 */
		public boolean isCamelCasePattern() {
			return patternMatcher.getMatchRule() == SearchPattern.RULE_CAMELCASE_MATCH;
		}

		/**
		 * Returns the pattern string.
		 *
		 * @return pattern for this filter
		 *
		 * @see SearchPattern#getPattern()
		 */
		public String getPattern() {
			return patternMatcher.getPattern();
		}

		/**
		 * Returns the rule to apply for matching keys.
		 *
		 * @return an implementation-specific match rule
		 *
		 * @see SearchPattern#getMatchRule() for match rules returned by the
		 *      default implementation
		 */
		public int getMatchRule() {
			return patternMatcher.getMatchRule();
		}

		/**
		 * Matches text with filter.
		 *
		 * @param text
		 *            the text to match with the filter
		 * @return <code>true</code> if text matches with filter pattern,
		 *         <code>false</code> otherwise
		 */
		protected boolean matches(String text) {
			return patternMatcher.matches(text);
		}

		/**
		 * General method for matching raw name pattern. Checks whether current
		 * pattern is prefix of name provided item.
		 *
		 * @param item
		 *            item to check
		 * @return <code>true</code> if current pattern is a prefix of name
		 *         provided item, <code>false</code> if item's name is shorter
		 *         than prefix or sequences of characters don't match.
		 */
		public boolean matchesRawNamePattern(Object item) {
			String prefix = patternMatcher.getPattern();
			String text = getElementName(item);

			if (text == null)
				return false;

			int textLength = text.length();
			int prefixLength = prefix.length();
			if (textLength < prefixLength) {
				return false;
			}
			for (int i = prefixLength - 1; i >= 0; i--) {
				if (Character.toLowerCase(prefix.charAt(i)) != Character
						.toLowerCase(text.charAt(i)))
					return false;
			}
			return true;
		}

		/**
		 * Matches an item against filter conditions.
		 *
		 * @param item
		 * @return <code>true<code> if item matches against filter conditions, <code>false</code>
		 *         otherwise
		 */
		public abstract boolean matchItem(Object item);

		/**
		 * Checks consistency of an item. Item is inconsistent if was changed or
		 * removed.
		 *
		 * @param item
		 * @return <code>true</code> if item is consistent, <code>false</code>
		 *         if item is inconsistent
		 */
		public abstract boolean isConsistentItem(Object item);

	}

	/**
	 * An interface to content providers for
	 * <code>FilterItemsSelectionDialog</code>.
	 */
	protected abstract class AbstractContentProvider {
		/**
		 * Adds the item to the content provider iff the filter matches the
		 * item. Otherwise does nothing.
		 *
		 * @param item
		 *            the item to add
		 * @param itemsFilter
		 *            the filter
		 *
		 * @see FilteredItemsSelectionDialog.ItemsFilter#matchItem(Object)
		 */
		public abstract void add(Object item, ItemsFilter itemsFilter);
	}

	/**
	 * Collects filtered elements. Contains one synchronized, sorted set for
	 * collecting filtered elements. All collected elements are sorted using
	 * comparator. Comparator is returned by getElementComparator() method.
	 * Implementation of <code>ItemsFilter</code> is used to filter elements.
	 * The key function of filter used in to filtering is
	 * <code>matchElement(Object item)</code>.
	 * <p>
	 * The <code>ContentProvider</code> class also provides item filtering
	 * methods. The filtering has been moved from the standard TableView
	 * <code>getFilteredItems()</code> method to content provider, because
	 * <code>ILazyContentProvider</code> and virtual tables are used. This
	 * class is responsible for adding a separator below history items and
	 * marking each items as duplicate if its name repeats more than once on the
	 * filtered list.
	 */
	private class ContentProvider extends AbstractContentProvider implements
			IStructuredContentProvider, ILazyContentProvider {

		private SelectionHistory selectionHistory;

		/**
		 * Raw result of the searching (unsorted, unfiltered).
		 * <p>
		 * Standard object flow:
		 * <code>items -> lastSortedItems -> lastFilteredItems</code>
		 */
		private Set items;

		/**
		 * Items that are duplicates.
		 */
		private Set duplicates;

		/**
		 * List of <code>ViewerFilter</code>s to be used during filtering
		 */
		private List filters;

		/**
		 * Result of the last filtering.
		 * <p>
		 * Standard object flow:
		 * <code>items -> lastSortedItems -> lastFilteredItems</code>
		 */
		private List lastFilteredItems;

		/**
		 * Result of the last sorting.
		 * <p>
		 * Standard object flow:
		 * <code>items -> lastSortedItems -> lastFilteredItems</code>
		 */
		private List lastSortedItems;

		/**
		 * Used for <code>getFilteredItems()</code> method canceling (when the
		 * job that invoked the method was canceled).
		 * <p>
		 * Method canceling could be based (only) on monitor canceling
		 * unfortunately sometimes the method <code>getFilteredElements()</code>
		 * could be run with a null monitor, the <code>reset</code> flag have
		 * to be left intact.
		 */
		private boolean reset;

		/**
		 * Creates new instance of <code>ContentProvider</code>.
		 */
		public ContentProvider() {
			this.items = Collections.synchronizedSet(new HashSet(2048));
			this.duplicates = Collections.synchronizedSet(new HashSet(256));
			this.lastFilteredItems = new ArrayList();
			this.lastSortedItems = Collections.synchronizedList(new ArrayList(
					2048));
		}

		/**
		 * Sets selection history.
		 *
		 * @param selectionHistory
		 *            The selectionHistory to set.
		 */
		public void setSelectionHistory(SelectionHistory selectionHistory) {
			this.selectionHistory = selectionHistory;
		}

		/**
		 * @return Returns the selectionHistory.
		 */
		public SelectionHistory getSelectionHistory() {
			return selectionHistory;
		}

		/**
		 * Removes all content items and resets progress message.
		 */
		public void reset() {
			reset = true;
			this.items.clear();
			this.duplicates.clear();
			this.lastSortedItems.clear();
		}

		/**
		 * Stops reloading cache - <code>getFilteredItems()</code> method.
		 */
		public void stopReloadingCache() {
			reset = true;
		}

		/**
		 * Adds filtered item.
		 *
		 * @param item
		 * @param itemsFilter
		 */
		
		public void add(Object item, ItemsFilter itemsFilter) {
			if (itemsFilter == filter) {
				if (itemsFilter != null) {
					if (itemsFilter.matchItem(item)) {
						this.items.add(item);
					}
				} else {
					this.items.add(item);
				}
			}
		}

		/**
		 * Add all history items to <code>contentProvider</code>.
		 *
		 * @param itemsFilter
		 */
		public void addHistoryItems(ItemsFilter itemsFilter) {
			if (this.selectionHistory != null) {
				Object[] items = this.selectionHistory.getHistoryItems();
				for (int i = 0; i < items.length; i++) {
					Object item = items[i];
					if (itemsFilter == filter) {
						if (itemsFilter != null) {
							if (itemsFilter.matchItem(item)) {
								if (itemsFilter.isConsistentItem(item)) {
									this.items.add(item);
								} else {
									this.selectionHistory.remove(item);
								}
							}
						}
					}
				}
			}
		}

		/**
		 * Refresh dialog.
		 */
		public void refresh() {
			scheduleRefresh();
		}

		/**
		 * Removes items from history and refreshes the view.
		 *
		 * @param item
		 *            to remove
		 *
		 * @return removed item
		 */
		public Object removeHistoryElement(Object item) {
			if (this.selectionHistory != null)
				this.selectionHistory.remove(item);
			if (filter == null || filter.getPattern().length() == 0) {
				items.remove(item);
				duplicates.remove(item);
				this.lastSortedItems.remove(item);
			}

			synchronized (lastSortedItems) {
				Collections.sort(lastSortedItems, getHistoryComparator());
			}
			return item;
		}

		/**
		 * Adds item to history and refresh view.
		 *
		 * @param item
		 *            to add
		 */
		public void addHistoryElement(Object item) {
			if (this.selectionHistory != null)
				this.selectionHistory.accessed(item);
			if (filter == null || !filter.matchItem(item)) {
				this.items.remove(item);
				this.duplicates.remove(item);
				this.lastSortedItems.remove(item);
			}
			synchronized (lastSortedItems) {
				Collections.sort(lastSortedItems, getHistoryComparator());
			}
			this.refresh();
		}

		/**
		 * @param item
		 * @return <code>true</code> if given item is part of the history
		 */
		public boolean isHistoryElement(Object item) {
			if (this.selectionHistory != null) {
				return this.selectionHistory.contains(item);
			}
			return false;
		}

		/**
		 * Sets/unsets given item as duplicate.
		 *
		 * @param item
		 *            item to change
		 *
		 * @param isDuplicate
		 *            duplicate flag
		 */
		public void setDuplicateElement(Object item, boolean isDuplicate) {
			if (this.items.contains(item)) {
				if (isDuplicate)
					this.duplicates.add(item);
				else
					this.duplicates.remove(item);
			}
		}

		/**
		 * Indicates whether given item is a duplicate.
		 *
		 * @param item
		 *            item to check
		 * @return <code>true</code> if item is duplicate
		 */
		public boolean isDuplicateElement(Object item) {
			return duplicates.contains(item);
		}

		/**
		 * Load history from memento.
		 *
		 * @param memento
		 *            memento from which the history will be retrieved
		 */
		public void loadHistory(IMemento memento) {
			if (this.selectionHistory != null)
				this.selectionHistory.load(memento);
		}

		/**
		 * Save history to memento.
		 *
		 * @param memento
		 *            memento to which the history will be added
		 */
		public void saveHistory(IMemento memento) {
			if (this.selectionHistory != null)
				this.selectionHistory.save(memento);
		}

		/**
		 * Gets sorted items.
		 *
		 * @return sorted items
		 */
		private Object[] getSortedItems() {
			if (lastSortedItems.size() != items.size()) {
				synchronized (lastSortedItems) {
					lastSortedItems.clear();
					lastSortedItems.addAll(items);
					Collections.sort(lastSortedItems, getHistoryComparator());
				}
			}
			return lastSortedItems.toArray();
		}

		/**
		 * Remember result of filtering.
		 *
		 * @param itemsFilter
		 */
		public void rememberResult(ItemsFilter itemsFilter) {
			List itemsList = Collections.synchronizedList(Arrays
					.asList(getSortedItems()));
			// synchronization
			if (itemsFilter == filter) {
				lastCompletedFilter = itemsFilter;
				lastCompletedResult = itemsList;
			}

		}

		
		public Object[] getElements(Object inputElement) {
			return lastFilteredItems.toArray();
		}

		public int getNumberOfElements() {
			return lastFilteredItems.size();
		}

		
		public void dispose() {
		}

		
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		
		public void updateElement(int index) {

			FilteredItemsSelectionDialog.this.list.replace((lastFilteredItems
					.size() > index) ? lastFilteredItems.get(index) : null,
					index);

		}

		/**
		 * Main method responsible for getting the filtered items and checking
		 * for duplicates. It is based on the
		 * {@link FilteredItemsSelectionDialog.ContentProvider#getFilteredItems(Object, IProgressMonitor)}.
		 *
		 * @param checkDuplicates
		 *            <code>true</code> if data concerning elements
		 *            duplication should be computed - it takes much more time
		 *            than standard filtering
		 *
		 * @param monitor
		 *            progress monitor
		 */
		public void reloadCache(boolean checkDuplicates,
				IProgressMonitor monitor) {

			reset = false;

			if (monitor != null) {
				// the work is divided into two actions of the same length
				int totalWork = checkDuplicates ? 200 : 100;

				monitor
						.beginTask(
								WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob,
								totalWork);
			}

			// the TableViewer's root (the input) is treated as parent

			lastFilteredItems = Arrays.asList(getFilteredItems(list.getInput(),
					monitor != null ? new SubProgressMonitor(monitor, 100)
							: null));

			if (reset || (monitor != null && monitor.isCanceled())) {
				if (monitor != null)
					monitor.done();
				return;
			}

			if (checkDuplicates) {
				checkDuplicates(monitor);
			}
			if (monitor != null)
				monitor.done();
		}

		private void checkDuplicates(IProgressMonitor monitor) {
			synchronized (lastFilteredItems) {
				IProgressMonitor subMonitor = null;
				int reportEvery = lastFilteredItems.size() / 20;
				if (monitor != null) {
					subMonitor = new SubProgressMonitor(monitor, 100);
					subMonitor
							.beginTask(
									WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob_checkDuplicates,
									5);
				}
				HashMap helperMap = new HashMap();
				for (int i = 0; i < lastFilteredItems.size(); i++) {
					if (reset
							|| (subMonitor != null && subMonitor.isCanceled()))
						return;
					Object item = lastFilteredItems.get(i);

					if (!(item instanceof ItemsListSeparator)) {
						Object previousItem = helperMap.put(
								getElementName(item), item);
						if (previousItem != null) {
							setDuplicateElement(previousItem, true);
							setDuplicateElement(item, true);
						} else {
							setDuplicateElement(item, false);
						}
					}

					if (subMonitor != null && reportEvery != 0
							&& (i + 1) % reportEvery == 0)
						subMonitor.worked(1);
				}
				helperMap.clear();
			}
		}

		/**
		 * Returns an array of items filtered using the provided
		 * <code>ViewerFilter</code>s with a separator added.
		 *
		 * @param parent
		 *            the parent
		 * @param monitor
		 *            progress monitor, can be <code>null</code>
		 * @return an array of filtered items
		 */
		protected Object[] getFilteredItems(Object parent,
				IProgressMonitor monitor) {
			int ticks = 100;
			if (monitor == null) {
				monitor = new NullProgressMonitor();
			}

			monitor
					.beginTask(
							WorkbenchMessages.FilteredItemsSelectionDialog_cacheRefreshJob_getFilteredElements,
							ticks);
			if (filters != null) {
				ticks /= (filters.size() + 2);
			} else {
				ticks /= 2;
			}

			// get already sorted array
			Object[] filteredElements = getSortedItems();

			monitor.worked(ticks);

			// filter the elements using provided ViewerFilters
			if (filters != null && filteredElements != null) {
				for (Iterator iter = filters.iterator(); iter.hasNext();) {
					ViewerFilter f = (ViewerFilter) iter.next();
					filteredElements = f.filter(list, parent, filteredElements);
					monitor.worked(ticks);
				}
			}

			if (filteredElements == null || monitor.isCanceled()) {
				monitor.done();
				return new Object[0];
			}

			ArrayList preparedElements = new ArrayList();
			boolean hasHistory = false;

			if (filteredElements.length > 0) {
				if (isHistoryElement(filteredElements[0])) {
					hasHistory = true;
				}
			}

			int reportEvery = filteredElements.length / ticks;

			// add separator
			for (int i = 0; i < filteredElements.length; i++) {
				Object item = filteredElements[i];

				if (hasHistory && !isHistoryElement(item)) {
					preparedElements.add(itemsListSeparator);
					hasHistory = false;
				}

				preparedElements.add(item);

				if (reportEvery != 0 && ((i + 1) % reportEvery == 0)) {
					monitor.worked(1);
				}
			}

			monitor.done();

			return preparedElements.toArray();
		}

		/**
		 * Adds a filter to this content provider. For an example usage of such
		 * filters look at the project <code>org.eclipse.ui.ide</code>, class
		 * <code>org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog.CustomWorkingSetFilter</code>.
		 *
		 *
		 * @param filter
		 *            the filter to be added
		 */
		public void addFilter(ViewerFilter filter) {
			if (filters == null) {
				filters = new ArrayList();
			}
			filters.add(filter);
			// currently filters are only added when dialog is restored
			// if it is changed, refreshing the whole TableViewer should be
			// added
		}

	}

	/**
	 * A content provider that does nothing.
	 */
	private class NullContentProvider implements IContentProvider {

		
		public void dispose() {
		}

		
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

	}

	/**
	 * DetailsContentViewer objects are wrappers for labels.
	 * DetailsContentViewer provides means to change label's image and text when
	 * the attached LabelProvider is updated.
	 */
	private class DetailsContentViewer extends ContentViewer {

		private CLabel label;

		/**
		 * Unfortunately, it was impossible to delegate displaying border to
		 * label. The <code>ViewForm</code> is used because
		 * <code>CLabel</code> displays shadow when border is present.
		 */
		private ViewForm viewForm;

		/**
		 * Constructs a new instance of this class given its parent and a style
		 * value describing its behavior and appearance.
		 *
		 * @param parent
		 *            the parent component
		 * @param style
		 *            SWT style bits
		 */
		public DetailsContentViewer(Composite parent, int style) {
			viewForm = new ViewForm(parent, style);
			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
			gd.horizontalSpan = 2;
			viewForm.setLayoutData(gd);
			label = new CLabel(viewForm, SWT.FLAT);
			label.setFont(parent.getFont());
			viewForm.setContent(label);
			hookControl(label);
		}

		/**
		 * Shows/hides the content viewer.
		 *
		 * @param visible
		 *            if the content viewer should be visible.
		 */
		public void setVisible(boolean visible) {
			viewForm.setVisible(visible);
			GridData gd = (GridData) viewForm.getLayoutData();
			gd.exclude = !visible;
			viewForm.getParent().layout();
		}

		
		protected void inputChanged(Object input, Object oldInput) {
			if (oldInput == null) {
				if (input == null) {
					return;
				}
				refresh();
				return;
			}

			refresh();

		}

		
		protected void handleLabelProviderChanged(
				LabelProviderChangedEvent event) {
			if (event != null) {
				refresh(event.getElements());
			}
		}

		
		public Control getControl() {
			return label;
		}

		
		public ISelection getSelection() {
			// not supported
			return null;
		}

		
		public void refresh() {
			Object input = this.getInput();
			if (input != null) {
				ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
				doRefresh(labelProvider.getText(input), labelProvider
						.getImage(input));
			} else {
				doRefresh(null, null);
			}
		}

		/**
		 * Sets the given text and image to the label.
		 *
		 * @param text
		 *            the new text or null
		 * @param image
		 *            the new image
		 */
		private void doRefresh(String text, Image image) {
			if ( text != null ) {
				text = LegacyActionTools.escapeMnemonics(text);
			}
			label.setText(text);
			label.setImage(image);
		}

		
		public void setSelection(ISelection selection, boolean reveal) {
			// not supported
		}

		/**
		 * Refreshes the label if currently chosen element is on the list.
		 *
		 * @param objs
		 *            list of changed object
		 */
		private void refresh(Object[] objs) {
			if (objs == null || getInput() == null) {
				return;
			}
			Object input = getInput();
			for (int i = 0; i < objs.length; i++) {
				if (objs[i].equals(input)) {
					refresh();
					break;
				}
			}
		}
	}

	/**
	 * Compares items according to the history.
	 */
	private class HistoryComparator implements Comparator {

		
		public int compare(Object o1, Object o2) {
			boolean h1 = isHistoryElement(o1);
			boolean h2 = isHistoryElement(o2);
			if (h1 == h2)
				return getItemsComparator().compare(o1, o2);

			if (h1)
				return -2;
			if (h2)
				return +2;

			return 0;
		}

	}


	/**
	 * Get the control where the search pattern is entered. Any filtering should
	 * be done using an {@link ItemsFilter}. This control should only be
	 * accessed for listeners that wish to handle events that do not affect
	 * filtering such as custom traversal.
	 *
	 * @return Control or <code>null</code> if the pattern control has not
	 *         been created.
	 */
	public Control getPatternControl() {
		return pattern;
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/distributed-mode.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/overview-page.html  -->


<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Running TLC in Distributed Mode</title>
</head>
<!-- a comment here -->

<body>
<h1>Running TLC in Distributed Mode</h1>

<pre>
Contents
  <a href="#different-modes">Different modes of Distributed TLC</a>
  <a href="#how-it-works">How Distributed TLC in <i>Ad Hoc</i> Mode Works</a>
  <a href="#running-master">Running the Master</a>
  <a href="#running-workers">Running the Slave Computers</a>
  <a href="#limitations">Limitations of Distributed Mode </a>
  <a href="#help">Getting and Giving Help</a>
</pre>


<a name="different-modes"></a><h2>Different modes of Distributed TLC</h2>

The TLA+ Toolbox has support to run distributed TLC in different modes (<i>ad hoc</i>, <i>Azure</i>, <i>aws-ec2</i>), which can be
generalized into <i>ad hoc</i> mode and <i>Cloud Distributed TLC</i>. The former (ad hoc) runs
TLC on a set of your own computers. It is up to you to install all necessary
prerequisites (<a href="#how-it-works">see below</a>) on each of the computers. The latter mode (Cloud Distributed TLC)
on the other hand, moves Distributed TLC into the <a href="https://en.wikipedia.org/wiki/Cloud_computing">cloud</a>
and thus can automate all the install steps of ad hoc mode for you. It comes at the price service charges by the cloud compute providers.
For Cloud Distributed TLC, please <a href="../cloudtlc/index.html">switch over to its dedicated documentation</a>

<hr>

<a name="how-it-works"></a><h2>How Distributed TLC in <i>Ad Hoc</i> Mode Works</h2>

TLC has a collection of worker threads that do the actual
model checking--that is, they compute the graph of reachable states
and check invariants and other safety properties.&nbsp; There is also
a master thread that coordinates the worker threads.&nbsp; In ordinary
(non-distributed) mode, these threads all run on the same Java Virtual
Machine (JVM) on the same computer as the Toolbox.&nbsp; In
distributed mode, the threads can be run on multiple computers.&nbsp;
The master thread runs on the same computer
as the Toolbox--a computer we call here the <i>master computer</i>.&nbsp;
The threads are run on a collection of <i>slave computers</i>.&nbsp;  Each
slave computer can run multiple threads--the default is to run as many threads
as it has processors (cores).

<p>
TLC keeps fingerprints of all states that it has found, which it uses to
determine if a newly computed state has already been examined.
&nbsp;

It writes the set of fingerprints to disk if it becomes too big to fit
in memory.&nbsp;  Having to read fingerprints from disk slows TLC down
considerably.&nbsp;  As explained below, you can have distributed TLC  distribute the
set of fingerprints to multiple slave computers (instead of keeping them
on the master computer).

</p>

<p>
Unless you're just trying it out, you're running TLC in
distributed mode because your model is quite large.&nbsp;

For any large model, it's a good idea to give TLC as much of the computer's memory
as is not needed by the operating system and other programs that will
be running at the same time.&nbsp;  This applies to TLC being run on the slaves
and on the master if slave fingerprint servers are not used.&nbsp;
</p>


<a name="running-master"></a><h2>Running the Master</h2>

<p>
TLC is run on a <a href="creating-model.html">model</a>.&nbsp;

To specify that it is to be run in distributed mode, select "ad hoc"
in the <i>Run in distributed mode</i> drop down list in the
<a href="overview-page.html#how-to-run">How to run?</a>  section
of the Model Overview Page.  That section also allows you to adjust
the amount of memory allocated to the master.
</p>

<p>
Your master computer is likely to have multiple network interface cards
and thus several different IP addresses. The <i>Master's network address</i>
drop down list shows all IP addresses the Toolbox could identify. Choose the one
to which the workers will be able to connect. The Toolbox tries guess the best
match and selects it by default.
<br>
It is up to you to configure your master's firewall to allow the workers incoming
connections.
</p>

<p> You start a TLC run in distributed mode as usual by clicking on
the <IMG SRC="run-icon.gif" Align="bottom"/> button, by selecting
<i>Run model</i> on the <i>TLC Model Checker</i> menu, or by typing
F11.&nbsp; This should cause the <i>Current status</i> field of the <a
href="results-page.html">Model Checking Results Page</a> to change to
<i>Master is waiting for (remote) workers</i> and then to indicate
that one or more workers have registered with the master.
</p>

<p>
If you want TLC to store the fingerprint set among slave computers,
you must run a (single) <i>fingerprint server</i> on each of them.&nbsp;
Your model must tell TLC how many fingerprint servers it will use.&nbsp;  If you
want fingerprints stored on 5 fingerprint servers (5 slave computers), you increase
the <i>Number of distributed fingerprint sets</i> spinner to 5. Setting it to 0, means
that the master will store the fingerprints. The master uses more memory in this mode.
</p>

<p>
For distributed mode, you may also want to add special arguments to
the command that launches the JVM that runs the master.&nbsp; As
explained <a href="#possible-problem">below</a>, one such argument may
be needed for the master and the workers to communicate.&nbsp; The
arguments are put in the <A href="tlc-options-page.html#jvmargs">JVM arguments</A> field
of the model's TLC Options page, which may be opened via a link on the Model Overview page.
</p>

<p>
If your model will run for a long time (days or weeks), you may not want to
keep the Toolbox open for the entire run.&nbsp;  Instead, you can run TLC from
a command line.&nbsp;

The easiest way to do this is to create the model
in the Toolbox, and <a href="executing-tlc.html#validating">validate it</a>.&nbsp;

You can then run distributed TLC with the following command, where <code>tool-path</code>
is the complete pathname of the directory containing the file <code>tla2tools.jar</code>
and <code>model-path</code> is is the complete pathname of the directory
<code>Spec.toolbox/ModelName</code>, with
<code>Spec</code> the specification's name and <code>ModelName</code>  the model's name
(see  <a href="executing-tlc.html#MC">How TLC is Run</a>):

<pre>
   java  -cp tool-path  tlc2.tool.distributed.TLCServer  model-path/MC
</pre>
Like the  JVM argument <code>-cp tool-path</code>, other JVM arguments can come between <code>java</code>
and <code>tlc2.tool.distributed.TLCServer</code> in this command. TLC options follow
<code>model-path/MC</code>.
<!--
 E.g. with the
<a href="executing-tlc.html#MC">model's subdirectory of the <code>.toolbox</code> directory</a>
and the Toolbox's installation directory in /opt, the command line will look like:
<pre>
   java -cp /opt/toolbox/plugins/org.lamport.tlatools_1.0.0.201211261208 -Dtlc2.tool.distributed.TLCServer.expectedFPSetCount=5 tlc2.tool.distributed.TLCServer /home/user/DieHard/DieHard.toolbox/Model_1/MC
</pre>
-->
</p>

<a name="running-workers"></a><h2>Running the Slave Computers</h2>

<p>
The following are the basic steps that must be accomplished to start
the slaves.&nbsp;  The details of how these steps are performed will vary
according to the operating system and network configuration that you
are using.&nbsp;  If you have trouble getting distributed TLC to
work on your system, try finding help on the
  <A href="https://groups.google.com/forum/?fromgroups#!forum/tlaplus">TLA+ Google group</a>.
</p>

<p>
To run the slaves, you must have a network of computers that can
communicate with one another and with the machine running the master
and the Toolbox.&nbsp;  We assume that there is some some remote
management/administration system installed on the computers that run
the workers.&nbsp;  Examples of such a system are Remote Desktop (Windows),
ssh, rsh, and telnet.&nbsp;  A Java Runtime Environment (JRE), version 11
or later, must also be installed on the machines.&nbsp;
</p>

<p>
  Start the Toolbox on the master computer, and then open a web browser to the URL
  <pre>
      http://master-computer:10996
  </pre>
  where <code>master-computer</code> is the name (or IP address) of the master computer.
  <br/>
  <br/>
  The resulting web page will have further instructions concerning running slaves, however the gist
  of it is:
  <br/>
  <br/>
  <dd>
  Start the Toolbox on the master computer.&nbsp;  Then do the following on a
  shell on each slave computer:
  <pre>
     wget http://master-computer:10996/files/tla2tools.jar
  </pre>
  Then execute one of the following commands in that slave's shell:
  <ul>
  <li> To run just worker threads on the slave, execute:
  <pre>
    java -cp tla2tools.jar tlc2.tool.distributed.TLCWorker master-computer
  </pre>
  </li>

  <li> To run just a fingerprint server on the slave, execute:
  <pre>
    java -cp tla2tools.jar tlc2.tool.distributed.fp.DistributedFPSet master-computer
  </pre>
  </li>

  <li> To run both worker threads and a fingerprint server on the slave, execute:
  <pre>
    java -cp tla2tools.jar tlc2.tool.distributed.fp.TLCWorkerAndFPSet master-computer
  </pre>
  </li>
  </ul>
  <p>
  The <code>wget</code> command downloads the file
  <code>tla2tools.jar</code> into the current directory on the worker
  machine, the <code>java</code> command actually starts the worker.&nbsp; The
  <code>wget</code> command therefore just has to be executed the first
  time you run a worker, and then whenever you install a new version of
  the Toolbox.&nbsp; The <code>wget</code> command is not part of
  Windows, but can be installed on Windows as part of Cygwin.
  <p>

  <p>
  You can add JVM arguments to the <code>java</code> command, such as the argument
  <code>-Xmx7G</code> that
  gives the slave 7 gigabytes of memory.
  </p>
  </dd>
</p>

<p>
By default, each slave that runs workers runs as many worker threads
as it has processors.&nbsp;  Running that many threads on the slave might
cause problems with some operating system.&nbsp;   The following JVM argument causes
each slave to run 2 threads:
<pre>
   -Dtlc2.tool.distributed.TLCWorker.threadCount=2
</pre>
(This JVM argument is only applicable for slaves and has no effect if passed to the master process).
</p>

<h3><a name="possible-problem"></a>A Possible Problem</h3>

The master-computer name you use in the instructions above for running
the workers is usually a name like <code>jones-home-laptop</code> or
<code>tla.msr-inria.inria.fr</code>.&nbsp;  However, some computers have
multiple network interfaces, with different IP addresses--for example,
<code>192.168.1.10</code> and <code>10.10.0.1</code>.&nbsp;  If the master
computer is such a computer, then it's possible that using this name
as the master-computer name in the instructions above will cause the
worker not to be able to communicate with the master because they are
using different IP addresses.&nbsp;  To solve this problem, choose one of
those IP addresses--say <code>192.168.1.10</code>.  Use that address
as the master-computer name in the instructions above for running the
workers, add the following  <A href="tlc-options-page.html#jvmargs">JVM argument</A>
to the model:

<pre>
   -Djava.rmi.server.hostname=192.168.1.10
</pre>

<!--  COMMENTED OUT
<h4>Using Multi-Core Worker Machines</h4>
Currently, workers are single threaded.&nbsp;  You can take advantage of
multi-core computers by running multiple workers on the same computer,
using one of the previous methods to start each of the workers.&nbsp;
The major disadvantage of doing this is that a separate copy of
the worker code is loaded into memory for each worker.
    END COMMENTED OUT -->

<a name="limitations"></a><h2>Limitations of Distributed Mode</h2>

When run in distributed mode, TLC cannot check liveness properties.
Nor does it use depth-first mode or simulation mode, even if one of
those modes is selected on the <a href="tlc-options-page.html">TLC Options Page</a>.&nbsp;

Coverage information is not provided.&nbsp; You should therefore check
a smaller model in ordinary non-distributed mode to make sure that the
specification specifies what you think it does.&nbsp;


<a name="help"></a><h2>Getting and Giving Help</h2>

You may want to run TLC in distributed mode with many workers.&nbsp;
(Preliminary tests suggest that linear speedup is possible even
with hundreds of workers.)&nbsp; Manually starting so many workers is
not practical.&nbsp; It is possible to implement scripts that can
automate the installation of the JRE and one of the two methods
described above for copying the <code>tla2tools.jar</code> file and
starting the workers.&nbsp; How this is done will depend on the
operating system and network configuration.&nbsp;
If you need help, try going to
the <A href="https://groups.google.com/forum/?fromgroups#!forum/tlaplus">TLA+ Google group</a>.

If you have successfully run TLC in distributed mode, please use that
Forum to tell others how you did it on your system.
<hr>
<!-- delete rest of line to comment out
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href="model-values.html"> Model Values and Symmetry </A></dd>
<dd> <a href="distributed-mode.html">Running TLC in Distributed Mode</a></dd>
</dl>
-->
<!-- delete rest of line to comment out -->
<a href = "overview-page.html">&uarr; Model Overview Page</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/RandomGenerator.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:38 PST by lamport
//      modified on Fri Jun 18 18:13:00 PDT 1999 by yuanyu

package tlc2.util;

import java.util.Random;

public class RandomGenerator extends Random {

  private long aril;

  public final static int[] primes =
  { 1277011, 1277021, 1277039, 1277041, 1277063, 1277069, 1277071, 1277083, 1277093,
    1277099, 1277113, 1277137, 1277147, 1277197, 1277207, 1277209, 1277233, 1277249,
    1277257, 1277267, 1277299, 1277321, 1277323, 1277357, 1277359, 1277369, 1277387,
    1277429, 1277449, 1277461, 1277477, 1277483, 1277491, 1277501, 1277543, 1277557,
    1277569, 1277593, 1277597, 1277621, 1277629, 1277651, 1277657, 1277677, 1277699,
    1277723, 1277729, 1277741, 1277743, 1277753, 1277761, 1277791, 1277803, 1277813,
    1277819, 1277833, 1277849, 1277863, 1277867, 1277879, 1277897, 1277909, 1277911,
    1277957, 1277971, 1277993, 1278007, 1278029, 1278031, 1278047, 1278097, 1278107,
    1278113, 1278131, 1278139, 1278163, 1278181, 1278191, 1278197, 1278203, 1278209,
    1278217, 1278227, 1278253, 1278287, 1278289, 1278323, 1278337, 1278341, 1278371,
    1278373, 1278379, 1278391, 1278397, 1278401, 1278419, 1278437, 1278439, 1278463,
    1278467, 1278479, 1278481, 1278493, 1278527, 1278551, 1278583, 1278601, 1278611,
    1278617, 1278619, 1278623, 1278631, 1278637, 1278659, 1278671, 1278701, 1278709,
    1278713, 1278721, 1278733, 1278769, 1278779, 1278787, 1278799, 1278803, 1278811,
    1278817, 1278839, 1278857, 1278881, 1278899, 1278911, 1278983, 1278997, 1279001,
    1279013, 1279021, 1279027, 1279039, 1279043, 1279081, 1279087, 1279093, 1279111,
    1279123, 1279133, 1279141, 1279163, 1279171, 1279177, 1279181, 1279183, 1279189,
    1279193, 1279211, 1279249, 1279253, 1279303, 1279307, 1279309, 1279319, 1279321,
    1279337, 1279357, 1279361, 1279417, 1279427, 1279457, 1279459, 1279483, 1279493,
    1279507, 1279511, 1279519, 1279541, 1279547, 1279549, 1279561, 1279583, 1279601,
    1279609, 1279627, 1279643, 1279657, 1279661, 1279667, 1279673, 1279679, 1279687,
    1279693, 1279703, 1279727, 1279753, 1279757, 1279787, 1279801, 1279807, 1279813,
    1279819, 1279823, 1279843, 1279847, 1279853, 1279871, 1279877, 1279907, 1279919,
    1279921, 1279931, 1279937, 1279961, 1279969, 1279997, 1280023, 1280101, 1280107,
    1280113, 1280119, 1280129, 1280131, 1280141, 1280159, 1280161, 1280173, 1280179,
    1280183, 1280221, 1280231, 1280267, 1280281, 1280291, 1280297, 1280309, 1280317,
    1280333, 1280371, 1280399, 1280401, 1280407, 1280417, 1280431, 1280453, 1280473,
    1280519, 1280537, 1280549, 1280561, 1280567, 1280597, 1280603, 1280623, 1280633,
    1280651, 1280659, 1280677, 1280693, 1280707, 1280737, 1280743, 1280759, 1280761,
    1280767, 1280789, 1280791, 1280803, 1280821, 1280833, 1280837, 1280857, 1280863,
    1280869, 1280887, 1280921, 1280947, 1280969, 1280987, 1280989, 1281029, 1281041,
    1281043, 1281047, 1281083, 1281089, 1281097, 1281101, 1281131, 1281149, 1281157,
    1281167, 1281187, 1281193, 1281211, 1281221, 1281229, 1281253, 1281257, 1281263,
    1281281, 1281283, 1281317, 1281331, 1281349, 1281367, 1281383, 1281389, 1281407,
    1281431, 1281433, 1281439, 1281451, 1281457, 1281463, 1281503, 1281521, 1281523,
    1281541, 1281547, 1281551, 1281563, 1281587, 1281649, 1281653, 1281667, 1281673,
    1281677, 1281691, 1281697, 1281703, 1281727, 1281739, 1281751, 1281773, 1281779,
    1281781, 1281799, 1281803, 1281809, 1281821, 1281823, 1281827, 1281853, 1281871,
    1281883, 1281899, 1281937, 1281941, 1281961, 1281971, 1281979, 1281983, 1282007,
    1282009, 1282031, 1282033, 1282051, 1282069, 1282079, 1282081, 1282093, 1282109,
    1282117, 1282121, 1282133, 1282153, 1282163, 1282187, 1282201, 1282213, 1282231,
    1282241, 1282261, 1282277, 1282279, 1282289, 1282297, 1282343, 1282349, 1282363,
    1282381, 1282387, 1282399, 1282417, 1282423, 1282427, 1282451, 1282469, 1282471,
    1282493, 1282499, 1282507, 1282511, 1282513, 1282517, 1282529, 1282543, 1282571,
    1282577, 1282597, 1282607, 1282613, 1282627, 1282637, 1282639, 1282649, 1282657,
    1282661, 1282681, 1282693, 1282703, 1282717, 1282739, 1282751, 1282763, 1282781,
    1282783, 1282807, 1282817, 1282867, 1282877, 1282903, 1282907, 1282909, 1282913,
    1282933, 1282943, 1282951, 1282961, 1282969, 1282993, 1283011, 1283017, 1283021,
    1283027, 1283063, 1283069, 1283083, 1283099, 1283111, 1283119, 1283129, 1283137,
    1283159, 1283167, 1283171, 1283173, 1283179, 1283207, 1283237, 1283297, 1283323,
    1283333, 1283339, 1283353, 1283383, 1283389, 1283417, 1283437, 1283441, 1283473,
    1283479, 1283509, 1283521, 1283537, 1283539, 1283543, 1283549, 1283563, 1283573,
    1283591, 1283603, 1283677, 1283683, 1283701, 1283707, 1283717, 1283719, 1283731,
    1283753, 1283759, 1283767, 1283771, 1283797, 1283831, 1283839, 1283873, 1283879,
    1283881, 1283897, 1283903, 1283939, 1283941, 1283957, 1283969, 1283981, 1283983,
    1284007, 1284037, 1284043, 1284047, 1284053, 1284083, 1284131, 1284169, 1284187,
    1284209, 1284211, 1284223, 1284263, 1284271, 1284287, 1284293, 1284301, 1284313,
    1284317, 1284329, 1284341, 1284373, 1284379, 1284383, 1284421, 1284427, 1284433,
    1284443, 1284467, 1284473, 1284487, 1284511, 1284523, 1284541, 1284551, 1284553,
    1284559, 1284583, 1284601, 1284617, 1284623, 1284631, 1284641, 1284659, 1284691,
    1284709, 1284713, 1284737, 1284739, 1284763, 1284769, 1284791, 1284793, 1284823,
    1284841, 1284847, 1284851, 1284863, 1284889, 1284901, 1284917, 1284931, 1284937,
    1284967, 1284971, 1284977, 1284991, 1285021, 1285049, 1285051, 1285057, 1285061,
    1285069, 1285099, 1285111, 1285117, 1285129, 1285139, 1285147, 1285159, 1285169,
    1285181, 1285199, 1285213, 1285223, 1285231, 1285237, 1285247, 1285259, 1285267,
    1285279, 1285283, 1285289, 1285301, 1285351, 1285381, 1285393, 1285397, 1285411,
    1285429, 1285441, 1285451, 1285469, 1285481, 1285507, 1285511, 1285513, 1285517,
    1285519, 1285547, 1285549, 1285553, 1285607, 1285619, 1285633, 1285649, 1285679,
    1285699, 1285703, 1285717, 1285741, 1285747, 1285759, 1285763, 1285777, 1285789,
    1285793, 1285799, 1285811, 1285813, 1285841, 1285847, 1285853, 1285859, 1285871,
    1285877, 1285891, 1285903, 1285913, 1285937, 1285943, 1285969, 1285981, 1285993,
    1286011, 1286017, 1286039, 1286071, 1286081, 1286093, 1286099, 1286107, 1286119,
    1286147, 1286149, 1286177, 1286189, 1286191, 1286209, 1286227, 1286239, 1286261,
    1286267, 1286269, 1286273, 1286287, 1286303, 1286323, 1286359, 1286371, 1286381,
    1286387, 1286399, 1286419, 1286447, 1286489, 1286491, 1286503, 1286513, 1286521,
    1286533, 1286557, 1286561, 1286569, 1286581, 1286587, 1286617, 1286629, 1286633,
    1286641, 1286647, 1286653, 1286657, 1286669, 1286683, 1286693, 1286707, 1286711,
    1286773, 1286777, 1286783, 1286797, 1286807, 1286819, 1286821, 1286833, 1286837,
    1286839, 1286843, 1286881, 1286939, 1286941, 1286953, 1286959, 1286969, 1286981,
    1286983, 1287007, 1287047, 1287059, 1287061, 1287067, 1287071, 1287101, 1287109,
    1287131, 1287133, 1287157, 1287163, 1287173, 1287179, 1287197, 1287199, 1287217,
    1287233, 1287239, 1287289, 1287323, 1287329, 1287343, 1287347, 1287353, 1287361,
    1287371, 1287373, 1287401, 1287431, 1287457, 1287467, 1287469, 1287479, 1287487,
    1287491, 1287499, 1287511, 1287541, 1287551, 1287553, 1287569, 1287589, 1287593,
    1287607, 1287613, 1287623, 1287661, 1287683, 1287691, 1287697, 1287707, 1287731,
    1287739, 1287743, 1287749, 1287751, 1287757, 1287761, 1287787, 1287799, 1287817,
    1287821, 1287829, 1287841, 1287857, 1287883, 1287887, 1287899, 1287917, 1287947,
    1287961, 1287967, 1287973, 1287983, 1287989, 1287997, 1288003, 1288009, 1288013,
    1288033, 1288037, 1288043, 1288051, 1288057, 1288061, 1288099, 1288103, 1288109,
    1288117, 1288163, 1288169, 1288171, 1288187, 1288193, 1288201, 1288213, 1288247,
    1288249, 1288291, 1288307, 1288337, 1288349, 1288361, 1288363, 1288367, 1288393,
    1288421, 1288423, 1288429, 1288439, 1288487, 1288513, 1288519, 1288531, 1288541,
    1288543, 1288559, 1288571, 1288597, 1288603, 1288607, 1288613, 1288643, 1288649,
    1288657, 1288691, 1288697, 1288699, 1288709, 1288711, 1288733, 1288769, 1288783,
    1288799, 1288817, 1288823, 1288829, 1288831, 1288843, 1288849, 1288853, 1288871,
    1288873, 1288877, 1288891, 1288919, 1288921, 1288933, 1288939, 1288951, 1288967,
    1288981, 1288993, 1288997, 1289003, 1289009, 1289027, 1289039, 1289053, 1289077,
    1289083, 1289111, 1289129, 1289149, 1289153, 1289159, 1289179, 1289213, 1289231,
    1289237, 1289261, 1289273, 1289287, 1289303, 1289329, 1289333, 1289341, 1289363,
    1289371, 1289381, 1289401, 1289411, 1289423, 1289429, 1289447, 1289459, 1289513,
    1289531, 1289537, 1289551, 1289557, 1289567, 1289593, 1289597, 1289599, 1289621,
    1289623, 1289627, 1289653, 1289657, 1289677, 1289711, 1289713, 1289731, 1289747,
    1289749, 1289753, 1289779, 1289789, 1289801, 1289803, 1289831, 1289839, 1289851,
    1289867, 1289881, 1289921, 1289927, 1289933, 1289963, 1289969, 1289971, 1290013,
    1290019, 1290031, 1290049, 1290077, 1290083, 1290109, 1290131, 1290143, 1290151,
    1290161, 1290167, 1290169, 1290173, 1290199, 1290203, 1290209, 1290257, 1290259,
    1290287, 1290293, 1290299, 1290319, 1290329, 1290371, 1290379, 1290427, 1290431,
    1290433, 1290439, 1290463, 1290467, 1290469, 1290491, 1290503, 1290533, 1290539,
    1290551, 1290563, 1290571, 1290581, 1290593, 1290607, 1290629, 1290631, 1290637,
    1290643, 1290649, 1290659, 1290673, 1290683, 1290719, 1290791, 1290811, 1290823,
    1290847, 1290853, 1290857, 1290869, 1290901, 1290907, 1290923, 1290937, 1290983,
    1291001, 1291007, 1291009, 1291019, 1291021, 1291063, 1291079, 1291111, 1291117,
    1291139, 1291153, 1291159, 1291163, 1291177, 1291193, 1291211, 1291217, 1291219,
    1291223, 1291229, 1291249, 1291271, 1291313, 1291321, 1291327, 1291343, 1291349,
    1291357, 1291369, 1291379, 1291387, 1291391, 1291421, 1291447, 1291453, 1291471,
    1291481, 1291483, 1291489, 1291501, 1291523, 1291547, 1291567, 1291579, 1291603,
    1291637, 1291669, 1291673, 1291691, 1291783, 1291793, 1291799, 1291817, 1291819,
    1291831, 1291861, 1291877, 1291883, 1291907, 1291909, 1291931, 1291957, 1291963,
    1291967, 1291991, 1291999, 1292009, 1292023, 1292029, 1292063, 1292069, 1292089,
    1292099, 1292113, 1292131, 1292141, 1292143, 1292149, 1292167, 1292177, 1292219,
    1292237, 1292243, 1292251, 1292257, 1292261, 1292281, 1292293, 1292309, 1292329,
    1292339, 1292353, 1292371, 1292383, 1292387, 1292419, 1292429, 1292441, 1292477,
    1292491, 1292503, 1292509, 1292539, 1292549, 1292563, 1292567, 1292579, 1292587,
    1292591, 1292593, 1292597, 1292609, 1292633, 1292639, 1292653, 1292657, 1292659,
    1292693, 1292701, 1292713, 1292717, 1292729, 1292737, 1292783, 1292789, 1292801,
    1292813, 1292831, 1292843, 1292857, 1292887, 1292927, 1292947, 1292953, 1292957,
    1292971, 1292983, 1292989, 1292999, 1293001, 1293011, 1293031, 1293077, 1293119,
    1293133, 1293137, 1293157, 1293169, 1293179, 1293199, 1293203, 1293233, 1293239,
    1293247, 1293251, 1293277, 1293283, 1293287, 1293307, 1293317, 1293319, 1293323,
    1293329, 1293361, 1293367, 1293373, 1293401, 1293419, 1293421, 1293433, 1293473,
    1293491, 1293493, 1293499, 1293529, 1293533, 1293541, 1293553, 1293559, 1293583,
    1293587, 1293613, 1293619, 1293647, 1293659, 1293701, 1293739, 1293757, 1293763,
    1293791, 1293797, 1293821, 1293829, 1293839, 1293841, 1293857, 1293869, 1293899,
    1293917, 1293923, 1293931, 1293947, 1293949, 1293961, 1293967, 1293977, 1293979,
    1293983, 1294019, 1294021, 1294031, 1294037, 1294039, 1294061, 1294081, 1294087,
    1294103, 1294121, 1294123, 1294129, 1294169, 1294177, 1294199, 1294201, 1294231,
    1294253, 1294273, 1294277, 1294301, 1294303, 1294309, 1294339, 1294351, 1294361,
    1294367, 1294369, 1294393, 1294399, 1294453, 1294459, 1294471, 1294477, 1294483,
    1294561, 1294571, 1294583, 1294597, 1294609, 1294621, 1294627, 1294633, 1294639,
    1294649, 1294651, 1294691, 1294721, 1294723, 1294729, 1294753, 1294757, 1294759,
    1294817, 1294823, 1294841, 1294849, 1294939, 1294957, 1294967, 1294973, 1294987,
    1294999, 1295003, 1295027, 1295033, 1295051, 1295057, 1295069, 1295071, 1295081,
    1295089, 1295113, 1295131, 1295137, 1295159, 1295183, 1295191, 1295201, 1295207,
    1295219, 1295221, 1295243, 1295263, 1295279, 1295293, 1295297, 1295299, 1295309,
    1295317, 1295321, 1295323, 1295339, 1295347, 1295369, 1295377, 1295387, 1295389,
    1295447, 1295473, 1295491, 1295501, 1295513, 1295533, 1295543, 1295549, 1295551,
    1295561, 1295563, 1295603, 1295611, 1295617, 1295639, 1295647, 1295653, 1295681,
    1295711, 1295717, 1295737, 1295741, 1295747, 1295761, 1295783, 1295803, 1295809,
    1295813, 1295839, 1295849, 1295867, 1295869, 1295873, 1295881, 1295947, 1295953 };

  public RandomGenerator() { this.aril = 0; }
  
  public RandomGenerator(long seed) {
    super(seed);
    this.aril = 0;
  }

  public synchronized void setSeed(long seed) {
    super.setSeed(seed);
    this.aril = 0;
  }

  protected synchronized int next(int bits) {
    // this.aril++;
    return super.next(bits);    
  }

  public void nextBytes(byte bytes[]) {
    // this.aril++;
    super.nextBytes(bytes);
  }

  public int nextInt() {
    // this.aril++;
    return super.nextInt();

  }

  public long nextLong() {
    // this.aril++;
    return super.nextLong();
  }

  public float nextFloat() {
    // this.aril++;
    return super.nextFloat();
  }

  public double nextDouble() {
    this.aril++;
    return super.nextDouble();
  }

  public synchronized double nextGaussian() {
    // this.aril++;
    return super.nextGaussian();
  }

  public long getAril() { return this.aril; }

  public void setSeed(long seed, long cnt) {
    this.setSeed(seed);
    while (cnt-- > 0) {
      this.nextDouble();
    }
  }

  public int nextPrime() {
    int index = primes.length;
    while (index == primes.length) {
      index = (int)Math.floor(this.nextDouble() * index);
    }
    return primes[index];
  }

	public static int nextPrime(Random r) {
		int index = primes.length;
		while (index == primes.length) {
			index = (int) Math.floor(r.nextDouble() * index);
		}
		return primes[index];
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/CToken.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS CToken                                                             *
*                                                                          *
* WARNING: THIS CLASS SEEMS TO HAVE BEEN OBTAINED BY MODIFYING THE TOKEN   *
* CLASS, AND THE COMMENTS WERE APPARENTLY NOT ALL MODIFIED APPROPRIATELY.  *
*                                                                          *
* A Token object represents a single token of the specification, where a   *
* token is either a single token of a TLA spec, a line of comment, or a    *
* line of the prolog or epilog.                                            *
*                                                                          *
* A Token object has the following fields:                                 *
*                                                                          *
*   String string : The actual input.                                      *
*   int column    : The column in the input line of its first              *
*                   character (counting from 0).                           *
*   int type      : The type of the token.  Possibilities are:             *
*                                                                          *
*   boolean isTLA : True if this token is to be interpreted as             *
*                   part of a TLA spec.                                    *
*                                                                          *
* The constructors are CToken() and CToken(string, column, type, isTLA).   *
*                                                                          *
* The methods are                                                          *
*                                                                          *
*   getWidth() : returns width of token in input.                          *
*   toString() : for debuggin                                              *
***************************************************************************/
package tla2tex;
import java.util.Vector;

public class CToken
  /*************************************************************************
  * This class defines the Token object, which is an element of a          *
  * tokenized specification.  It is expected that some token types may be  *
  * subclassed.  In particular, there will be a CommentToken class that    *
  * is a subclass of Token.  Every token of type COMMENT should belong to  *
  * this class.                                                            *
  *************************************************************************/
  { public String string;
      /*********************************************************************
      * The string of the token.  This is usually what the user has        *
      * typed, but it may also be something else.                          *
      *********************************************************************/

    public int column;
      /*********************************************************************
      * The column in which the first character of the token appears in    *
      * the input.                                                         *
      *********************************************************************/
      
    public boolean isTLA;
      /*********************************************************************
      * True if this token is to be interpreted as part of a TLA spec.     *
      *********************************************************************/

    public boolean isAmbiguous;
      /*********************************************************************
      * True if this token could be either a spec token or part of         *
      * ordinary text.                                                     *
      *********************************************************************/
      
    public int type ;
       /********************************************************************
       * The type of the token.  Here are the possibilities:               *
       ********************************************************************/
       public static final int BUILTIN = 1 ;
         /******************************************************************
         * A built-in token.                                               *
         ******************************************************************/

       public static final int NUMBER = 2 ;
         /******************************************************************
         * A number like "2" or "\O777".                                   *
         ******************************************************************/

       public static final int STRING = 3 ;
         /******************************************************************
         * A string like "foo".  In this type, the string field does not   *
         * contain the enclosing quotes.                                   *
         ******************************************************************/

       public static final int IDENT = 4 ;
         /******************************************************************
         * An identifier, such as foo_Bar.                                 *
         ******************************************************************/

       public static final int OTHER = 5 ;
         /******************************************************************
         * A comment.  This will be subclassed to include an additional    *
         * field containing the tokenization of the comment.               *
         ******************************************************************/
         
       public static final int REP_CHAR = 6 ;
         /******************************************************************
         * A sequence of repeated repeatChar characters.                   *
         ******************************************************************/

       public static final int LEFT_DQUOTE = 7 ;
         /******************************************************************
         * A left double-quote token.                                      *
         ******************************************************************/

       public static final int RIGHT_DQUOTE = 8 ;
         /******************************************************************
         * A right double-quote token.                                     *
         ******************************************************************/

       public static final int VERB = 9 ;
         /******************************************************************
         * A string that is to be typeset verbatim.                        *
         ******************************************************************/

       public static final int TEX = 10 ;
         /******************************************************************
         * A string that is to be typeset as TeX input.                    *
         ******************************************************************/

       public static final int NULL = 11 ;
         /******************************************************************
         * A special null token.                                           *
         ******************************************************************/

       public static final int PF_STEP = 12;
         /******************************************************************
         * This is a proof-step number, such as "<42>" or "<37>2a.".       *
         * It shouldn't make any difference, but the definitions of        *
         * PF_STEP in Token and CToken are made the same just in case.     *
         ******************************************************************/
      
    /***********************************************************************
    * Below are the methods for this object class, including the           *
    * constructor.                                                         *
    ***********************************************************************/
    public CToken(String str, int col, int typ, boolean tla, boolean amb)
      /*********************************************************************
      * A CToken constructor.                                              *
      *********************************************************************/
      { string = str ;
        column = col ;
        type   = typ ;
        isTLA  = tla ;
        isAmbiguous = amb ;
      }

    public CToken()
      /*********************************************************************
      * A default Token constructor, apparently needed for subclasses.     *
      *********************************************************************/
      { string = "" ;
        column = 0 ;
        type   = 0 ;
        isTLA  = false ;
      } ;

    public static CToken nullCToken = new CToken("", 0, NULL, false, false) ;
      /*********************************************************************
      * A special null CToken.                                             *
      *********************************************************************/
      
    public int getWidth() 
      /*********************************************************************
      * Returns a width, which is the number of columns the token spans    *
      * in the original input stream.                                      *
      *********************************************************************/
      { if (string == null) 
          {return 0;}
        else
          { if (type == STRING)
              { return string.length() + 2; }
          }
       return string.length();
      };      

    /***********************************************************************
    * The method FindPfStepCTokens replaces each sequence of three to five *
    * tokens created by a TokenizeComment method for something like        *
    * "<42>" or "<42>1a." into a single token of type PF_STEP.             *
    ***********************************************************************/
    static void FindPfStepCTokens(CToken[][] toks) {
      boolean lastIsTLA = false ;
      for (int k = 0 ; k < toks.length ; k++) 
        { CToken[] input = toks[k] ;
          Vector outputVec = new Vector(input.length) ;
          int i = 0 ;
          while (i < input.length)
           { if (   (i < input.length - 2)
                 && (input[i].string.equals("<"))
                 && (input[i+1].column == input[i].column + 1)
                 && (input[i+1].type == NUMBER)
                 && (input[i+2].string.equals(">"))
                 && (input[i+2].column == 
                         input[i+1].column + input[i+1].getWidth()) )
               { int numOfToks = 3 ;
                 String str = "<" + input[i+1].string + ">" ;
                 if (   (i < input.length - 3)
                     && (input[i+3].column == input[i+2].column + 1)
                     && (   (input[i+3].type == NUMBER)
                         || (input[i+3].type == IDENT)))
                   { str = str + input[i+3].string ;
                     numOfToks = 4;
                     if (   (i < input.length - 4)
                         && (input[i+4].column == 
                               input[i+3].column + input[i+3].getWidth())
                         && (input[i+4].string.equals(".")))
                       { str = str + "." ;
                         numOfToks = 5;
                       } ;
                   };
                 outputVec.addElement(new CToken(str,
                                                input[i].column,
                                                PF_STEP,
                                                input[i].isTLA,
                                                input[i].isAmbiguous) );
                 i = i + numOfToks;
               } // if
             else { outputVec.addElement(input[i]) ;
                    i = i+1 ;
                  } // else
           } ; // while
          if (outputVec.size() != input.length)
            { toks[k] = new CToken[outputVec.size()] ;
              for (i = 0; i < outputVec.size(); i++) 
                 { toks[k][i] = (CToken) outputVec.elementAt(i) ;
                 } ;
            }
        } // for k
      } 

    /***********************************************************************
    * The following defines a toString() method for printing a Token for   *
    * debugging.  To do a decent job, it splits it into reasonably-sized   *
    * lines, using the Misc.BreakLine method.                              *
    ***********************************************************************/
    public String mostOfString()
      /*********************************************************************
      * This returns everything in toString() except the final "]", so it  *
      * can be used by the toString() method of subclasses.                *
      *********************************************************************/
      { String typeName = "";
        switch (type) 
          { case BUILTIN      : typeName = "BUILTIN"       ; break ;
            case NUMBER       : typeName = "NUMBER"        ; break ;
            case STRING       : typeName = "STRING"        ; break ;
            case IDENT        : typeName = "IDENT"         ; break ;
            case OTHER        : typeName = "OTHER"         ; break ;
            case REP_CHAR     : typeName = "REP_CHAR"      ; break ;
            case LEFT_DQUOTE  : typeName = "LEFT_DQUOTE"   ; break ;
            case RIGHT_DQUOTE : typeName = "RIGHT_DQUOTE"  ; break ;
            case VERB         : typeName = "VERB"          ; break ;
            case TEX          : typeName = "TEX"           ; break ;
          } ;
        String str = "\"" + string + "\"";
        if (string == null) {str = "null";};

        String result =    "[str |-> "    + str
                         + ",\t type |-> "  + typeName
                         + ",\t col |-> "   + column
                         + ",\t width |-> " + getWidth() ;
        if (isTLA) 
          {result = result + ",\t isTLA |-> true";};
        if (isAmbiguous)
          {result = result + ",\t isAmbig |-> true";};
        return result; 
      };
      

    public String toString()
      /*********************************************************************
      * For debugging.                                                     *
      *********************************************************************/
      {  return Misc.BreakLine(mostOfString() + "]") ; };  

  }


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLADocumentSetupParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;

/**
 * Responsible for document setup
 * @author <NAME>
 * @version $Id$
 */
public class TLADocumentSetupParticipant implements IDocumentSetupParticipant
{
    public void setup(IDocument document) {
        if (document instanceof IDocumentExtension3) {
            IDocumentExtension3 extension3= (IDocumentExtension3) document;
            IDocumentPartitioner partitioner= new TLAFastPartitioner(TLAEditorActivator.getDefault().getTLAPartitionScanner(), TLAPartitionScanner.TLA_PARTITION_TYPES);
                                                // Changed from FastPartitioner by LL on 12 Aug 2012
            extension3.setDocumentPartitioner(TLAPartitionScanner.TLA_PARTITIONING, partitioner);
            partitioner.connect(document);
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/ValueExcept.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Wed  4 Jul 2007 at 17:31:51 PST by lamport
//      modified on Wed Jul 25 11:04:30 PDT 2001 by yuanyu

package tlc2.value.impl;

import tla2sany.semantic.FormalParamNode;

public class ValueExcept {
  public Value[] path;
  public Value value;
  public int idx;

  public ValueExcept(Value [] lhs, Value  rhs) {
    this.path = lhs;
    this.value = rhs;
    this.idx = 0;
  }
  
  public ValueExcept(ValueExcept ex, int idx) {
    this.path = ex.path;
    this.value = ex.value;
    this.idx = idx;
  }

  public final ValueExcept checkArg(FcnLambdaValue fcn) {
    Value  argv = this.path[idx];
    if (fcn.getParams().length() == 1) {
      if (!fcn.getParams().domains[0].member(argv)) return null;
    }
    else {
      TupleValue tval = (TupleValue)argv;
      Value [] argList = tval.elems;
      FormalParamNode[][] formals = fcn.getParams().formals;
      Value [] domains = fcn.getParams().domains;
      int argn = 0;
      for (int i = 0; i < fcn.getParams().formals.length; i++) {
        FormalParamNode[] formal = formals[i];
        for (int j = 0; j < formal.length; j++) {
          if (!domains[i].member(argList[argn++])) return null;
        }
      }
    }
    return this;
  }

  public final Value  current() { return this.path[this.idx]; }

  public final boolean isLast() {
    return this.idx == (this.path.length - 1);
  }

  public final String toString() {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < path.length; i++) {
      sb.append(".(" + this.idx + ")");
      sb.append(path[i]);
    }
    sb.append(" = ");
    sb.append(this.value);
    return sb.toString();
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/actions/OpenDeclarationInCurrentAction.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.actions;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;

public class OpenDeclarationInCurrentAction extends Action implements IHyperlink {
	private final IRegion location;
	private final String label;
	private final IRegion hyperlinkLocation;
	private final TLAEditor editor;

	public OpenDeclarationInCurrentAction(TLAEditor editor, IRegion targetLocation, String hyperlinkLabel, IRegion hyperlinkLocation) {
		super();
		this.editor = editor;
		this.location = targetLocation;
		this.label = hyperlinkLabel;
		this.hyperlinkLocation = hyperlinkLocation;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.jface.action.Action#run()
	 */
	public void run() {
		EditorUtil.setReturnFromOpenDecl();
		this.editor.selectAndReveal(location.getOffset(), location.getLength());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkRegion()
	 */
	public IRegion getHyperlinkRegion() {
		return this.hyperlinkLocation;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getHyperlinkText()
	 */
	public String getHyperlinkText() {
		return this.label;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#getTypeLabel()
	 */
	public String getTypeLabel() {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.hyperlink.IHyperlink#open()
	 */
	public void open() {
		run();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/tool/SpecEvent.java<|end_filename|>
package org.lamport.tla.toolbox.tool;

import org.lamport.tla.toolbox.spec.Spec;

/**
 * Specification life cycle event
 * 
 * 
 * <br>This class is not intended to be sub-classed
 * <br>This class is not intended to be instantiated by the tool developers
 * @author <NAME>
 * @version $Id$
 */
public class SpecEvent
{
    public static final int TYPE_CREATE = 1;
    public static final int TYPE_DELETE = 2;
    public static final int TYPE_RENAME = 4;
    public static final int TYPE_OPEN = 8;
    public static final int TYPE_CLOSE = 16;
    public static final int TYPE_PARSE = 32;  // This means that the spec has been parsed, not just a submodule.
    /**
     * All events
     */
    public static final int TYPE_ALL = TYPE_CREATE | TYPE_DELETE | TYPE_RENAME | TYPE_OPEN | TYPE_CLOSE | TYPE_PARSE;
    
    
    public static SpecEvent CLOSE(Spec spec) 
    {
        return new SpecEvent(spec, TYPE_CLOSE);
    }
    
    
    private int type;
    private Spec spec;
    
    /**
     * Construct the immutable SpecEvent object
     * @param type one of the constants
     * @param spec
     */
    public SpecEvent(Spec spec, int type)
    {
        this.spec = spec;
        this.type = type;
    }

    /**
     * Retrieves the type of the event 
     */
    public final int getType()
    {
        return type;
    }
    /**
     * Retrieves the spec
     */
    public final Spec getSpec()
    {
        return spec;
    }

    public String toString()
    {
        
        return ((spec != null) ? spec.getName() : "no spec") + " | " + getType(); 
    }
    
    
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/ParseAlgorithmException.java<|end_filename|>
package pcal.exception;

import pcal.AST;

/**
 * @author <NAME>
 * @version $Id$
 */
public class ParseAlgorithmException extends UnrecoverablePositionedException
{

    /**
     * @param message
     */
    public ParseAlgorithmException(String message)
    {
        super(message);
    }

    /**
     * @param string
     * @param elementAt
     */
    public ParseAlgorithmException(String message, AST elementAt)
    {
        super(message, elementAt);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/modelexplorer/ModelLabelProvider.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer;

import java.io.File;
import java.text.SimpleDateFormat;

import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.navigator.IDescriptionProvider;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer.ModelContentProvider.Group;

/**
 * Provides labels for the TLC models
 */
public class ModelLabelProvider extends LabelProvider implements IDescriptionProvider {
	private static final SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss");

	private Image modelImage = TLCUIActivator.getImageDescriptor("/icons/full/choice_sc_obj.gif").createImage();
	private Image modelNoError = TLCUIActivator.getImageDescriptor("/icons/full/model_no_error.gif").createImage();
	private Image modelWithError = TLCUIActivator.getImageDescriptor("/icons/full/model_with_error.gif").createImage();
	private Image modelCloudTLCRunning = TLCUIActivator.getImageDescriptor("/icons/full/thread_view.png").createImage();
	
	/**
	 * Retrieves model's image
	 */
	public Image getImage(final Object element) {
		if (element instanceof Group) {
			return modelImage;
		} else if (element instanceof Model) {
			final Model model = (Model) element;
			if (model.isSnapshot()) {
				if (model.isRunningRemotely()) {
					return modelCloudTLCRunning;
				}
				if (model.hasError()) {
					return modelWithError;
				}
				return modelNoError;
			} else {
				return modelImage;
			}
		}
		return super.getImage(element);
	}

	/**
	 * Retrieves model's label
	 */
	public String getText(final Object element) {
		if (element instanceof Model) {
			final Model model = (Model) element;
			if (model.isSnapshot()) {
				return sdf.format(model.getSnapshotTimeStamp());
			}
			final String modelName = model.getName();
			if (model.isStale()) {
				return modelName + " [ crashed ]";
			}
			if (model.isRunning()) {
				return modelName + " [ modelchecking ]";
			}
			return modelName;
		} else if (element instanceof Group) {
			return element.toString();
		}
		return null;
	}

	/**
	 * Description to be shown in the status bar
	 */
	public String getDescription(final Object element) {
		if (element instanceof Model) {
			final Model model = (Model) element;
			final String comments = model.getComments();
			if (comments.equals("")) {
				return getText(element) + " [ " + model.getFolder().getLocation().toFile() + File.separator + " ]";
			}
			return comments;
		}
		return null;
	}

	/**
	 * Dispose the image
	 */
	public void dispose() {
		if (modelImage != null) {
			modelImage.dispose();
		}
		modelImage = null;
		if (modelNoError != null) {
			modelNoError.dispose();
		}
		modelNoError = null;
		if (modelWithError != null) {
			modelWithError.dispose();
		}
		modelWithError = null;
		super.dispose();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/source/TagBasedTLCOutputIncrementalParserTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.easymock.EasyMock;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITypedRegion;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.lamport.tla.toolbox.tool.tlc.model.Model;

import tlc2.output.MP;
import util.TLAConstants;

public class TagBasedTLCOutputIncrementalParserTest {

	private List<String> input = new ArrayList<String>();
	
	@Before
	public void setUp() throws Exception {

		URL url = this.getClass().getClassLoader().getResource("files/ShortFindOp.out");
        InputStream inputStream = url.openConnection().getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		
		// Read the input fully here
		String line;
		while((line = reader.readLine()) != null) {
			input.add(line);
		}
		
		reader.close();
	}
	
	@Test
	public void testNoNewline() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);

		
		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2262:0 @!@!@");
		} catch (BadLocationException e) {
			return;
		}
		Assert.fail("Parser is expected to throw BLE on input without newline");
	}
	
	@Test
	public void testAddIncrementTLCHeader() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);

		
		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2262:0 @!@!@\n");
			parser.addIncrement("TLC2 Version 2.03 of 10 April 2011\n");
			parser.addIncrement("@!@!@ENDMSG 2262 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}
		
		parser.done();
	}

	@Test
	public void testAddIncrementState() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		
		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2217:4 @!@!@\n");
			parser.addIncrement("1: <Initial predicate>\n");
			parser.addIncrement("/\\ pos_f = defaultInitValue\n");
			parser.addIncrement("/\\ foundTokenSpecs = <<>>\n");
			parser.addIncrement("/\\ delim = defaultInitValue\n");
			parser.addIncrement("/\\ leftTok = defaultInitValue\n");
			parser.addIncrement("/\\ left_ = defaultInitValue\n");
			parser.addIncrement("/\\ returnVal = defaultInitValue\n");
			parser.addIncrement("/\\ delimLen_ = defaultInitValue\n");
			parser.addIncrement("/\\ line = ( 0 :> \";\" @@\n");
			parser.addIncrement("1 :> \";\" @@\n");
			parser.addIncrement("2 :> \";\" @@\n");
			parser.addIncrement("3 :> \";\" @@\n");
			parser.addIncrement("4 :> \";\" @@\n");
			parser.addIncrement("5 :> \";\" @@\n");
			parser.addIncrement("6 :> \";\" @@\n");
			parser.addIncrement("7 :> \";\" @@\n");
			parser.addIncrement("8 :> \";\" @@\n");
			parser.addIncrement("9 :> \";\" @@\n");
			parser.addIncrement("10 :> \"f\" @@\n");
			parser.addIncrement("11 :> \"(\" @@\n");
			parser.addIncrement("12 :> \"b\" @@\n");
			parser.addIncrement("13 :> \")\" @@\n");
			parser.addIncrement("14 :> \" \" @@\n");
			parser.addIncrement("15 :> \";\" @@\n");
			parser.addIncrement("16 :> \";\" @@\n");
			parser.addIncrement("17 :> \";\" @@\n");
			parser.addIncrement("18 :> \";\" @@\n");
			parser.addIncrement("19 :> \";\" @@\n");
			parser.addIncrement("20 :> \";\" @@\n");
			parser.addIncrement("21 :> \";\" @@\n");
			parser.addIncrement("22 :> \";\" @@\n");
			parser.addIncrement("23 :> \";\" @@\n");
			parser.addIncrement("24 :> \";\" )(\n");
			parser.addIncrement("/\\ jdelim_ = defaultInitValue\n");
			parser.addIncrement("/\\ i = defaultInitValue\n");
			parser.addIncrement("/\\ foundBangToken = defaultInitValue\n");
			parser.addIncrement("/\\ pos = defaultInitValue\n");
			parser.addIncrement("/\\ pc = \"Lbl_77\"\n");
			parser.addIncrement("/\\ ipos_ = defaultInitValue\n");
			parser.addIncrement("/\\ pos_fi = defaultInitValue\n");
			parser.addIncrement("/\\ pos_fin = defaultInitValue\n");
			parser.addIncrement("/\\ notDone = defaultInitValue\n");
			parser.addIncrement("/\\ pos_find = defaultInitValue\n");
			parser.addIncrement("/\\ temp1 = defaultInitValue\n");
			parser.addIncrement("/\\ temp2 = defaultInitValue\n");
			parser.addIncrement("/\\ temp3 = defaultInitValue\n");
			parser.addIncrement("/\\ delimLen = defaultInitValue\n");
			parser.addIncrement("/\\ rt = defaultInitValue\n");
			parser.addIncrement("/\\ notLastToken = FALSE\n");
			parser.addIncrement("/\\ ipos = defaultInitValue\n");
			parser.addIncrement("/\\ left = defaultInitValue\n");
			parser.addIncrement("/\\ token = <<>>\n");
			parser.addIncrement("/\\ rt_ = defaultInitValue\n");
			parser.addIncrement("/\\ rightTok = defaultInitValue\n");
			parser.addIncrement("/\\ jdelim = defaultInitValue\n");
			parser.addIncrement("/\\ tokIdx = defaultInitValue\n");
			parser.addIncrement("/\\ pos_ = defaultInitValue\n");
			parser.addIncrement("/\\ curPos = 11\n");
			parser.addIncrement("/\\ delim_ = defaultInitValue\n");
			parser.addIncrement("/\\ tokArray = defaultInitValue\n");
			parser.addIncrement("/\\ lastToken = FALSE\n");
			parser.addIncrement("/\\ currentToken = defaultInitValue\n");
			parser.addIncrement("/\\ stack = <<>>\n");
			parser.addIncrement("/\\ tempVar1 = defaultInitValue\n");
			parser.addIncrement("/\\ tempVar2 = defaultInitValue\n");
			parser.addIncrement("/\\ tempVar3 = defaultInitValue\n");
			parser.addIncrement("@!@!@ENDMSG 2217 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}
		
		parser.done();
	}

	@Test
	public void testAddPrintTStmt() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);
		
		// read in test input and feed it to the parser
		try {
			parser.addIncrement("UC\n");
			parser.addIncrement("@!@!@STARTMSG 2189:0 @!@!@\n");
			parser.addIncrement("C\n");
			parser.addIncrement("@!@!@ENDMSG 2189 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}
		
		parser.done();

		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all regions detected", 2, regions.size());

		// detected what kind of region?
		int none = 0;
		int out = 0;
		for (ITypedRegion region : regions) {
			if (region instanceof TLCRegion) {
				TLCRegion tlcRegion = (TLCRegion) region;
				switch (tlcRegion.getSeverity()) {
				case MP.NONE:
					none++;
				}
			} else {
				out++;
			}
		}
		Assert.assertEquals("Not all TLCRegions detected", 1, none);
		Assert.assertEquals("Not all non-TLCRegions detected", 1, out);
	}
	
	@Test
	public void testAddPrintTStmtFull() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2262:0 @!@!@\n");
			parser.addIncrement("TLC2 Version 2.03 of 10 March 2011\n");
			parser.addIncrement("@!@!@ENDMSG 2262 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2187:0 @!@!@\n");
			parser.addIncrement("Running in Model-Checking mode.\n");
			parser.addIncrement("@!@!@ENDMSG 2187 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2220:0 @!@!@\n");
			parser.addIncrement("Starting SANY...\n");
			parser.addIncrement("@!@!@ENDMSG 2220 @!@!@\n");
			parser.addIncrement(TLAConstants.LoggingAtoms.PARSING_FILE + " MC.tla\n");
			parser.addIncrement(TLAConstants.LoggingAtoms.PARSING_FILE + " Test.tla\n");
			parser.addIncrement(TLAConstants.LoggingAtoms.PARSING_FILE + " /toolbox/plugins/org.lamport.tla.toolbox_1.0.0/StandardModules/TLC.tla\n");
			parser.addIncrement(TLAConstants.LoggingAtoms.PARSING_FILE + " /tla/toolbox/plugins/org.lamport.tla.toolbox_1.0.0/StandardModules/Naturals.tla\n");
			parser.addIncrement(TLAConstants.LoggingAtoms.PARSING_FILE + " /tla/toolbox/plugins/org.lamport.tla.toolbox_1.0.0/StandardModules/Sequences.tla\n");
			parser.addIncrement("Semantic processing of module Naturals\n");
			parser.addIncrement("Semantic processing of module Sequences\n");
			parser.addIncrement("Semantic processing of module TLC\n");
			parser.addIncrement("Semantic processing of module Test\n");
			parser.addIncrement("Semantic processing of module MC\n");
			parser.addIncrement("@!@!@STARTMSG 2219:0 @!@!@\n");
			parser.addIncrement("SANY finished.\n");
			parser.addIncrement("@!@!@ENDMSG 2219 @!@!@\n");

			parser.addIncrement("@!@!@STARTMSG 2185:0 @!@!@\n");
			parser.addIncrement("S\n");
			parser.addIncrement("@!@!@ENDMSG 2185 @!@!@\n");

			parser.addIncrement("SomeUserContent\n");
			parser.addIncrement("<<\"$!@$!@$!@$!@$!\", 999>>\n");

			parser.addIncrement("@!@!@STARTMSG 2189:0 @!@!@\n");
			parser.addIncrement("C\n");
			parser.addIncrement("@!@!@ENDMSG 2189 @!@!@\n");

			parser.addIncrement("@!@!@STARTMSG 2190:0 @!@!@\n");
			parser.addIncrement("Finished computing initial states: 0 distinct states generated.\n");
			parser.addIncrement("@!@!@ENDMSG 2190 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2193:0 @!@!@\n");
			parser.addIncrement("Model checking completed. No error has been found.\n");
			parser.addIncrement("  Estimates of the probability that TLC did not check all reachable states\n");
			parser.addIncrement("  because two distinct states had the same fingerprint:\n");
			parser.addIncrement("  calculated (optimistic):  val = 0\n");
			parser.addIncrement("  based on the actual fingerprints:  val = 1.1E-19\n");
			parser.addIncrement("@!@!@ENDMSG 2193 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2200:0 @!@!@\n");
			parser.addIncrement("Progress(0) at 2011-07-21 10:14:49: 0 states generated, 0 distinct states found, 0 states left on queue.\n");
			parser.addIncrement("@!@!@ENDMSG 2200 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2199:0 @!@!@\n");
			parser.addIncrement("0 states generated, 0 distinct states found, 0 states left on queue.\n");
			parser.addIncrement("@!@!@ENDMSG 2199 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2194:0 @!@!@\n");
			parser.addIncrement("The depth of the complete state graph search is 0.\n");
			parser.addIncrement("@!@!@ENDMSG 2194 @!@!@\n");
			parser.addIncrement("@!@!@STARTMSG 2186:0 @!@!@\n");
			parser.addIncrement("Finished. (2011-07-21 10:14:49)\n");
			parser.addIncrement("@!@!@ENDMSG 2186 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}

		parser.done();

		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all regions detected", 14, regions.size());

		// detected what kind of region?
		int none = 0;
		int out = 0;
		for (ITypedRegion region : regions) {
			if (region instanceof TLCRegion) {
				TLCRegion tlcRegion = (TLCRegion) region;
				switch (tlcRegion.getSeverity()) {
				case MP.NONE:
					none++;
				}
			} else {
				out++;
			}
		}
		Assert.assertEquals("Not all TLCRegions detected", 12, none);
		Assert.assertEquals("Not all non-TLCRegions detected", 2, out);
	}

	@Test
	public void testAddOneLevelNesting() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2185:0 @!@!@\n");
			parser.addIncrement("someText\n");
			parser.addIncrement("@!@!@ENDMSG 2185 @!@!@\n");
			
			// <nested content>
			parser.addIncrement("@!@!@STARTMSG 2105:1 @!@!@\n");
			parser.addIncrement("0 level\n");

			// 1st level
			parser.addIncrement("@!@!@STARTMSG 2154:0 @!@!@\n");
			parser.addIncrement("1st level\n");
			parser.addIncrement("@!@!@ENDMSG 2154 @!@!@\n");
			
			parser.addIncrement("@!@!@ENDMSG 2105 @!@!@\n");
			// </nested content>
			
			parser.addIncrement("@!@!@STARTMSG 2186:0 @!@!@\n");
			parser.addIncrement("someText\n");
			parser.addIncrement("@!@!@ENDMSG 2186 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}

		parser.done();

		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all or too many regions detected", 3, regions.size());
	}

	@Test
	public void testAddTwoLevelNesting() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		// read in test input and feed it to the parser
		try {
			parser.addIncrement("@!@!@STARTMSG 2185:0 @!@!@\n");
			parser.addIncrement("someText\n");
			parser.addIncrement("@!@!@ENDMSG 2185 @!@!@\n");
			
			// <nested content>
			parser.addIncrement("@!@!@STARTMSG 2105:1 @!@!@\n");
			parser.addIncrement("0 level\n");

			// 1st level
			parser.addIncrement("@!@!@STARTMSG 2154:0 @!@!@\n");
			parser.addIncrement("1st level\n");
			
			// 2nd level
			parser.addIncrement("@!@!@STARTMSG 2178:0 @!@!@\n");
			parser.addIncrement("2nd level\n");
			parser.addIncrement("@!@!@ENDMSG 2178 @!@!@\n");

			parser.addIncrement("@!@!@ENDMSG 2154 @!@!@\n");
			
			parser.addIncrement("@!@!@ENDMSG 2105 @!@!@\n");
			// </nested content>
			
			parser.addIncrement("@!@!@STARTMSG 2186:0 @!@!@\n");
			parser.addIncrement("someText\n");
			parser.addIncrement("@!@!@ENDMSG 2186 @!@!@\n");
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}

		parser.done();

		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all or too many regions detected", 3, regions.size());
	}
	
	private class DummyModel extends Model {

		DummyModel() {
			super(EasyMock.createNiceMock(ILaunchConfiguration.class));
		}

		public String getName() {
			// Stop super from delegating to ILC
			return "TagBasedTLCOutputIncrementalParserTest";
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/module/SequencesTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.module;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.tool.EvalException;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.StringValue;
import tlc2.value.impl.TupleValue;
import tlc2.value.impl.Value;
import util.UniqueString;

public class SequencesTest {

	// Tail("abc") = "bc"
	// TLC can evaluate Tail("abc") because its value, "bc", can be written without
	// explicitly writing any character (characters would be 'b' and 'c', which do 
	// not exist in TLC).
	// https://github.com/tlaplus/tlaplus/issues/512#issuecomment-717602371
	
	@Test
	public void testTailString() {
		Value v = Sequences.Tail(new StringValue("abc"));
		assertTrue(v instanceof StringValue);
		assertEquals(UniqueString.of("bc"), ((StringValue) v).val);
	}

	// Head("a") = "a"[1]  and TLC cannot evaluate "a"[1]:
	// Error evaluating expression: '"abc"[1]'
	// A non-function (a string) was applied as a function.
	
	@Test
	public void testHeadString() {
		try {
			Sequences.Head(new StringValue("a"));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_ONE_ARGUMENT_ERROR, e.getErrorCode());
			return;
		}
		fail();
	}

	@Test
	public void testHeadStringEmpty() {
		try {
			Sequences.Head(new StringValue(""));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_ONE_ARGUMENT_ERROR, e.getErrorCode());
			return;
		}
		fail();
	}

	@Test
	public void testAppendString() {
		try {
			Sequences.Append(new StringValue(""), new StringValue("a"));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	@Test
	public void testAppendString2() {
		try {
			Sequences.Append(new StringValue("abc"), new StringValue("d"));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}
	@Test
	public void testAppendStringNonString() {
		try {
			Sequences.Append(new StringValue(""), IntValue.ValZero);
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	// "a" \o <<>> or <<>> \o "a" should produce an error. There is little value in
	// implementing it because concat would only work for the empty sequence.
	
	@Test
	public void testConcatStringToSeq() {
		try {
			Sequences.Concat(new TupleValue(new StringValue("abc")), new StringValue("d"));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	@Test
	public void testConcatSeqToString() {
		try {
			Sequences.Concat(new StringValue("abc"), new TupleValue(new StringValue("d")));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	// "a" \o "b" = "ab"
	
	@Test
	public void testConcatStringToString() {
		Value v = Sequences.Concat(new StringValue("abc"), (new StringValue("d")));
		assertTrue(v instanceof StringValue);
		assertEquals(UniqueString.of("abcd"), ((StringValue) v).val);
	}

	@Test
	public void testConcatIntToSeq() {
		try {
			Sequences.Concat(new TupleValue(new StringValue("abc")), IntValue.ValOne);
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	@Test
	public void testConcatSeqToInt() {
		try {
			Sequences.Concat(IntValue.ValOne, new TupleValue(new StringValue("d")));
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}

	// 1 \o 1 # 11
	
	@Test
	public void testConcatIntToInt() {
		try {
			Sequences.Concat(IntValue.ValOne, IntValue.ValOne);
		} catch (EvalException e) {
			assertEquals(EC.TLC_MODULE_EVALUATING, e.getErrorCode());
			return;
		}
		fail();
	}
	
	// SubSeq("abc", 1, 1) = "a"
	
	@Test
	public void testSubseq() {
		Value v = Sequences.SubSeq(new StringValue("abc"), IntValue.ValOne, IntValue.ValOne);
		assertTrue(v instanceof StringValue);
		assertEquals(UniqueString.of("a"), ((StringValue) v).val);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/perspective/InitialPerspective.java<|end_filename|>
package org.lamport.tla.toolbox.ui.perspective;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

/**
 * The initial perspective with actions for the spec manager and the welcome view
 * 
 * @author <NAME>
 * @version $Id$
 */
public class InitialPerspective implements IPerspectiveFactory
{

    public static final String ID = "org.lamport.tla.toolbox.ui.perspective.initial";

    public void createInitialLayout(IPageLayout layout)
    {
        layout.setEditorAreaVisible(false);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/Messages.java<|end_filename|>
package tlc2.output;

import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * Retrieves the TLC messages
 * @author <NAME>
 * @version $Id$
 */
public class Messages
{
    // full path to the message file
    private static final String BUNDLE_NAME = "tlc2.output.messages"; //$NON-NLS-1$

    private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);

    private Messages()
    {
    }

    /**
     * Retrieves the string by key
     * @param key 
     * @return
     */
    public static String getString(String key)
    {
        try
        {
            return RESOURCE_BUNDLE.getString(key);
        } catch (MissingResourceException e)
        {
            return '!' + key + '!';
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test-verify/tlc2/tool/queue/StateQueueJPFTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.queue;

import java.io.IOException;

import org.junit.Test;

import gov.nasa.jpf.util.test.TestJPF;
import tlc2.tool.TLCState;

public class StateQueueJPFTest extends TestJPF {

	public static void main(String[] args) {
		new StateQueueJPFTest().test();
	}
	
	@Test
	public void test() {
		if (verifyNoPropertyViolation()) {
			final StateQueue queue = new DummyStateQueue();
			final TLCState tlcState = new DummyTLCState();
			queue.enqueue(tlcState);
			
			Thread main = new Thread(new Runnable() {
				public void run() {
					queue.suspendAll();
					// critical section (taking a checkpoint)
					queue.resumeAll();
				}
			}, "Main");
			main.start();

			for (int i = 0; i < 3; i++) {
				Thread worker = new Thread(new Runnable() {
					public void run() {
						for (int i = 0; i < 3; i++) {
							TLCState state = queue.dequeue();
							if (state == null) {
								queue.finishAll();
								return;
							}
							queue.enqueue(tlcState);
						}
						queue.finishAll();
					}
				}, "Worker" + i);
				worker.start();
			}
		}
	}
	
	/*
	 * Dummy implementation of StateQueue with minimal functionality compared to
	 * DiskStateQueue or MemStateQueue. After all, we verify the abstract
	 * StateQueue and not the implementations (which should be done separately).
	 */
	private static class DummyStateQueue extends StateQueue {

		private TLCState state;

		void enqueueInner(TLCState state) {
			this.state = state;
		}

		TLCState dequeueInner() {
			return state;
		}

		TLCState peekInner() {
			return state;
		}

		public void beginChkpt() throws IOException {
			// checkpointing not being verified
		}

		public void commitChkpt() throws IOException {
			// checkpointing not being verified
		}

		public void recover() throws IOException {
			// checkpointing not being verified
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/nature/TLAParsingBuilder.java<|end_filename|>
package org.lamport.tla.toolbox.spec.nature;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.util.ChangedModulesGatheringDeltaVisitor;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.TLAMarkerHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * The parsing builder
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLAParsingBuilder extends IncrementalProjectBuilder
{
    public static final String BUILDER_ID = "toolbox.builder.TLAParserBuilder";

    /* (non-Javadoc)
     * @see org.eclipse.core.resources.IncrementalProjectBuilder#clean(org.eclipse.core.runtime.IProgressMonitor)
     */
    protected void clean(IProgressMonitor monitor) throws CoreException
    {
        Activator.getDefault().logDebug("Clean has been invoked");
        // clean removes all markers
        Spec spec = Activator.getSpecManager().getSpecLoaded();
        TLAMarkerHelper.removeProblemMarkers(spec.getProject(), monitor);

        /*
         * Forget the state
         */
        forgetLastBuiltState();

    }

    /* (non-Javadoc)
     * @see org.eclipse.core.resources.IncrementalProjectBuilder#build(int, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
     */
    protected IProject[] build(int kind, @SuppressWarnings("rawtypes") Map args, IProgressMonitor monitor) throws CoreException
    {
    	if (!Activator.isSpecManagerInstantiated()) {
			// Reschedule the build assuming the spec manager will be
			// instantiated later. The spec manager gets created by a workspace
			// job in Activator#start, thus belonging to the same job family 
    		// which is why it can run with us concurrently.
    		// Also see PCalDetectingBuilder.
			ResourcesPlugin.getWorkspace().build(kind, null);
            return null;
    	}
    	
        Spec spec = Activator.getSpecManager().getSpecLoaded();
        if (spec == null || getProject() != spec.getProject())
        {
            // skip the build calls on wrong projects (which are in WS, but not
            // a current spec)
            return null;
        }

        /*
         * In July 2013, LL discovered that the "Reparse specification on spec module save" preference 
         * had stopped working.  (Once upon a time it did work, but on examining the code, he saw no 
         * reason why it should ever have worked, so someone must have screwed up the code without leaving
         * a suitable trace.)  See the comments below made on 23 July 2013.
         * On 23 July 2013 LL added the second disjunct to the following `if' test. 
         * A tiny bit of testing reveals that this seems to have fixed the problem, and it seems that the worst
         * thing the change can do is reparse the entire spec when it shouldn't.  But since LL has no idea
         * how things actually work, he has little confidence in this change.
         */
        if (IncrementalProjectBuilder.FULL_BUILD == kind 
        		|| PreferenceStoreHelper.getInstancePreferenceStore().getBoolean(
                        IPreferenceConstants.I_PARSE_SPEC_ON_MODIFY))
        {
            monitor.beginTask("Invoking the SANY to re-parse the spec", IProgressMonitor.UNKNOWN);
            // explicit full build
            // on workspace start
            // or after clean
            ParserHelper.rebuildSpec(new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
            monitor.done();
        } else
        {
            // an incremental build
            // triggered manually or by resource modification
            IResourceDelta delta = getDelta(getProject());
            if (delta == null)
            {
                monitor.beginTask("Invoking the SANY to re-parse the spec", IProgressMonitor.UNKNOWN);
                // no increment found, run a full build
                ParserHelper.rebuildSpec(new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));

                monitor.done();
            } else
            {
                /*
                 * The delta is a tree, with a root element pointing to the
                 * containing project, and children indicating the files
                 * 
                 * Run a visitor on it in order to find out the changed files
                 */
                ChangedModulesGatheringDeltaVisitor moduleFinder = new ChangedModulesGatheringDeltaVisitor();
                delta.accept(moduleFinder);

                IResource rootFile = null;
                if (spec != null)
                {
                    rootFile = spec.getRootFile();
                }

                // LL comment added 23 July 2013:  Because of the change made above on this date,
                // control should never get here unless the next statement sets buildSpecOnly
                // to false.  However, the way this value is used, setting it true seems to cause
                // the spec to be rebuilt only when reparsing the root module, which should cause the
                // spec to be rebuilt anyway.  So I have no idea what the writer of this code thought
                // he was doing.
                boolean buildSpecOnly = PreferenceStoreHelper.getInstancePreferenceStore().getBoolean(
                        IPreferenceConstants.I_PARSE_SPEC_ON_MODIFY);

                // this preference is no longer an option
                // 22 Oct 2009
                /*boolean buildFiles = PreferenceStoreHelper
                		.getInstancePreferenceStore().getBoolean(
                				IPreferenceConstants.I_PARSE_FILES_ON_MODIFY);*/

                for (int i = 0; i < moduleFinder.getModules().size(); i++)
                {

                    IResource changedModule = (IResource) moduleFinder.getModules().get(i);

                    // call build on the changed resource
                    // if the file is a Root file it will call buildSpec
                    // otherwise buildModule is invoked
                    build(changedModule.getProjectRelativePath().toString(), rootFile, new SubProgressMonitor(monitor,
                            IProgressMonitor.UNKNOWN));

                    // get the modules to rebuild
                    List<String> modulesToRebuild = Activator.getModuleDependencyStorage().getListOfModulesToReparse(
                            changedModule.getProjectRelativePath().toString());

                    // iterate over modules and rebuild them
                    for (int j = 0; j < modulesToRebuild.size(); j++)
                    {
                        String moduleToBuild = (String) modulesToRebuild.get(j);

                        // root module found
                        if (buildSpecOnly && rootFile != null && rootFile.getName().equals(moduleToBuild))
                        {
                            build(moduleToBuild, rootFile, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
                            // for this build the root module is already found
                            // do not need to look for it again
                            buildSpecOnly = false;
                            continue;

                        } else
                        {
                            Activator.getDefault().logDebug("There is a root file, but the setting AUTO_BUILD_SPEC is off.");
                        }

                        // this is no longer an option for the user
                        /*if (buildFiles) {
                        	// call build on dependent resources
                        	// if the file is a Root file it will call buildSpec
                        	// otherwise buildModule is invoked
                        	build(moduleToBuild, rootFile,
                        			new SubProgressMonitor(monitor,
                        					IProgressMonitor.UNKNOWN));
                        } else {
                        	Activator
                        			.logDebug("There are dependent files, but the setting AUTO_BUILD_FILES is off.");
                        }*/
                    }
                }
            }
        }

        // since every project is one spec and we do not want to touch other
        // specs always return NULL!
        return null;
    }

    private void build(String moduleFileName, IResource rootFile, IProgressMonitor monitor)
    {
        // if the changed file is a root file - run the spec build
        if (rootFile != null && (rootFile.getName().equals(moduleFileName)))
        {
            monitor.beginTask("Invoking the SANY to re-parse the spec", IProgressMonitor.UNKNOWN);
            // this will rebuild the spec starting from root, and change the
            // spec status
            // still, we want to continue and keep the dependency information
            // about other files
            ParserHelper.rebuildSpec(new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));

            monitor.done();
        } else
        {
            // retrieve a resource
            IProject project = getProject();
            // get the file
            IResource moduleFile = project.getFile(moduleFileName);

            /*
             * At this point of time, all modules should have been linked if
             * (!moduleFile.exists()) { moduleFile =
             * ResourceHelper.getLinkedFile(project, moduleFileName, false); }
             */

            if (moduleFile == null || !moduleFile.exists())
            {
                throw new IllegalStateException("Resource not found during build: " + moduleFileName);
            }

            // never build derived resources
            if (!moduleFile.isDerived())
            {
                monitor.beginTask("Invoking SANY to re-parse a module " + moduleFileName, IProgressMonitor.UNKNOWN);
                // run the module build
                ParserHelper.rebuildModule(moduleFile, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));

                monitor.done();
            } else
            {
                Activator.getDefault().logDebug("Skipping resource: " + moduleFileName);
            }
        }

    }

    public static class OutOfBuildSpecModulesGatheringDeltaVisitor implements IResourceDeltaVisitor
    {
        Vector<IResource> modules = new Vector<IResource>();
        Hashtable<String, String> dependancyTable = null;
        Spec spec = null;

        public OutOfBuildSpecModulesGatheringDeltaVisitor()
        {
            // We cannot get the spec manager if it has not been instantiated
            // because this would trigger a resource change event, and this code
            // is being called within a resourceChanged method. Such an
            // infinite loop is not allowed.
            if (Activator.isSpecManagerInstantiated())
            {
                spec = Activator.getSpecManager().getSpecLoaded();
                if (spec != null)
                {
                    String specRootFileName = spec.getRootFile().getName();
                    List<String> dependancyList = Activator.getModuleDependencyStorage().getListOfExtendedModules(
                            specRootFileName);
                    dependancyTable = new Hashtable<String, String>(dependancyList.size());
                    dependancyTable.put(specRootFileName, specRootFileName);
                    Iterator<String> iterator = dependancyList.iterator();
                    while (iterator.hasNext())
                    {
                        String moduleName = iterator.next();
                        dependancyTable.put(moduleName, moduleName);
                    }
                }
            }
        }

        /**
         * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
         */
        public boolean visit(IResourceDelta delta) throws CoreException
        {
            IResource resource = delta.getResource();
            if (resource.exists() && IResource.FILE == resource.getType())
            {
                // a file found
                if (ResourceHelper.isModule(resource))
                {
                    // if the spec is null, this means that we are unable to get
                    // access to the spec manager
                    // because it has not yet been instantiatec. Instantiating
                    // it would trigger a resource change
                    // event which is not allowed
                    if (spec == null)
                    {
                        modules.add(resource);

                    } else if (spec.getRootFile().getParent().equals(resource.getParent()))
                    {
                        // we are only concerned with modules in the same
                        // directory as the root module because those are the
                        // only ones allowed to be a part of the spec
                        if (resource.getPersistentProperty(TLAParsingBuilderConstants.LAST_BUILT) == null)
                        {
                            if (spec.getStatus() < IParseConstants.PARSED && spec.getStatus() > IParseConstants.UNKNOWN)
                            {
                                // If the property has never been set, the
                                // resource has never been built. If the
                                // current status is parsed, then it cannot be
                                // relevant because it would have been built
                                // if it were relevant. If the status is
                                // unknown, it should remain unknown. In all
                                // other cases, it is possible that the resource
                                // is relevant but it is not known because there
                                // was not a successful parse. Conservatively we
                                // should consider it relevant.
                                modules.add(resource);
                            }
                        }
                        // If there current spec status is a problem status (see
                        // AdaptorFactory.isProblemStatus),
                        // then it is not known whether a given resource is
                        // relevant so all resources are considered
                        // relevant. Relevant resources are not necessarily in
                        // dependancy storage. Any resource that is
                        // out of build when the parse status is error is added to
                        // the list of modules.
                        else if (Long.parseLong(resource.getPersistentProperty(TLAParsingBuilderConstants.LAST_BUILT)) < resource
                                .getLocalTimeStamp()
                                && (dependancyTable.containsKey(resource.getName()) || (spec.getStatus() < IParseConstants.PARSED && spec
                                        .getStatus() > IParseConstants.UNPARSED)))
                        {
                            modules.add(resource);
                        }
                    }
                }
            }
            // we want the visitor to visit the whole tree
            return true;
        }

        /**
         * Retrieves found modules, or an empty list, if nothing found
         * 
         * @return a list with found modules
         */
        public List<IResource> getModules()
        {
            return modules;
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAColorProvider.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;

/**
 * Color provider
 * @author <NAME>
 */
public class TLAColorProvider {
	public static final String CONTENT_ASSIST_BACKGROUND_KEY = "content_assist.background";
	public static final String DEFAULT_TEXT_KEY = "all.default";
	public static final String PCAL_KEYWORD_KEY = "pcal.keyword";
	public static final String TLA_KEYWORD_KEY = "tla.keyword";
	public static final String TLA_MULTI_LINE_COMMENT_KEY = "tla.comment.multiline";
	public static final String TLA_SINGLE_LINE_COMMENT_KEY = "tla.comment.single";
	public static final String TLA_VALUE_KEY = "tla.value";
	
	
	/** Colors for a light theme **/
    private static final RGB CONTENT_ASSIST_BACKGROUND_RGB = new RGB(150, 150, 0);
    private static final RGB DEFAULT_RGB = new RGB(0, 0, 0);
    private static final RGB PCAL_KEYWORD_RGB = new RGB(175, 40, 10);
    private static final RGB TLA_KEYWORD_RGB = new RGB(128, 0, 128); 
	private static final RGB TLA_MULTI_LINE_COMMENT_RGB = new RGB(64, 64, 255);
    private static final RGB TLA_SINGLE_LINE_COMMENT_RGB = new RGB(0, 128, 64);
    private static final RGB TLA_VALUE_RGB = new RGB(0, 0, 255); 

	/** Colors for a dark theme **/
    private static final RGB CONTENT_ASSIST_BACKGROUND_DARK_RGB = new RGB(150, 150, 0);
    private static final RGB DEFAULT_DARK_RGB = new RGB(3, 167, 226);
    private static final RGB PCAL_KEYWORD_DARK_RGB = new RGB(245, 115, 67);
    private static final RGB TLA_KEYWORD_DARK_RGB = new RGB(172, 226, 156); 
	private static final RGB TLA_MULTI_LINE_COMMENT_DARK_RGB = new RGB(245, 235, 191);
    private static final RGB TLA_SINGLE_LINE_COMMENT_DARK_RGB = new RGB(0, 207, 104);
    private static final RGB TLA_VALUE_DARK_RGB = new RGB(226, 200, 99); 
    
    private static final Map<String, RGB> COLOR_KEY_RGB_MAP;
    
    static {
    	COLOR_KEY_RGB_MAP = new HashMap<>();
    	
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(CONTENT_ASSIST_BACKGROUND_KEY, false), CONTENT_ASSIST_BACKGROUND_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(DEFAULT_TEXT_KEY, false), DEFAULT_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(PCAL_KEYWORD_KEY, false), PCAL_KEYWORD_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_KEYWORD_KEY, false), TLA_KEYWORD_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_MULTI_LINE_COMMENT_KEY, false), TLA_MULTI_LINE_COMMENT_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_SINGLE_LINE_COMMENT_KEY, false), TLA_SINGLE_LINE_COMMENT_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_VALUE_KEY, false), TLA_VALUE_RGB);
    	
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(CONTENT_ASSIST_BACKGROUND_KEY, true), CONTENT_ASSIST_BACKGROUND_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(DEFAULT_TEXT_KEY, true), DEFAULT_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(PCAL_KEYWORD_KEY, true), PCAL_KEYWORD_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_KEYWORD_KEY, true), TLA_KEYWORD_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_MULTI_LINE_COMMENT_KEY, true), TLA_MULTI_LINE_COMMENT_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_SINGLE_LINE_COMMENT_KEY, true), TLA_SINGLE_LINE_COMMENT_DARK_RGB);
    	COLOR_KEY_RGB_MAP.put(getThemeContextualizedKey(TLA_VALUE_KEY, true), TLA_VALUE_DARK_RGB);
    }
    
    private static String getThemeContextualizedKey(final String key, final boolean themeIsDark) {
    	return key + "_" + (themeIsDark ? "dunkel" : "hell");
    }
    
    
    private final Map<String, Color> keyColorMap;
    
    public TLAColorProvider() {
    	keyColorMap = new HashMap<>();
    }

    /**
     * Release all of the color resources held onto by the receiver.
     */
	public void dispose() {
		final Iterator<Color> e = keyColorMap.values().iterator();
        while (e.hasNext()) {
            e.next().dispose();
        }
    }
    
    /**
     * Return the color that is stored in the color table under, referenced by the supplied key, and the current
     * Toolbox theme (dark v. light.)
     * 
     * @param colorKey one of the public static String keys defined in this class
     * @return the color, adjusted for current theme, or null if the key provided is unknown to this class
     */
	public Color getColor(final String colorKey) {
		final String key = getThemeContextualizedKey(colorKey, TLAEditorActivator.getDefault().isCurrentThemeDark());
		Color color = keyColorMap.get(key);
		if (color == null) {
			final RGB rgb = COLOR_KEY_RGB_MAP.get(key);
			if (rgb != null) {
				color = new Color(Display.getCurrent(), rgb);
				keyColorMap.put(key, color);
			}
		}
		return color;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/SynchronousDiskIntStack.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import java.io.File;

import tlc2.output.EC;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;

public class SynchronousDiskIntStack implements IntStack {

	public final static int BufSize = 8388608; // ~32mb
	private final static int BufSizeMax = BufSize << 5; // ~1024mb

	private final int bufSize;
	private final String filePrefix;
	
	private long size = 0L;
	private int index = 0;

	private int hiPool = 0;
	
	private int[] buf;

	public SynchronousDiskIntStack(String diskdir, String name) {
		this(diskdir, name, BufSize);
	}
	
	public SynchronousDiskIntStack(String diskdir, String name, int capacity) {
		// Hard-limit capacity to 1gb per page file
		capacity = Math.min(BufSizeMax, capacity);
		this.filePrefix = diskdir + FileUtil.separator + name;
		this.bufSize = capacity;
		this.buf = new int[capacity];
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#size()
	 */
	public long size() {
		return this.size;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#pushInt(int)
	 */
	public void pushInt(int x) {
		if (this.index == bufSize) {
			// flush to disk
			try {
				final File poolFile = new File(this.filePrefix + Integer.toString(this.hiPool));
				poolFile.deleteOnExit();
				final BufferedDataOutputStream bdos = FileUtil.newBdFOS(false, poolFile);
				final int len = buf.length;
				for (int i = 0; i < len; i++) {
					bdos.writeInt(buf[i]);
				}
				bdos.close();
				this.hiPool++;
				this.index = 0;
			} catch (Exception e) {
				Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES, new String[] { "stack", e.getMessage() });
			}
		}
		this.buf[this.index++] = x;
		this.size++;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#pushLong(long)
	 */
	public void pushLong(long x) {
		this.pushInt((int) (x & 0xFFFFFFFFL));
		this.pushInt((int) (x >>> 32));
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#popInt()
	 */
	public int popInt() {
		if (this.index == 0 && hasPool()) {
			// fill buffer
			try {
				final File poolFile = new File(this.filePrefix + Integer.toString(this.hiPool - 1));
				final BufferedDataInputStream bdis = FileUtil.newBdFIS(false, poolFile);
				final int len = buf.length;
				for (int i = 0; i < len; i++) {
					buf[i] = bdis.readInt();
				}
				bdis.close();
				this.hiPool--;
				this.index = len;
			} catch (Exception e) {
				Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES, new String[] { "stack", e.getMessage() });
			}
		}
		this.size--;
		return this.buf[--this.index];
	}
	
	private boolean hasPool() {
		return this.hiPool >= 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#popLong()
	 */
	public long popLong() {
		long high = this.popInt();
		long low = this.popInt();
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#reset()
	 */
	public void reset() {
		this.size = 0L;
		this.index = 0;

		this.hiPool = 0;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/queue/DummyTLCState.java<|end_filename|>
package tlc2.tool.queue;

import java.util.HashSet;
import java.util.Set;

import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.SymbolNode;
import tlc2.tool.StateVec;
import tlc2.tool.TLCState;
import tlc2.value.IValue;
import util.UniqueString;

@SuppressWarnings("serial")
public class DummyTLCState extends TLCState {

	private final long fp;

	public DummyTLCState() {
		uid = 0;
		TLCState.Empty = this;
		this.fp = 0L;
	}
	
	public DummyTLCState(long fp) {
		this.fp = fp;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#bind(util.UniqueString, tlc2.value.Value, tla2sany.semantic.SemanticNode)
	 */
	public TLCState bind(UniqueString name, IValue value) {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#bind(tla2sany.semantic.SymbolNode, tlc2.value.Value, tla2sany.semantic.SemanticNode)
	 */
	public TLCState bind(SymbolNode id, IValue value) {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#unbind(util.UniqueString)
	 */
	public TLCState unbind(UniqueString name) {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#lookup(util.UniqueString)
	 */
	public IValue lookup(UniqueString var) {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#containsKey(util.UniqueString)
	 */
	public boolean containsKey(UniqueString var) {
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#copy()
	 */
	public TLCState copy() {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#deepCopy()
	 */
	public TLCState deepCopy() {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#addToVec(tlc2.tool.StateVec)
	 */
	public StateVec addToVec(StateVec states) {
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#deepNormalize()
	 */
	public void deepNormalize() {
		
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#fingerPrint()
	 */
	public long fingerPrint() {
		return this.fp;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#allAssigned()
	 */
	public boolean allAssigned() {
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#getUnassigned()
	 */
	public final Set<OpDeclNode> getUnassigned() {
		return new HashSet<OpDeclNode>();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#createEmpty()
	 */
	public TLCState createEmpty() {
		return this;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#toString()
	 */
	public String toString() {
		return "Dummy#" + uid + ":" + fp;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.TLCState#toString(tlc2.tool.TLCState)
	 */
	public String toString(TLCState lastState) {
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jclouds/src/org/lamport/tla/toolbox/jcloud/AzureCloudTLCInstanceParameters.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.jcloud;

import java.io.File;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jclouds.ContextBuilder;

public class AzureCloudTLCInstanceParameters extends CloudTLCInstanceParameters {

	public AzureCloudTLCInstanceParameters(final String tlcParams, int numberOfWorkers) {
        super(tlcParams.trim(), numberOfWorkers);
	}
	
	// vm args

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaVMArgs()
	 */
	@Override
	public String getJavaVMArgs() {
		return System.getProperty("azure.vmargs", super.getJavaVMArgs("-Xmx96G -Xms96G"));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaWorkerVMArgs()
	 */
	@Override
	public String getJavaWorkerVMArgs() {
		return System.getProperty("azure.vmworkerargs",
				super.getJavaWorkerVMArgs("-Xmx32G -Xms32G -XX:MaxDirectMemorySize=64g"));
	}
	
	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getTLCParameters()
	 */
	@Override
	public String getTLCParameters() {
		return System.getProperty("azure.tlcparams", super.getTLCParameters(16));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getCloudProvier()
	 */
	@Override
	public String getCloudProvider() {
		return "azurecompute";
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getRegion()
	 */
	@Override
	public String getRegion() {
		return System.getProperty("azure.region", "us-east");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getImageId()
	 */
	@Override
	public String getImageId() {
		// 'azure vm image list eastus canonical' (manually lookup image release date
		// from output, note the extra digit after the date YYYYMMDD (below separated by
		// a dot) which appears to be a sequence number for the images on the given
		// date).
		// With azure-cli v2 (based on Python) extract date from 'az vm image list --all --publisher Canonical'.
		//   ... {
		// "offer": "UbuntuServer",
		// "publisher": "Canonical",
		// "sku": "18.04-LTS",
		// "urn": "Canonical:UbuntuServer:18.04-LTS:18.04.201902121",
		// "version": "18.04.201902121"
		// 	  }, ...
		// 
		return System.getProperty("azure.image", "b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-18_04-LTS-amd64-server-20190212.1-en-us-30GB");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getHardwareId()
	 */
	@Override
	public String getHardwareId() {
		// STANDARD_D14: 16 cores, 112GB
		return System.getProperty("azure.instanceType", "STANDARD_D14");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getIdentity()
	 */
	@Override
	public String getIdentity() {
		final String identity = System.getenv("AZURE_COMPUTE_IDENTITY");
		Assert.isNotNull(identity);
		return identity;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getCredentials()
	 */
	@Override
	public String getCredentials() {
		final String credential = System.getenv("AZURE_COMPUTE_CREDENTIALS");
		Assert.isNotNull(credential);
		return credential;
	}

	private String getSubscriptionId() {
		final String subscription = System.getenv("AZURE_COMPUTE_SUBSCRIPTION");
		Assert.isNotNull(subscription);
		return subscription;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#validateCredentials()
	 */
	@Override
	public IStatus validateCredentials() {
		final String credential = System.getenv("AZURE_COMPUTE_CREDENTIALS");
		final String identity = System.getenv("AZURE_COMPUTE_IDENTITY");
		final String subscription = System.getenv("AZURE_COMPUTE_SUBSCRIPTION");
		if (credential == null || identity == null || subscription == null) {
			return new Status(Status.ERROR, "org.lamport.tla.toolbox.jcloud",
					"Invalid credentials, please check the environment variables "
							+ "(AZURE_COMPUTE_CREDENTIALS & AZURE_COMPUTE_IDENTITY "
							+ "and AZURE_COMPUTE_SUBSCRIPTION) are correctly "
							+ "set up and picked up by the Toolbox."
							+ "\n\nPlease visit the Toolbox help and read section 4 "
							+ "of \"Cloud based distributed TLC\" on how to setup authentication.");
		}
		// Verify that the identity file exists.
		final File file = new File(identity);
		if (!file.exists()) {
			return new Status(Status.ERROR, "org.lamport.tla.toolbox.jcloud", String.format(
					"The file %s referenced by the AZURE_COMPUTE_IDENTITY environment variable does not exist.", file));
		}
		return Status.OK_STATUS;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#mungeBuilder(org.jclouds.ContextBuilder)
	 */
	@Override
	public void mungeBuilder(ContextBuilder builder) {
		builder.endpoint("https://management.core.windows.net/" + getSubscriptionId());
	}
	
	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getHostnameSetup()
	 */
	@Override
	public String getHostnameSetup() {
		// Append ".cloudapp.net" to automatically set hostname and add a mapping from
		// public ip (obtained via third party service ifconfig.co) to hostname in
	    // /etc/hosts. Results in FQDN being used my MailSender and thus less likely
		// to be classified or rejected as spam.
		// The suffix ".cloudapp.net" is something that might change on the Azure end in
		// the future. It will then break this statement (suffix can be found in portal).
		// It would also be nice for Azure to offer a public API to query the hostname
		// (similar to EC2CloudTLCInstanceParameters#getHostnameSetup.
		return "hostname \"$(hostname).cloudapp.net\" && echo \"$(curl -s ifconfig.co) $(hostname)\" >> /etc/hosts";
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/OpApplNodeWrapperTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.AbortException;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.xml.SymbolContext;
import tlc2.TLCGlobals;
import util.TestPrintStream;
import util.ToolIO;
import util.UniqueString;

public class OpApplNodeWrapperTest {

	@Before
	public void setup() {
		TLCGlobals.coverageInterval = 1;
		ToolIO.out = new TestPrintStream();
	}
	
	@Test
	public void testReportCoverage01() {
		final OpApplNodeWrapper root = new OpApplNodeWrapper();
		root.report();
		((TestPrintStream) ToolIO.out).assertEmpty();
		
		root.addChild(new OpApplNodeWrapper());
	}
	
	@Test
	public void testReportCoverage02() {
		final OpApplNodeWrapper root = new OpApplNodeWrapper();
		root.incInvocations(42);
		
		root.addChild(getNode(23));
		root.addChild(getNode(24));
		root.addChild(getNode(0)); // Not reported

		root.report();
		((TestPrintStream) ToolIO.out)
				.assertContains("  Unknown location: 42\n" + 
						"  |In module --TLA+ BUILTINS--: 23\n" + 
						"  |In module --TLA+ BUILTINS--: 24");
	}
	
	@Test
	public void testReportCoverage03() {
		final OpApplNodeWrapper root = new OpApplNodeWrapper();
		root.incInvocations(42);
		
		OpApplNodeWrapper childA = getNode(23);
		childA.addChild(getNode(546));
		root.addChild(childA);
		
		OpApplNodeWrapper childB = getNode(24);
		root.addChild(childB);
		childB.addChild(getNode(0)); // Not reported because 0
		
		OpApplNodeWrapper childC = getNode(0);
		root.addChild(childC); // Not reported

		childC.addChild(getNode(17)); // Must be reported despite C being 0
		
		root.report();
		((TestPrintStream) ToolIO.out)
				.assertContains("  Unknown location: 42\n" + 
						"  |In module --TLA+ BUILTINS--: 23\n" + 
						"  ||In module --TLA+ BUILTINS--: 546\n" + 
						"  |In module --TLA+ BUILTINS--: 24\n" + 
						"  |In module --TLA+ BUILTINS--: 17");
	}
	
	/*
  line 8, col 12 to line 8, col 21 of module A: 1
  |line 5, col 11 to line 5, col 49 of module A: 1
  ||line 5, col 31 to line 5, col 49 of module A: 131072
  ||line 5, col 20 to line 5, col 27 of module A: 131072
  |||line 5, col 27 to line 5, col 27 of module A: 1
  |line 8, col 16 to line 8, col 20 of module A: 1
	 */
	@Test
	public void testReportCoverage04() {
		final OpApplNodeWrapper root = new OpApplNodeWrapper();
		root.incInvocations(1);
		
		OpApplNodeWrapper childA = getNode(1);
		root.addChild(childA);
		
		childA.addChild(getNode(131072));
		
		OpApplNodeWrapper cChildA = getNode(131072);
		childA.addChild(cChildA);
		
		cChildA.addChild(getNode(1));
		
		OpApplNodeWrapper childB = getNode(1);
		root.addChild(childB);
		
		root.report();
		((TestPrintStream) ToolIO.out)
				.assertContains("  Unknown location: 1\n" + 
						"  |In module --TLA+ BUILTINS--: 1\n" + 
						"  ||In module --TLA+ BUILTINS--: 131072\n" + 
						"  ||In module --TLA+ BUILTINS--: 131072\n" + 
						"  |||In module --TLA+ BUILTINS--: 1\n" + 
						"  |In module --TLA+ BUILTINS--: 1");
	}
	
	// It is dummies all the way down...
	
	private OpApplNodeWrapper getNode(long count) {
		final SymbolNode sn = new DummySymbolNode(Long.toString(count));
		final OpApplNode node = new DummyOpApplNode(sn);
		return new OpApplNodeWrapper(node, count);
	}
	
	private static class DummySymbolNode extends SymbolNode {

		protected DummySymbolNode(String name) {
			super(1, SyntaxTreeNode.nullSTN, UniqueString.uniqueStringOf(name));
		}

		@Override
		public int getArity() {
			throw new UnsupportedOperationException("not implemented");
		}

		@Override
		public boolean isLocal() {
			throw new UnsupportedOperationException("not implemented");
		}

		@Override
		public boolean match(OpApplNode test, ModuleNode mn) throws AbortException {
			throw new UnsupportedOperationException("not implemented");
		}

		@Override
		protected Element getSymbolElement(Document doc, SymbolContext context) {
			throw new UnsupportedOperationException("not implemented");
		}

		@Override
		protected String getNodeRef() {
			throw new UnsupportedOperationException("not implemented");
		}
		
	}
	
	private static class DummyOpApplNode extends OpApplNode {

		public DummyOpApplNode(SymbolNode sn) {
			super(sn);
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/IntPair.java<|end_filename|>
/***************************************************************************
* CLASS IntPair                                                            *
*                                                                          *
* Having a procedure return a tuple of values is an obvious thing to do.   *
* After 40 years of programming-language design, one might have expected   *
* that any language that pretends to be slightly higher-level than         *
* assembly language would provide a simple way to do that.  But no such    *
* luck.  The only way I can figure out to write a procedure in Java that   *
* returns a tuple of values is to define a separate class of objects for   *
* each type of tuple one wants.  So, here's a class whose objects are      *
* pairs of ints.  More precisely, IntPair(a, b) is the constructor of      *
* object obj such that obj.one = a and obj.two = b.  (It would             *
* be nicer to name the fields "1st" and "2nd", but apparently Java isn't   *
* sophisticated enough to allow such esoteric field names, and "first"     *
* and "second" are too long.  I'm surprised it lets me call them "one"     *
* and "two" instead of requiring them to be called "zero" and "one".)      *
***************************************************************************/
package pcal;

public class IntPair
  { public int one = 0 ;
    public int two = 0 ;
    public IntPair(int a, int b)
     { one = a ; 
       two = b ;
     }

    /***********************************************************************
    * For debugging.                                                       *
    ***********************************************************************/
    public String toString()
     { return "(" + one + ", " + two + ")" ;
     }    
  }


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/FPSetStatistic.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;

public interface FPSetStatistic {

	/**
	 * @return the bucketsCapacity counting all allocated (used and unused) fp slots in the in-memory storage.
	 */
	public long getBucketCapacity();
	
	/**
	 * @return The allocated (used and unused) array length of the first level in-memory storage.
	 */
	public long getTblCapacity();

	/**
	 * @return the index.length
	 */
	public long getIndexCapacity();

	/**
	 * @return {@link DiskFPSet#getBucketCapacity()} + {@link DiskFPSet#getTblCapacity()} + {@link DiskFPSet#getIndexCapacity()}.
	 */
	public long getOverallCapacity();
	
	/**
	 * @return	Number of used slots in tbl by a bucket
	 * {@link DiskFPSet#getTblLoad()} <= {@link DiskFPSet#getTblCnt()}
	 */
	public long getTblLoad();
	
	/**
	 * @return the amount of fingerprints stored in memory. This is less or equal to {@link DiskFPSet#getTblCnt()} depending on if there collision buckets exist. 
	 */
	public long getTblCnt();
	
	/**
	 * @return the maximal amount of fingerprints stored in memory. 
	 */
	public long getMaxTblCnt();
	
	/**
	 * @return the amount of fingerprints stored on disk
	 */
	public long getFileCnt();
	
	/**
	 * @return the diskLookupCnt
	 */
	public long getDiskLookupCnt();

	/**
	 * @return the diskHitCnt
	 */
	public long getMemHitCnt();

	/**
	 * @return the diskHitCnt
	 */
	public long getDiskHitCnt();

	/**
	 * @return the diskWriteCnt
	 */
	public long getDiskWriteCnt();

	/**
	 * @return the diskSeekCnt
	 */
	public long getDiskSeekCnt();
	
	/**
	 * @return the diskSeekCache
	 */
	public long getDiskSeekCache();
	
	/**
	 * @return the growDiskMark
	 */
	public int getGrowDiskMark();
	
	/**
	 * @return the checkPointMark
	 */
	public int getCheckPointMark();
	
	/**
	 * @return The memory size of the {@link DiskFPSet}
	 */
	public long sizeof();
	
	/**
	 * @return Accumulated time it has taken to flush {@link FPSet} to disk
	 */
	public long getFlushTime();
	
	/**
	 * @return DiskFPSet#getLockCnt()
	 */
	public int getLockCnt();
	
	/**
	 * @see DiskFPSet#getReaderWriterCnt()
	 */
	public int getReaderWriterCnt();
	
	/**
	 * @return DiskFPSet#getLoadFactor();
	 */
	double getLoadFactor();

	/**
	 * @return DiskFPSet#forceFlush();
	 */
	void forceFlush();
	
	/**
	 * @see DiskFPSet#checkInvariant()
	 */
	boolean checkInvariant() throws IOException;
}


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/MultiThreadedOffHeapDiskFPSetTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.junit.Assert;

import tlc2.tool.fp.generator.PartitionedFingerPrintGenerator;

public class MultiThreadedOffHeapDiskFPSetTest extends MultiThreadedFPSetTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractFPSetTest#getFPSet(long)
	 */
	@Override
	protected FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws IOException {
		return new OffHeapDiskFPSet(new FPSetConfiguration(1.0d, OffHeapDiskFPSet.class.getName()));
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.MultiThreadedFPSetTest#testMaxFPSetSizePartitioned()
	 */
	@Override
	public void testMaxFPSetSizePartitioned()
			throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		final OffHeapDiskFPSet fpSet = (OffHeapDiskFPSet) doTest(PartitionedFingerPrintGenerator.class);
		Assert.assertEquals(0, fpSet.getBucketCapacity()); // bucket capacity is actually reprobe which expected to be zero.
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/ModulePropertiesHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.action.IAction;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * @author <NAME>
 * @version $Id$
 * @deprecated is not used for two reasons: because there
 *             are no module properties, and it doesn't
 *             need to be used if we add some because we're
 *             using the default handler.
 */
public class ModulePropertiesHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {

        IAction action = new PropertyDialogAction(UIHelper.getShellProvider(), UIHelper
                .getActiveEditorFileSelectionProvider());
        action.run();

        return null;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/TLAExprException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class TLAExprException extends UnrecoverableException
{

    /**
     * @param message
     */
    public TLAExprException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/Errors.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

/***************************************************************************
* Every Semantic node has an errors field that is an Errors object.  A     *
* SpecObj object also has a few different kinds of Errors objects.  Here   *
* are the relevant methods:                                                *
*                                                                          *
*    addWarning                                                            *
*    addError                                                              *
*    addAbort   : These methods add the indicated level of error.          *
*                                                                          *
*    isSuccess()                                                           *
*    isFailure() : Indicates if addError or addAbort was called.           *
*                                                                          *
*    getNumErrors()                                                        *
*    getNumAbortsAndErrors()                                               *
*    getNumMessages()        : Return approximately obvious values.        *
*                                                                          *
*    toString() : Returns all the errors as a single string.               *
***************************************************************************/
package tla2sany.semantic;

import tla2sany.st.Location;
import tla2sany.utilities.Vector;


public class Errors {

  private boolean succeed = true;

  private int    numAborts   = 0;
  private int    numErrors   = 0;
  private int    numWarnings = 0;

  private Vector warnings = new Vector();
  private Vector errors   = new Vector();
  private Vector aborts   = new Vector();

  /*************************************************************************
  * The following methods to return the warnings, errors, and aborts in a  *
  * sane way were added by LL on 12 May 2008.                              *
  *************************************************************************/
  public String[] getAborts()   { return StringVectortoStringArray(aborts) ; }
  public String[] getErrors()   { return StringVectortoStringArray(errors) ; }
  public String[] getWarnings() { return StringVectortoStringArray(warnings) ; }

  private String[] StringVectortoStringArray(Vector vec) {
    String[] retVal = new String[vec.size()] ;
    for (int i = 0 ; i < retVal.length; i++) {
      retVal[i] = (String) vec.elementAt(i) ;
     } ;
    return retVal;
   }

  public final void addWarning( Location loc, String str ) { 
    if (loc == null) loc = Location.nullLoc;

    int i;
    for (i = warnings.size()-1; i >= 0; i--) {
      if ( (loc.toString() + "\n\n" + str).equals( warnings.elementAt(i) ) ) break;
    }

    if ( i < 0) {
      warnings.addElement( loc.toString() + "\n\n"+ str );
      numWarnings++;
    }
  }


  public final void addError(Location loc, String str) {
    if (loc == null) loc = Location.nullLoc;

    int i;
    for (i = errors.size()-1; i >= 0; i--) {
      if ( (loc.toString() + "\n\n" + str).equals( errors.elementAt(i) ) )  break;
    }

    if ( i < 0) {
      errors.addElement( loc.toString() + "\n\n"+ str );
      numErrors++;
    }
    succeed = false;

  }
  

  /**
   * 
   * @param loc
   * @param str
   * @param abort throw an abort exception iff true 
   * @throws AbortException
   */
  public final void addAbort(Location loc, String str, boolean abort) throws AbortException {
    String errMsg = loc.toString() + "\n\n" + str;
    int i;
    for (i = aborts.size()-1; i >= 0; i--) {
      if (errMsg.equals(aborts.elementAt(i))) break;
    }
    if (i < 0) {
      aborts.addElement(errMsg);
      numAborts++;
    }
    succeed = false;

    if (abort){
      // System.out.println(this.toString());
      throw new AbortException(); 
    }
  }

  public final void addAbort(Location loc, String str ) throws AbortException {
    addAbort(loc, str, true);
  }


  public final void addAbort(String str, boolean abort) throws AbortException {
    addAbort(Location.nullLoc, str, abort);
  }


  public final void addAbort(String str) throws AbortException {
    addAbort(Location.nullLoc, str, true);
  }

  public final boolean isSuccess()             { return succeed; }

  public final boolean isFailure()             { return !succeed; }

  public final int     getNumErrors()          { return numErrors; }

  public final int     getNumAbortsAndErrors() { return numAborts + numErrors; }

  public final int     getNumMessages()        { return numAborts + numErrors + numWarnings; }

  public final String  toString()  { 
    StringBuffer ret = new StringBuffer("");

    ret.append((numAborts > 0) ? "*** Abort messages: " + numAborts + "\n\n" : "");
    for (int i = 0; i < aborts.size(); i++)   {
      ret.append(aborts.elementAt(i) + "\n\n\n");
    }

    ret.append((numErrors > 0) ? "*** Errors: " + numErrors + "\n\n" : "");
    for (int i = 0; i < errors.size(); i++)   {
      ret.append(errors.elementAt(i) + "\n\n\n");
    }

    ret.append((numWarnings > 0) ? "*** Warnings: " + numWarnings + "\n\n" : "");
    for (int i = 0; i < warnings.size(); i++) {
      ret.append(warnings.elementAt(i) + "\n\n\n");
    }

    return ret.toString();
  }
	    
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/FindAlignments.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
//
// This is the version of FindAlignments modified to be consistent
// with the versions of TokenizeSpec, BuiltInSymbols, etc. that have
// been modified to handle PlusCal, but with no special PlusCal alignments
// added.  It is also being modified to add a special rule for 
// aligning labels -- or more precisely, aligning tokens that
// follow labels with other tokens.

/***************************************************************************
* CLASS FindAlignments                                                     *
*                                                                          *
* Contains the one public method                                           *
*                                                                          *
*    public static void FindAlignments(Token[][] spec)                     *
*                                                                          *
* that sets the aboveAlign, belowAlign, and isAlignmentPoint fields for    *
* all tokens in the tokenized spec spec--except for NULL and MULTI         *
* comment tokens, for which the aboveAlign field is set by                 *
* CommentToken.processComments.  (This method should be called after       *
* CommentToken.processComments.)                                           *
*                                                                          *
* There are six kinds of alignments, illustrated by the following          *
* example:                                                                 *
*                                                                          *
*    Alignment Type         Tokens so aligned                              *
*    --------------         -----------------                              *
*    FirstNonLeftComment   foo, x, + , /\ , y/comment r, u/comment k       *
*                                           ^^^^^^^^^^^                    *
*                                I think this should be +/comment r        *
*    LeftComment           comments j                                      *
*    CommentInner          comments p                                      *
*    InfixInner            ==, => , >                                      *
*    AfterInfixInner       m, c,                                           *
*    InfixArg              a, z/z, y/z                                     *
*                                                                          *
*             foo == LET x == /\ a  =>  m * n >  c                         *
*             |   |      | |  |  |  |   |     |  |                         *
*    (* j *)  |   |      | |  /\ a  =>  m / q >  c  (* p *)                *
*    |        |   |      | |                        |                      *
*    (* j *)  |   |      x ==   z                   |                      *
*             |   |             |                   |                      *
*             |   |           + z                   \* p                   *
*             |   |           | |                   |                      *
*             |   |           | |                   (* p *)                *
*             |   |           | |                   |                      *
*             |   |           + y                   (* p *)                *
*             |   |           |                                            *
*             |   |           \* r                                         *
*             |   |                                                        *
*             foo ==                                                       *
*              |                                                           *
*              (* k *)                                                     *
*              |                                                           *
*              u + v                                                       *
*                                                                          *
* For InfixInner and CommentInner alignment, a token's belowAlign          *
* field points to the token directly below it with which it is             *
* aligned.                                                                 *
*                                                                          *
* For all alignment types, if a token t1 is aligned with a token           *
* t2 above it, then t1.aboveAlign points to:                               *
*                                                                          *
*   IF t2 has no aboveAlign pointer THEN t2                                *
*                                   ELSE t2.abovealign.                    *
*                                                                          *
* Thus, in the example above, the aboveAlign pointer for all the p         *
* comments point to the first p comment.                                   *
*                                                                          *
* To define the types of alignment, we use the following definitions:      *
*                                                                          *
* - A LEFT-COMMENT is a comment that is the first token on its line but    *
*   not the last token on its line.  (The comments (* j *) in the          *
*   example are left-comments.)  For all the types of alignment except     *
*   CommentInner, left-comments are treated as if they didn't exist.       *
*                                                                          *
* - A RIGHT-COMMENT is a comment that is the last token on its line.       *
*                                                                          *
* Any comment other than a left-comment or a right-comment is treated      *
* like any other non-built-in token.  We also define:                      *
*                                                                          *
* - The COVERING TOKEN of a token t is the right-most token ct that        *
*   covers t on the last line (one with biggest line number) containing    *
*   a token that covers t, where a token t1 COVERS a token t2 if t1        *
*   lies on an earlier line than t2 and t1.column \leq t2.column.          *
*   However, if there is a DASH between ct and t, or                       *
*   on the same line as ct, then t has no covering token.                  *
*   (This definition has two versions, depending on whether or not         *
*   left-comments are ignored.)                                            *
*                                                                          *
* - The BLOCKING TOKEN of a token t is the left-most token s with          *
*   s.column \geq t.column on the last line before t's line containing     *
*   such a non-left-comment token s.                                       *
*                                                                          *
* Here are the descriptions of the different types of alignment.           *
*                                                                          *
*                                                                          *
* CommentInner:                                                            *
*    Token t at position pos is CommentInner above-aligned with its        *
*    blocking token bt at position bpos iff:                               *
*       /\ t is a right-comment                                            *
*       /\ bt is a right-comment                                           *
*       /\ t.column = bt.column                                            *
*       /\ \/ bt is not above-aligned with anything                        *
*          \/ bt is CommentInner aligned with a token above it             *
*                                                                          *
* FirstNonLeftComment                                                      *
*    If t is the first token on a line that is not a left-comment, and is  *
*    not a right-comment that is CommentInner aligned with a token above   *
*    it, then t is FirstNonLeftComment aligned with its covering token.    *
*                                                                          *
* LeftComment:                                                             *
*    If t is a left-comment token, then it is LeftComment aligned          *
*    with its covering token (where left-comments are visible).            *
*                                                                          *
* InfixInner:                                                              *
*    Token t at position pos is InfixInner aligned with its covering       *
*    token ct at position cpos iff t is not FirstNonLeftComment aligned,   *
*    and both t and ct are built-in symbols with the same nonzero alignment  *
*    class.  (The name InfixInner is misleading because non-infix symbols  *
*    like ":" get aligned by this mechanism.)                              *
*                                                                          *
* AfterInfixInner:                                                         *
*    Token t is After InfixInner aligned with the token above it iff       *
*                                                                          *
*       LET lt  == the token to the left of t                              *
*           alt == the token at position lt.aboveAlign                     *
*           at  == the token to the right of alt                           *
*       IN  /\ t is not the first token on the line                        *
*           /\ lt is InnerAligned with token alt above it                  *
*           /\ alt is not the last token on its line.                      *
*           /\ at is the covering token of t                               *
*           /\ t.column = at.column                                        *
*           /\ at is not a comment                                         *
*    (The name AfterInfixInner means "after InfixInner alignment".         *
*    Remember that some non-infix symbols get InfixInner aligned.)         *
*                                                                          *
* InfixArg:                                                                *
*    Token t is InfixArg aligned with its covering token ct iff:           *
*       LET lt == the token to the left of t                               *
*           alt == the token at position lt.aboveAlign                     *
*       IN  /\ t is not the first token on the line                        *
*           /\ lt is the first non-left-comment token                      *
*           /\ lt is an infix operator                                     *
*           /\ lt is not InfixInner aligned with any token above it.       *
*           /\ t.column = ct.column                                        *
*           /\ alt is the token to the left of ct                          *
*           /\ lt is either aligned with or lies entirely to the           *
*              right of alt.                                               *
*                                                                          *
*   Note: The large number of conditions are an attempt to rule            *
*   out spurious alignments.                                               *
* ----------------------------------------------------------------------   *
*                                                                          *
* PlusCal Alignment                                                        *
* -----------------                                                        *
*                                                                          *
* The following rule is added for PlusCal.                                 *
*                                                                          *
* Define a token t to be a FIRST NON-LABEL if either                       *
*     (a) it is the first token on the line, or                            *
*     (b) it is the 2nd token on its line and the first token on           *
*         the line is a label.                                             *
*                                                                          *
* AfterLabel:                                                              *
*   A token t is AfterLabel aligned with a token ta iff:                   *
*     /\ t is a first non-label that is the 2nd token on its line          *
*     /\ t and ta are left-aligned                                         *
*     /\ there is no line between t and ta containing any token            *
*        to the left of t other than a label that is the line's            *
*        first token.                                                      *
*     /\ \/ ta is a first non-label                                        *
*        \/ /\ ta is above t                                               *
*           /\ \/ ta is the first token on the line                        *
*              \/ the token to the left of ta is a label or                *
*                 a PlusCal symbol                                         *
*                                                                          *
* Here's an example of AfterLabel alignment.  Token b and all the x        *
* tokens are AfterLabel aligned with token A. Tokens A and B and all the   *
* other x tokens are also AfterLabel aligned with the first and last x     *
* tokens.                                                                  *
*                                                                          *
*            { B                                                           *
*          l:  x                                                           *
*          m:    z                                                         *
*              x                                                           *
*          l:  A                                                           *
*                z                                                         *
*              x                                                           *
*        l:    x                                                           *
*            } z                                                           *
*                                                                          *
* Note that B is the only token whose alignment is due to the second       *
* disjunction of the last conjunction.  That disjunct is designed to try   *
* to rule out bogus alignments such as the alignment of the y's with the   *
* 0 in                                                                     *
*                                                                          *
*     if (x = 0) {                                                         *
*       lab:  y := 1;                                                      *
*       lab:  y := 2  }                                                    *
*                                                                          *
* while aligning the the y's in                                            *
*                                                                          *
*      if (x = 0) {     y := 0;                                            *
*                  lab: y := 1;                                            *
*                  lab: y := 2  }                                          *
*                                                                          *           
* and in                                                                   *
*                                                                          *
*      if (x = 0) { y := 0;                                                *
*   lab:            y := 1;                                                *
*   lab:            y := 2  }                                              *
*                                                                          *
* ----------------------------------------------------------------------   *
*                                                                          *
* Note: A possible addition is a special case to recognize alignments      *
* after a comma, as in                                                     *
*                                                                          *
*        <<abcdef,  ghi + 7, jklmn>>                                       *
*                   |        |                                             *
*        <<a,       bc,      def>>                                         *
*                                                                          *
* However, that should be done only if there's a clear intention to align  *
* them--as evidenced here by the extra spaces between the "a,", the "cb,"  *
* and the "def".  Otherwise, there would be too many chance alignments.    *
***************************************************************************/
package tla2tex;

public class FindAlignments
{ public static void FindAlignments(Token[][] spec)
    { setSubscriptField(spec) ;
        /*******************************************************************
        * Set the subscript fields of the tokens.                          *
        *******************************************************************/
      int line = 0 ;
        
      /*********************************************************************
      * Skip all lines beginning with a prolog token.  This means that if  *
      * the module begins on the same line as a prolog token, then the     *
      * first line of the spec is ignored for alignment.  Tant pis!        *
      *********************************************************************/
      boolean inProlog = true ;
      while (inProlog && (line < spec.length))
       { if (    (spec[line].length > 0)
              && (spec[line][0].type != Token.PROLOG))
           { inProlog = false;}
         else
           { line = line + 1;}
       };
      
      /*********************************************************************
      * Set aboveAlign and belowAlign "pointers".                          *
      *********************************************************************/
      while (line < spec.length)
       { int item = 0 ;
         boolean prevInfixInner = false ;
           /****************************************************************
           * True iff the previous item on the line was InfixInner         *
           * aligned.                                                      *
           ****************************************************************/
         while (item < spec[line].length)
          { 
            /***************************************************************
            * Set token, pos to the current token and its position.        *
            ***************************************************************/
            Position pos = new Position(line, item) ;
            Token    token = spec[line][item] ;

            if (! token.subscript)
             {/*************************************************************
              * Do not align subscript tokens.                             *
              *************************************************************/
              if (isRightComment(spec, pos))
              { /***********************************************************
                * This is a RightComment.  First check if it should be     *
                * CommentInner aligned.  If not, check if it should be     *
                * FirstNonLeftComment aligned.                             *
                ***********************************************************/

                /***********************************************************
                * Set btoken, bpos to the blocking token of `token' and    *
                * its position.                                            *
                ***********************************************************/
                Position bpos   = blockingPosition(spec, pos);              
                Token    btoken =  null ;
                if (bpos.line != -1) {btoken = bpos.toToken(spec);};
                
                /***********************************************************
                * Set ctok to be a CommentToken alias for token.           *
                ***********************************************************/
                CommentToken ctok = (CommentToken) token ;
                if (   (ctok.subtype == CommentToken.MULTI)
                    || (ctok.subtype == CommentToken.NULL))
                 { /********************************************************
                   * This is the continuation of a multi-column comment.   *
                   ********************************************************/
                   Debug.Assert(   (btoken != null) 
                                && (btoken.type == Token.COMMENT),
                      "Bad blocking token for a MULTI or NULL token");
                   
                   /********************************************************
                   * Set token's aboveAlign to point to the BEGIN_MULTI    *
                   * token beginning the commnet.                          *
                   ********************************************************/
                   if ( ((CommentToken) btoken).subtype 
                            == CommentToken.BEGIN_MULTI)
                     { token.aboveAlign = bpos ; }
                   else
                     { token.aboveAlign = btoken.aboveAlign ; };

                   /********************************************************
                   * Make the blocking token's belowAlign pointer point    *
                   * to token.                                             *
                   ********************************************************/
                   btoken.belowAlign = pos ;
                 } // END then OF if  if ((ctok.subtype == .. ))
                else
                 { /********************************************************
                   * This is not the continuation of a multi-line          *
                   * comment.  Try to CommentInner align it.               *
                   ********************************************************/

                   if (   (bpos.line != -1)
                       && isRightComment(spec, bpos)
                       && (btoken.column == token.column)
                       && (   (   (btoken.aboveAlign.line == -1)
                               && (bpos.item > 0))
                           || (   (btoken.aboveAlign.line != -1)
                               && (btoken.aboveAlign.
                                     toToken(spec).belowAlign.line != -1))
                                /**********************************************
                                * Asserts that bpos is aboveAligned with a    *
                                * token that is belowAligned with something,  *
                                * which is possible only if bpos is           *
                                * CommentInner aligned.                       *
                                **********************************************/
                          )     
                      )
                     { /****************************************************
                       * CommentInner align.                               *
                       ****************************************************/
                       btoken.belowAlign = pos ; 
                       if (btoken.aboveAlign.line == -1)
                         { token.aboveAlign = bpos; }
                       else
                         { token.aboveAlign = btoken.aboveAlign ;};
                     }  // END then OF if ((bpos.line != -1)...)
                   else
                     { /*******************************************************
                       * FirstNonLeftComment align iff it is the first        *
                       * non-left comment.                                    *
                       *******************************************************/
                       if (   (item == 0)
                           || (   (item == 1)
                               && (spec[line][0].type == Token.COMMENT)))
                         { pos.toToken(spec).aboveAlign = 
                             coveringPosition(spec, pos, true) ;
                         } ;
                     }; // END else OF if ((bpos.line != -1)...)


                 } // END else OF if  if ((ctok.subtype == .. ))
                prevInfixInner = false ;
              } // END then OF if (isRightComment(spec, pos))                

              { /***********************************************************
                * This is not a right-comment.  Check for every kind of    *
                * alignment except CommentInner.                           *
                ***********************************************************/
                if (prevInfixInner)
                 { /********************************************************
                   * Check for AfterInfixInner alignment.                  *
                   *                                                       *
                   * In the following, the positions lPos, alPos, and      *
                   * aPos are defined by                                   *
                   *                            alPos --- aPos             *
                   *                              |                        *
                   *                              |                        *
                   *                             lPos --- pos              *
                   ********************************************************/
                   Debug.Assert(pos.item > 0, 
                      "prevInfixInner true for first item on line");
                   Position lPos  = new Position(pos.line, pos.item - 1);
                   Debug.Assert(lPos.toToken(spec).aboveAlign.line != -1,
                     "prevInfixInner true, but token to left not aligned");
                   Position alPos = lPos.toToken(spec).aboveAlign ;
                   Token alToken = alPos.toToken(spec);
                   if (alPos.item + 1 < spec[alPos.line].length)
                    { Position aPos   = 
                          new Position(alPos.line, alPos.item + 1) ;
                      Token    atoken = aPos.toToken(spec);
                      Position cPos   = coveringPosition(spec, pos, true);
                      if (   (cPos.line == aPos.line)
                          && (cPos.item == aPos.item)
                          && (token.column == atoken.column)
                          && (atoken.type != Token.COMMENT) )
                        { /*************************************************
                          * AfterInfixInner aligned.                       *
                          *************************************************/
                           token.aboveAlign = aPos;
                        } ;
                    } // END if (alPos.item + 1 < spec[alPos.line].length)
                   prevInfixInner = false;
                 } // END then OF if (prevInfixInner)
               else
                 { /********************************************************
                   * Check for every kind of alignment except              *
                   * AfterInfixInner and CommentInner.                     *
                   *                                                       *
                   * First, check if FirstNonLeftComment aligned.          *
                   ********************************************************/
                   if (   ((item == 0) && (token.type != Token.COMMENT))
                       || ((item == 1) && (spec[line][0].type 
                                              == Token.COMMENT)))
                    { /*****************************************************
                      * FirstNonLeftCommentAligned.                        *
                      *****************************************************/
                      token.aboveAlign = 
                            coveringPosition(spec, pos, true);
                    }
                   else
                    { /*****************************************************
                      * Not FirstNonLeftCommentAligned.                    *
                      *                                                    *
                      * Next, check if LeftComment aligned.                *
                      *****************************************************/
                      if (isLeftComment(spec, pos))
                        { token.aboveAlign = 
                            coveringPosition(spec, pos, false);
                        }
                      else
                        { /*************************************************
                          * Next, check if InfixInner aligned.             *
                          *************************************************/
                          Position cpos = coveringPosition(spec, pos, true) ;
                          Token ctoken = null ;
                            /***********************************************
                            * cpos and ctoken are the covering position    *
                            * and covering token of the current token.     *
                            ***********************************************/
                          if (cpos.line != -1)
                            { ctoken = cpos.toToken(spec);};
                          int alignClass = 0 ;  // The alignment classes
                          int calignClass = 0;  //   of pos and cpos.
                          if (token.type == Token.BUILTIN)
                           { alignClass = 
                                BuiltInSymbols.GetBuiltInSymbol(
                                   token.string, true).alignmentType ; } ;
                          if (   (ctoken != null)
                              && (ctoken.type == Token.BUILTIN))
                           { calignClass = 
                                BuiltInSymbols.GetBuiltInSymbol(
                                   ctoken.string, true).alignmentType ; } ;
                          if (   (ctoken != null)
                              && (token.column == ctoken.column)
                              && (alignClass != 0)
                              && (alignClass == calignClass))
                           { /**********************************************
                             * InfixInner alignment.                       *
                             **********************************************/
                             ctoken.belowAlign = pos ;
                             if (ctoken.aboveAlign.line == -1)
                              {token.aboveAlign = cpos ; }
                             else
                              { token.aboveAlign = ctoken.aboveAlign ; };
                             prevInfixInner = true;
                           }  // END then OF if ((token.column == ...))
                          else
                           { /**********************************************
                             * Not InfixInner alignment.  Check last       *
                             * possibility, which is InfixArg alignment.   *
                             **********************************************/
                             if (   (   (item == 1)
                                     || (   (item == 2)
                                         && (spec[line][0].type == 
                                               Token.COMMENT)))
                                 && (spec[line][item-1].type == Token.BUILTIN)
                                 && (BuiltInSymbols.GetBuiltInSymbol(
                                       spec[line][item-1].string, true).symbolType
                                      == Symbol.INFIX)
                                 /******************************************
                                 * Correction made 7 Nov 2001.             *
                                 * The conjunct above replaced the         *
                                 * following.                              *
                                 *                                         *
                                 * && (BuiltInSymbols.GetBuiltInSymbol(    *
                                 *       spec[line][item-1].string         *
                                 *        ).alignmentType != 0)            *
                                 *                                         *
                                 * It seems reasonable that this           *
                                 * alignment should be performed only      *
                                 * when the token to the left is an infix  *
                                 * operator.                               *
                                 ******************************************/
                                 && (ctoken != null) 
                                 && (token.column == ctoken.column)
                                 && (spec[line][item-1].aboveAlign.line
                                       != -1)
                               )
                              { /*******************************************
                                * Possible InfixArg alignment.             *
                                *******************************************/
                             // This can happen and seems harmless.
                             //   Debug.Assert(ctoken.belowAlign.line == -1,
                             //       "Trying to InfixArg align with token "
                             //   + "that is not aligned with token below it");

                                 Token lTok = spec[line][item-1] ;
                                   /****************************************
                                   * The token to the left of the current  *
                                   * token.                                *
                                   ****************************************/
                                Position alPos = lTok.aboveAlign ;
                                Token alTok = alPos.toToken(spec);
                                  /*****************************************
                                  * The token with which lTok is aligned   *
                                  * above.                                 *
                                  *****************************************/
                                if (   (alPos.line == cpos.line)
                                    && (alPos.item == cpos.item - 1)
                                    )
                                 { /****************************************
                                   * InfixArg alignment with a token       *
                                   * having a token to its left, as in     *
                                   *                                       *
                                   *   x ==   a                            *
                                   *          |                            *
                                   *        + b                            *
                                   ****************************************/
                                   token.aboveAlign = cpos; 
                                   // following fixes the mis-alignment that occurs if
                                   // the "x == " occupies less space than the "+".
                                   // However, for safety, I'm only fixing it for the
                                   // case of labels, which should be more common.
                                   // However, I'm not doing it until I find
                                   // some example of the bug for fear that it
                                   // might break something else.
                                   //
                                   //    ctoken.belowAlign = pos ;
                                 } 
                               else
                                 { if (   (cpos.item == 0)
                                       || (   (cpos.item == 1)
                                           && (spec[cpos.line][0].type 
                                                        == Token.COMMENT)))
                                    { /*****************************************
                                      * InfixArg alignment with a token        *
                                      * having no token to its left.  In       *
                                      * this case, we can have a               *
                                      * situation like                         *
                                      *                                        *
                                      *    x ==                                *
                                      *     a                                  *
                                      *   + b                                  *
                                      *                                        *
                                      * where a is both above-aligned          *
                                      * with x and below-aligned with b.       *
                                      * I hope this doesn't cause              *
                                      * problems.                              *
                                      *****************************************/
                                      token.aboveAlign = cpos;           
                                      ctoken.belowAlign = pos ;
                                    } ;
                                 }
                              };
                           };// END else OF if ((token.column == ...))
                        }; // END else of if (isLeftComment(spec, pos))
                    }; // END else OF if (   ((item == 0) && ... ))
                 }; // END else OF if (prevInfixInner)
              }; // END else OF (isRightComment(spec, pos))                   
             }   // END then OF if (! token.subscript)
            else
             { prevInfixInner = false ;
                 /**********************************************************
                 * Need to reset prevInfixInner for the tokens following   *
                 * a ^ or _.                                               *
                 **********************************************************/
             } ;  
           item = item + 1 ;
          } ; // END while (item < spec[line].length)

         line = line + 1;
         /******************************************************************
         * Skip over epilog lines.                                         *
         ******************************************************************/
         if (    (line < spec.length) 
              && (spec[line].length > 0)
              && (spec[line][0].type == Token.EPILOG))
           { line = spec.length ;} ;
       }; // END while (line < spec.length)

       // Add the AfterLabel alignments.
       FindLabelAlignments(spec) ;

       /*********************************************************************
      * Set isAlignmentPoint flags.  For simplicity, it is set true for    *
      * any token that is not the first on the line and is either the      *
      * source or target of a belowAlign pointer                           *
      *********************************************************************/
      line = 0 ;
      while (line < spec.length)
       { int item = 0 ;
         while (item < spec[line].length)
          { Token token = spec[line][item] ;
            if (token.aboveAlign.line != -1)
              { if (item > 0)
                  {token.isAlignmentPoint = true ;
                  };
                if (token.aboveAlign.item != 0)
                   /********************************************************
                   * Corrected apparent bug on 16 Jan 00: This if          *
                   * condition was: token.aboveAlign.line != 0.            *
                   ********************************************************/
                  { token.aboveAlign.toToken(spec).isAlignmentPoint 
                            = true; 
                  };
              } ;

            if (token.belowAlign.line != -1)
              { if (item > 0)
                  {token.isAlignmentPoint = true ;
                  };
                if (token.belowAlign.line != 0)
                  { token.belowAlign.toToken(spec).isAlignmentPoint 
                            = true; 
                  };
              } ;

            item = item + 1 ;
          } ; // END while (item < spec[line].length)

         line = line + 1;
       }; // END while (line < spec.length)
    } ;

  /**
   * Adds AfterLabel alignments to spec.  More precisely, for something like
   * 
   *  if (x) { stmt
   *    label: stmt
   *           stmt
   *    label: stmt
   *           stmt
   *           stmt
   *        }
   * 
   * it makes the belowAlign field of all stmts but the last one point to the
   * stmt below it, and the aboveAlign field of all but the first stmt point to
   * the one above it.  In this case
   * 
   *    while x
   *           stmt
   *    label: stmt
   * 
   * the first stmt's aboveAlign field should point to x by the FirstNonLeftComment
   * alignment rule.  For
   * 
   *    while x
   *    label: stmt
   *    label: stmt
   * 
   * the method sets the first stmt's aboveAlign field
   *  
   * @param spec
   */
  public static void FindLabelAlignments(Token[][] spec) {
      /*
       * Do nothing if there is no PlusCal algorithm.
       */
      if (!TokenizeSpec.hasPcal) {
          return ;
      }
      
      /*
       * We get the first and last line that may begin with a label or a 
       * PlusCal statement.  Since the algorithm begins with --algorithm
       * or --fair, we skip the algorithm's first line.
       */
      int pcalStartLine = TokenizeSpec.pcalStart.line + 1 ;
      int pcalEndLine   = TokenizeSpec.pcalEnd.line ;
      
      /*
       * The algorithm works by repeatedly searching for the next line beginning
       * with a label followed by a token tok.  It then performs the following
       * two steps
       * 
       * 1. Searche downward for tokens AfterLabel aligned with tok, setting
       *    aboveAlign/belowAlign fields as it finds them. It stops when it reaches a 
       *    line in which tok is not not aligned with the first token on the
       *    line.  If there's a token etok on that line that is AfterLabel
       *    aligned with tok, so it must follow a label, then the aboveAlign
       *    field of etok is set to point to the AfterLabel aligned token above
       *    it, whose belowAlign field points to etok.
       *    
       * 2. IF tok's aboveAlign field points to a token whose belowAlign field
       *       points to a field whose belowAlign field points to tok
       *     THEN do nothing.  I think this is possible only if those fields were set
       *          by step 1 for a previous label.  If I'm wrong and there's some weird
       *          situation that caused this alignment (which I think can only be
       *          the case if tok is a comment), then not stopping will probably
       *          do more harm than good.
       *     ELSE search upwards to set aboveAlign/belowAlign fields of tokens 
       *          AfterLabel aligned with tok. As indicated above, if there
       *          are no tokens above tok that are AfterLabel aligned with it,
       *          then tok's aboveAlign field must be set to point to its
       *          covering token.   
       */
      int curLabelLine = pcalStartLine ;
      
      while (   (curLabelLine <= pcalEndLine)
             && (curLabelLine < spec.length) ) {
          /* 
           * set curLabelLine to the first line at or below its current
           * position that begins with a label.
           */
          if (   (spec[curLabelLine].length > 1)
              && (spec[curLabelLine][0].type == Token.PCAL_LABEL) ) {
              
              Token tok = spec[curLabelLine][1] ;
              int alignCol = tok.column ;

              // Perform step 1 for token tok
              int curLine = curLabelLine + 1 ;
              
              // spec[alignLine][alignItem] is the token to which the
              // next token to be aligned is aligned with.
              int alignLine = curLabelLine ;
              int alignItem = 1 ;
              boolean notDone = true ;
              // Test of curLine < spec.length added 4 Aug 2015 to fix
              // bug caused by running off the end of the spec when called by
              // TLATeX to format a snippet of PlusCal code.  See comment from
              // this date in TokenizeSpec.
              while (notDone && (curLine < spec.length)) {
                  int curItem = 0 ;
                     // If spec[alignLine][alignItem] is to be aligned with a token
                     // on this line, then the token is spec[curLine][nextItem] 
                     // 
                  boolean shouldSkip = false ;
                  if (spec[curLine].length != 0) {
                      if (spec[curLine][0].type == Token.PCAL_LABEL) {
                          // line begins with label
                          if (spec[curLine].length > 1) {
                              curItem = 1 ;
                          }
                          else {
                              // The label is the only token on the line.  Stop
                              // iff the label is to the left of the alignment
                              // column.
                              notDone = (spec[curLine][0].column >= alignCol) ;
                              shouldSkip = true ;
                          }
                      }
                      else {
                          // line doesn't begin with label
                      }
                      if (!shouldSkip) {
                          if (spec[curLine][curItem].column < alignCol) {
                              notDone = false ;
                          }
                          else if (spec[curLine][curItem].column == alignCol) {
                              spec[alignLine][alignItem].belowAlign = 
                                      new Position(curLine, curItem) ;
                              spec[curLine][curItem].aboveAlign =
                                      new Position(alignLine, alignItem) ;
                              alignLine = curLine ;
                              alignItem = curItem ;
                          }
                      }
                  }
                  curLine++ ;
                  if (   (curLine > pcalEndLine)
                      || (curLine >= spec.length)) {
                      notDone = false ;
                  }
              }
              
              // Perform step 2 for token tok
              
              if (    (tok.aboveAlign.line != -1)
                   && (tok.aboveAlign.toToken(spec).belowAlign.equals(new Position(curLabelLine, 1)))) {
                  // already aligned with above tokens so do nothing
              }
              else {
                  curLine = curLabelLine - 1 ;
                  alignLine = curLabelLine ;
                  alignItem = 1 ;
                  notDone = true ;
                  while (notDone) {
                     if (   (spec[curLine].length > 0 )
                         && (spec[curLine][0].column <= alignCol)
                         && (   (spec[curLine][0].type != Token.PCAL_LABEL)
                             || (   (spec[curLine].length > 1)
                                  && (spec[curLine][1].column <= alignCol) ) )
                            // the conjunct above causes the line to be skipped
                            // if the only token to the left of tok on this
                            // line is an initial label followed by a token
                            // to the right of tok.
                        ) {
                         if (spec[curLine][0].column == alignCol) {
                             //  spec[curLine][0] is to be aligned with 
                             //  spec[alignLine][alignItem] 
                             spec[alignLine][alignItem].aboveAlign = 
                                     new Position(curLine, 0) ;
                             spec[curLine][0].belowAlign =
                                     new Position(alignLine, alignItem) ;
                             alignLine = curLine ;
                             alignItem = 0 ; 
                         }
                         else if (spec[alignLine][alignItem].aboveAlign.line == -1) {        
                             // we need to align spec[alignLine][alignItem] with the
                             // right-most token on line curLine with column \leq alignCol
                             int item = 0 ;
                             while (   (item < spec[curLine].length)
                                    && (spec[curLine][item].column <= alignCol)) {
                                 item++;
                             }
                             // item is now either off the line or pointing to a token
                             // to the right of the alignment token ;
                             item-- ;
                             
                             // We  set the aboveAlign pointer of 
                             // to point to spec[curLine][item] if the latter token is either
                             // the first one on its line, or else the token to its left is
                             // either a label or a PlusCal token.  
                             // If that's the case, we also set the belowAlign pointer of 
                             // spec[curLine][item] if that token is in the same column
                             // as spec[alignLine][alignItem].
                             // 
                             Token altok = null ;
                             if (item > 0) {
                                 altok = spec[curLine][item-1] ;
                             }
                             if (   (altok != null)
                                 && (   (altok.type == Token.PCAL_LABEL)
                                     || (   (altok.type == Token.BUILTIN)
                                         && BuiltInSymbols.IsBuiltInSymbol(altok.string, true)
                                         && ! BuiltInSymbols.IsBuiltInSymbol(altok.string, false)
                                        )
                                    )
                                ) {
                                 spec[alignLine][alignItem].aboveAlign = 
                                            new Position(curLine, item) ;
                                
                                 if (spec[curLine][item].column == alignCol) {
                                     spec[curLine][item].belowAlign =
                                             new Position(alignLine, alignItem) ;
                                 }
                             }
                             // This ends step 2
                             notDone = false ;
                         }
                         else {
                             notDone = false ;
                         }
                     }
                     curLine-- ;
                     if (curLine < pcalStartLine) {
                         notDone = false ;
                     }
                  }
              }     
          }
          curLabelLine++ ;
      }       
  }
  /*************************************************************************
  * The following are functions used in FindAlignments.                    *
  *************************************************************************/
  private static boolean isLeftComment(Token[][] spec, Position p)
    /***********************************************************************
    * A left-comment is a comment token that is the first token on a line  *
    * and has another token to its right.  This method returns true iff    *
    * the token at position p of spec is a left-comment.                   *
    ***********************************************************************/
    { return    (p.item == 0)
             && (spec[p.line][p.item].type == Token.COMMENT) 
             && (spec[p.line].length > 1) ;
    } ;

  private static boolean isRightComment(Token[][] spec, Position p)
    /***********************************************************************
    * A right-comment is a comment token that is the last token on its     *
    * line.  This method returns true iff the token at position p in spec  *
    * is a right-comment.                                                  *
    ***********************************************************************/
    { return    (p.item == spec[p.line].length - 1)
             && (spec[p.line][p.item].type == Token.COMMENT) ;
    } ;

  private static Position coveringPosition( 
                          Token[][] spec, Position p, boolean ignore)
    /***********************************************************************
    * A token t1 COVERS a token t2 if t1 lies on an earlier line than t2   *
    * and t1.column \leq t2.column.  This method searches upwards to find  *
    * the first line with a token that covers the token at position p,     *
    * and then returns the position of the right-most token on that line   *
    * that covers the token at p.  When searching for the covering token,  *
    * left-comments are ignored iff the ignore parameter is true.          *
    ***********************************************************************/
    { /*********************************************************************
      * Find covering line.                                                *
      *********************************************************************/
      int   line = p.line - 1 ;
      Token tok = p.toToken(spec) ;
      boolean notDone = true ;
      while ((line >= 0) && notDone)
       { if (spec[line].length > 0)
           { if (spec[line][0].type == Token.PROLOG)
               { line = -1 ;
                 notDone = false;
               }
             else
               { int item = 0 ;
                 if (ignore && isLeftComment(spec, new Position(line, 0)))
                   { item = 1 ; }
                 if (spec[line][item].column <= tok.column)
                   { notDone = false ;} ;
               }
           }; // END if (spec[line].length > 0)
         if (notDone) {line = line - 1 ;};
       } // END while ((line >= 0) && notDone)

     /**********************************************************************
     * If no covering line, return (-1, 0).                                *
     **********************************************************************/
     if (line == -1) {return new Position(-1, 0);} ;

     /**********************************************************************
     *      Find covering item.                                            *
     **********************************************************************/
     int item = 0;
     int nsItem = 0;
       /********************************************************************
       * item is the current item.                                         *
       * nsItem is the last non-subscript item found that covers tok.      *
       ********************************************************************/
     boolean dashFound = false ;
     if (spec[line][0].type == Token.DASHES)
      { dashFound = true;} ;
     while (    (! dashFound)
             && (item + 1 < spec[line].length)
             && (spec[line][item + 1].column <= tok.column))
          { if (spec[line][item+1].type == Token.DASHES)
             {dashFound = true;} ;
            item = item + 1;
            if (!spec[line][item].subscript)
                {nsItem = item;};
          };
     if (dashFound) {return new Position(-1, 0);} ;

     /**********************************************************************
     * Return (line, nsItem).                                              *
     **********************************************************************/
     return new Position(line, nsItem);
    } ;

  private static Position blockingPosition(Token[][] spec, Position p)
    /***********************************************************************
    * Searches upwards from position p to find the first token at the      *
    * same column or to the right of the token at p that is not            *
    * a subscript token.                                                   *
    ***********************************************************************/
    { int line = p.line - 1 ;
      int item = 0 ;
      Token tok = p.toToken(spec) ;
      boolean notDone = true ;
      while ((line >= 0) && notDone)
       { if (spec[line].length > 0)
           { if (spec[line][0].type == Token.PROLOG)
               { line = -1 ;
                 notDone = false;
               }
             else
               { item = 0 ;
                 if (isLeftComment(spec, new Position(line, 0)))
                   { item = 1 ; } ;
                 while (notDone && (item < spec[line].length))
                  { if (   (spec[line][item].column >= tok.column)
                        && (! spec[line][item].subscript))
                      { notDone = false ; }
                    else 
                      { item = item+1; };
                  } ;
               } ;
           }; // END if (spec[line].length > 0)
         if (notDone) {line = line - 1 ;} ;
       } // END while ((line >= 0) && notDone)

     /**********************************************************************
     * If no token found, return (-1, 0).                                  *
     **********************************************************************/
     if (line == -1) {return new Position(-1, 0);} ;

     /**********************************************************************
     * Return (line, item).                                                *
     **********************************************************************/
     return new Position(line, item);
    } ;

  private static void setSubscriptField(Token[][] spec)
    /***********************************************************************
    * Sets the subscript field of the tokens.  (This field is true iff     *
    * the token is part of a sub- or superscript.)  Upon encountering a    *
    * "^" or a token that is a built-in symbol with symbolType -           *
    * Symbol.SUBSCRIPTED token, the next token or all tokens in the        *
    * properly parenthesized expression that follows it are                *
    * subscripted--iff all those tokens lie on the same line.              *
    ***********************************************************************/
    { int line = 0 ;
      while (line < spec.length)
       { int item = 0 ;
         int startSub = -1 ;
           /****************************************************************
           * If a subscript has begun, then this is its first item;        *
           * otherwise, it equals -1.                                      *
           ****************************************************************/
         int nestingDepth = 0 ;
           /****************************************************************
           * The current parenthesis nesting level inside a subscript, or  *
           * 0 if not in a subscript.                                      *
           ****************************************************************/
           

         while (item < spec[line].length)
          { Token tok = spec[line][item] ;
              /*************************************************************
              * tok is the current token.                                  *
              *************************************************************/
            if (startSub == -1)
             { /************************************************************
               * A subscript has not yet begun.                            *
               ************************************************************/
               if (   (tok.type == Token.BUILTIN)
                   && (   (BuiltInSymbols.GetBuiltInSymbol(
                                                    tok.string, true).symbolType 
                            == Symbol.SUBSCRIPTED)
                       || (tok.string.equals("^"))))
                { 
                  startSub = item + 1 ;
                } // END then OF if ((tok.type == Token.BUILTIN) ...)
               else 
                { /*********************************************************
                  * Do nothing.                                            *
                  *********************************************************/
                }; // END else OF if ((tok.type = Token.BUILTIN) ...)

             }  // END then OF if (startSub == -1)
            else
             { /************************************************************
               * A subscript has begun.                                    *
               *                                                           *
               * Set symType to the symbol type of the token, or           *
               * NOT_A_SYMBOL if it isn't a symbol.                        *
               ************************************************************/
               int symType = Symbol.NOT_A_SYMBOL ;
               if (tok.type == Token.BUILTIN)
                 { symType = 
                      BuiltInSymbols.GetBuiltInSymbol(
                         tok.string, true).symbolType ;
                 };

               if (   (   (nestingDepth == 0) 
                       && (symType != Symbol.LEFT_PAREN))
                   || (   (nestingDepth == 1) 
                       && (symType == Symbol.RIGHT_PAREN)))
                { /*********************************************************
                  * This ends the subscript.  Set the subscript field of   *
                  * all tokens from startSub to item and reset startSub.   *
                  *********************************************************/
                  nestingDepth = 0 ;
                  while (startSub <= item)
                   { spec[line][startSub].subscript = true ;
                     startSub = startSub + 1;
                   }
                  startSub = -1 ;
                } // END then OF if (((nestingDepth == 0)... ))
               else
                { /*********************************************************
                  * The subscript continues.                               *
                  *********************************************************/
                  if (symType == Symbol.LEFT_PAREN)
                    { nestingDepth = nestingDepth + 1; }
                  else
                    { if (symType == Symbol.RIGHT_PAREN)
                        { nestingDepth = nestingDepth - 1; };
                    };
                }; // END else OF if (((nestingDepth == 0)... ))

             }; // END else OF if (startSub == -1)

           item = item + 1 ;
          } ; // END while (item < spec[line].length)


         line = line + 1;
       } // END while (line < spec.length)
      
    } ;
    
    
}

/* last modified on Sun  5 August 2012 at 17:07:48 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/impl/InitializeValueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.BeforeClass;
import org.junit.Test;

import tlc2.util.FP64;
import util.InternTable;
import util.UniqueString;

public class InitializeValueTest {

	@BeforeClass
	public static void setup() {
		FP64.Init();
	}
	
	/**
	 * Test method for {@link tlc2.value.impl.UnionValue#deepNormalize()}.
	 */
	@Test
	public void union() {
		final ValueVec vec = new ValueVec();
		vec.addElement(new SetEnumValue(new IntValue[] {IntValue.gen(42)}, false));
		vec.addElement(new SetEnumValue(new IntValue[] {IntValue.gen(23)}, false));
		vec.addElement(new SetEnumValue(new IntValue[] {IntValue.gen(4711)}, false));
		vec.addElement(new SetEnumValue(new IntValue[] {IntValue.gen(1)}, false));
		
		final UnionValue uv = new UnionValue(new SetEnumValue(vec, false));
		assertFalse(uv.isNormalized());
		assertFalse(uv.set.isNormalized());
		
		uv.initialize();
		
		assertTrue(uv.set.isNormalized());
		assertTrue(uv.isNormalized());
	}

	/**
	 * Test method for {@link tlc2.value.impl.SetCapValue#deepNormalize()}.
	 */
	@Test
	public void setcap() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		
		SetCapValue scv = new SetCapValue(new SetEnumValue(vec, false), new SetEnumValue(vec, false));
		assertFalse(scv.isNormalized());
		assertFalse(scv.set1.isNormalized());
		assertFalse(scv.set2.isNormalized());
		
		scv.initialize();
		
		assertTrue(scv.set1.isNormalized());
		assertTrue(scv.set2.isNormalized());
		assertTrue(scv.isNormalized());
	}

	@Test
	public void setcup() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		
		SetCupValue scv = new SetCupValue(new SetEnumValue(vec, false), new SetEnumValue(vec, false));
		assertFalse(scv.isNormalized());
		assertFalse(scv.set1.isNormalized());
		assertFalse(scv.set2.isNormalized());
		
		scv.initialize();
		
		assertTrue(scv.set1.isNormalized());
		assertTrue(scv.set2.isNormalized());
		assertTrue(scv.isNormalized());
	}

	@Test
	public void setdiff() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		
		SetDiffValue sdv = new SetDiffValue(new SetEnumValue(vec, false), new SetEnumValue(vec, false));
		assertFalse(sdv.isNormalized());
		assertFalse(sdv.set1.isNormalized());
		assertFalse(sdv.set2.isNormalized());
		
		sdv.initialize();
		
		assertTrue(sdv.isNormalized());
		assertTrue(sdv.set1.isNormalized());
		assertTrue(sdv.set2.isNormalized());
	}

	@Test
	public void subset() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		
		SubsetValue sub = new SubsetValue(new SetEnumValue(vec, false));
		assertFalse(sub.isNormalized());
		assertFalse(sub.set.isNormalized());
		
		sub.initialize();
		
		assertTrue(sub.set.isNormalized());
		assertTrue(sub.isNormalized());
	}

	@Test
	public void record() {
		final InternTable internTable = new InternTable(2);
		final UniqueString a = internTable.put("a");
		final UniqueString b = internTable.put("b");
		
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		final Value aVal = new SetEnumValue(vec, false);
		final Value bVal = new SetEnumValue(vec, false);
		
		final RecordValue rcdv = new RecordValue(new UniqueString[] {b, a}, new Value[] {bVal, aVal}, false);

		assertFalse(rcdv.isNormalized());
		for (Value v : rcdv.values) {
			assertFalse(v.isNormalized());
		}
		
		rcdv.initialize();
		
		for (Value v : rcdv.values) {
			assertTrue(v.isNormalized());
		}
		assertTrue(rcdv.isNormalized());
	}

	@Test
	public void fcnrecord() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		final Value aVal = new SetEnumValue(vec, false);
		final Value bVal = new SetEnumValue(vec, false);

		final FcnRcdValue rcdv = new FcnRcdValue(new Value[] { new StringValue("B"), new StringValue("A") },
				new Value[] { bVal, aVal }, false);

		assertFalse(rcdv.isNormalized());
		for (Value v : rcdv.values) {
			assertFalse(v.isNormalized());
		}
		
		rcdv.initialize();
		
		for (Value v : rcdv.values) {
			assertTrue(v.isNormalized());
		}
		assertTrue(rcdv.isNormalized());
	}
	
	@Test
	public void tuple() {
		final ValueVec vec = new ValueVec();
		vec.addElement(IntValue.gen(42));
		vec.addElement(IntValue.gen(23));
		vec.addElement(IntValue.gen(4711));
		vec.addElement(IntValue.gen(1));
		final Value aVal = new SetEnumValue(vec, false);
		
		final TupleValue tuple = new TupleValue(aVal);

//		for (Value v : tuple.elems) {
//			assertFalse(v.isNormalized());
//		}
//		assertFalse(tuple.isNormalized());

		tuple.initialize();
		
		assertTrue(tuple.isNormalized());
		for (Value v : tuple.elems) {
			assertTrue(v.isNormalized());
		}
	}
	
	@Test
	public void setOfTuple() {
		final IntervalValue intVal = new IntervalValue(1, 2);
		final SetOfTuplesValue inner = new SetOfTuplesValue(intVal, intVal);
		final SetOfTuplesValue tuples = new SetOfTuplesValue(inner, inner);
		
//		for (Value v : tuples.sets) {
//			assertFalse(v.isNormalized());
//		}
//		assertFalse(tuples.isNormalized());
		
		tuples.initialize();
		
		assertTrue(tuples.isNormalized());
		for (Value v : tuples.sets) {
			assertTrue(v.isNormalized());
		}
	}
	
	@Test
	public void setOfRcds() {

		final Value[] values = new Value[3];
		values[0] = new SetEnumValue(getValue(7, "a"), true);
		values[1] = new IntervalValue(1, 2);
		values[2] = new IntervalValue(1, 4);

		final SetOfRcdsValue setOfRcrds= new SetOfRcdsValue(getNames(3), values, true);

//		for (Value v : setOfRcrds.values) {
//			assertFalse(v.isNormalized());
//		}
//		assertFalse(setOfRcrds.isNormalized());

		setOfRcrds.initialize();

		assertTrue(setOfRcrds.isNormalized());
		for (Value v : setOfRcrds.values) {
			assertTrue(v.isNormalized());
		}
	}

	private static final Value[] getValue(final int n, String str) {
		final Value[] values = new Value[n];
		for (int i = 0; i < n; i++) {
			values[i] = new StringValue(str + i);
		}
		return values;
	}

	private static final UniqueString[] getNames(final int n) {
		final UniqueString[] names = new UniqueString[n];
		for (int i = 0; i < names.length; i++) {
			names[i] = UniqueString.uniqueStringOf("N" + i);
		}
		return names;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/Spec.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 19 May 2008 at  1:13:48 PST by lamport
//      modified on Fri Aug 24 14:43:24 PDT 2001 by yuanyu

package tlc2.tool.impl;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import tla2sany.modanalyzer.ParseUnit;
import tla2sany.semantic.APSubstInNode;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.FrontEnd;
import tla2sany.semantic.LabelNode;
import tla2sany.semantic.LetInNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.Subst;
import tla2sany.semantic.SubstInNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.ThmOrAssumpDefNode;
import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.tool.Action;
import tlc2.tool.BuiltInOPs;
import tlc2.tool.Defns;
import tlc2.tool.TLCState;
import tlc2.tool.ToolGlobals;
import tlc2.tool.impl.Tool.Mode;
import tlc2.util.Context;
import tlc2.util.ObjLongTable;
import tlc2.util.Vect;
import tlc2.value.ValueConstants;
import tlc2.value.impl.LazyValue;
import tlc2.value.impl.ModelValue;
import util.Assert;
import util.FilenameToStream;
import util.MonolithSpecExtractor;
import util.UniqueString;

// Note that we use all of the {@code default} defined functionality in our
//		implemented interface {@link SymbolNodeValueLookupProvider} (and our
//		lack of implementation of {@link OpDefEvaluator} is why this class
//		is marked {@code abstract}.)
abstract class Spec
		implements ValueConstants, ToolGlobals, Serializable, OpDefEvaluator, SymbolNodeValueLookupProvider {
	private static final long serialVersionUID = 1L;

	/**
	 * @see See note on performance in CostModelCreator.
	 */
	protected static final boolean coverage = TLCGlobals.isCoverageEnabled();

	protected static final int toolId = FrontEnd.getToolId();
	
	protected final String specDir; // The spec directory.
    protected final String rootFile; // The root file of this spec.
    protected final String configFile; // The model config file.
    protected final Set<OpDefNode> processedDefs ; 
      // The set of OpDefNodes on which processSpec has been called.
      // Added by LL & YY on 25 June 2014 to eliminate infinite
      // loop when a recursively defined operator is used as an
      // operator argument in its own definition.
    protected final Defns defns; // Global definitions reachable from root
	protected final Defns unprocessedDefns;
    protected final TLAClass tlaClass; // TLA built-in classes.
    private final FilenameToStream resolver; // takes care of path to stream resolution

    protected final ModelConfig config; // The model configuration.
    private final SpecProcessor specProcessor;

    // SZ Feb 20, 2009: added support to name resolver, to be able to run outside of the tool
	public Spec(final String specDir, final String specFile, final String configFile, final FilenameToStream resolver,
			Mode mode) {
        this.specDir = specDir;
        this.rootFile = specFile;
        this.defns = new Defns();
        this.tlaClass = new TLAClass("tlc2.module", resolver);
        this.processedDefs = new HashSet<OpDefNode>();
        this.resolver = resolver;
        
        // SZ Mar 9, 2009: added initialization of the modelValue class
        ModelValue.init();
        this.configFile = configFile;
        this.config = new ModelConfig(MonolithSpecExtractor.getConfig(configFile), resolver);
        this.config.parse();
        ModelValue.setValues(); // called after seeing all model values

        specProcessor = new SpecProcessor(getRootName(), resolver, toolId, defns, config, this, this, tlaClass, mode);
        
        this.unprocessedDefns = specProcessor.getUnprocessedDefns();
    }
    
    protected Spec(final Spec other) {
    	this.specDir = other.specDir;
    	this.rootFile = other.rootFile;
    	this.configFile = other.configFile;
    	this.processedDefs = other.processedDefs;
    	this.defns = other.defns;
    	this.tlaClass = other.tlaClass;
        this.resolver = other.resolver;
        this.unprocessedDefns = other.unprocessedDefns;
    	this.config = other.config;
        this.specProcessor = other.specProcessor;
    }
    
    public ModelConfig getModelConfig() {
    	return config;
    }
    
    public SpecProcessor getSpecProcessor() {
    	return specProcessor;
    }

    /* Return the variable if expr is a primed state variable. Otherwise, null. */
    public final SymbolNode getPrimedVar(SemanticNode expr, Context c, boolean cutoff)
    {
        if (expr instanceof OpApplNode)
        {
            OpApplNode expr1 = (OpApplNode) expr;
            SymbolNode opNode = expr1.getOperator();

            if (BuiltInOPs.getOpCode(opNode.getName()) == OPCODE_prime)
            {
                return this.getVar(expr1.getArgs()[0], c, cutoff, toolId);
            }

            if (opNode.getArity() == 0)
            {
                boolean isVarDecl = (opNode.getKind() == VariableDeclKind);
                Object val = this.lookup(opNode, c, cutoff && isVarDecl, toolId);

                if (val instanceof LazyValue)
                {
                    LazyValue lval = (LazyValue) val;
                    return this.getPrimedVar(lval.expr, lval.con, cutoff);
                }
                if (val instanceof OpDefNode)
                {
                    return this.getPrimedVar(((OpDefNode) val).getBody(), c, cutoff);
                }
            }
        }
        return null;
    }

    /** 
     * Get model constraints.  
     */
	public final ExprNode[] getModelConstraints() {
		return specProcessor.getModelConstraints();
	}

    /**
     * Get action constraints.  
     */
	public final ExprNode[] getActionConstraints() {
		return specProcessor.getActionConstraints();
	}

    /* Get the initial state predicate of the specification.  */
	public final Vect<Action> getInitStateSpec() {
		return specProcessor.getInitPred();
	}

    /* Get the action (next state) predicate of the specification. */
	public final Action getNextStateSpec() {
		return specProcessor.getNextPred();
	}

    /** 
     * Get the view mapping for the specification. 
     */
    public final SemanticNode getViewSpec()
    {
        String name = this.config.getView();
        if (name.length() == 0)
            return null;

        Object view = this.defns.get(name);
        if (view == null)
        {
            Assert.fail(EC.TLC_CONFIG_SPECIFIED_NOT_DEFINED, new String[] { "view function", name });
        }
        if (!(view instanceof OpDefNode))
        {
            Assert.fail(EC.TLC_CONFIG_ID_MUST_NOT_BE_CONSTANT, new String[] { "view function", name });
        }
        OpDefNode def = (OpDefNode) view;
        if (def.getArity() != 0)
        {
            Assert.fail(EC.TLC_CONFIG_ID_REQUIRES_NO_ARG, new String[] { "view function", name });
        }
        return def.getBody();
    }

    /* Get the alias declaration for the state variables. */
    public final SemanticNode getAliasSpec()
    {
        String name = this.config.getAlias();
        if (name.length() == 0)
        {
            Assert.fail(EC.TLC_CONFIG_NO_STATE_TYPE);
        }

        // A true constant-level alias such as such as [ x |-> "foo" ] will be evaluated
        // eagerly and type be an instance of RecordValue.  It would be good to return a
        // proper warning.
        Object type = this.defns.get(name);
        if (type == null)
        {
            Assert.fail(EC.TLC_CONFIG_SPECIFIED_NOT_DEFINED, new String[] { "alias", name });
        }
        if (!(type instanceof OpDefNode))
        {
            Assert.fail(EC.TLC_CONFIG_ID_MUST_NOT_BE_CONSTANT, new String[] { "alias", name });
        }
        OpDefNode def = (OpDefNode) type;
        if (def.getArity() != 0)
        {
            Assert.fail(EC.TLC_CONFIG_ID_REQUIRES_NO_ARG, new String[] { "alias", name });
        }
        return def.getBody();
    }

    public final SemanticNode getPostConditionSpec()
    {
        String name = this.config.getPostCondition();
        if (name.length() == 0)
        {
            return null;
        }

        Object type = this.defns.get(name);
        if (type == null)
        {
            Assert.fail(EC.TLC_CONFIG_SPECIFIED_NOT_DEFINED, new String[] { "post condition", name });
        }
        if (!(type instanceof OpDefNode))
        {
            Assert.fail(EC.TLC_CONFIG_ID_MUST_NOT_BE_CONSTANT, new String[] { "post condition", name });
        }
        OpDefNode def = (OpDefNode) type;
        if (def.getArity() != 0)
        {
            Assert.fail(EC.TLC_CONFIG_ID_REQUIRES_NO_ARG, new String[] { "post condition", name });

        }
        return def.getBody();
    }

	public final boolean livenessIsTrue() {
		return getImpliedTemporals().length == 0;
	}

    /* Get the fairness condition of the specification.  */
    public final Action[] getTemporals()
    {
        return specProcessor.getTemporal();
    }

    public final String[] getTemporalNames()
    {
        return specProcessor.getTemporalNames();
    }

    /* Get the liveness checks of the specification.  */
	public final Action[] getImpliedTemporals() {
		return specProcessor.getImpliedTemporals();
	}

	public final String[] getImpliedTemporalNames() {
		return specProcessor.getImpliedTemporalNames();
	}

    /* Get the invariants of the specification. */
	public final Action[] getInvariants() {
		return specProcessor.getInvariants();
	}

	public final String[] getInvNames() {
		return specProcessor.getInvariantsNames();
	}

    /* Get the implied-inits of the specification. */
	public final Action[] getImpliedInits() {
		return specProcessor.getImpliedInits();
	}

	public final String[] getImpliedInitNames() {
		return specProcessor.getImpliedInitNames();
	}

    /* Get the implied-actions of the specification. */
	public final Action[] getImpliedActions() {
		return specProcessor.getImpliedActions();
	}

	public final String[] getImpliedActNames() {
		return specProcessor.getImpliedActionNames();
	}

    /* Get the assumptions of the specification. */
	public final ExprNode[] getAssumptions() {
		return specProcessor.getAssumptions();
	}
    
    /* Get the assumptionIsAxiom field */
    public final boolean[] getAssumptionIsAxiom() {
        return specProcessor.getAssumptionIsAxiom();
    }
    
    /**
     * This method gets the value of a symbol from the environment. We
     * look up in the context c, its tool object, and the state s.
     * 
     * It and the lookup method that follows it were modified by LL
     * on 10 April 2011 to fix the following bug.  When a constant definition
     *    Foo == ...
     * is overridden to substitute Bar for Foo, the TLC tool object for
     * the body of Foo's OpDef node is set to the OpDefNode for Bar.
     * When evaluating a use of Foo, the lookup method is apparently
     * supposed to return the OpDefNode for Bar.  (I don't understand
     * how the callers make use of the returned value.) That's what it
     * does for uses of Foo in the module in which Foo is defined.
     * However, if Foo is imported by instantiation with renaming as 
     * X!Foo, then it appears that looking up X!Foo should also return 
     * the OpDefNode for Bar.  If the instantiated module had no
     * parameters, then that's what happened because the body of the
     * OpDefNode for X!Foo is the same (contains a pointer to the
     * same object) as the body of Foo's OpDefNode.  However, that
     * wasn't the case if the instantiated module had parameters,
     * because then X!Foo's OpDefNode consists of a sequence of
     * nested SubstInNode objects, the last of which points to
     * the body of Foo's OpDefNode.  So, LL modified the lookup
     * methods so they follow the sequence of SubstInNode bodies
     * down to the body of Foo's OpDefNode when looking up the result.  
     * (If a SubstInNode has a non-null TLC tool object for a
     * SubstInNode, then it returns that object.  I don't think this 
     * should ever be the case, and if it is, I have no idea what the
     * lookup method should do.)
     * 
     */
    public final Object lookup(SymbolNode opNode, Context c, TLCState s, boolean cutoff)
    {
        Object result = lookup(opNode, c, cutoff, toolId);
        if (result != opNode) {
            return result;
        }

		// CalvinL/LL/MAK 02/2021: Added conditional as part of Github issue #362 Name
		// clash between variable in refined spec and operator in instantiated spec. See
		// releated test in Github362.java.
        if (opNode.getKind() != UserDefinedOpKind) {
			result = s.lookup(opNode.getName());
			if (result != null) {
				return result;
			}
		}

        return opNode;
    }

    public final Object lookup(final SymbolNode opNode)
    {
        return lookup(opNode, Context.Empty, false, toolId);
    }

    /**
     * The following added by LL on 23 October 2012 to fix bug in evaluation of names of theorems and 
     * assumptions imported by parameterized instantiation.
     *  
     * @param opDef
     * @param args
     * @param c
     * @param cachable
     * @return
     */
    public final Context getOpContext(ThmOrAssumpDefNode opDef, ExprOrOpArgNode[] args, Context c, boolean cachable)
    {
        FormalParamNode[] formals = opDef.getParams();
        int alen = args.length;
        Context c1 = c;
        for (int i = 0; i < alen; i++)
        {
            Object aval = this.getVal(args[i], c, cachable, toolId);
            c1 = c1.cons(formals[i], aval);
        }
        return c1;
    }
    
    /**
     * Return a table containing the locations of subexpression in the
     * spec of forms x' = e and x' \in e. Warning: Current implementation
     * may not be able to find all such locations.
     */
    public final ObjLongTable<SemanticNode> getPrimedLocs()
    {
        final ObjLongTable<SemanticNode> tbl = new ObjLongTable<SemanticNode>(10);
        final Action act = this.getNextStateSpec();
		if (act == null) {
			// MAK 10/17/2018: If spec defines no next-state action (see e.g.
			// tlc2.tool.ASTest) and this method is called before ModelChecker checks
			// actions (search for tlc2.output.EC.TLC_STATES_AND_NO_NEXT_ACTION) this will
			// NPE.
			return tbl;
		}
        this.collectPrimedLocs(act.pred, act.con, tbl);
        return tbl;
    }

    public final void collectPrimedLocs(SemanticNode pred, Context c, ObjLongTable<SemanticNode> tbl)
    {
        switch (pred.getKind()) {
        case OpApplKind: {
            OpApplNode pred1 = (OpApplNode) pred;
            this.collectPrimedLocsAppl(pred1, c, tbl);
            return;
        }
        case LetInKind: {
            LetInNode pred1 = (LetInNode) pred;
            this.collectPrimedLocs(pred1.getBody(), c, tbl);
            return;
        }
        case SubstInKind: {
            SubstInNode pred1 = (SubstInNode) pred;
            Subst[] subs = pred1.getSubsts();
            Context c1 = c;
            for (int i = 0; i < subs.length; i++)
            {
                Subst sub = subs[i];
                c1 = c1.cons(sub.getOp(), this.getVal(sub.getExpr(), c, true, toolId));
            }
            this.collectPrimedLocs(pred1.getBody(), c, tbl);
            return;
        }

        // Added by LL on 13 Nov 2009 to handle theorem and assumption names.
        case APSubstInKind: {
            APSubstInNode pred1 = (APSubstInNode) pred;
            Subst[] subs = pred1.getSubsts();
            Context c1 = c;
            for (int i = 0; i < subs.length; i++)
            {
                Subst sub = subs[i];
                c1 = c1.cons(sub.getOp(), this.getVal(sub.getExpr(), c, true, toolId));
            }
            this.collectPrimedLocs(pred1.getBody(), c, tbl);
            return;
        }


            /***********************************************************************
            * LabelKind case added by LL on 13 Jun 2007.                           *
            ***********************************************************************/
        case LabelKind: {
            LabelNode pred1 = (LabelNode) pred;
            this.collectPrimedLocs(pred1.getBody(), c, tbl);
            return;
        }
        }
    }

    private final void collectPrimedLocsAppl(OpApplNode pred, Context c, ObjLongTable<SemanticNode> tbl)
    {
        ExprOrOpArgNode[] args = pred.getArgs();
        SymbolNode opNode = pred.getOperator();
        int opcode = BuiltInOPs.getOpCode(opNode.getName());

        switch (opcode) {
        case OPCODE_fa: // FcnApply
        {
            this.collectPrimedLocs(args[0], c, tbl);
            break;
        }
        case OPCODE_ite: // IfThenElse
        {
            this.collectPrimedLocs(args[1], c, tbl);
            this.collectPrimedLocs(args[2], c, tbl);
            break;
        }
        case OPCODE_case: // Case
        {
            for (int i = 0; i < args.length; i++)
            {
                OpApplNode pair = (OpApplNode) args[i];
                this.collectPrimedLocs(pair.getArgs()[1], c, tbl);
            }
            break;
        }
        case OPCODE_eq:   // x' = 42
        case OPCODE_in: { // x' \in S (eq case "falls through")
            SymbolNode var = this.getPrimedVar(args[0], c, false);
            if (var != null && var.getName().getVarLoc() != -1)
            {
                tbl.put(pred, 0);
            }
            break;
        }
        case OPCODE_cl: // ConjList
        case OPCODE_dl: // DisjList
        case OPCODE_be: // BoundedExists
        case OPCODE_bf: // BoundedForall
        case OPCODE_land:
        case OPCODE_lor:
        case OPCODE_implies:
        case OPCODE_nop: // This case added 13 Nov 2009 by LL to handle subexpression names.
          {
            for (int i = 0; i < args.length; i++)
            {
                this.collectPrimedLocs(args[i], c, tbl);
            }
            break;
        }
        case OPCODE_unchanged: {
            this.collectUnchangedLocs(args[0], c, tbl);
            break;
        }
        case OPCODE_aa: // AngleAct <A>_e
        {
            this.collectPrimedLocs(args[0], c, tbl);
            break;
        }
        case OPCODE_sa: // [A]_e
        {
            this.collectPrimedLocs(args[0], c, tbl);
            tbl.put(args[1], 0);
            break;
        }
        default: {
            if (opcode == 0)
            {
                Object val = this.lookup(opNode, c, false, toolId);

                if (val instanceof OpDefNode)
                {
                    OpDefNode opDef = (OpDefNode) val;
                    // Following added by LL on 10 Apr 2010 to avoid infinite 
                    // recursion for recursive operator definitions
                    if (opDef.getInRecursive()) {
                        return ;
                    }
                    Context c1 = this.getOpContext(opDef, args, c, true, toolId);
                    this.collectPrimedLocs(opDef.getBody(), c1, tbl);
                } else if (val instanceof LazyValue)
                {
                    LazyValue lv = (LazyValue) val;
                    this.collectPrimedLocs(lv.expr, lv.con, tbl);
                }
            }
        }
        }
    }

	private final void collectUnchangedLocs(final SemanticNode expr, final Context c,
			final ObjLongTable<SemanticNode> tbl) {
        if (expr instanceof OpApplNode)
        {
            OpApplNode expr1 = (OpApplNode) expr;
            SymbolNode opNode = expr1.getOperator();
            UniqueString opName = opNode.getName();
            int opcode = BuiltInOPs.getOpCode(opName);

            if (opName.getVarLoc() >= 0)
            {
                // a state variable:
                tbl.put(expr, 0);
                return;
            }

            ExprOrOpArgNode[] args = expr1.getArgs();
            if (opcode == OPCODE_tup)
            {
				// a tuple, might be:
            	// UNCHANGED <<x,y,z>>
            	// or:
            	// vars == <<x,y,z>>
            	// ...
            	// UNCHANGED vars
				// For the latter, we don't want vars == <<x,y,z>> to show up, but the vars in
				// UNCHANGED vars (see CoverageStatisticsTest).
                for (int i = 0; i < args.length; i++)
                {
               		this.collectUnchangedLocs(args[i], c, tbl);
                }
                return;
            }

            if (opcode == 0 && args.length == 0)
            {
                // a 0-arity operator:
                Object val = this.lookup(opNode, c, false, toolId);
                if (val instanceof OpDefNode)
                {
                    this.collectUnchangedLocs(((OpDefNode) val).getBody(), c, tbl);
                    return;
                }
            }
        }
        return;
    }

    public FilenameToStream getResolver()
    {
        return resolver;
    }
    
    public String getRootName() {
    	return new File(this.rootFile).getName();
    }
    
    public String getRootFile() {
    	return this.rootFile;
    }

    public String getConfigFile() {
    	return this.configFile;
    }
    
    public String getSpecDir() {
    	return this.specDir;
    }
    
    public int getId() {
    	return toolId;
    }

	public ModuleNode getModule(final String moduleName) {
		return getSpecProcessor().getSpecObj().getExternalModuleTable().getModuleNode(moduleName);
	}

	public List<File> getModuleFiles(final FilenameToStream resolver) {
		final List<File> result = new ArrayList<File>();
	
		final Enumeration<ParseUnit> parseUnitContext = specProcessor.getSpecObj().parseUnitContext.elements();
		while (parseUnitContext.hasMoreElements()) {
			ParseUnit pu = (ParseUnit) parseUnitContext.nextElement();
			File resolve = resolver.resolve(pu.getFileName(), false);
			result.add(resolve);
		}
		return result;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.uitest/src-aj/org/lamport/tla/toolbox/test/threading/MonitorAdaptor.java<|end_filename|>
package org.lamport.tla.toolbox.test.threading;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.lang.JoinPoint;
import org.eclipse.swt.widgets.Display;

public class MonitorAdaptor {

	/**
	 * Set of all triggered join points
	 */
	private static Set<JoinPoint> joinPoints = new HashSet<JoinPoint>();

	/**
	 * Checks if the current joinPoint has been triggered inside the main (UI)
	 * thread
	 * 
	 * @param joinPoint
	 */
	public static void enter(JoinPoint joinPoint) {
		final Thread currentThread = Thread.currentThread();
		final Thread swtThread = Display.getDefault().getThread();
		if (currentThread == swtThread) {
			joinPoints.add(joinPoint);
//				System.err.println("Called backend code from UI thread!!! "
//						+ joinPoint.toLongString());
		}
	}

	public static boolean hasTriggeredBackendCode() {
		return !joinPoints.isEmpty();
	}

	public static Set<JoinPoint> getTriggeredJoinPoints() {
		return Collections.unmodifiableSet(joinPoints);
	}

	public static void reset() {
		joinPoints.clear();
	}

	/**
	 * Holder for the aspect
	 */
	private static Object aspect;
	
	public static void setAspect(Object o) {
		aspect = o;
	}
	
	public static boolean aspectIsActive() {
		return aspect != null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/pretty-printing.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/spec/pretty-printing.html  -->


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Pretty-Printing Modules</title>
</head>
<!-- a comment here -->

<body>
<h1>Pretty-Printing Modules</h1>

 <P>
You can create and view a pretty-printed
<a href="http://www.adobe.com/products/acrobat/adobepdf.html"  target="_blank">PDF (Portable
Document Format)</a> version of a module.&nbsp;  Just view the module
in a module editor and select&nbsp; <samp>File/Produce PDF Version</samp>.&nbsp;  However,
to do this, you must have the&nbsp; <samp>pdflatex</samp>&nbsp; program installed.&nbsp;
This program is distributed with most versions of&nbsp;
<a href="http://www.latex-project.org/"  target="_blank"><samp>LaTeX</samp></a>&nbsp;
and&nbsp; <a href="http://www.tug.org/"  target="_blank"><samp>TeX</samp></a>.&nbsp;  A popular source
of TeX for PCs is&nbsp; <samp><a href="http://www.miktex.org/"  target="_blank">MiKTeX</a></samp>.
 </P>

<p>The Toolbox runs&nbsp; <samp>pdflatex</samp>&nbsp; to produce a PDF file with the
same name as the module, but with the extension&nbsp; <code>.pdf</code>.&nbsp;  It displays this
file in a separate page of the module editor, using your computer's default browser
to display the PDF file.&nbsp;  (If the browser doesn't have a plug-in that displays PDF files,
you can
<a href="http://get.adobe.com/reader/otherversions/"  target="_blank">find one on the web.</a>)&nbsp;

You can switch between the editable
ASCII version of the module and the PDF version by clicking on the appropriate
tab in the lower-left corner.&nbsp;

Changes made to the module are not automatically made to the PDF version.&nbsp;
To see them, you must create the PDF version again.
</p>

<!--
<p><font size=-1>
On Windows 7 and perhaps other operating systems, the PDF version is displayed outside
the Toolbox in a separate window.&nbsp;  That window must be closed before you can create
a new pretty-printed version.&nbsp; We have not yet figured out how to solve this problem.</font>
</p>
-->

<p>There are things you can do to help the pretty printer
produce better output.&nbsp;  They are described in the
<a href="help-print.html">Helping the Pretty-Printer</a>
help page.
</p>

<p>
A version of the program that does the pretty-printing can be used to add TLA+ and/or
PlusCal code to a LaTeX document.&nbsp;
See the section on the TLATeX Pretty-Printer on
<a href="https://lamport.azurewebsites.net/tla/tools.html#tlatex?unhideBut=hide-tlatex&unhideDiv=tlatex">this page</a>
of the TLA+ Web site.

</p>

<h3>Preferences</h3>

<p>
The&nbsp; <samp>PDF Viewer Preferences</samp>&nbsp; page on
the&nbsp; <samp>File/Preferences</samp>&nbsp; menu provides the following options:

<h4>'Have your OS open PDFs' (macOS) or 'Use built-in PDF viewer' (Windows &amp; Linux)</h4>

By default, the PDF file is displayed using your system's default PDF viewer.&nbsp;

This option causes the Toolbox to instead either have the operating system open the PDF
using the user's default PDF viewing application (in macOS) or to use its own built-in viewer (in Windows and Linux.)&nbsp;

On some systems, the default viewer displays the PDF file in a
separate window that you must close before you can generate a new
version of the file.&nbsp;

If that is not what you want to happen, choose this option.&nbsp;

The built-in viewer does not yet provide a toolbar.&nbsp;

You can navigate with the <samp>Page Up</samp> and <samp>Page Down</samp> keys.&nbsp;

Use the <samp>+</samp> and <samp>-</samp> keys to zoom in and out.&nbsp;

The built-in viewer option is not offered on Mac OS X.

<h4>Regenerate pretty-printed PDF of spec save</h4>

When checked, the Toolbox automatically updates the pretty-printed version of the module every time
its corresponding editor is saved.
This is especially useful in presentations and trainings when the spec editor and PDF viewer
are arranged side by side to interactively build-up the spec but show attendees the pretty-printed version.

<h4>Shade comments</h4>
Comments are shaded in gray.&nbsp;  This is the default.&nbsp;  The darkness of the shading is specified
by the <b>Specify gray level</b> option.&nbsp;  This must be a number between
0.0 (completely black) and 1.0 (no shading).&nbsp;  The default is 0.85.

<p>

Note that comments within comments are not shown in the PDF view.&nbsp; The one exception is that
comments to PlusCal code are shown (even though they and the PlusCal code appear in a comment).

<h4>Do not shade PlusCal code</h4>
A PlusCal algorithm appears in a comment, so shading comments normally causes
PlusCal code to be shaded.&nbsp;  This option causes PlusCal code
not to be shaded.  (The code's comments are still shaded.)


<h4>Number lines</h4>

Number lines in the PDF output.&nbsp;  (This is independent of the line-numbering option for
the module editor.)&nbsp;  The default is unnumbered lines.

<h4>Specify dot command</h4>

This is the command with which the Toolbox calls&nbsp; <samp>dot</samp>&nbsp;
to produce state graph visualizations.&nbsp;  The default value&nbsp; <samp>dot</samp>&nbsp;
should work if the&nbsp; <samp>dot</samp>&nbsp; program is installed on your
computer.&nbsp;  However, if it is not properly installed, you may have to prefix it with the path name
of the program's directory.

<h4>Specify pdflatex command</h4>

This is the command with which the Toolbox calls&nbsp; <samp>pdflatex</samp>&nbsp;
to produce the pretty-printed version.&nbsp;  The default value&nbsp; <samp>pdflatex</samp>&nbsp;
should work if the&nbsp; <samp>pdflatex</samp>&nbsp; program is installed on your
computer.&nbsp;  However, if it is not properly installed, you may have to prefix it with the path name
of the program's directory.

<h4>Specify gray level</h4>

See the <b>Shade comments</b> option above.
</p>
<hr>
<!-- delete rest of line to comment out -->
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href="help-print.html"> Helping the Pretty-Printer </A></dd>
</dl>
<!-- -->
<!-- delete rest of line to comment out -->
<a href = "spec.html">&uarr; Managing Your Specifications</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/Activator.java<|end_filename|>
package org.lamport.tla.toolbox;

import java.util.concurrent.CountDownLatch;

import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.resource.ImageDescriptor;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.spec.nature.TLAParsingBuilder.OutOfBuildSpecModulesGatheringDeltaVisitor;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.spec.parser.ParserDependencyStorage;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

/**
 * The activator class controls the plug-in life cycle
 */
public class Activator extends AbstractTLCActivator
{

    // The plug-in ID
    public static final String PLUGIN_ID = "org.lamport.tla.toolbox";
    
    public static final String IMG_SPEC_OPEN = "img_spec_open";
    public static final String IMG_SPEC_CLOSED = "img_spec_closed";

    // The shared instance
    private static Activator plugin;
    private static WorkspaceSpecManager specManager;
    private static final CountDownLatch latch = new CountDownLatch(1);
    private static ParserDependencyStorage parserDependencyStorage;

    /**
     * The constructor
     */
    public Activator()
    {
    	super(PLUGIN_ID);
    }

    public void start(final BundleContext context) throws Exception
    {
        super.start(context);
        plugin = this;
     
		// Eclipse Neon has started to use PNG instead of GIF icons to support display
		// with high dpi counts. Load two pngs which we used to get from the Eclipse
		// Foundation but now have to provide ourself.
		getImageRegistry().put(IMG_SPEC_OPEN, ImageDescriptor.createFromURL(
				Platform.getBundle(org.lamport.tla.toolbox.Activator.PLUGIN_ID).getEntry("/icons/full/obj16/prj_obj.png")));
		getImageRegistry().put(IMG_SPEC_CLOSED, ImageDescriptor.createFromURL(
				Platform.getBundle(org.lamport.tla.toolbox.Activator.PLUGIN_ID).getEntry("/icons/full/obj16/cprj_obj.png")));
        
        // register the listeners
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        
		// Eagerly initialize the WorkspaceSpecManager to prevent a possible
		// deadlock among threads (including main) that arises if jobs get
		// scheduled and try to lazily access the WorkspaceSpecManager which -in
		// turn- hasn't been initialized yet but locked by another thread.
        //
		// At this point, it can safely be assumed that no build job is running,
        // because we schedule prior to loading the TLAParserBuilder class.
        //
		// Using a WorkspaceJob instead of a "normal" Job makes sure the
		// operation is executed atomically.
        //
		// We do this in a separate thread and not in Activator.start() because
		// the OSGi contract requires for short-running bundle activation
		// (start/stop) methods. Initializing the WorkspaceSpecManager involves
		// I/O though, which makes it a potentially long-running task.
        //
        // @see Bug #260 in general/bugzilla/index.html
        final Job initializerJob = new WorkspaceJob("Initializing workspace...") {
			/* (non-Javadoc)
			 * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor)
			 */
			public IStatus runInWorkspace(IProgressMonitor monitor)
					throws CoreException {
				
				// Wait until bundle is done starting up and we can safely
				// load classes in this thread
				int state = context.getBundle().getState();
				while(state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
					// Do not yield the job because we would potentially give
					// away the lock to the autobuilder job which would then get
					// stuck on the latch we are supposed to take down.
					try {
						synchronized(getThread()) {
							getThread().wait(100);
						}
					} catch (InterruptedException e) {
						logError(e.getMessage(), e);
					}
					state = context.getBundle().getState();
				}
				
				specManager = new WorkspaceSpecManager(monitor);
				latch.countDown();
				return Status.OK_STATUS;
			}
        };
        initializerJob.setRule(workspace.getRuleFactory().buildRule());
		// Give initializerJob a higher priority than regular (autobuild) jobs
		// (e.g. TLAParsingBuilder/PCalDetectingBuilder) which belong to the
		// same job family but have a lower priority. Some - again e.g.
		// TLAParsingBuilder/PCalDetectingBuilder - require the initializerJob
		// to be done.
        initializerJob.setPriority(Job.LONG);
        initializerJob.schedule();
        
		// Running plug-in tests with Eclipse 4.5, the foundation suspends the
		// JobManager at startup causing our jobs to never be executed. In turn,
		// this causes the Toolbox to hang at startup. Thus, resume the JobManager
        // which is a no-op outside the test mode.
        Job.getJobManager().resume();

        // activate handler to show the radio buttons in perspective selection
        // UIJob job = new UIJob("InitCommandsWorkaround") {
        // public IStatus runInUIThread(IProgressMonitor monitor)
        // {
        //
        // ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
        // .getService(ICommandService.class);
        // Command switchPerspectiveCommand = commandService.getCommand(SwitchPerspectiveHandler.COMMAND_ID);
        // switchPerspectiveCommand.isEnabled();
        // return new Status(IStatus.OK, PLUGIN_ID, "Init commands workaround performed succesfully");
        // }
        //
        // };
        // job.schedule();

        workspace.addResourceChangeListener(new IResourceChangeListener() {

            public void resourceChanged(IResourceChangeEvent event)
            {
                IResourceDelta delta = event.getDelta();
                if (delta != null)
                {

                    OutOfBuildSpecModulesGatheringDeltaVisitor moduleFinder = new OutOfBuildSpecModulesGatheringDeltaVisitor();
                    try
                    {
                        // We cannot get the spec manager if it has not been instantiated
                        // because this would trigger a resource change event, and this code
                        // is being called within a resourceChanged method. Such an
                        // infinite loop is not allowed.
                        if (Activator.isSpecManagerInstantiated())
                        {
                            delta.accept(moduleFinder);
                            if (!moduleFinder.getModules().isEmpty())
                            {
                                Spec spec = getSpecManager().getSpecLoaded();
                                if (spec != null)
                                {
                                    spec.setStatus(IParseConstants.UNPARSED);
                                }
                            }
                        }
                    } catch (CoreException e)
                    {
                        Activator.getDefault().logError("Error during post save status update", e);
                    }
                }

            }

        }, IResourceChangeEvent.POST_CHANGE);
    }

    public void stop(BundleContext context) throws Exception
    {
        // unregister the listeners
    	if (specManager != null)
    		specManager.terminate();
        
		// do not null specManager and plugin to let backend jobs finish cleanly
        //
        // remember: Nulling specManager might cause the initialization of a new
        // specManager object during shutdown if this method nulls it and subsequent
        // calls to getSpecManager() occur. This might potentially leave an inconsistent 
        // spec manager on which terminate() might never be called.

//        specManager = null;
//        plugin = null;

    	// In case of a clean shutdown explicitly do a *full* workspace save. If omitted,
    	// the Eclipse foundation's default is to just trigger a *snapshot* save.
    	// The default snapshot save is apparently insufficient when the Eclipse foundation
    	// itself gets updated to a newer version (from 3.x to 4.x in the current case)
    	// (The assumption being that the on-disk format of the *.snap files changed causing 
    	// a subsequent startup to crash the whole Toolbox). 
    	final IWorkspace workspace = ResourcesPlugin.getWorkspace();
        final Job saveJob = new WorkspaceJob("Saving workspace...") {
			/* (non-Javadoc)
			 * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor)
			 */
			public IStatus runInWorkspace(final IProgressMonitor monitor)
					throws CoreException {
		        return workspace.save(true, monitor);
			}
        };
        saveJob.setRule(workspace.getRuleFactory().buildRule());
        saveJob.schedule();
    	
        super.stop(context);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static Activator getDefault()
    {
        return plugin;
    }

	/**
	 * Retrieves a working spec manager instance
	 */
	public static WorkspaceSpecManager getSpecManager() {
		try {
			latch.await();
		} catch (InterruptedException e) {
			// shall never happen
			e.printStackTrace();
			return null;
		}
		return specManager;
	}
    
    /**
     * Retrieves a working instance of parser dependency storage
     */
    public static synchronized ParserDependencyStorage getModuleDependencyStorage()
    {
        if (parserDependencyStorage == null)
        {
            parserDependencyStorage = new ParserDependencyStorage();
        }
        return parserDependencyStorage;
    }

    public static boolean isSpecManagerInstantiated()
    {
        return specManager != null;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/ToolboxCompletionProcessor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic;

import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.BoldStylerProvider;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension5;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension7;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.lamport.tla.toolbox.editor.basic.tla.ITLAReserveredWords;
import org.lamport.tla.toolbox.editor.basic.util.DocumentHelper;
import org.lamport.tla.toolbox.tool.ToolboxHandle;

import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.SymbolMatcher;
import tla2sany.semantic.SymbolNode;
import util.UniqueString;

public abstract class ToolboxCompletionProcessor {
	
    protected final SortedMap<String, List<CompletionProposalTemplate>> proposals = new TreeMap<String, List<CompletionProposalTemplate>>();
    
    protected final SymbolMatcher.NameAndTypeMatcher matcher = new SymbolMatcher.NameAndTypeMatcher();
    
	public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
		final IDocument document = viewer.getDocument();
		// get the selection range
		final Point selectedRange = viewer.getSelectedRange();

		final List<ICompletionProposal> propList = new ArrayList<ICompletionProposal>();
		try {
			// The zero-based row index of the caret.
			final int caretRowIndex = document.getLineOfOffset(offset);
			// The zero-based column index of the caret.
			final int carretColumnIndex = offset - document.getLineOffset(caretRowIndex);
			if (selectedRange.y > 0) {
				// the range is non-empty
				final String text = document.get(selectedRange.x, selectedRange.y);
				computeWordProposals(text, offset, carretColumnIndex, propList);
			} else {
				// the range is empty, no selection in the editor

				// get the region
				final IRegion wordRegion = DocumentHelper.getRegionExpandedBackwards(document, offset,
						DocumentHelper.getDefaultWordDetector());
				final String word = document.get(wordRegion.getOffset(), wordRegion.getLength());
				computeWordProposals(word, offset, carretColumnIndex, propList);
			}
		} catch (final BadLocationException ignore) {
		}
		return propList.toArray(new ICompletionProposal[propList.size()]);
	}

    /**
     * Syntax-based proposal based for word beginning
     */
	private void computeWordProposals(final String word, final int offset, final int carretColumnIndex, final List<ICompletionProposal> propositionList) {
		final int qualifierLength = word.length();
		final int replacementOffset = offset - qualifierLength;

		// keyword and other static proposals
		for (List<CompletionProposalTemplate> list : filterPrefix(proposals, word).values()) {
			// and add to result list
			for (CompletionProposalTemplate template : list) {
				propositionList.add(template.getProposal(replacementOffset, carretColumnIndex - qualifierLength, qualifierLength));
			}
		}
		
		// Try to find matches among the spec's set of symbols (e.g. operators definitions and declarations).
		final SpecObj specObj = ToolboxHandle.getSpecObj();
		if (specObj != null && specObj.getRootModule() != null) { // null if spec hasn't been parsed.
			final ModuleNode rootModule = specObj.getRootModule();

			final Collection<SymbolNode> symbols = rootModule.getSymbols(matcher.setPrefix(word));
			for (final SymbolNode symbolNode : symbols) {
				propositionList.add(new CompletionProposalTemplate(symbolNode.getSignature(), symbolNode.getName(),
						symbolNode.getHumanReadableImage()).getProposal(replacementOffset, carretColumnIndex - qualifierLength, qualifierLength));
			}
		}
	}
    
	public static SortedMap<String, List<CompletionProposalTemplate>> filterPrefix(SortedMap<String, List<CompletionProposalTemplate>> baseMap, String prefix) {
		if (prefix.length() > 0) {
			final char nextLetter = (char) (prefix.charAt(prefix.length() - 1) + 1);
 			final String end = prefix.substring(0, prefix.length() - 1) + nextLetter;
			return baseMap.subMap(prefix, end);
		}
		return baseMap;
	}

	public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
		// Retrieve selected range
		final Point selectedRange = viewer.getSelectedRange();
		if (selectedRange.y > 0) {
			// Text is selected. Create a context information array.
			final IContextInformation[] contextInfos = new ContextInformation[ITLAReserveredWords.ALL_WORDS_ARRAY.length];

			// Create one context information item for each style
			for (int i = 0; i < ITLAReserveredWords.ALL_WORDS_ARRAY.length; i++) {
				contextInfos[i] = new ContextInformation(null, ITLAReserveredWords.ALL_WORDS_ARRAY[i] + " Style");
			}
			return contextInfos;
		}
		return new ContextInformation[0];
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
     */
	public char[] getCompletionProposalAutoActivationCharacters() {
		return null;
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
     */
	public char[] getContextInformationAutoActivationCharacters() {
		return null;
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
     */
	public IContextInformationValidator getContextInformationValidator() {
		return null;
	}

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
     */
	public String getErrorMessage() {
		return null;
	}
	
	protected static class CompletionProposalTemplate {
		private final String fReplacementString;
		private final Image fImage;
		private final IContextInformation fContextInformation;
		private final String fAdditionalProposalInfo;
		private final String fDisplayString;
		
		public CompletionProposalTemplate(String replacementString, Image image, String dipslayString,
				IContextInformation contextInformation, String additionalProposalInfo) {
			this.fReplacementString = replacementString;
			this.fImage = image;
			this.fDisplayString = dipslayString;
			this.fContextInformation = contextInformation;
			this.fAdditionalProposalInfo = additionalProposalInfo;
		}
		
		public CompletionProposalTemplate(String replacementString, Image image, String dipslayString,
				String additionalProposalInfo) {
			this.fReplacementString = replacementString;
			this.fImage = image;
			this.fDisplayString = dipslayString;
			this.fContextInformation = null;
			this.fAdditionalProposalInfo = additionalProposalInfo;
		}
		
		public CompletionProposalTemplate(UniqueString replacementString, UniqueString dipslayString,
				String additionalProposalInfo) {
			this(replacementString.toString(), dipslayString.toString(), additionalProposalInfo);
		}
		
		public CompletionProposalTemplate(String replacementString, UniqueString dipslayString,
				String additionalProposalInfo) {
			this(replacementString, dipslayString.toString(), additionalProposalInfo);
		}
		
		public CompletionProposalTemplate(String replacementString, String dipslayString,
				String additionalProposalInfo) {
			this.fReplacementString = replacementString;
			this.fImage = null;
			this.fDisplayString = dipslayString;
			this.fContextInformation = null;
			this.fAdditionalProposalInfo = additionalProposalInfo;
		}
		
		public CompletionProposalTemplate(String replacementString) {
			this.fReplacementString = replacementString;
			this.fImage = null; // Image for keywords?!
			this.fContextInformation = null;
			this.fAdditionalProposalInfo = null;
			this.fDisplayString = null;
		}

		public ICompletionProposal getProposal(final int replacementOffset, final int wordStartColumnIndex, final int qualifierLength) {
			final String indent = CharBuffer.allocate(wordStartColumnIndex).toString().replace( '\0', ' ' );
			final String indentedReplacementString = fReplacementString.replace("\n", "\n" + indent);
			return new ToolboxCompletionProposal(indentedReplacementString, replacementOffset, qualifierLength,
					indentedReplacementString.length(), fImage, fDisplayString, fContextInformation,
					fAdditionalProposalInfo);
		}
	}
	
	public static class ToolboxCompletionProposal implements ICompletionProposal, ICompletionProposalExtension5, ICompletionProposalExtension7 {

		/** The string to be displayed in the completion proposal popup. */
		private String fDisplayString;
		/** The replacement string. */
		private String fReplacementString;
		/** The replacement offset. */
		private int fReplacementOffset;
		/** The replacement length. */
		private int fReplacementLength;
		/** The cursor position after this proposal has been applied. */
		private int fCursorPosition;
		/** The image to be displayed in the completion proposal popup. */
		private Image fImage;
		/** The context information of this proposal. */
		private IContextInformation fContextInformation;
		/** The additional info of this proposal. */
		private String fAdditionalProposalInfo;

		/**
		 * Creates a new completion proposal based on the provided information. The
		 * replacement string is considered being the display string too. All remaining
		 * fields are set to <code>null</code>.
		 *
		 * @param replacementString
		 *            the actual string to be inserted into the document
		 * @param replacementOffset
		 *            the offset of the text to be replaced
		 * @param replacementLength
		 *            the length of the text to be replaced
		 * @param cursorPosition
		 *            the position of the cursor following the insert relative to
		 *            replacementOffset
		 */
		public ToolboxCompletionProposal(String replacementString, int replacementOffset, int replacementLength,
				int cursorPosition) {
			this(replacementString, replacementOffset, replacementLength, cursorPosition, null, null, null, null);
		}

		/**
		 * Creates a new completion proposal. All fields are initialized based on the
		 * provided information.
		 *
		 * @param replacementString
		 *            the actual string to be inserted into the document
		 * @param replacementOffset
		 *            the offset of the text to be replaced
		 * @param replacementLength
		 *            the length of the text to be replaced
		 * @param cursorPosition
		 *            the position of the cursor following the insert relative to
		 *            replacementOffset
		 * @param image
		 *            the image to display for this proposal
		 * @param displayString
		 *            the string to be displayed for the proposal
		 * @param contextInformation
		 *            the context information associated with this proposal
		 * @param additionalProposalInfo
		 *            the additional information associated with this proposal
		 */
		public ToolboxCompletionProposal(String replacementString, int replacementOffset, int replacementLength,
				int cursorPosition, Image image, String displayString, IContextInformation contextInformation,
				String additionalProposalInfo) {
			Assert.isNotNull(replacementString);
			Assert.isTrue(replacementOffset >= 0);
			Assert.isTrue(replacementLength >= 0);
			Assert.isTrue(cursorPosition >= 0);

			fReplacementString = replacementString;
			fReplacementOffset = replacementOffset;
			fReplacementLength = replacementLength;
			fCursorPosition = cursorPosition;
			fImage = image;
			fDisplayString = displayString;
			fContextInformation = contextInformation;
			fAdditionalProposalInfo = additionalProposalInfo;
		}

		public void apply(IDocument document) {
			try {
				document.replace(fReplacementOffset, fReplacementLength, fReplacementString);
			} catch (BadLocationException x) {
				// ignore
			}
		}

		public Point getSelection(IDocument document) {
			return new Point(fReplacementOffset + fCursorPosition, 0);
		}

		public IContextInformation getContextInformation() {
			return fContextInformation;
		}

		public Image getImage() {
			return fImage;
		}

		public String getDisplayString() {
			if (fDisplayString != null)
				return fDisplayString;
			return fReplacementString;
		}

		public String getAdditionalProposalInfo() {
			return fAdditionalProposalInfo;
		}

		public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
			return getAdditionalProposalInfo();
		}

		public StyledString getStyledDisplayString(IDocument document, int offset,
				BoldStylerProvider boldStylerProvider) {
			final StyledString styledString = new StyledString();
			styledString.append(getDisplayString());
			styledString.append(": ");
			styledString.append(fReplacementString.replaceAll("\n[ ]*", " "), StyledString.COUNTER_STYLER);
			return styledString;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/FPSetFactoryTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;

import org.junit.Assume;
import org.junit.Test;

import tlc2.tool.distributed.fp.FPSetRMI;
import util.TLCRuntime;

@SuppressWarnings("deprecation")
public class FPSetFactoryTest {
	// Has to be larger than util.TLCRuntime.MinFpMemSize. For off-heap/non-heap
	// tests it should not exceed what the VM allocates by default (usually
	// 64mb). 64mb is also the default used by util.TLCRuntime.getNonHeapPhysicalMemory().
	private static final long MEMORY = 64L * 1024L * 1024L;

	/* Test diskfpset subclasses which always require two instances */
	
	@Test
	public void testGetDiskFPSet() {
		assertTrue(FPSetFactory.isDiskFPSet(DiskFPSet.class.getName()));
		assertTrue(FPSetFactory.isDiskFPSet(HeapBasedDiskFPSet.class.getName()));
		assertTrue(FPSetFactory.isDiskFPSet(OffHeapDiskFPSet.class.getName()));
		assertTrue(FPSetFactory.isDiskFPSet(LSBDiskFPSet.class.getName()));
		assertTrue(FPSetFactory.isDiskFPSet(MSBDiskFPSet.class.getName()));

		assertFalse(FPSetFactory.isDiskFPSet(FPSet.class.getName()));
		assertFalse(FPSetFactory.isDiskFPSet(FPSetRMI.class.getName()));
		
		assertFalse(FPSetFactory.isDiskFPSet(MultiFPSet.class.getName()));
		
		assertFalse(FPSetFactory.isDiskFPSet(MemFPSet.class.getName()));
		assertFalse(FPSetFactory.isDiskFPSet(MemFPSet1.class.getName()));
		assertFalse(FPSetFactory.isDiskFPSet(MemFPSet2.class.getName()));
		
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		assertTrue(fpSetConfiguration.allowsNesting());
	}
	
	/* Test single FPSet with default memory */

	@Test
	public void testGetFPSetMSB() throws RemoteException {
		// Explicitly set MSBDiskFPSet to overwrite any previous setting (if any)
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		doTestGetFPSet(MSBDiskFPSet.class, fpSetConfiguration);
	}

	@Test
	public void testGetFPSetLSB() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		doTestGetFPSet(LSBDiskFPSet.class, fpSetConfiguration);
	}

	@Test
	public void testGetFPSetOffHeap() throws RemoteException {
		Assume.assumeTrue(TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86_64);
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		doTestGetFPSet(OffHeapDiskFPSet.class, fpSetConfiguration);
	}

	/* Test single FPSet with explicit memory */
	
	@Test
	public void testGetFPSetMSBWithMem() throws RemoteException {
		// Explicitly set MSBDiskFPSet to overwrite any previous setting (if any)
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setRatio(1.0d);
		FPSet fpSet = doTestGetFPSet(MSBDiskFPSet.class, fpSetConfiguration);
		assertEquals(MEMORY, fpSet.getConfiguration().getMemoryInBytes());

		doTestNested(MSBDiskFPSet.class, fpSetConfiguration, (MultiFPSet) fpSet);
	}

	@Test
	public void testGetFPSetLSBWithMem() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setRatio(1.0d);
		FPSet fpSet = doTestGetFPSet(LSBDiskFPSet.class, fpSetConfiguration);
		assertEquals(MEMORY, fpSet.getConfiguration().getMemoryInBytes());

		doTestNested(LSBDiskFPSet.class, fpSetConfiguration, (MultiFPSet) fpSet);
	}
	
	/* Test single FPSet with explicit memory and ratio */
	
	@Test
	public void testGetFPSetMSBWithMemAndRatio() throws RemoteException {
		// Explicitly set MSBDiskFPSet to overwrite any previous setting (if any)
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setRatio(.5d);
		FPSet fpSet = doTestGetFPSet(MSBDiskFPSet.class, fpSetConfiguration);
		assertEquals(MEMORY / 2, fpSet.getConfiguration().getMemoryInBytes());

		doTestNested(MSBDiskFPSet.class, fpSetConfiguration, (MultiFPSet) fpSet);
	}

	@Test
	public void testGetFPSetLSBWithMemAndRatio() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setRatio(.5d);
		FPSet fpSet = doTestGetFPSet(LSBDiskFPSet.class, fpSetConfiguration);
		assertEquals(MEMORY / 2, fpSet.getConfiguration().getMemoryInBytes());


		doTestNested(LSBDiskFPSet.class, fpSetConfiguration, (MultiFPSet) fpSet);
	}
	
	/* Test MultiFPSet with default memory */
	
	@Test
	public void testGetFPSetMultiFPSet() throws RemoteException {
		// Explicitly set MSBDiskFPSet to overwrite any previous setting (if any)
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setFpBits(1);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);
		
		doTestNested(MSBDiskFPSet.class, fpSetConfiguration, mFPSet);
	}
	
	@Test
	public void testGetFPSetLSBMultiFPSet() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setFpBits(1);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);

		doTestNested(LSBDiskFPSet.class, fpSetConfiguration, mFPSet);
	}
	
	@Test
	public void testGetFPSetOffHeapMultiFPSet() throws RemoteException {
		Assume.assumeTrue(TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86_64);
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setFpBits(1);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);

		doTestNested(OffHeapDiskFPSet.class, fpSetConfiguration, mFPSet);
	}
	
	/* Test MultiFPSet with explicit memory */

	@Test
	public void testGetFPSetMultiFPSetWithMem() throws RemoteException {
		// Explicitly set MSBDiskFPSet to overwrite any previous setting (if any)
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setFpBits(1);
		fpSetConfiguration.setRatio(1.0d);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);
		
		doTestNested(MSBDiskFPSet.class, fpSetConfiguration, mFPSet);
	}
	
	@Test
	public void testGetFPSetLSBMultiFPSetWithMem() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setFpBits(1);
		fpSetConfiguration.setRatio(1.0d);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);

		doTestNested(LSBDiskFPSet.class, fpSetConfiguration, mFPSet);
	}
	
	@Test
	public void testGetFPSetOffHeapMultiFPSetWithMem() throws RemoteException {
		Assume.assumeTrue(TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86_64);
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(MEMORY);
		fpSetConfiguration.setFpBits(1);
		fpSetConfiguration.setRatio(1.0d);
		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);

		doTestNested(OffHeapDiskFPSet.class, fpSetConfiguration, mFPSet);
	}

	@Test
	public void testGetFPSetOffHeapMultiFPSet42() throws RemoteException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		
		final long nonHeapPhysicalMemory = TLCRuntime.getInstance().getNonHeapPhysicalMemory();
		
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		assertEquals(nonHeapPhysicalMemory, fpSetConfiguration.getMemoryInBytes());
		assertEquals(nonHeapPhysicalMemory / FPSet.LongSize, fpSetConfiguration.getMemoryInFingerprintCnt());

		final MultiFPSet mFPSet = (MultiFPSet) doTestGetFPSet(MultiFPSet.class, fpSetConfiguration);

		final FPSetConfiguration multiConfig = mFPSet.getConfiguration();
		assertEquals(OffHeapDiskFPSet.class.getName(), multiConfig.getImplementation());
		assertEquals(1, multiConfig.getFpBits());
		assertEquals(2, multiConfig.getMultiFPSetCnt());
		assertEquals(nonHeapPhysicalMemory, multiConfig.getMemoryInBytes());
		assertEquals(nonHeapPhysicalMemory / FPSet.LongSize, multiConfig.getMemoryInFingerprintCnt());
		
		final FPSet[] fpSets = mFPSet.getFPSets();
		assertEquals(2, fpSets.length);
		
		for (FPSet fpSet : fpSets) {
			final OffHeapDiskFPSet offFPset = (OffHeapDiskFPSet) fpSet;
			final FPSetConfiguration offConfig = offFPset.getConfiguration();
			assertEquals(OffHeapDiskFPSet.class.getName(), offConfig.getImplementation());
			assertEquals(1, offConfig.getFpBits());
			assertEquals(2, offConfig.getMultiFPSetCnt());
			assertEquals(nonHeapPhysicalMemory / 2L, offConfig.getMemoryInBytes());
			assertEquals((nonHeapPhysicalMemory / FPSet.LongSize) / 2L, offConfig.getMemoryInFingerprintCnt());
			assertEquals((offConfig.getMemoryInBytes() / FPSet.LongSize), offConfig.getMemoryInFingerprintCnt());
		}
	}

	/* Helper methods */
	
	private FPSet doTestGetFPSet(final Class<? extends FPSet> class1, final FPSetConfiguration fpSetConfig) throws RemoteException, NoSuchObjectException {
		final FPSet fpSet = FPSetFactory.getFPSet(fpSetConfig);
		if (!FPSetFactory.isDiskFPSet(class1.getName())) {
			assertTrue(class1.isAssignableFrom(fpSet.getClass()));
		}
		
		return fpSet;
	}
	
	private void doTestNested(final Class<? extends FPSet> clazz, final FPSetConfiguration fpSetConfiguration,
			final MultiFPSet mFPSet) {
		final FPSet[] fpSets = mFPSet.getFPSets();

		// Check expected amount of fpSets created
		assertEquals(fpSetConfiguration.getMultiFPSetCnt(), fpSets.length);
		
		long memoryInBytes = 0L;
		for (FPSet fpSet : fpSets) {
			// Check if all nested FPSets have proper type
			assertTrue(clazz.isAssignableFrom(fpSet.getClass()));
			
			// Check if correct amount of memory allocated/dedicated
			memoryInBytes += fpSet.getConfiguration().getMemoryInBytes();
			
			// Check correct memory again (this time via DiskFPSet stats)
			if (fpSet instanceof FPSetStatistic) {
				long maxTblCnt = ((FPSetStatistic) fpSet).getMaxTblCnt();
				// make sure nested FPSets don't overallocate memory
				assertTrue("Nested FPSet has over-allocated memory.", fpSet.getConfiguration()
						.getMemoryInFingerprintCnt() >= maxTblCnt);
				
				assertTrue(fpSet.getConfiguration().getMemoryInFingerprintCnt() >= maxTblCnt);
			}
		}
		
		// All nested FPSets combined are supposed to use all FPSet memory
		// dedicated to the MultiFPSet (unless the user decides to live with the
		// implementation default)
		assertEquals(mFPSet.getConfiguration().getMemoryInBytes(), memoryInBytes);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TableauNodePtrTable.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

/**
 * {@link TableauNodePtrTable} (and its sibling {@link NodePtrTable} for
 * tableau-less liveness checking) is a - highly optimized - set of all nodes in
 * the behavior graph {@link TableauDiskGraph}.
 * <p>
 * Each node in the behavior graph consists of the pair <<state, tidx>> (where
 * state is a state's fingerprint) and auxiliary information. The auxiliary
 * information is:
 * <ul>
 * <li>An offset into the second set (@see {@link AbstractDiskGraph#nodeRAF})
 * which represents the arcs between the nodes (logically outgoing transitions).
 * Technically this is a pointer location into the second disk file of
 * {@link TableauDiskGraph}.</li>
 * <li>The node's link number during Tarjan's SCC search.</li>
 * <li>A flag if the node is done or not (see {@link TableauNodePtrTable#UNDONE}
 * below).</li>
 * <li>A flag that marks a node an initial node.</li>
 * <li>A flag if the node has been seen before during error trace re-creation
 * (see {@link LiveWorker#printTrace}.</li>
 * </ul>
 * <p>
 * The last item indicates that this class is used in two scenarios. It's
 * primary purpose is to be the backing store of the liveness/behavior disc
 * graph. Additionally though, LiveWorker#printTrace independently instantiates
 * a new {@link TableauNodePtrTable} to do its work.
 * <p>
 * To minimize {@link TableauNodePtrTable}'s space/memory requirements, the
 * auxiliary information replace each other depending on the phase of liveness
 * checking.<br>
 * During model checking (safety checking) the auxiliary information is set to a
 * pointer location (long) pointing into the arcs set and the high bits of the
 * long are used to mark nodes as done or undone.<br>
 * As soon as the SCC search starts, the pointer location is replaced by the SCC
 * link number.<br>
 * Once a liveness violation has been detected, the seen flag is set during the
 * error trace path reconstruction.
 * <p>
 * Internally {@link TableauNodePtrTable} hashes the node's fingerprint to a
 * bucket address. In case of hash collision, open addressing is used.
 */
public class TableauNodePtrTable {

	/**
	 * A node is marked UNDONE if it is:
	 * <ul>
	 * <li>An initial node <b>s0</b> and not yet visited again by
	 * LiveChecker#addNextState(<b>s0</b>)</li>
	 * <li>A previously unseen successor node <b>t</b> of a node <b>s</b> that
	 * is added as an outgoing transition of <b>s</b> when <b>s</b> is being
	 * added via LiveChecker#addNextState(<b>s</b> )</li>
	 * </ul>
	 * <p>
	 * It logically markers the successor node <b>t</b> to be incomplete which
	 * can only happen during liveness checking of a <b>partial</b> liveness
	 * graph.
	 */
	public static final long UNDONE = 0xFFFFFFFE00000000L;
	
	private int count;
	private int length;
	private int thresh;
	private int[][] nodes;

	public TableauNodePtrTable(int size) {
		this.count = 0;
		this.length = size;
		this.thresh = (int) (size * 0.75);
		this.nodes = new int[size][];
	}

	/* The number of elements in this table. */
	public final int size() {
		return this.count;
	}

	public final int getSize() {
		return this.length;
	}

	/**
	 * Return the value associated with the key <k, tidx> if the table contains
	 * <k, tidx>. Otherwise, return -1.
	 */
	public final long get(final long k, final int tidx) {
		if (count >= thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				return -1;
			}
			if (getKey(node) == k) {
				int idx = getIdx(node, tidx);
				if (idx == -1) {
					return -1;
				}
				return getElem(node, idx);
			}
			loc = (loc + 1) % this.length;
		}
	}

	/**
	 * Add <tidx, elem> into the table. If the table has already contained <k,
	 * tidx>, overwrite the old value.
	 */
	public final void put(long k, int tidx, long elem) {
		if (this.count >= this.thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				this.nodes[loc] = addElem(k, tidx, elem);
				this.count++;
				return;
			}
			// Verify that the node at position loc has the correct key. Due to
			// hash collisions, it might be a different node that hashes to the
			// same bucket. If this is the case, increment the location to check
			// the next bucket (loc + 1 below).
			if (getKey(node) == k) {
				// Iff this is the correct key, search through the nodes and get
				// the one with the matching tableau index.
				int cloc = getIdx(node, tidx);
				if (cloc == -1) {
					// The list of nodes does not contain the give tableau idx
					// yet, thus append a new element. Technically, it means we
					// grow the nodes array by three and insert the tableau idx
					// and its element.
					this.nodes[loc] = appendElem(node, tidx, elem);
				} else {
					// Nodes already contains an entry for the given tableau.
					// Update its element. The element is either a pointer
					// location, MAX_LINK, MAX_PTR or a REACHABLE mark. The
					// previous value is overwritten.
					putElem(this.nodes[loc], elem, cloc);
				}
				return;
			}
			loc = (loc + 1) % this.length;
		}
	}

	/**
	 * Return k's location if the table contains <k, tidx>. Otherwise, return
	 * -1.
	 */
	public final int getLoc(long k, int tidx) {
		if (count >= thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				return -1;
			}
			if (getKey(node) == k) {
				if (getIdx(node, tidx) == -1) {
					return -1;
				}
				return loc;
			}
			loc = (loc + 1) % this.length;
		}
	}

	/* Return all nodes with key k. Return null if this does not contain k. */
	public final int[] getNodes(long k) {
		if (count >= thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				return null;
			}
			if (getKey(node) == k) {
				return this.nodes[loc];
			}
			loc = (loc + 1) % this.length;
		}
	}

	/* Return k's location. Return -1 if this does not contain k. */
	public final int getNodesLoc(long k) {
		if (count >= thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				return -1;
			}
			if (getKey(node) == k) {
				return loc;
			}
			loc = (loc + 1) % this.length;
		}
	}

	public final int[] getNodesByLoc(int loc) {
		return this.nodes[loc];
	}

	/**
	 * This method returns true iff we have already done the nodes with key k.
	 * If we have done with k and a new node is being added, we must get this
	 * new node done.
	 */
	public final boolean isDone(long k) {
		int[] node = this.getNodes(k);
		if (node == null) {
			return false;
		}
		if (node.length == 2) {
			return true;
		}
		// see NOT_DONE constant".
		return node[3] != -2;
	}

	// Called by addNextState
	public final int setDone(long k) {
		if (this.count >= this.thresh) {
			this.grow();
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			int[] node = this.nodes[loc];
			if (node == null) {
				this.nodes[loc] = addKey(k);
				this.count++;
				return loc;
			}
			if (getKey(node) == k) {
				if (node.length > 2 && node[3] == -2) {
					// Set this to something other than -2 (see NOT_DONE).
					node[3] = -3;
				}
				return loc;
			}
			loc = (loc + 1) % this.length;
		}
	}

	private final void put(int[] node) {
		long k = getKey(node);
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			if (this.nodes[loc] == null) {
				this.nodes[loc] = node;
				return;
			}
			loc = (loc + 1) % this.length;
		}
	}
	
	/**
	 * Clears the seen flag of all records set by static setSeen(..) calls
	 * earlier.
	 * <p>
	 * Post-Condition: None of the records is marked seen.
	 * 
	 * @see TableauNodePtrTable#setSeen(int[])
	 * @see TableauNodePtrTable#setSeen(int[], int)
	 */
	public final void resetElems() {
		// Only called when the error trace is being printed. 
		for (int i = 0; i < this.nodes.length; i++) {
			int[] node = this.nodes[i];
			if (node != null) {
				for (int j = 3; j < node.length; j += getElemLength()) {
					node[j] &= 0x7FFFFFFF; // Clear the MSB set by setSeen(..)
				}
			}
		}
	}

	/* Double the table when the table is full by the threshhold. */
	private final void grow() {
		this.length = 2 * this.length + 1;
		this.thresh = (int) (this.length * 0.75);
		int[][] oldNodes = this.nodes;
		this.nodes = new int[this.length][];
		for (int i = 0; i < oldNodes.length; i++) {
			int[] node = oldNodes[i];
			if (node != null) {
				this.put(node);
			}
		}
	}
	
	/**
	 * @return The length of an elem "record" in nodes[]
	 */
	public int getElemLength() {
		return 3;
	}

	/*
	 * Private static helper methods below
	 */

	private static int[] addKey(long key) {
		int[] node = new int[2];
		node[0] = (int) (key >>> 32);
		node[1] = (int) (key & 0xFFFFFFFFL);
		return node;
	}

	protected int[] addElem(long key, int tidx, long elem) {
		int[] node = new int[3 + getElemLength() - 1];
		node[0] = (int) (key >>> 32);
		node[1] = (int) (key & 0xFFFFFFFFL);
		node[2] = tidx;
		node[3] = (int) (elem >>> 32);
		node[4] = (int) (elem & 0xFFFFFFFFL);
		return node;
	}

	protected int[] appendElem(int[] node, int tidx, long elem) {
		int len = node.length;
		int[] newNode = new int[len + getElemLength()];
		System.arraycopy(node, 0, newNode, 0, len);
		newNode[len] = tidx;
		newNode[len + 1] = (int) (elem >>> 32);
		newNode[len + 2] = (int) (elem & 0xFFFFFFFFL);
		return newNode;
	}

	/*
	 * Static helper methods below
	 */
	
	public static long getKey(int[] node) {
		long high = node[0];
		long low = node[1];
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	public static long getElem(int[] node, int loc) {
		long high = node[loc + 1];
		long low = node[loc + 2];
		return (high << 32) | (low & 0xFFFFFFFFL);
	}
	

	public final int getIdx(int[] node, int tidx) {
		int len = node.length;
		for (int i = 2; i < len; i += getElemLength()) {
			if (node[i] == tidx) {
				return i;
			}
		}
		return -1;
	}
	
	public int getElemTidx(int[] node, int loc) {
		// This implementation does not store the tableau index.
		return -1;
	}

	public void putElem(int[] node, long elem, int tableauIdx, int loc) {
		node[loc + 1] = (int) (elem >>> 32);
		node[loc + 2] = (int) (elem & 0xFFFFFFFFL);
		// ignores tableau index
	}

	public static void putElem(int[] node, long elem, int loc) {
		node[loc + 1] = (int) (elem >>> 32);
		node[loc + 2] = (int) (elem & 0xFFFFFFFFL);
	}

	public static int getTidx(int[] node, int loc) {
		return node[loc];
	}

	/*
	 * Helper methods used by LiveWorker#printTrace(..) only. Note that
	 * printTrace does not use the TNPT instance of the DiskGraph but its own
	 * instance only containing a single SCC.
	 */
	public static final int END_MARKER = -1;
	
	public static int startLoc(int[] node) {
		return (node.length > 2) ? 2 : END_MARKER;
	}

	public static int nextLoc(int[] node, int curLoc) {
		int loc = curLoc + 3;
		return (loc < node.length) ? loc : END_MARKER;
	}

	/**
	 * @param nodes
	 * @return True, iff the record at tloc has been marked seen.
	 * @see TableauNodePtrTable#setSeen(int[], int)
	 */
	public static boolean isSeen(int[] nodes, int tloc) {
		return getElem(nodes, tloc) < 0;
	}

	/**
	 * Marks the record at tloc seen.
	 * 
	 * @param nodes
	 * @see TableauNodePtrTable#setSeen(int[])
	 * @see TableauNodePtrTable#resetElems()
	 */
	public static void setSeen(int[] nodes, int tloc) {
		long ptr = getElem(nodes, tloc);
		putElem(nodes, (ptr | 0x8000000000000000L), tloc); // Set the MSB
	}

	public static long getPtr(long ptr) {
		return (ptr & 0x7FFFFFFFFFFFFFFFL);
	}

	/**
	 * @see TableauNodePtrTable#setSeen(int[])
	 * @param nodes
	 * @return True, iff the record has been marked seen.
	 */
	public static boolean isSeen(int[] nodes) {
		return nodes[3] < 0;
	}

	/**
	 * Marks this record seen.
	 * 
	 * @param nodes
	 * @see TableauNodePtrTable#resetElems()
	 */
	public static void setSeen(int[] nodes) {
		nodes[3] |= 0x80000000; // Set the MSB
	}

	public static final int NO_PARENT = -1;
	
	public static int getParent(int[] nodes) {
		return nodes[4];
	}

	public static void setParent(int[] nodes, int loc) {
		assert loc >= NO_PARENT && loc <= AbstractDiskGraph.MAX_PTR;
		nodes[4] = loc;
	}

  	/*
	 * The detailed formatter below can be activated in Eclipse's variable view
	 * by choosing "New detailed formatter" from the nodePtrTable's context menu.
	 * Insert "TableauNodePtrTable.DetailedFormatter.toString(this);".
	 */
  	public static class DetailedFormatter {
  		public static String toString(final TableauNodePtrTable table) {
  			final StringBuffer buf = new StringBuffer(table.count);
  			for (int i = 0; i < table.nodes.length; i++) {
  				if (table.nodes[i] != null) {
  					final int[] node = table.nodes[i];
  					
  					// fingerprint
  					final long fp = ((long) node[0] << 32) | ((long) node[1] & 0xFFFFFFFFL);
  					buf.append("fp (key): " + fp);
  					buf.append(" (idx: " + i + ")");
  					buf.append(" isDone: " + (node.length == 2 || (node.length > 2 && node[3] != -2)));
  					buf.append("\n");
  					
					// A node maintains n records. Each record logically
					// contains information - combined with the fingerprint -
					// about the full tuple <<fp, tidx, loc>>.
  					// Depending on the state of the record, the loc might
  					// also be overwritten by the SCC link number. 
  					int j = 2;
  					for (; j < node.length - 1; j+=table.getElemLength()) { // don't miss the ptr at the end
  						buf.append("\t");
  						// tableau index
  						final int tidx = node[j];
  						buf.append(" tidx: " + tidx);
  						// element
  						final long elem = getElem(node, j);
  						if (AbstractDiskGraph.isFilePointer(elem)) {
  							if (table.isDone(fp)) {
  								buf.append("  ptr: " + elem);
  							} else {
  								buf.append("  ptr: undone");
  							}
  						} else if (AbstractDiskGraph.MAX_PTR == elem){
  							buf.append(" elem: Init State");
  						} else {
  							final long offset = AbstractDiskGraph.MAX_PTR + 1;
  							buf.append(" pred: " + (elem - offset));
  						}
  						final int predTidx = table.getElemTidx(node, j);
  						if (predTidx != -1) {
  							buf.append(" predtidx: " + predTidx);
  						}
  						buf.append(", isSeen: " + isSeen(node, j));
  						buf.append("\n");
  					}
  				}
  			}
  			return buf.toString();
  		}
  	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/coverage/CoverageHashTable.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import java.util.Set;

import tla2sany.explorer.ExploreNode;
import tla2sany.semantic.OpDefNode;

@SuppressWarnings("serial")
class CoverageHashTable extends java.util.Hashtable<Integer, ExploreNode> {
	private final Set<OpDefNode> nodes;

	public CoverageHashTable(final Set<OpDefNode> nodes) {
		this.nodes = nodes;
	}

	@Override
	public ExploreNode get(Object key) {
		// Return null here to visit an OpDefNode D multiple times if D is "called" from
		// multiple OpApplNodes. However, stop endless recursion if D is a RECURSIVE
		// operator.
		final ExploreNode v = super.get(key);
		if (v instanceof OpDefNode) {
			final OpDefNode odn = (OpDefNode) v;
			if (odn.getInRecursive()) {
				if (nodes.contains(odn)) {
					// RECURSIVE operators
					return v;
				}
			}
		}
		return null;
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/ObligationStatusMessage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;

import tla2sany.st.Location;

/**
 * Contains data about the status of an obligation.
 * 
 * An obligation status message contains an id, method, status,
 * and potentially the pretty printed obligation string. These attributes
 * can be accessed by their respective get methods.
 * 
 * @author drickett
 *
 * Modified 16 April 2011 to add `reason' field.
 */
public class ObligationStatusMessage extends TLAPMMessage
{

    public static final String ID_FIELD = "id";
    public static final String METH_FIELD = "meth";
    public static final String OBL_FIELD = "obl";
    public static final String PROVER_FIELD = "prover";
    public static final String ALREADY_FIELD = "already";
    public static final String REASON_FIELD = "reason";

    /**
     * Status of the obligation.
     */
    private String status;
    /**
     * Location in module of obligation.
     */
    private Location location;
    /**
     * The obligation as a string.
     */
    private String obString;
    /**
     * The name of the backend used.
     */
    private String prover;
    /**
     * The method used by prover.
     */
    private String method;
    /**
     * The id of the obligation.
     */
    private int id;
    /**
     * True iff this status comes
     * from the fingerprints file.
     */
    private boolean alreadyProcessed = false;

    /**
     * The reason field either indicates a timeout value
     * or equals "false".
     */
    private String reason;
    /**
     * 
     * @param offset
     * @param length
     * @param type
     * @param status see status constants in this class.
     */
    private ObligationStatusMessage()
    {
    }

    /**
     * Gets the string representing what the latest
     * status for this obligation is for the prover given
     * by {@link #getMethod()}.
     * 
     * @return
     */
    public String getStatus()
    {
        return status;
    }

    /**
     * Returns the location describing the step.
     * This location is consistent with SANY Locations
     * in that the end column corresponds to the column before the last
     * character in the location.
     * For example, if the location described the string
     * "ab", then begin column would be n and end column would be n+1.
     * 
     * @return
     */
    public Location getLocation()
    {
        return location;
    }

    /**
     * Returns the pretty printed form of the obligation
     * if that is part of the message. Otherwise returns
     * null.
     * 
     * @return
     */
    public String getObString()
    {
        return obString;
    }

    /**
     * Returns the id of the obligation.
     * 
     * @return
     */
    public int getID()
    {
        return id;
    }

    /**
     * Returns the name of the backend for which this is
     * a message. tlapm, isabelle, zenon, etc.
     * 
     * Returns null if there is no prover associated
     * with this message. This occurs if the status
     * is {@link ProverHelper#TO_BE_PROVED}.
     * That is the first message that arrives for every
     * obligation.
     * 
     * @return
     */
    public String getBackend()
    {
        return prover;
    }

    /**
     * Returns the method used by the prover whose name is given
     * by {@link #getBackend()}. Cooper, auto, etc.
     * 
     * Returns null if there is no method associated
     * with this message. This currently only occurs
     * when the status is {@link ProverHelper#TO_BE_PROVED}
     * or {@link ProverHelper#TRIVIAL}.
     * 
     * @return
     */
    public String getMethod()
    {
        return method;
    }

    /**
     * Returns true iff this status comes
     * from the fingerprints file.
     */
    public boolean isAlreadyProcessed()
    {
        return alreadyProcessed;
    }

    public String getReason() {
        return reason;
    }
    /**
     * Creates a new {@link ObligationStatusMessage} from the {@link Set}
     * of {@link Entry} where the key of each {@link Entry} is the field
     * name and the value is the field value string as output by the TLAPM.
     * 
     * @param fieldPairs
     * @return
     */
    public static ObligationStatusMessage getObMessage(Set fieldPairs, String moduleName)
    {
        ObligationStatusMessage message = new ObligationStatusMessage();

        for (Iterator it = fieldPairs.iterator(); it.hasNext();)
        {
            Map.Entry nextEntry = (Map.Entry) it.next();
            String fieldName = (String) nextEntry.getKey();
            String fieldValue = (String) nextEntry.getValue();
            if (fieldName != null && fieldValue != null)
            {
                if (fieldName.equals(LOC_FIELD))
                {
                    message.location = parseLocation(fieldValue, moduleName);
                } else if (fieldName.equals(OBL_FIELD))
                {
                    message.obString = fieldValue;
                } else if (fieldName.equals(STATUS_FIELD))
                {
                    message.status = fieldValue;
                } else if (fieldName.equals(ID_FIELD))
                {
                    try
                    {
                        message.id = Integer.parseInt(fieldValue.trim());
                    } catch (NumberFormatException e)
                    {
                        ProverUIActivator.getDefault().logError("Error parsing obligation id from TLAPM message. ID string : "
                                + fieldValue, e);
                    }
                } else if (fieldName.equals(METH_FIELD))
                {
                    message.method = fieldValue;
                } else if (fieldName.equals(PROVER_FIELD))
                {
                    message.prover = fieldValue;
                } else if (fieldName.equals(ALREADY_FIELD))
                {
                    message.alreadyProcessed = Boolean.parseBoolean(fieldName.trim());
                } else if (fieldName.equals(REASON_FIELD)) {
                    message.reason = fieldValue;
                } else
                {
                    ProverUIActivator.getDefault().logDebug("Unknown field name for obligation status message : " + fieldName + ".");
                }
            }
        }

        return message;
    }

    public String toString()
    {
        return "---------Obligation status message--------" + "\nLOCATION : " + location + "\nID : " + id
                + "\nOBLIGATION : " + obString + "\nSTATUS : " + status + "\nMETHOD : " + method;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/StatefulRuntimeException.java<|end_filename|>
package tlc2.tool;

@SuppressWarnings("serial")
public class StatefulRuntimeException extends RuntimeException {

	private boolean isKnown = false;
	
	public StatefulRuntimeException() {
		super();
	}

	public StatefulRuntimeException(String message) {
		super(message);
	}

	public StatefulRuntimeException(String message, Throwable cause) {
		super(message, cause);
	}

	public boolean setKnown() {
		boolean old = isKnown;
		isKnown = true;
		return old;
	}

	public boolean isKnown() {
		return isKnown;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/handler/EmbeddedPDFViewerRunnable.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox.tool.tla2tex.handler;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PartInitException;
import org.lamport.tla.toolbox.util.UIHelper;

public class EmbeddedPDFViewerRunnable extends AbstractPDFViewerRunnable {

	public EmbeddedPDFViewerRunnable(final ProducePDFHandler handler, final IWorkbenchPartSite site, final IResource aSpecFile) {
		super(handler, site, aSpecFile);
	}

	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		monitor.subTask("Opening PDF File");

		try {
			//TODO Open on part stack next to the spec editor
			part = UIHelper.openEditorUnchecked(
					// Referencing de.vonloesch...
					// creates an _implicit_
					// dependency which is not made
					// explicit in the bundle's
					// Manifest
					"de.vonloesch.pdf4eclipse.editors.PDFEditor",
					outputFile,
					false); // don't activate (give focus) the editor
		} catch (PartInitException e) {
			MessageDialog.openWarning(UIHelper.getShellProvider().getShell(),
					"PDF File Not Modified",
					"The pdf file could not be modified. "
							+ "Make sure that the file " + outputFileName
							+ " is not open in any external programs.");
		}
		
		monitor.worked(1);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tla2tex.handler.AbstractPDFViewerRunnable#setFile(java.lang.String)
	 */
	@Override
	public void setFile(String outputFileName) throws CoreException {
		super.setFile(outputFileName);
		// explicitly touch the file to trigger a resource change event that is
		// received by the pdf editor. This causes the pdf editor to refresh its
		// content, if it has been open with the same pdf file already
		this.outputFile.touch(new NullProgressMonitor());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/tool/ModuleOverwritesBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import tlc2.tool.impl.FastTool;
import tlc2.value.impl.FcnRcdValue;
import tlc2.value.impl.Value;
import util.SimpleFilenameToStream;
import util.ToolIO;
import util.UniqueString;

@State(Scope.Benchmark)
public class ModuleOverwritesBenchmark {

	/*
	 * Run with: java -jar target/benchmarks.jar -wi 2 -i 2 -f2 -rf json -rff
	 * ModuleOverwritesBenchmark-$(de +%s)-$(git rev-parse --short HEAD).json
	 * -jvmArgsPrepend "-Xms8192m -Xmx8192m" -jvmArgsAppend
	 * "-Dtlc2.tool.ModuleOverwritesBenchmark.base=/home/markus/src/TLA/tla/tlatools/test-model tlc2.tool.ModuleOverwritesBenchmark "
	 */
	
	private static final String BASE_PATH = System
			.getProperty(ModuleOverwritesBenchmark.class.getName() + ".base");

	private static final ITool tool;
	private static final TLCStateMut state;

	static {
		String dir = BASE_PATH + File.separator + "ModuleOverwrites";
		System.err.println(dir);
		ToolIO.setUserDir(dir);

		tool = new FastTool("", "ModuleOverwrites", "ModuleOverwrites", new SimpleFilenameToStream());

		state = (TLCStateMut) tool.getInitStates().elementAt(0);
	}

	@Benchmark
	public boolean aNoModuleOverwrite() {
		shuffleValues();
		return tool.isValid(tool.getInvariants()[0], state);
	}

	@Benchmark
	public boolean bModuleOverwrite() {
		shuffleValues();
		return tool.isValid(tool.getInvariants()[1], state);
	}

	@Benchmark
	public boolean cModuleOverwriteLinear() {
		shuffleValues();
		return tool.isValid(tool.getInvariants()[2], state);
	}

	private static final void shuffleValues() {
		final FcnRcdValue frv = (FcnRcdValue) state.getVals().get(UniqueString.uniqueStringOf("t"));

		final List<Value> values = Arrays.asList(frv.values);
		Collections.shuffle(values);

		for (int i = 0; i < values.size(); i++) {
			frv.values[i] = values.get(i);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/ITLCModelLaunchDataPresenter.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.data;

/**
 * A presenter is responsible for the presentation of data handled by the {@link TLCModelLaunchDataProvider}
 * @author <NAME>
 */
public interface ITLCModelLaunchDataPresenter
{
    /* constants for the fields */
	public final static int USER_OUTPUT = 1;
	public final static int PROGRESS_OUTPUT = USER_OUTPUT << 1;
	public final static int START_TIME = PROGRESS_OUTPUT << 1;
	public final static int END_TIME = START_TIME << 1;
	public final static int COVERAGE_TIME = END_TIME << 1;
	public final static int COVERAGE = COVERAGE_TIME << 1;
	public final static int COVERAGE_END = COVERAGE << 1;
	public final static int COVERAGE_END_OVERHEAD = COVERAGE_END << 1;
	public final static int PROGRESS = COVERAGE_END_OVERHEAD << 1;
	public final static int ERRORS = PROGRESS << 1;
	public final static int LAST_CHECKPOINT_TIME = ERRORS << 1;
	public final static int CURRENT_STATUS = LAST_CHECKPOINT_TIME << 1;
	public final static int CONST_EXPR_EVAL_OUTPUT = CURRENT_STATUS << 1;
	public final static int FINGERPRINT_COLLISION_PROBABILITY = CONST_EXPR_EVAL_OUTPUT << 1;
	public static final int DISTRIBUTED_SERVER_RUNNING = FINGERPRINT_COLLISION_PROBABILITY << 1;
	public static final int DISTRIBUTED_WORKER_REGISTERED = DISTRIBUTED_SERVER_RUNNING << 1;
	public static final int TLC_MODE = DISTRIBUTED_WORKER_REGISTERED << 1;
	public static final int WARNINGS = TLC_MODE << 1;

	public final static int[] ALL_FIELDS = { USER_OUTPUT, PROGRESS_OUTPUT, START_TIME, END_TIME, LAST_CHECKPOINT_TIME,
			COVERAGE_TIME, COVERAGE, COVERAGE_END, PROGRESS, ERRORS, CONST_EXPR_EVAL_OUTPUT,
			FINGERPRINT_COLLISION_PROBABILITY, DISTRIBUTED_SERVER_RUNNING, DISTRIBUTED_WORKER_REGISTERED, TLC_MODE,
			WARNINGS };

    /**
     * Inform the presenter about the data changes
     * @param dataProvider data source
     * @param fieldId id of the changed field
     */
    public void modelChanged(final TLCModelLaunchDataProvider dataProvider, final int fieldId);
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalBuiltInSymbols.java<|end_filename|>
/***************************************************************************
* CLASS PcalBuiltInSymbols                                                 *
*                                                                          *
* THIS IS A VERSION OF tlatex.BuiltInSymbols MODIFIED TO ADD ";" AS A      *
* BUILTIN SYMBOL, AND TO MAKE "]_" and ">>_" SYMBOLS OF TYPE               *
* "RIGHT_PAREN".                                                           *
*                                                                          *
* Defines the TLA+ built-in symbols, their alignment classes, and how      *
* they are typeset.  Provides the following methods.                       *
*                                                                          *
*   Initialize()                                                           *
*     Must be called before any other methods of the class are             *
*     called.                                                              *
*                                                                          *
*   GetBuiltInSymbol(String str)                                           *
*     If str is a built-in TLA symbol, it returns the corresponding        *
*     Symbol object.  Otherwise, it returns null.                          *
*                                                                          *
*   IsBuiltInSymbol(String str)                                            *
*     True iff str is a built-in TLA symbol.                               *
*                                                                          *
*   IsBuiltInPrefix(String str)                                            *
*     True iff str is a non-empty prefix (possibly the entire string)      *
*     of a built-in TLA symbol that is not a string of letters (like       *
*     "ENABLED" or "WF_") and is not a "\\" (a backslash) followed by      *
*     a string of letters (like "\\cup").                                  *
*                                                                          *
*   IsStringChar(char c)                                                   *
*     True iff c is a character that can appear un-escaped (not            *
*     preceded by "\") in a TLA+ string.                                   *
*                                                                          *
* See the Symbol class for more information.                               *
***************************************************************************/
package pcal;
import java.util.Enumeration;
import java.util.Hashtable;

import tla2tex.Misc;
import tla2tex.Symbol;
import util.TLAConstants;

public final class PcalBuiltInSymbols
  { 
    /***********************************************************************
    * The following three hash tables are built by the Initialize method.  *
    ***********************************************************************/
    private static Hashtable<String, Symbol> builtInHashTable = new Hashtable<>(200);
      /*********************************************************************
      * Maps built-in symbols (which are strings) to their Symbol          *
      * objects.                                                           *
      *********************************************************************/

    private static Hashtable<String, String> prefixHashTable  = new Hashtable<>(700);
      /*********************************************************************
      * A table containing the prefixes of all built-in symbols.  (It      *
      * holds only their keys.)                                            *
      *********************************************************************/

    private static Hashtable<String, String> stringCharTable  = new Hashtable<>(100);
      /*********************************************************************
      * A table of all the characters that may appear in a TLA+ string     *
      * token.                                                             *
      *********************************************************************/

    private static String nullString = "" ;
      /*********************************************************************
      * Some hash tables are used only to remember the keys; there is no   *
      * value attached to them.  However, the Hashtable class stores a     *
      * non-null object with each key.  This is the object we use.         *
      *********************************************************************/
      
    public static void Initialize()
      { buildHashTable(); 
        buildPrefixHashTable(); 
        buildStringCharTable();
      } ;

    public static boolean IsBuiltInSymbol(String str) 
      { return (null != GetBuiltInSymbol(str)) ;
      } ;

    public static Symbol GetBuiltInSymbol(String str)
      { return builtInHashTable.get(str);
      } ;

    public static boolean IsBuiltInPrefix(String str)
      { return prefixHashTable.containsKey(str) ;
      } ;

    public static boolean IsStringChar(char ch)
      { return stringCharTable.containsKey("" + ch) ;
      } ;

    private static void buildStringCharTable() 
      { String legalChars = 
                 /**********************************************************
                 * Here are all the non-escaped characters that can        *
                 * appear in a TLA+ string.                                *
                 **********************************************************/
                    "abcdefghijklmnopqrstuvwxyz"
                  + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                  + " ~!@#$%^&*()_-+={}[]|:;<,>.?/`'" 
                  + "0123456789" ;
        int n = 0 ;
        while (n < legalChars.length())
          { stringCharTable.put("" + legalChars.charAt(n), nullString);
            n = n + 1 ;
          }
      } ;

    private static void add(String tla, String tex, int stype, int atype)
      /*********************************************************************
      * Adds an entry to the builtInHashTable.                             *
      *********************************************************************/
      { builtInHashTable.put(tla, new Symbol(tla, tex, stype, atype) ) ; } ;


    private static void buildHashTable() 
      /*********************************************************************
      * Initializes builtInHashTable.  This code actually defines the      *
      * symbol and alignment types and the LaTeX input for each built-in   *
      * symbol.  It is required that, if two symbols have the same         *
      * alignment type, then their typeset versions have the same width.   *
      *                                                                    *
      * The LaTeX commands for all the infix symbols and some other        *
      * symbols are of the form \.{...}, where the \. command puts         *
      * \mbox{} before and after its argument.  This is necessary because  *
      * otherwise, TeX may vary the space around the symbol depending on   *
      * what comes before or after it, screwing up the alignment.          *
      *********************************************************************/
      { 
        add("_",          "\\_",             Symbol.KEYWORD, 0);
        add("ASSUME",     "{\\ASSUME}",      Symbol.KEYWORD, 0);
        add("ASSUMPTION", "{\\ASSUMPTION}",  Symbol.KEYWORD, 0);
        add("AXIOM",      "{\\AXIOM}",       Symbol.KEYWORD, 0);
        add("BOOLEAN",    "{\\BOOLEAN}",     Symbol.KEYWORD, 0);
        add("CASE",       "{\\CASE}",        Symbol.KEYWORD, 0);
        add(TLAConstants.KeyWords.CONSTANT,   "{\\CONSTANT}",    Symbol.KEYWORD, 0);
        add(TLAConstants.KeyWords.CONSTANTS,  "{\\CONSTANTS}",   Symbol.KEYWORD, 0);
        add("EXCEPT",     "{\\EXCEPT}",      Symbol.KEYWORD, 0);
        add(TLAConstants.KeyWords.EXTENDS,    "{\\EXTENDS}",     Symbol.KEYWORD, 0);
        add("FALSE",      "{\\FALSE}",       Symbol.KEYWORD, 0);
        add("IF",         "{\\IF}",          Symbol.KEYWORD, 0);
        add("INSTANCE",   "{\\INSTANCE}",    Symbol.KEYWORD, 0);
        add("LOCAL",      "{\\LOCAL}",       Symbol.KEYWORD, 0);
        add(TLAConstants.KeyWords.MODULE,     "{\\MODULE}",      Symbol.KEYWORD, 0);
        add("OTHER",      "{\\OTHER}",       Symbol.KEYWORD, 0);
        add("STRING",     "{\\STRING}",      Symbol.KEYWORD, 0);
        add("THEOREM",    "{\\THEOREM}",     Symbol.KEYWORD, 0);
        add("TRUE",       "{\\TRUE}",        Symbol.KEYWORD, 0);
        add(TLAConstants.KeyWords.VARIABLE,   "{\\VARIABLE}",    Symbol.KEYWORD, 0);
        add("VARIABLES",  "{\\VARIABLES}",   Symbol.KEYWORD, 0);
        add("WITH",       "{\\WITH}",        Symbol.KEYWORD, 0);

        add("WF_", "{\\WF}",        Symbol.SUBSCRIPTED, 0);
        add("SF_", "{\\SF}",        Symbol.SUBSCRIPTED, 0);
        add(">>_", "{\\rangle}",    Symbol.RIGHT_PAREN, 0);
        add("]_",  "]",             Symbol.RIGHT_PAREN, 0);

        add("(",   "(",           Symbol.LEFT_PAREN, 0);
        add("[",   "[",           Symbol.LEFT_PAREN, 0);
        add("{",   "\\{",         Symbol.LEFT_PAREN, 0);
        add("<<",  "{\\langle}",  Symbol.LEFT_PAREN, 0);

        add(")",   ")",           Symbol.RIGHT_PAREN, 0);
        add("}",   "\\}",         Symbol.RIGHT_PAREN, 0);
        add("]",   "]",           Symbol.RIGHT_PAREN, 0);
        add(">>",  "{\\rangle}",  Symbol.RIGHT_PAREN, 0);

        add("\\A",         "\\A\\,",          Symbol.PREFIX, 0);
        add("\\forall",    "\\forall\\,",     Symbol.PREFIX, 0);
        add("\\E",         "\\E\\,",          Symbol.PREFIX, 0);
        add("\\exists",    "\\exists\\,",     Symbol.PREFIX, 0);
        add("\\AA",        "{\\AA}",         Symbol.PREFIX, 0);
        add("\\EE",        "{\\EE}",         Symbol.PREFIX, 0);
        add("~",           "{\\lnot}",       Symbol.PREFIX, 0);
        add("\\lnot",      "{\\lnot}",       Symbol.PREFIX, 0);
        add("\\neg",       "{\\neg}",        Symbol.PREFIX, 0);
        add("<>",          "{\\Diamond}",    Symbol.PREFIX, 0);
        add("CHOOSE",      "{\\CHOOSE}",     Symbol.PREFIX, 0);
        add("ENABLED",     "{\\ENABLED}",    Symbol.PREFIX, 0);
        add("UNCHANGED",   "{\\UNCHANGED}",  Symbol.PREFIX, 0);
        add("SUBSET",      "{\\SUBSET}",     Symbol.PREFIX, 0);
        add("UNION",       "{\\UNION}",      Symbol.PREFIX, 0);
        add("DOMAIN",      "{\\DOMAIN}",     Symbol.PREFIX, 0);

        add("'",    "\\.{'}",            Symbol.POSTFIX, 0);
        add("^+",   "\\.{\\mbox{}^+}",   Symbol.POSTFIX, 0);
        add("^*",   "\\.{\\mbox{}^*}",   Symbol.POSTFIX, 0);
        add("^#",   "\\.{\\mbox{}^{\\#}}",   Symbol.POSTFIX, 0);


        add("=>",           "\\.{\\implies}",    Symbol.INFIX, 1);
        add("\\cdot",       "\\.{\\cdot}",       Symbol.INFIX, 2);
        add("<=>",          "\\.{\\equiv}",      Symbol.INFIX, 3);
        add("\\equiv",      "\\.{\\equiv}",      Symbol.INFIX, 4);
        add("~>",           "\\.{\\leadsto}",    Symbol.INFIX, 5);
        add("-+->",         "\\.{\\whileop}",    Symbol.INFIX, 6);

        add("\\subseteq",   "\\.{\\subseteq}",   Symbol.INFIX, 7); 
        add("\\subset",     "\\.{\\subset}",     Symbol.INFIX, 7); 
        add("\\supset",     "\\.{\\supset}",     Symbol.INFIX, 7); 
        add("\\supseteq",   "\\.{\\supseteq}",   Symbol.INFIX, 7); 

        add("\\ll",         "\\.{\\ll}",         Symbol.INFIX, 8);
        add("\\gg",         "\\.{\\gg}",         Symbol.INFIX, 8);
          /*****************************************************************
          * \ll and \gg not aligned with = and < because they are wider,   *
          * and they're not used enough to bother accomodating.            *
          *****************************************************************/
          
        add("\\",           "\\.{\\,\\backslash\\,}",  Symbol.INFIX, 9);
        add("\\cap",        "\\.{\\cap}",        Symbol.INFIX, 10);
        add("\\intersect",  "\\.{\\cap}",        Symbol.INFIX, 11);
        add("\\cup",        "\\.{\\cup}",        Symbol.INFIX, 12);
        add("\\union",      "\\.{\\cup}",        Symbol.INFIX, 13);
        add("/\\",          "\\.{\\land}",       Symbol.INFIX, 14);
        add("\\/",          "\\.{\\lor}",        Symbol.INFIX, 15);
        add("\\land",       "\\.{\\land}",       Symbol.INFIX, 16);
        add("\\lor",        "\\.{\\lor}",        Symbol.INFIX, 17);
        add("\\X",          "\\.{\\times}",      Symbol.INFIX, 18);
        add("-",            "\\.{-}",            Symbol.INFIX, 19);
        add("+",            "\\.{+}",            Symbol.INFIX, 19);
        add("*",            "\\.{*}",            Symbol.INFIX, 20);
        add("/",            "\\.{/}",            Symbol.INFIX, 21);
        add("^",            "\\.{\\ct}",         Symbol.INFIX, 22);
        add("|",            "\\.{\\,|\\,}",      Symbol.INFIX, 23);
        add("||",           "\\.{\\,||\\,}",     Symbol.INFIX, 24);
        add("&",            "\\.{\\,\\&\\,}",    Symbol.INFIX, 25);
        add("&&",           "\\.{\\,\\&\\&\\,}", Symbol.INFIX, 26);
        add("++",           "\\.{\\pp}",         Symbol.INFIX, 27);
        add("--",           "\\.{\\mm}",         Symbol.INFIX, 27);
        add("**",           "\\.{\\stst}",       Symbol.INFIX, 28);
        add("//",           "\\.{\\slsl}",       Symbol.INFIX, 29);
        add("^^",           "\\.{\\ct\\ct}",     Symbol.INFIX, 30);
        add("|-",           "\\.{\\vdash}",      Symbol.INFIX, 31);
        add("|=",           "\\.{\\models}",     Symbol.INFIX, 32);
        add("-|",           "\\.{\\dashv}",      Symbol.INFIX, 33);
        add("=|",           "\\.{\\eqdash}",     Symbol.INFIX, 34);
        add("<:",           "\\.{\\ltcolon}",    Symbol.INFIX, 35);
        add(":>",           "\\.{\\colongt}",    Symbol.INFIX, 35);
        add(":=",           "\\.{:=}",           Symbol.INFIX, 35);
        add("::=",          "\\.{::=}",          Symbol.INFIX, 36);

        add("(+)",          "\\.{\\oplus}",      Symbol.INFIX, 37); 
        add("(-)",          "\\.{\\ominus}",     Symbol.INFIX, 37); 
        add("\\oplus",      "\\.{\\oplus}",      Symbol.INFIX, 37); 
        add("\\ominus",     "\\.{\\ominus}",     Symbol.INFIX, 37); 

        add("(.)",          "\\.{\\odot}",       Symbol.INFIX, 38);
        add("\\odot",       "\\.{\\odot}",       Symbol.INFIX, 38);

        add("(/)",          "\\.{\\oslash}",     Symbol.INFIX, 39);
        add("\\oslash",     "\\.{\\oslash}",     Symbol.INFIX, 39);

        add("(\\X)",        "\\.{\\otimes}",     Symbol.INFIX, 40);
        add("\\otimes",     "\\.{\\otimes}",     Symbol.INFIX, 40);

        add("\\uplus",      "\\.{\\uplus}",      Symbol.INFIX, 41);
        add("\\sqcap",      "\\.{\\sqcap}",      Symbol.INFIX, 42);
        add("\\sqcup",      "\\.{\\sqcup}",      Symbol.INFIX, 43);
        add("\\div",        "\\.{\\div}",        Symbol.INFIX, 44);
        add("\\star",       "\\.{\\star}",       Symbol.INFIX, 45);

        add("\\o",          "\\.{\\circ}",       Symbol.INFIX, 46);
        add("\\circ",       "\\.{\\circ}",       Symbol.INFIX, 46);

        add("\\bigcirc",    "\\.{\\bigcirc}",    Symbol.INFIX, 47);
        add("\\bullet",     "\\.{\\bullet}",     Symbol.INFIX, 48);

        add("\\in",         "\\.{\\in}",         Symbol.INFIX, 49);
        add("\\notin",      "\\.{\\notin}",      Symbol.INFIX, 49);
        add("=",            "\\.{=}",            Symbol.INFIX, 49);
        add("#",            "\\.{\\neq}",        Symbol.INFIX, 49);
        add("/=",           "\\.{\\neq}",        Symbol.INFIX, 49);
        add("<",            "\\.{<}",            Symbol.INFIX, 49);
        add(">",            "\\.{>}",            Symbol.INFIX, 49);
        add("=<",           "\\.{\\leq}",        Symbol.INFIX, 49);
        add("<=",           "\\.{\\leq}",        Symbol.INFIX, 49);
        add(">=",           "\\.{\\geq}",        Symbol.INFIX, 49);
        add("\\prec",       "\\.{\\prec}",       Symbol.INFIX, 49);
        add("\\succ",       "\\.{\\succ}",       Symbol.INFIX, 49);
        add("\\preceq",     "\\.{\\preceq}",     Symbol.INFIX, 49);
        add("\\succeq",     "\\.{\\succeq}",     Symbol.INFIX, 49);
        add("\\sim",        "\\.{\\sim}",        Symbol.INFIX, 49);
        add("\\simeq",      "\\.{\\simeq}",      Symbol.INFIX, 49);
        add("\\approx",     "\\.{\\approx}",     Symbol.INFIX, 49);
        add("\\doteq",      "\\.{\\doteq}",      Symbol.INFIX, 49);

        add("\\asymp",      "\\.{\\asymp}",      Symbol.INFIX, 50);

        add("\\sqsubset",   "\\.{\\sqsubset}",   Symbol.INFIX, 51);
        add("\\sqsupset",   "\\.{\\sqsupset}",   Symbol.INFIX, 51);
        add("\\sqsubseteq", "\\.{\\sqsubseteq}", Symbol.INFIX, 51);
        add("\\sqsupseteq", "\\.{\\sqsupseteq}", Symbol.INFIX, 51);

        add("\\propto",     "\\.{\\propto}",     Symbol.INFIX, 52);
        add(":",            "\\.{:}",            Symbol.PUNCTUATION, 53);
        add("->",           "\\.{\\rightarrow}", Symbol.INFIX, 54);
        add("|->",          "\\.{\\mapsto}",     Symbol.INFIX, 55);
        add("<-",           "\\.{\\leftarrow}",  Symbol.INFIX, 56);
        add("==",           "\\.{\\defeq}",      Symbol.INFIX, 57);

        add("ELSE",         "\\.{\\ELSE}",       Symbol.PREFIX, 58);
        add("THEN",         "\\.{\\THEN}",       Symbol.PREFIX, 58);
        add("LET",          "\\.{\\LET}",        Symbol.PREFIX, 59);
        add("IN",          "\\.{\\IN}",          Symbol.PREFIX, 59);
        add("[]",          "{\\Box}",            Symbol.PREFIX, 60);

        add("..",           "\\.{\\dotdot}",     Symbol.INFIX, 0);
        add("...",          "\\.{\\dots}",       Symbol.INFIX, 0);
        add("$",            "\\.{\\,\\$\\,}",    Symbol.INFIX, 0);
        add("$$",           "\\.{\\,\\$\\$\\,}", Symbol.INFIX, 0);
        add("?",            "\\.{?}",            Symbol.INFIX, 0);
        add("??",           "\\.{\\,??\\,}",     Symbol.INFIX, 0);
        add("%",            "\\.{\\%}",          Symbol.INFIX, 0);
        add("%%",           "\\.{\\,\\%\\%\\,}", Symbol.INFIX, 0);
        add("##",           "\\.{\\,\\#\\#\\,}", Symbol.INFIX, 0);
        add("@@",           "\\.{\\,@@\\,}",     Symbol.INFIX, 0);
        add("!!",           "\\.{!!}",           Symbol.INFIX, 0);
        add("\\times",      "\\.{\\times}",      Symbol.INFIX, 0);
        add("\\leq",        "\\.{\\leq}",        Symbol.INFIX, 0);
        add("\\geq",        "\\.{\\geq}",        Symbol.INFIX, 0);
        add("\\mod",        "\\.{\\%}",          Symbol.INFIX, 0);
        add("\\wr",         "\\.{\\wr}",         Symbol.INFIX, 0);
        add("\\cong",       "\\.{\\cong}",       Symbol.INFIX, 0);
        add("!",            "!",                 Symbol.INFIX, 0);

        add(";",   ";",     Symbol.PUNCTUATION, 0);
        add(",",   ",\\,",   Symbol.PUNCTUATION, 0);
        add(".",   ".",     Symbol.PUNCTUATION, 0);

        add("-.",  "\\.{-\\!.\\,}",    Symbol.MISC, 0);
        add("@",  "@",      Symbol.MISC, 0);

      } ;      


    private static void buildPrefixHashTable() 
      /*********************************************************************
      * Initializes prefixHashTable, assuming that builtInHashTable is     *
      * already initialized.                                               *
      *********************************************************************/
      { Enumeration<String> builtInEnum = builtInHashTable.keys();
        while (builtInEnum.hasMoreElements())
          { String symbol = builtInEnum.nextElement();
            if (    Misc.IsLetter(symbol.charAt(0))
                 ||    (symbol.length() > 1)
                    && (symbol.charAt(0) == '\\')
                    && Misc.IsLetter(symbol.charAt(1)))
              { /***********************************************************
                * Should not put prefixes of this symbol in                *
                * prefixHashTable.                                         *
                ***********************************************************/
              }
            else
              { /***********************************************************
                * Put symbol and all its prefixes in prefixHashTable.      *
                ***********************************************************/
                while (symbol.length() > 0)                              
                 { prefixHashTable.put(symbol, nullString);             
                   symbol = symbol.substring(0, symbol.length() - 1);   
                 } ;                                                    
              } ;
          }
      }

   }  

/* last modified on Fri  1 Jul 2005 at 16:48:44 UT by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/help-print.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/.html  -->

 
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Helping the Pretty-Printer</title>
</head>
<!-- a comment here -->

<body>
<h1>Helping the Pretty-Printer</h1>
<pre>
Contents
  <a href="#intro">Introduction</a>
  <a href="#spec">How TLATeX Typesets the Specification</a>
  <a href="#comments">How TLATeX Typesets Comments</a>
  <a href="#latex">Using LaTeX Commands to Format Comments</a>
</pre>
<h2><a name="intro"> Introduction</a></h2>
 <P> 
The toolbox pretty prints a module by calling the
TLATeX program.&nbsp;  TLATeX is a Java program for typesetting TLA+ specifications with&nbsp; 
<a href="http://www.latex-project.org/"><samp>LaTeX</samp></a>.&nbsp;
It was written by <NAME>, based on ideas by <NAME>.  
 </P>

<p>TLATeX's output should be good enough for most users.&nbsp;  Later sections
describe how you can get TLATeX to do a better job, and will explain
what happened in the unlikely case that it produces weird output.&nbsp;
However, if you happen to use any of the two-character 
sequences 
  <pre>
   `~   `^   `.
 </pre>
in a comment, you'd better read section <a href="#comments">How TLATeX Typesets Comments</a>.</p>

<h2><a name="spec"> How TLATeX Typesets the Specification</a></h2>

<p>
TLATeX should typeset the specification itself pretty much the way you
would want it to.&nbsp;  It preserves most of the meaningful alignments in
the specification.&nbsp;  For example, if the specification contains
<pre>  
  Action == /\ x'   = x - y
            /\ yy'  = 123
            /\ zzz' = zzz
</pre> <p> then the&nbsp; <code>/\</code>&nbsp; and&nbsp;
<code>=</code>&nbsp; symbols will be aligned in the output.&nbsp;  Extra
spaces in the input will be reflected in the output.&nbsp;  However, TLATeX
treats 0 and 1 space between symbols the same, so&nbsp;
<code>x+y</code>&nbsp; and&nbsp; <code>x&nbsp;+&nbsp;y</code>&nbsp;
produce the same output, but&nbsp;
<code>x&nbsp;&nbsp;+&nbsp;&nbsp;y</code>&nbsp; produces extra space
around the&nbsp; <code>+</code>&nbsp;.
</p>

<p>
TLATeX typesets the single TLA+ module that must appear in the input
file.&nbsp;  It will also typeset any material that precedes and follows the
module as if it were a comment.&nbsp;  However, that text won't be shaded.
</p>

<p>
TLATeX does not check that the specification is syntactically correct
TLA+ input.&nbsp;  However, it will report an error, which will be
reported to you by the Toolbox,  if the specification
contains an illegal lexeme, such as a semicolon (<code>;</code>). 
</p>


<h2><a name="comments"> How TLATeX Typesets Comments</a></h2>

 WARNING: A left single-quote&nbsp; <code>`</code>&nbsp; has special meaning to       
 TLATeX.&nbsp;  Enclosing a word in single-quotes like&nbsp; <code>`foo'</code>&nbsp; is      
 harmless, while&nbsp; <code>``</code>&nbsp; and&nbsp; <code>''</code>&nbsp; are 
just typeset as double-quotes.&nbsp;  
 But beware of an unmatched left-quote and of the following    
 two-character sequences:                                      
<pre>                                                               
    `~   `^   `.                                                 
</pre>                                                               
 See below for further details about what single-quotes and    
 these special sequences mean.&nbsp;                                 

<p>
TLATeX distinguishes between one-line and multi-line comments.&nbsp;  A
one-line comment is any comment that is not a multi-line comment.&nbsp;
Multi-line comments can be typed in any of the following three ways:
</p>

<pre>
  (*************************)
  (* This is the text of a *)
  (* multi-line comment.   *)
  (*************************)

  \********************
  \* This is the text 
  \* of the comment.  
  \********************

  (* This is the text
     of the comment.   *)
</pre>

<p> In the first two ways, the&nbsp; <code>(*</code>&nbsp; or&nbsp;
<code>\*</code>&nbsp; characters on the left must all be aligned, and
the last line of&nbsp; <code>*</code>&nbsp; characters is optional.&nbsp;
In the first way, nothing may appear to the right of the
comment--otherwise, the input is considered to be a sequence of
separate one-line comments.&nbsp;  In a multi-line comment, TLATeX usually
considers a sequence of non-blank lines to be a single paragraph, in
which case it will typeset them as one paragraph and ignore the line
breaks in the input.  </p>

<p>
TLATeX does its best to do a sensible job of typesetting comments.&nbsp;
You can help it by ending each sentence with a period (<code>.</code>) and by
adding blank lines to indicate logical separation of items.
</p>

<p>
There are three ways in which TLATeX can mess up the typesetting of
comments:
</p>

<ol>
 <li> Parts of a specification, such as identifiers and certain
    operators like&nbsp; <code>-</code>&nbsp;, should be typeset differently from ordinary
    text.&nbsp;  Identifiers should be italicized, and the minus in the
    expression&nbsp; <code>x-y</code>&nbsp; should be typeset differently from the dash 
    in &nbsp;<code>x-ray</code>.&nbsp; TLATeX gets this right most of the time, but it
    does make mistakes.
<p>
    You can tell TLATeX to treat something as part of a specification
    by putting single quotes&nbsp; <code>(`</code>&nbsp; and&nbsp; <code>')</code>&nbsp; 
    around it.&nbsp;  You can tell
    TLATeX to treat something as ordinary text by putting&nbsp; <code>`^</code>&nbsp; 
    and&nbsp; <code>^'</code>&nbsp; 
    around it--for example:
<pre>
       \***********************************
       \* To find the latest value of `bar',
       \* see `^http::/frob/bar^'.
       \***********************************
</pre>
    But, this is seldom necessary.&nbsp;  TLATeX usually does the right
    thing.
   <p>
    WARNING: Do not put any character between&nbsp; <code>`^</code>&nbsp; 
    and&nbsp; <code>^'</code>&nbsp; 
    except letters, numbers, and ordinary punctuation.&nbsp;  In 
    particular, do not put any of the following characters 
    between&nbsp; <code>`^</code>&nbsp; and&nbsp; <code>^'</code>:
<pre>                                                           
        _  ~  #  $  %  ^  &  <  >  \ "                     
</pre>                                                           
    See the section below on using LaTeX commands in comments    
    for further information about what can go 
    between&nbsp; <code>`^</code>&nbsp; and&nbsp; <code>^'</code>. 
 </li>

 <li> TLATeX does not do any fancy formatting of paragraphs.&nbsp;  For
    example, TLATeX will not precisely align the "A"s when typesetting:
<pre>
       \***********************
       \* gnat: A tiny insect.
       \*
       \* gnu:  A short word.
       \***********************
</pre>
    You can tell TLATeX to typeset a sequence of lines precisely the
    way they appear in the input, using a fixed-width font, by
    enclosing the lines with `.  and .' , as in:
<pre>
       \**********************************************
       \* The following picture explains everything:
       \*
       \*      `. -----------          --------
       \*        | Processor |------->| Memory |   
       \*         -----------          --------  .'
       \**********************************************
</pre>

    Using&nbsp; <code>`.</code>&nbsp; and&nbsp; <code>.'</code>&nbsp; 
    is the only reasonable thing to do for a
    diagram.&nbsp;  However, if you know (or want to learn) LaTeX, the
    section below on using LaTeX commands in comments will explain
    how you can get TLATeX to do a good job of formatting things like
    lists and tables.
</li>

<li> A paragraph may be typeset loosely, with one or more lines
    containing  &nbsp;&nbsp;  lots  &nbsp;&nbsp;     of  &nbsp;&nbsp; space  
     &nbsp;&nbsp;    between     
      &nbsp;&nbsp;  the    &nbsp;&nbsp;  words.&nbsp;
    This happens if there is no good way to typeset the paragraph.&nbsp;
    If this bothers you, the easiest solution is to rewrite the
    paragraph.&nbsp;  You can also try to fix the problem with LaTeX
    commands.&nbsp;  (See the section below on using LaTeX commands to
    format comments.)
</li> </ol> 

<p> 
TLATeX ignores any&nbsp; <code>(*</code>&nbsp; ...&nbsp; <code>*)</code>&nbsp; 
comment that appears within another comment.&nbsp;  So, you can get it not
to typeset part of a comment by enclosing that part between&nbsp; <code>(*</code>&nbsp; 
and&nbsp; <code>*)</code>&nbsp; 
But a better way to omit part of a comment is to enclose it between&nbsp; <code>`~</code>&nbsp; 
and&nbsp; <code>~'</code>. 
</p>

<h2><a name="latex">Using LaTeX Commands to Format Comments</a></h2>

TLATeX puts any text enclosed between&nbsp; <code>`^</code>&nbsp; 
and&nbsp; <code>^'</code>&nbsp; 
in a comment into the
LaTeX input file exactly as it appears.&nbsp;  This allows you to insert
LaTeX formating commands in comments.&nbsp;  There are two ways to use this.

<ol>
<li> You can enclose between `^ and ^' a short phrase appearing on
    a single line of input.&nbsp;  LaTeX typesets that phrase as part of
    the enclosing paragraph.
</li>
 
<li>
  You can enclose one or more complete lines of a multi-line
    comment between&nbsp; <code>`^</code>&nbsp; 
and&nbsp; <code>^'</code>&nbsp;.&nbsp; That text is typeset as one or
more separate paragraphs whose prevailing left margin is determined by
the position of the &nbsp; <code>`^</code>&nbsp;.&nbsp; For example,
the input
<pre>
       \**********************************
       \* The first comment paragraph.
       \*
       \*    The second comment
       \*    paragraph.
       \*
       \*    `^ Some LaTeX-formated 
       \*  text  ^'
       \**********************************
</pre>
    causes the LaTeX-formated text to be typeset in a separate
    paragraph whose prevailing left margin is the same as in the
    second comment paragraph.
</li>
</ol>
LaTeX typesets the text between&nbsp; <code>`^</code>&nbsp; 
and&nbsp; <code>^'</code>&nbsp; in LR mode for a one-line
comment and in paragraph mode for a multi-line comment.&nbsp;  The LaTeX
file produced by TLATeX defines a "describe" environment that is
useful for formating text in a multi-line&nbsp; 
<code>`^&nbsp;...&nbsp;^'</code>&nbsp;.&nbsp;  This
environment is the same as the standard LaTeX "description"
environment, except that it takes an argument, which should be the
widest item label in the environment.&nbsp;  For example, the input might
contain
<pre>
       \***********************
       \*    `^ \begin{describe}{gnat:}
       \*        \item[gnat:] A tiny insect.
       \*  
       \*        \item[gnu:]  A short word.
       \*       \end{describe} ^'
       \***********************
</pre>
<p>
<em>Warning:</em> An error in a LaTeX command inside &nbsp; 
<code>`^&nbsp;...&nbsp;^'</code>&nbsp; text
can  
cause TLATeX not to produce any output. 
</p>

<p>
TLATeX has a feature that is not relevant to use with the Toolbox
that involves putting code between&nbsp; <code>`~</code>&nbsp; 
and&nbsp; <code>~'</code>&nbsp;.&nbsp;   Unless you are also using
TLATeX outside the Toolbox and know what you're doing, do
not put &nbsp; <code>`~</code>&nbsp; 
or&nbsp; <code>~'</code>&nbsp; in comments.
</p>

<hr> 

<!-- delete rest of line to comment out 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 --> 
<!-- delete rest of line to comment out -->  
<a href = "pretty-printing.html">&uarr; Pretty-Printing Modules</a>
<!-- --> 
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/EvalException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:27:18 PST by lamport
//      modified on Thu Dec  7 20:32:45 PST 2000 by yuanyu

package tlc2.tool;

import tlc2.output.MP;

/**
 * Evaluation exception
 * @author <NAME>
 * @version $Id$
 */
public class EvalException extends StatefulRuntimeException
{
// SZ Jul 14, 2009: not used since error codes are in the {@link EC} class    
//    public final static int ERROR = 0;
//    public final static int ASSERT = 1;
//    private int type;


    private final int errorCode;
    private final String[] parameters;

	public EvalException(int errorCode, String[] parameters)
    {
        super(MP.getMessage(errorCode, parameters));
		this.errorCode = errorCode;
		this.parameters = parameters;
    }

    public EvalException(int errorCode, String parameter)
    {
    	this(errorCode, new String[] {parameter});
    }

    public EvalException(int errorCode)
    {
        super(MP.getMessage(errorCode));
		this.errorCode = errorCode;
		this.parameters = null;
    }

    public int getErrorCode() {
    	return errorCode;
    }

	public String[] getParameters() {
		return parameters;
	}

	public boolean hasParameters() {
		return parameters != null;
	}
    
    // SZ Jul 14, 2009: refactored and deprecated, all usage changed to standard constructor 
    // public EvalException(int type, String message)
    // {
    //      super(message);
    //      this.type = type;
    // }
    
    

    // SZ Jul 14, 2009: not used
    // public final int getErrno()
    // {
    //      return this.type;
    // }

    // SZ Jul 14, 2009: not used
    // public final EvalException addMessage(String msg) {
    //      return new EvalException(this.errno, this.getMessage() + "\n" + msg);
    // }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/LevelException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

class LevelException extends Exception {

  LevelException(String s) { super(s); }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jclouds/src/org/lamport/tla/toolbox/jcloud/EC2CloudTLCInstanceParameters.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2014 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.jcloud;

import java.util.Properties;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.reference.AWSEC2Constants;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.location.reference.LocationConstants;

public class EC2CloudTLCInstanceParameters extends CloudTLCInstanceParameters {

	public EC2CloudTLCInstanceParameters(final String tlcParams, int numberOfWorkers) {
        super(tlcParams.trim(), numberOfWorkers);
	}

	private String getOwnerId() {
		// ubuntu official
		return "owner-id=owner-id=099720109477;state=available;image-type=machine";
	}

	@Override
	public String getCloudProvider() {
		return "aws-ec2";
	}

	@Override
	public String getIdentity() {
		return System.getenv("AWS_ACCESS_KEY_ID");
	}

	@Override
	public String getCredentials() {
		return System.getenv("AWS_SECRET_ACCESS_KEY");
	}
	
	// http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AWSCredentials.html
	@Override
	public IStatus validateCredentials() {
		// must not be null
		if (getIdentity() != null && getCredentials() != null) {
			// identity always starts with "AIKA" and has 20 chars
			if (getIdentity().matches("AKIA[a-zA-Z0-9]{16}")) {
				// secret has 40 chars
				if (getCredentials().length() == 40) {
					return Status.OK_STATUS;
				}
			}
		}
		return new Status(Status.ERROR, "org.lamport.tla.toolbox.jcloud",
				"Invalid credentials, please check the environment variables "
						+ "(AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY) are correctly "
						+ "set up and picked up by the Toolbox."
						+ "\n\nPlease visit the Toolbox help and read section 4 "
						+ "of \"Cloud based distributed TLC\" on how to setup authentication.");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#mungeProperties(java.util.Properties)
	 */
	@Override
	public void mungeProperties(Properties properties) {
		properties.setProperty(AWSEC2Constants.PROPERTY_EC2_AMI_QUERY, getOwnerId());
		// Confine jclouds to a single region. Since the Toolbox only supports a
		// single region, there is no point in querying others. This has been
		// added because I was seeing intermittent timeouts with other regions
		// (i.e. South America).
		properties.setProperty(LocationConstants.PROPERTY_REGIONS, getRegion());
	}
	
	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#mungeTemplateOptions(org.jclouds.compute.options.TemplateOptions)
	 */
	@Override
	public void mungeTemplateOptions(TemplateOptions templateOptions) {
		//TODO Create (and the reuse) subnet automatically for instance types that require it.
		final String subnetId = System.getProperty("aws-ec2.subnetid");
		if (subnetId != null) {
			// Manually create a subnet first:
			// 1) Log into https://console.aws.amazon.com/vpc/ and select the correct region (match getRegion())
			// 1a) Optionally choose tenancy "dedicated" for more predictable performance
			// 2) Create a VPC (defaults are fine)
			// 3) Create a subnet (accept defaults) associated with VPC
			// 3a) "Modify auto-assign IP settings" of newly created subnet to automatically assign a public ip
			// 4) Create an Internet Gateway associated with the VPC
			// 4a) Associate with VPC 
			// 5) Create a Route Table for the VPC
			// 5a) Create a route with CIDR 0.0.0.0/0 via the gateway created in 4)
			// 6) Modify inbound rules of (automatically) created security group to include ssh/22,http/80,https/443 with source "0.0.0.0/0"
			templateOptions.as(AWSEC2TemplateOptions.class).subnetId(subnetId);
		}
	}

	@Override
	public String getHostnameSetup() {
		// Lookup public ipv4 hostname and configure /etc/hosts accordingly. Otherwise,
		// MailSender uses the internal name which increases likelihood of email being
		// classified/rejected as spam.
		return "echo \"$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4) $(curl -s http://169.254.169.254/latest/meta-data/public-hostname)\" >> /etc/hosts && hostname $(curl -s http://169.254.169.254/latest/meta-data/public-hostname)";
	}
	

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getImageId()
	 */
	@Override
	public String getImageId() {
		// Ubuntu 64bit 18.04 Xenial
		// http://cloud-images.ubuntu.com/locator/ec2/
		// See http://aws.amazon.com/amazon-linux-ami/instance-type-matrix/
		// for paravirtual vs. hvm (if instance startup fails with funny errors
		// such as symlinks failing to be created, you accidentally picked paravirtual.
		 // "us-east-1,bionic,amd64,hvm:instance-store"
		final String imageId = System.getProperty("aws-ec2.image", "ami-053295bb822a154ba");
		return getRegion() + "/" + imageId;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getRegion()
	 */
	@Override
	public String getRegion() {
		return System.getProperty("aws-ec2.region", "us-east-1");
	}

	@Override
	public String getHardwareId() {
		return System.getProperty("aws-ec2.instanceType", "c3.8xlarge");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getOSFilesystemTuning()
	 */
	@Override
	public String getOSFilesystemTuning() {
		return System.getProperty("aws-ec2.tuning", getOSFilesystemTuningDefault());
	}
	
	private String getOSFilesystemTuningDefault() {
		// Create a raid0 out of the two instance store
		// disks and optimize its fs towards performance
		// by sacrificing data durability.
		return "umount /mnt ; "
		+ "/usr/bin/yes|/sbin/mdadm --create --force --auto=yes /dev/md0 --level=0 --raid-devices=2 --assume-clean --name=tlaplus /dev/xvdb /dev/xvdc && "
		+ "/sbin/mdadm --detail --scan >> /etc/mdadm/mdadm.conf && "
		+ "sed -i '\\?^/dev/xvdb?d' /etc/fstab && "
		+ "echo \"/dev/md127 /mnt ext4 defaults 0 0\" >> /etc/fstab && "
		+ "/sbin/mkfs.ext4 -O ^has_journal /dev/md0 && "
		+ "mount /dev/md0 /mnt";
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaVMArgs()
	 */
	@Override
	public String getJavaVMArgs() {
		return System.getProperty("aws-ec2.vmargs",
				super.getJavaVMArgs(System.getProperty("aws-ec2.vmargs.memory", "-Xmx56G -Xms56G")));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getTLCParameters()
	 */
	@Override
	public String getTLCParameters() {
		return System.getProperty("aws-ec2.tlcparams", super.getTLCParameters(Integer.getInteger("aws-ec2.tlcparams.workers", 32)));
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getJavaWorkerVMArgs()
	 */
	@Override
	public String getJavaWorkerVMArgs() {
		return System.getProperty("aws-ec2.vmworkerargs", super.getJavaWorkerVMArgs(
				System.getProperty("aws-ec2.vmworkerargs.memory", "-Xmx24G -Xms24G -XX:MaxDirectMemorySize=32g")));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jnlp/src/org/lamport/tla/toolbox/distributed/FPSetJNLPGeneratorServlet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package org.lamport.tla.toolbox.distributed;

/**
 * Serves the JNLP file for the fingerprint server.
 * 
 * Beginning with 1.7.0 we ceased supporting JNLP, due to our move to Java 11. Until a contributor arrives to take over
 * this functionality, including providing a nice way to bundle IcedTea or similar with the Toolbox, i am marking this
 * class as deprecated.
 * 
 * @deprecated
 */
@SuppressWarnings("serial")
public class FPSetJNLPGeneratorServlet extends JNLPGeneratorServlet {
	
	public static final String JNLP = "fpset.jnlp";
	public static final String DESCRIPTION = "Distributed TLC fingerprint set";
	public static final String INDEX_DESC = "Start a fingerprint (FPSet) server:";
	public static final String MAINCLASS = "tlc2.tool.distributed.fp.DistributedFPSet";

	public FPSetJNLPGeneratorServlet() {
		super(MAINCLASS, DESCRIPTION, JNLP);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/InstanceNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import util.UniqueString;

public class InstanceNode extends LevelNode {

  /**
   * This class represents a TLA module instantiation whose general form is
   *
   *    I(param[1], ... , param[p]) ==
   *       INSTANCE M WITH mparam[1] <- mexp[1], ... , mparam[r] <- mexp[r]
   *
   * or simply
   *
   *   INSTANCE M WITH mparam[1] <- mexp[1], ... , mparam[r] <- mexp[r]
   *
   *  where I         instance name
   *        param[i]  instance paramater
   *        M         module being instantiated
   *        mparam[i] constant and variable declared in M
   *        mexp[i]   expression substituted for mexp[i] in this instance
   *
   *  The parameters param[1] ... params[p] may be missing if there
   *  are no instance params; the name I (and the "==") may also be
   *  missing if this is an unnamed instance.  The substitutions WITH
   *  mparam[1] <- mexp[1], ... , mparam[r] <- mexp[r] may be missing if
   *  module M does not declare any constants or variables; and any
   *  particular substitution mparam[i] <- mexp[i] if the expression
   *  mexp[i] is a simply a reference to a constant or variable
   *  declared in the current module that has the same name as mparam[i]
   *  declared in M (or a module M extends).
   *
   *  On 30 Jan 2013, LL added some public get...() methods that
   *  return some fields.
   */

  UniqueString      name;
     // The name of this instance, e.g. "I" in the example above;
     //   null if this is an unnamed instance.

  public UniqueString getName() {
      return name ;
  }
  FormalParamNode[] params;
     // The instance parameters, e.g. param[1]  ... param[n] in the
     // example above. Has length zero if there is no param.
  ModuleNode        module;
     // Reference to the module, M, being instantiated

  public ModuleNode getModule() {
      return module ;
  }

  Subst[]           substs;
     // The substitutions mparam[1] <- mexp[1], ... , mparam[r] <- mexp[r]
     // This includes substitutions not explicitly mentioned in the
     // surface syntax because they are of the form c <- c or x <- x
     // Have length 0 if there is no substitution.


  /*************************************************************************
  * The following field was added by LL on 29 Jul 2007.                    *
  *************************************************************************/
  boolean local;
    /***********************************************************************
    * True iff this is a LOCAL instance.                                   *
    ***********************************************************************/

  public boolean getLocal() {
      return this.local ;
  }

  /**
   * If the InstanceNode is a proof step, this is the step number.  It
   * is made a UniqueString for consistency; there's no need to make
   * comparison efficient.  It is null if the proof step has only
   * a level (like <9>) rather than a complete step number.
   * Added by LL on 6 June 2010.
   */
  private UniqueString stepName = null;
  public void setStepName(UniqueString stepName)
   {
    this.stepName = stepName;
   }

  /**
   * @return the stepName
   */
  public UniqueString getStepName()
   {
    return stepName;
   }

  public InstanceNode(UniqueString name, boolean localness,
                      FormalParamNode[] params,
                      ModuleNode module, Subst[] substs, TreeNode stn) {
    super(InstanceKind, stn);
    this.name = name;
    this.local = localness;
    this.params = (params != null ? params : new FormalParamNode[0]);
    this.module = module;
    this.substs = (substs != null ? substs : new Subst[0]);
  }

  public boolean isLocal() { return local ; }

  /* Level checking */
// These fields are now declared in all LevelNode subclasses
//  private boolean levelCorrect;
//  private SetOfLevelConstraints levelConstraints;
//  private SetOfArgLevelConstraints argLevelConstraints;
//  private HashSet argLevelParams;

  public final boolean levelCheck(int itr) {
    /***********************************************************************
    * I believe this should only be called once, with itr = 1.            *
    ***********************************************************************/
    if (this.levelChecked >= itr) return this.levelCorrect ;
    levelChecked = itr ;


    levelParams = new HashSet() ;
      /*********************************************************************
      * Added in SANY2.                                                    *
      *********************************************************************/

    /***********************************************************************
    * Level check the components this.module and this.substs[i].getExpr(). *
    ***********************************************************************/
    this.levelCorrect = true;
    if (!this.module.levelCheck(itr)) {
      this.levelCorrect = false;
    }
    for (int i = 0; i < this.substs.length; i++ ) {
      if (!this.substs[i].getExpr().levelCheck(itr)) {
        this.levelCorrect = false;
      }
    }

    // Check constraints on the substitution.
    for (int i = 0; i < this.substs.length; i++ ) {
      SymbolNode mparam = substs[i].getOp();
      ExprOrOpArgNode mexp = substs[i].getExpr();
      mexp.levelCheck(itr) ;
      mparam.levelCheck(itr);
        /*****************************************************************
        * Have to call levelCheck on these objects before calling        *
        * getLevel.                                                      *
        *****************************************************************/
      /*********************************************************************
      * Check level constraints for a constant module.                     *
      *********************************************************************/
      if (!this.module.isConstant()) {
        if (mexp.getLevel() > mparam.getLevel()) {
          if (mexp.levelCheck(itr) && mparam.levelCheck(itr)) {
            errors.addError(
               this.stn.getLocation(),
               "Level error in instantiating module '" + module.getName() +
               "':\nThe level of the expression or operator substituted for '"
                   + mparam.getName() +
               "' \nmust be at most " + mparam.getLevel() + ".");
          }
          this.levelCorrect = false;
         } //  if (mexp.getLevel() > mparam.getLevel())
       } // if (!this.module.isConstant())

        /*******************************************************************
        * For if mparam an operator parameter, check that mexp is          *
        * Leibniz.                                                         *
        *******************************************************************/
      if (mexp.getKind() == OpArgKind) {
        SymbolNode op = ((OpArgNode) mexp).getOp() ;
        if (   (   (op.getKind() == UserDefinedOpKind)
                || (op.getKind() == BuiltInKind))
            && ( ! ((OpDefNode) op).isLeibniz)) {
          errors.addError(
               this.stn.getLocation(),
               "Error in instantiating module '" + module.getName() +
               "':\n A non-Leibniz operator substituted for '"
                   + mparam.getName() + "'.");
            } // if ;
        } // if (mexp.getKind() == OpArgKind) ;
      } // for i

    SetOfLevelConstraints lcSet = this.module.getLevelConstraints();
    SetOfArgLevelConstraints alcSet = this.module.getArgLevelConstraints();
    for (int i = 0; i < this.substs.length; i++ ) {
      SymbolNode mparam = substs[i].getOp();
      ExprOrOpArgNode mexp = substs[i].getExpr();
        /*******************************************************************
        * mexp was level-checked above.                                    *
        *******************************************************************/
      Integer plevel = (Integer)lcSet.get(mparam);
      if (plevel != null &&
          mexp.getLevel() > plevel.intValue()) {
        if (mexp.levelCheck(itr)) {
          errors.addError(this.stn.getLocation(),
            "Level error in instantiating module '" + module.getName() +
            "':\nThe level of the expression or operator substituted for '" +
            mparam.getName() + "' \nmust be at most " + plevel + ".");
        }
        this.levelCorrect = false;
      }

      int alen = mparam.getArity();
      if (alen > 0 && ((OpArgNode)mexp).getOp() instanceof OpDefNode) {
        OpDefNode opDef = (OpDefNode)((OpArgNode)mexp).getOp();
        for (int j = 0; j < alen; j++) {
          ParamAndPosition pap = new ParamAndPosition(mparam, j);
          Integer alevel = (Integer)alcSet.get(pap);
          boolean opDefLevelCheck = opDef.levelCheck(itr) ;
            /***************************************************************
            * Need to call opDef.levelCheck before calling                 *
            * opDef.getMaxLevel.                                           *
            ***************************************************************/
          if (alevel != null &&
              opDef.getMaxLevel(j) < alevel.intValue()) {
            if (opDefLevelCheck) {
              /*************************************************************
              * Apparently, we only bother reporting this error if level   *
              * checking opDef didn't cause an error.                      *
              *************************************************************/
              errors.addError(
                this.stn.getLocation(),
                "Level error in instantiating module '" + module.getName() +
                  "':\nThe level of the argument " + j + " of the operator " +
                  opDef.getName() + " \nmust be at least " + plevel + ".");
            }
            this.levelCorrect = false;
          }
        }
      }
    }

    Iterator iter = this.module.getArgLevelParams().iterator();
    while (iter.hasNext()) {
      ArgLevelParam alp = (ArgLevelParam)iter.next();
      for (int i = 0; i < this.substs.length; i++) {
        SymbolNode pi = this.substs[i].getOp();
        for (int j = 0; j < this.substs.length; j++) {
          if (alp.op == pi &&
              alp.param == this.substs[j].getOp()) {
            SymbolNode op = ((OpArgNode)this.substs[i].getExpr()).getOp();
            boolean opLevelCheck = op.levelCheck(itr) ;
               /************************************************************
               * Need to level check before calling op.getMaxLevel.        *
               ************************************************************/
            if (op instanceof OpDefNode &&
                this.substs[j].getExpr().getLevel() >
                   ((OpDefNode)op).getMaxLevel(alp.i)) {
              if (opLevelCheck &&
                  this.substs[j].getExpr().levelCheck(itr)) {
                errors.addError(
                   this.stn.getLocation(),
                   "Level error when instantiating module '" +
                      module.getName() + "':\nThe level of the argument " +
                      alp.i + " of the operator " +
                      pi.getName() + "' \nmust be at most " +
                      ((OpDefNode)op).getMaxLevel(alp.i) + ".");
              }
              this.levelCorrect = false;
            }
          }
        } // for f
      } // for i
    } // while (iter.hasNext())

    // Calculate level information.
//    this.levelConstraints = new SetOfLevelConstraints();
    lcSet = Subst.getSubLCSet(this.module, this.substs,
                              this.module.isConstant(), itr);
      /*********************************************************************
      * At this point, levelCheck(itr) has been called on this.module and  *
      * on all nodes substs[i].getExpr(), which is a precondition for      *
      * calling getSubLCSet.                                               *
      *********************************************************************/
    iter = lcSet.keySet().iterator();
    while (iter.hasNext()) {
      SymbolNode param = (SymbolNode)iter.next();
      if (!param.occur(this.params)) {
        this.levelConstraints.put(param, lcSet.get(param));
      }
    }
    for (int i = 0; i < this.substs.length; i++) {
      lcSet = this.substs[i].getExpr().getLevelConstraints();
      iter = lcSet.keySet().iterator();
      while (iter.hasNext()) {
        SymbolNode param = (SymbolNode)iter.next();
        if (!param.occur(this.params)) {
          this.levelConstraints.put(param, lcSet.get(param));
        }
      }
    }

//    this.argLevelConstraints = new SetOfArgLevelConstraints();
    alcSet = Subst.getSubALCSet(this.module, this.substs, itr);
    iter = alcSet.keySet().iterator();
    while (iter.hasNext()) {
      ParamAndPosition pap = (ParamAndPosition)iter.next();
      if (!pap.param.occur(this.params)) {
        this.argLevelConstraints.put(pap, alcSet.get(pap));
      }
    }
    for (int i = 0; i < this.substs.length; i++) {
      alcSet = this.substs[i].getExpr().getArgLevelConstraints();
      iter = alcSet.keySet().iterator();
      while (iter.hasNext()) {
        ParamAndPosition pap = (ParamAndPosition)iter.next();
        if (!pap.param.occur(this.params)) {
          this.argLevelConstraints.put(pap, alcSet.get(pap));
        }
      }
    }

//    this.argLevelParams = new HashSet();
    HashSet alpSet = Subst.getSubALPSet(this.module, this.substs);
      /*********************************************************************
      * At this point, levelCheck(itr) has been called on this.module      *
      * and all nodes substs[i].getExpr(), which is a precondition for     *
      * calling getSubALPSet.                                              *
      *********************************************************************/
    iter = alpSet.iterator();
    while (iter.hasNext()) {
      ArgLevelParam alp = (ArgLevelParam)iter.next();
      if (!alp.occur(this.params)) {
        this.argLevelParams.add(alp);
      }
    }
    for (int i = 0; i < this.substs.length; i++) {
      alpSet = this.substs[i].getExpr().getArgLevelParams();
      iter = alpSet.iterator();
      while (iter.hasNext()) {
        ArgLevelParam alp = (ArgLevelParam)iter.next();
        if (!alp.occur(this.params)) {
          this.argLevelParams.add(alp);
        }
      }
    }
    return this.levelCorrect;
  }

  public final int getLevel() {
    /***********************************************************************
    * In SANY1, this was never called.  In SANY2 it is called for          *
    * instance nodes inside proofs.  However, the INSTANCE doesn't affect  *
    * the proof's level because it only imports definitions, so we let     *
    * its level be 0.                                                      *
    ***********************************************************************/
// Assert.fail("Internal Error: Should never call InstanceNode.getLevel().");
    return 0;    // make compiler happy
  }

  public final HashSet getLevelParams() {
    /***********************************************************************
    * In SANY1, this was never called.  However, in SANY2 it is called     *
    * for instance nodes inside proofs.                                    *
    ***********************************************************************/
// Assert.fail("Internal Error: Should never call InstanceNode.getLevelParams().");
    return levelParams ; // make compiler happy
  }

  public final SetOfLevelConstraints getLevelConstraints() {
    return this.levelConstraints;
  }

//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    return this.argLevelConstraints;
//  }
//
//  public final HashSet getArgLevelParams() { return this.argLevelParams; }

  public final String levelDataToString() {
    return "LevelConstraints: "    + this.levelConstraints    + "\n" +
           "ArgLevelConstraints: " + this.argLevelConstraints + "\n" +
           "ArgLevelParams: "      + this.argLevelParams      + "\n";
  }
  /**
   * The children of an instance are the expressions beings
   * substituted for parameters.
   */
  public SemanticNode[] getChildren() {
      SemanticNode[] res = new SemanticNode[substs.length];
      for (int i = 0; i < substs.length; i++) {
          res[i] = substs[i].getExpr();
      }
      return res;
   }

  public final void walkGaph(Hashtable<Integer, ExploreNode> semNodesTable, final ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;

    semNodesTable.put(myUID, this);
    visitor.preVisit(this);

    for (int i = 0; i < params.length; i++) {
      params[i].walkGraph(semNodesTable, visitor);
    }
    module.walkGraph(semNodesTable, visitor);
    visitor.postVisit(this);
  }

  public final String toString(int depth) {
    if (depth <= 0) return "";

    String ret = "\n*InstanceNode " + super.toString(depth) +
                 "  InstanceName = " + (name == null ? "(none)" : name.toString()) +
                 Strings.indent(2, "\nModule: " + module.getName())
   +             Strings.indent(2, "\nlocal: " + this.local);
    if (params.length > 0) {
      ret += Strings.indent(2,"\nInstance parameters:");
      for ( int i = 0; i < params.length; i++ ) {
        ret += Strings.indent(4,params[i].toString(depth-1));
      }
    }

    if (substs.length > 0) {
      ret += Strings.indent(2, "\nSubstitutions:");
      for (int i = 0; i < substs.length; i++) {
        ret += Strings.indent(2,
                              Strings.indent(2, "\nSubst:" +
                                             (substs[i] != null ?
                                              Strings.indent(2, substs[i].toString(depth-1)) :
                                              "<null>")));
      }
    }
    return ret;
  }

  protected Element getLevelElement(Document doc, tla2sany.xml.SymbolContext context) {

      Element sbts = doc.createElement("substs");
      for (int i=0; i<substs.length; i++) {
        sbts.appendChild(substs[i].export(doc,context));
      }

      Element prms = doc.createElement("params");
      for (int i=0; i<params.length; i++) {
        prms.appendChild(params[i].export(doc,context));
      }

      Element ret = doc.createElement("InstanceNode");
      if (name != null) ret.appendChild(appendText(doc,"uniquename",name.toString()));
      ret.appendChild(appendText(doc, "module", module.getName().toString() ));
      ret.appendChild(sbts);
      ret.appendChild(prms);
      return ret;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/Stack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.utilities;

public class
Stack extends tla2sany.utilities.Vector {

  public Stack() { super(); }

  public Stack( int size ) { super( size ); }

  public final boolean empty() {
    return size==0;
  }

  public final Object peek() {
    if (size == 0 )
      throw new java.util.EmptyStackException();
    else
      return info[ size -1 ];
  }

  public final Object pop() {
    if (size == 0 )
      throw new java.util.EmptyStackException();
    else
      return info[ size-- -1 ];
  }

  public final Object push( Object obj) {
    super.addElement( obj );
    return obj;
  }

  public final int search( Object obj ){
   for (int lvi = size-1; lvi >= 0; lvi-- )
     if ( obj == info[ lvi ] ) return lvi;
   return -1;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/TLAtoPCalMapping.java<|end_filename|>
/**
 */
package pcal;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Vector;

/**
 * A TLA+ to PlusCal mapping is a mapping from regions of the TLA+ translation 
 * to regions of the PlusCal code.  It is used to implement a command that allows the
 * user to jump from a selected region in the TLA+ translation to the region of the
 * PlusCal code that produced that region of the translation, as well as commands
 * to jump directly from the location indicated in an error report from SANY or TLC
 * to the PlusCal code responsible for the error.
 * <p>
 * The TLA+ to PlusCal mapping is computed and put in the {@link TLAtoPCalMapping#mapping}
 * field of this class.  A TLA+ spec of how this mapping is used to map from a region of
 * the translation to a region of the code is contained in the TLAToPCal module that is 
 * appended to the end of this file, and that is kept in the generals/docs project.
 * <p>
 *  BUGS IN THE IMPLEMENTATION OF THE TRANSLATION MAPPING
 *  - Sometimes, the selected region of of the translation should consist of an entire 
 *    labeled statement--that is, all code that can be executed in one action 
 *    starting from a label.  However, that code may be disconnected, with
 *    other labeled statements within it.  The implementation sticks to the pardigm 
 *    of making the displayed text the selected region, which must be connected.  
 *    The current implementation does not use MappingObject.Break objects, so it should 
 *    map the selected region to the smallest connected region of PlusCal code containing
 *    the labeled statement.  It does seem to do that.
 * 
 *  BUGS FOUND AND NOT CORRECTED IN ORIGINAL
 *  - In the construct with (v \in S) {...}, the translation should
 *    put a space before the ":" in "\E v \in S:".
 *    
 *  - The location of the error message generated by
 *  
 *        throw new PcalTLAGenException("Multiple assignment to " ...)
 *        
 *    in PcalTLAGen.GenAssign reports a pretty inaccurate error location.
 *    
 *  - The UNCHANGED line for an individual clause of an either statement
 *    is not wrapped if it's too long.
 *    
 *  - While some wrapping of long lines seems to be done in the fairness 
 *    conjunction of the Spec, I haven't figured out where because it can
 *    produce long lines that could be wrapped--e.g., in the WF and SF clause
 *    for a process with a lot of long ":+" labels.
 *    
 *  TRANSLATION OPTIMIZATIONS THAT I DISCOVERED COULD BE MADE:
 *  
 *  - In multiprocess Init conjunct for the pc, remove the CASE if there's
 *    just one process.
 *    
 *  - In GenProcedure and GenProcess, for a process or procedure whose body
 *    consists of just a single labeled statement, can eliminate the 
 *    def
 *    
 *       procName(self) == label(self)
 *    
 *    and use label instead of procName in the definition of Next.
 *    
 * @author lamport
 *
 */
public class TLAtoPCalMapping implements Serializable {
	/**
	 * If {@link TLAtoPCalMapping#mapping} is changed or additional
	 * (non-transient) fields are added (that are intended for serialization),
	 * this UID has to change (by e.g. incrementing by 1). This indicates a
	 * schema change to the serializer.
	 * <p>
	 * For more information on Java serialzation read Java(TM) Object
	 * Serialization Specification.
	 * 
	 * @see http
	 *      ://docs.oracle.com/javase/1.5.0/docs/guide/serialization/spec/version
	 *      .html#9419
	 */
	private static final long serialVersionUID = 4996600307008990835L;

  /**
   * The mapping field represents an element of TPMap in the TLAToPCal spec.
   *  
   */
  private MappingObject[][] mapping = new MappingObject[0][] ;
  
  /**
   * Sets the mapping field to an array version of mapVec, which must be a vector 
   * of vectors of MappingObjects.
   * 
   * @param mapVec
   * @return
   */
  public void  makeMapping(Vector<Vector<MappingObject>> mapVec) {
     this.mapping = new MappingObject[mapVec.size()][] ;
      for (int i = 0 ; i < this.mapping.length; i++) {
          Vector<MappingObject> line = mapVec.elementAt(i);
          this.mapping[i] = new MappingObject[line.size()];
          for (int j = 0; j < line.size(); j++) {
              this.mapping[i][j] = line.elementAt(j);
          }
      }
      return ;
  }

	/**
	 * Calls {@link TLAtoPCalMapping#ApplyMapping(TLAtoPCalMapping, Region)} to
	 * find the PCal {@link Region}, using the {@link Region} tlaRegion obtained
	 * by adjusting the line numbers of the selected region by
	 * currentAlgorithmLine.
	 * 
	 * @param tlaRegion
	 *            The TLA {@link Region} for which the PCal {@link Region} is to
	 *            be returned
	 * @param currentAlgorithmLine
	 *            The current line of the "--algorithm" or "--fair" keyword in
	 *            the module (in Java coordinates)
	 * @return The {@link Region} of the PCal counterpart
	 * @see TLAtoPCalMapping#ApplyMapping(TLAtoPCalMapping, Region)
	 */
	public Region mapTLAtoPCalRegion(final Region tlaRegion, int currentAlgorithmLine) {
		final int delta = currentAlgorithmLine - algLine;

		// a) Adjust TLA region with the current line of the algorithm. This is
		// necessary because the mapping bases its calculation on the original
		// line of the algorithm which has moved by now.
		tlaRegion.getBegin().adjustLineBy(tlaStartLine + delta);
		tlaRegion.getEnd().adjustLineBy(tlaStartLine + delta);
		
		// b) Actually map TLA to PCal based on the translation
		final Region pcalRegion = ApplyMapping(this, tlaRegion);
		
		// c) Translate the pcalRegion back to the current algorithm location to reverse
		// step a) if not null (null means there is no valid mapping)
		if (pcalRegion != null) {
			pcalRegion.getBegin().adjustLineBy(delta);
			pcalRegion.getEnd().adjustLineBy(delta);
		}
		
		return pcalRegion;
	}
  
	  /* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + algColumn;
		result = prime * result + algLine;
		result = prime * result + Arrays.hashCode(mapping);
		result = prime * result + tlaStartLine;
		return result;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		TLAtoPCalMapping other = (TLAtoPCalMapping) obj;
		if (algColumn != other.algColumn)
			return false;
		if (algLine != other.algLine)
			return false;
		if (tlaStartLine != other.tlaStartLine)
			return false;
		// mapping is an [][] for which Arrays.equals(Object[],Object[]) check
		// referential equality on its elements. Since the element is an array
		// itself, object equality has to be checked.
		if (!equals(mapping, other.mapping))
			return false;
		return true;
	}
	
	/**
	 * @see Arrays#equals(Object[], Object[]) except that elements are checked
	 *      via object identity instead of referential identity.
	 */
	private boolean equals(MappingObject[][] m, MappingObject[][] m2) {
        if (m==m2)
            return true;
        if (m==null || m2==null)
            return false;

        int length = m.length;
        if (m2.length != length)
            return false;

        for (int i=0; i<length; i++) {
            MappingObject[] o1 = m[i];
            MappingObject[] o2 = m2[i];
            // Use object instead of referential identity here
            if (!(o1==null ? o2==null : Arrays.equals(o1,o2)))
                return false;
        }

        return true;

	}
	
    /**
     * Returns the line number (zero based) of the line containing the first
     * "--algorithm" or "--fair algorithm" token(s) that begin(s) a PlusCal algorithm. 
     * Returns -1 if there is none.
     */
	public static int GetLineOfPCalAlgorithm(String moduleAsString) {
		final int algorithmStringLocation = moduleAsString.indexOf(PcalParams.BeginAlg);
		final int fairStringLocation = moduleAsString.indexOf(PcalParams.BeginFairAlg);
		if (fairStringLocation == -1
				|| ((algorithmStringLocation != -1) && (algorithmStringLocation < fairStringLocation))) {
			return algorithmStringLocation;
		}
		int i = fairStringLocation + PcalParams.BeginFairAlg.length();
		while (Character.isWhitespace(moduleAsString.charAt(i))) {
			i++;
		}
		if ((i != fairStringLocation + PcalParams.BeginFairAlg.length())
				&& (moduleAsString.startsWith(PcalParams.BeginFairAlg2, i))
				&& !Character.isLetterOrDigit(moduleAsString.charAt(i + PcalParams.BeginFairAlg2.length()))) {
			return fairStringLocation;
		} else {
			return algorithmStringLocation;
		}
	}

/**
   * Returns the PCal code location to which `mapping' maps the tpregion Region in the
   * TLA+ translation, where line numbers in `selection' are relative to tlaStartLine.
   * It returns null if the mapping does not map the selection to any PCal code. 
   * This implements the algorithm of module TLAToPCal.
   * <p> 
   * Preconditions: 1. The first and last lines of mapping.mapping are not empty.
   * 
   * @param mapping
   * @param tpregion
   * @return
   */
  public static Region ApplyMapping(TLAtoPCalMapping mapping, Region tpregion) {
      /*
       * This method is the implementation of the algorithm in TLAToPCal.tla.  In that
       * algorithm, a mapping specification is a sequence of tokens.  That sequence
       * corresponds to the concatenation of the lines mapping[0], mapping[1], ...
       * In other words, an index into a specification in the algorithm is implemented
       * by a PCalLocation.  The PCalLocation pcl is the index of the MappingObject
       * mapping.mapping[pcl.line][pcl.column].
       * 
       * However, we modify that spec slightly in the following ways:
       *   - The RegionToTokPair method implements something slightly different
       *     than is specified by the operator of that name in TLAToPCal.
       * 
       */
      
      MappingObject[][] tpMap = mapping.mapping;
//MappingObject.printMapping(map);
      Region tokPairRegion = RegionToTokPair(tpMap, tpregion) ;
      if (tokPairRegion == null) {
          return null;
      }
      
      PCalLocation ltok = tokPairRegion.getBegin();
      PCalLocation rtok = tokPairRegion.getEnd();
      
      /* 
       * The algorithm sets allExpr to true iff tok.inExpr is true for all 
       * tokens from ltok to rtok, where tok.inExpr is true iff token tok
       * comes from an expression.  A TLAToken object contains no information
       * about whether or not it is from an expression, and neither does
       * a MappingObject.SourceToken or MappingObject.Begin/EndTLAToken
       * object.  We can infer whether a MappingObject comes from an
       * expression from the following observations:
       * 
       * - Every SourceToken or Begin/EndToken in an expression comes from
       *   a TLAToken object in a TLAExpr in the field of an AST object.
       * 
       * - The only TLAToken objects in an AST are in a TLAExpr field.
       * 
       * - The preceding observations imply that all SourceToken MappingObjects with
       *   non-null origin come from expressions.  
       *   
       * - The only TLATokens in a TLAExpr that have null origin are added
       *   by PcalTLAGen.addSubscriptsToExpr.  However, all of those added with
       *   null origin lie inside Left/RightParen pairs.  
       *   
       * From all this, we conclude that to determine the entire selection
       * lies within an expression iff every MappingObject at minimum
       * depth is a SourceToken (which I believe represents a TLAToken
       * with non-null origin).
       *                          ------
       * If d is the parenthesis depth of ltok, then set rtokDepth and minDepth 
       * such that d + rtokDepth is the depth of rtok, d + minDepth is the
       * minimum depth of tokens, and allExpr is true iff all tokens in
       * positions ltok to rtok are expression tokens.  However, we take
       * into account that each SourceToken represents in module TLAToPCal
       * a TLAToken enclosed in parentheses.  In computing minDepth and
       * rtokDepth, the only one of those parentheses have to be taken into 
       * consideration are the ones that might lie to the immediate right of
       * ltok and to the immediate left of rtok.
       */
      int rtokDepth = 0;
      int minDepth = 0;
      boolean allExpr = false;
      MappingObject ltokObj = ObjectAt(ltok, tpMap);
      MappingObject rtokObj = ObjectAt(rtok, tpMap);
      if (ltokObj.getType() == MappingObject.SOURCE_TOKEN) {
          allExpr = true;
          minDepth = -1;
          rtokDepth = -1;
      }
      PCalLocation i = NextLocOf(ltok, tpMap);
      while (LTEq(i, rtok)) {
          int newDepth = ModifiedDepth(rtokDepth, i, true, tpMap);
          if (newDepth < minDepth) {
              /*
               * If we've just reached a new minDepth, then token i is
               * a RightParen and we must reset allExpr, which 
               * should reflect only tokens at the minimum depth.
               */
              minDepth = newDepth;
              allExpr = true; 
          }
          else if ((newDepth == rtokDepth) && (newDepth == minDepth)){
              /*
               * We are at minDepth and this token i is not a Paren, so
               * we set allExpr false if token i is not a SourceToken
               */
              allExpr = allExpr && (ObjectAt(i, tpMap).getType() == MappingObject.SOURCE_TOKEN);
          }
          rtokDepth = newDepth;
          i = NextLocOf(i, tpMap);
      }
      
      if (rtokObj.getType() == MappingObject.SOURCE_TOKEN) {
          rtokDepth++;
          if (rtokDepth < minDepth) {
              minDepth = rtokDepth;
          }
      }

      if (allExpr 
              /*
               * The spec has the following conjunction, but it seems to work correctly
               * without it.
               */
             // && ((ltok.getColumn() != rtok.getColumn()) || (ltok.getLine() != rtok.getLine()))
         ){
          minDepth++;
      }
          
      /*
       * Set bParen to first left paren to left of ltok that descends to
       * relative paren depth minDepth.  That left paren can be the implicit
       * left paren before a SourceToken only if that SourceToken is ltok.
       * That is the case iff minDepth is 0, in which case bParen is set to
       * ltok rather than to a LeftParen object.
       */
      int curDepth = 0;
      i = ltok;
      boolean sourceTok = (ltokObj.getType() == MappingObject.SOURCE_TOKEN);

      if ((minDepth != 0) || (!sourceTok)) {
          if (sourceTok) {
              curDepth = -1;
          }
          i = PrevLocOf(ltok, tpMap);
          while (! (   (ObjectAt(i, tpMap).getType() == MappingObject.LEFT_PAREN)
                    && (curDepth == minDepth))){
              curDepth = ModifiedDepth(curDepth, i, false, tpMap);
              i = PrevLocOf(i, tpMap);
          }
      }
      MappingObject bParen = ObjectAt(i, tpMap);
      
      /*
       * Set eParen to first right paren to the right of rtok that rises
       * from relative paren depth minDepth.  That is the implicit right
       * paren after a SourceToken iff the SourceToken is rtok and 
       * rtokDepth = minDepth, in which case eParen is set to rtok rather
       * than an RightParen object.
       */
      curDepth = rtokDepth; 
      i = rtok;
      sourceTok = (rtokObj.getType() == MappingObject.SOURCE_TOKEN);
      if ((minDepth != rtokDepth) || (!sourceTok)) {
          if (sourceTok) {
              curDepth--;
          }
          i = NextLocOf(rtok, tpMap);
          while (! (   (ObjectAt(i, tpMap).getType() == MappingObject.RIGHT_PAREN)
                    && (curDepth == minDepth))){
              curDepth = ModifiedDepth(curDepth, i, true, tpMap);
              i = NextLocOf(i, tpMap);
          }
      }
      MappingObject eParen = ObjectAt(i, tpMap);
      
      /*
       * The algorithm of TLAToPCal now looks for breaks between bParen and eParen to compute the
       * sequence of disjoint regions that should really be highlighted.  This is not being
       * implemented now, so we skip that part and just construct and return the result.
       */
    
      /*
       * Set lpos and rpos to the PCalLocations marking the left and right of bParen and eParen.
       */
      PCalLocation lpos ;
      if (bParen.getType() == MappingObject.SOURCE_TOKEN) {
          lpos = ((MappingObject.SourceToken) bParen).getOrigin().getBegin();
      }
      else {
          lpos = ((MappingObject.LeftParen) bParen).getLocation();
      }
      
      PCalLocation rpos ;
      if (eParen.getType() == MappingObject.SOURCE_TOKEN) {
          rpos = ((MappingObject.SourceToken) eParen).getOrigin().getEnd();
      }
      else {
          rpos = ((MappingObject.RightParen) eParen).getLocation();
      }
      
      /*
       * If lpos is the location (0,0), then return null.  Else, return (lpos, rpos)
       */
      if (lpos.getLine() == 0 && lpos.getColumn() == 0) {
          return null;
      }
      return new Region(lpos, rpos);
  }
  
  /**
   * If var is the parenthesis depth of the token at location pos, then
   * the following method sets var to the parenthesis depth of the token
   * at the location past pos if movingForward = TRUE, else the depth at
   * the location before pos if movingForward = FALSE.  This essentially
   * implements the macro of the same name in the algorithm of module
   * TLAToPCal.
   * @return
   */
  private static int ModifiedDepth(int var, PCalLocation pos, boolean movingForward, MappingObject[][] tpMap) {
      int amt = 0;
      int type = ObjectAt(pos, tpMap).getType();
      if (type == MappingObject.LEFT_PAREN) {
          amt = 1;
      }
      else if (type == MappingObject.RIGHT_PAREN) {
          amt = -1;
      }
      return var + (movingForward ? amt : -amt);
  }
  
  /**
   * This implements the operator of the same name in TLAToPCal.tla.  The
   * Region return value is the position in spec of a pair of PCalLocations 
   * of a BeginTLAToken and EndTLAToken, which delimit the region in the
   * TLA+ translation that we interpret the user's selection as having chosen.
   * However, if the user has effectively chosen the entire algorithm, it
   * returns null.
   * 
   * Note: the spec implies that if the right edge of reg is at the beginning of
   * a token, then that token is part of the region returned.  Similarly, if
   * the left edge of reg is at the end of a token, that token is part of the returned
   * region.  This is counterintuitive, and perhaps it should be changed.  However, I
   * will see if this is a practical problem before fixing it.
   * 
   * Preconditions of this method:
   *   The first and last lines of spec are non-empty.
   * @param map
   * @param reg
   * @return
   */
  private static Region RegionToTokPair(MappingObject[][] spec, Region reg) {
      /*
       * Set regBegin, regEnd to the endpoints of Region reg.
       */
      PCalLocation regBegin = reg.getBegin();
      PCalLocation regEnd = reg.getEnd();
      /*
       * If the entire region is outside the translation, return null.
       * If one endpoint is outside the translation, then move it to
       * the beginning or end.
       */
      if (regEnd.getLine() < 0 || regBegin.getLine() >= spec.length) {
          return null;
      }
      
      if (regBegin.getLine() < 0) {
          regBegin = new PCalLocation(0, 0) ;
      }
      
      if (regEnd.getLine() >= spec.length) {
          regEnd = new PCalLocation(spec.length-1,999);
      }
      
      /*
       * Set tokAtOrRightOfBeginning to the location of the first BeginTLAToken 
       * or SourceToken object of 
       * spec such that either regBegin lies within the TLA+ translation region
       * marked by it and its matching EndTLAToken object, of regBegin lies
       * to its left.  Set to null if there is no such BeginTLAToken object.
       * 
       */
      PCalLocation tokAtOrRightOfBeginning = null ;
      
      boolean prevIsBeginToLeft = false;
        // set to true when a BeginTLAToken object is found on line
        // makring a position at or to the left of regBegin.
      boolean notDone = true;
      /*
       * Set locLine to the first line at or after the regBegin.line for
       * which spec has a non-empty line.
       */
      int locLine = regBegin.getLine() ;
      while (locLine < spec.length && spec[locLine].length == 0) {
          locLine++;
      }
      if (locLine >= spec.length) {
          notDone = false;
      }
      PCalLocation loc = new PCalLocation(locLine, 0);
      PCalLocation prevloc = null ;
      
      while (notDone && loc != null) {
          if (prevIsBeginToLeft) {
              MappingObject.EndTLAToken mobj 
                  = (MappingObject.EndTLAToken) ObjectAt(loc, spec) ;
                // This will throw an exception if a BeginTLAToken is not
                // immediately followed by an EndTLAToken
              if (LT(regBegin, new PCalLocation(loc.getLine(), mobj.getColumn()))) {
                  tokAtOrRightOfBeginning = prevloc;
                  notDone = false;
              }
              else {
                  prevIsBeginToLeft = false;
              }
          } 
          else {
              MappingObject obj = ObjectAt(loc, spec);
              if (obj.getType() == MappingObject.END_TLATOKEN) {
                 // If we encounter an EndTLAToken object before a BeginTLAToken
                 // object, then the matching BeginTLAToken object is at an
                 // earlier line than regBeg and is therefore the one we want,
                 // if it is at or to the right of regBegin.
                 MappingObject.EndTLAToken eobj = (MappingObject.EndTLAToken) obj;
                 if (LT(regBegin, new PCalLocation(loc.getLine(), eobj.getColumn()))) {
                     tokAtOrRightOfBeginning = PrevLocOf(loc, spec);
                     notDone = false;
                 }
              }
              else if (obj.getType() == MappingObject.BEGIN_TLATOKEN) {
                  MappingObject.BeginTLAToken bobj = (MappingObject.BeginTLAToken) obj;
                  if (LTEq(regBegin, new PCalLocation(loc.getLine(), bobj.getColumn()))) {
                      tokAtOrRightOfBeginning = loc;
                      notDone = false;
                  }
                  else {
                      prevIsBeginToLeft = true;
                  }
              }
              else if (obj.getType() == MappingObject.SOURCE_TOKEN) {
                  MappingObject.SourceToken sobj = (MappingObject.SourceToken) obj;
                  if (LT(regBegin, new PCalLocation(loc.getLine(), sobj.getEndColumn()))) {
                      tokAtOrRightOfBeginning = loc;
                      notDone = false;
                  }
              }
          }
          prevloc = loc;
          loc = NextLocOf(loc, spec);
      }
      
      /*
       * Set tokAtOrLeftOfEnd to the location of the first EndTLAToken or
       * SourceToken object of spec such that either regEnd lies within 
       * the TLA+ translation region marked by it and its matching EndTLAToken 
       * object, of regBegin lies to its left.  Set to null if there is no 
       * such BeginTLAToken object.  This code is the "mirror image" of
       * the code above for tokAtOrRightOfBegin
       * 
       */

      PCalLocation tokAtOrLeftOfEnd = null ;
      // If regEnd lies within the region of the TLA+ translation delimited 
      // by a BeginTLAToken, EndTLAToken pair, then this is the BeginTLAToken.
      boolean prevIsEndToRight = false;
      // set to true when a BeginTLAToken object is found on line
      // makring a position at or to the left of regBegin.
      notDone = true;
    /*
     * Set locLine to the first line at or after the regEnd.line for
     * which spec has a non-empty line.
     */
    locLine = regEnd.getLine() ;
    while (locLine >= 0 && spec[locLine].length == 0) {
        locLine--;
    }
    if (locLine < 0) {
        notDone = false;
    }
    loc = new PCalLocation(locLine, spec[locLine].length-1);
    prevloc = null ;
    
    while (notDone && loc != null) {
        if (prevIsEndToRight) {
            MappingObject.BeginTLAToken mobj 
                = (MappingObject.BeginTLAToken) ObjectAt(loc, spec) ;
              // This will throw an exception if a BeginTLAToken is not
              // immediately followed by an EndTLAToken
            if (LT(new PCalLocation(loc.getLine(), mobj.getColumn()), regEnd)) {  // should be LT
                tokAtOrLeftOfEnd = prevloc;
                notDone = false;
            }
            else {
                prevIsEndToRight = false;
            }
        } 
        else {
            MappingObject obj = ObjectAt(loc, spec);
            if (obj.getType() == MappingObject.BEGIN_TLATOKEN) {
               // If we encounter a BeginTLAToken object before an EndTLAToken
               // object, then the matching EndTLAToken object is at a
               // later line than regEnd and is therefore the one we want
               // if this BeginTLAToken is at or to the left of regEnd.
               MappingObject.BeginTLAToken eobj = (MappingObject.BeginTLAToken) obj;
               if (LT(new PCalLocation(loc.getLine(), eobj.getColumn()), regEnd)) {
                   tokAtOrLeftOfEnd = NextLocOf(loc, spec);
                   notDone = false;
               }
            }
            else if (obj.getType() == MappingObject.END_TLATOKEN) {
                MappingObject.EndTLAToken bobj = (MappingObject.EndTLAToken) obj;
                if (LTEq(new PCalLocation(loc.getLine(), bobj.getColumn()), regEnd)) {
                    tokAtOrLeftOfEnd = loc;
                    notDone = false;
                }
                else {
                    prevIsEndToRight = true;
                }
            }
            else if (obj.getType() == MappingObject.SOURCE_TOKEN) {
                MappingObject.SourceToken sobj = (MappingObject.SourceToken) obj;
                if (LT(new PCalLocation(loc.getLine(), sobj.getBeginColumn()), regEnd)) {
                    tokAtOrLeftOfEnd = loc;
                    notDone = false;
                }
            }
        }
        prevloc = loc;
        loc = PrevLocOf(loc, spec);
    }
    
    if (tokAtOrRightOfBeginning != null) {
        if (tokAtOrLeftOfEnd == null) {
            return new Region(tokAtOrRightOfBeginning, tokAtOrRightOfBeginning);
        }
        else if (LTEq(tokAtOrRightOfBeginning, tokAtOrLeftOfEnd)) {
            return new Region(tokAtOrRightOfBeginning, tokAtOrLeftOfEnd) ;
        } 
        else {
            /*
             * This is the case in which the region is between TLA+ tokens, so
             * we want to select the token that is closest to that region.  The
             * two possibilities are the one lying to the right, whose beginning
             * is tokAtOrRightOfBeginning, or the one lying to the left,
             * whose end is tokAtOrLeftOfEnd.  We first find their distances
             * to the region.
             */
             int distToLeft;
             MappingObject obj = ObjectAt(tokAtOrLeftOfEnd, spec);
             if (obj.getType() == MappingObject.END_TLATOKEN) {
                 distToLeft = Dist(new PCalLocation (tokAtOrLeftOfEnd.getLine(), 
                                                     ((MappingObject.EndTLAToken) obj).getColumn()),
                                   regBegin);
             }
             else {
                 distToLeft = Dist(new PCalLocation (tokAtOrLeftOfEnd.getLine(), 
                                                      ((MappingObject.SourceToken) obj).getEndColumn()),
                                    regEnd);
             }
             int distToRight;
              obj = ObjectAt(tokAtOrRightOfBeginning, spec);
             if (obj.getType() == MappingObject.BEGIN_TLATOKEN) {
                 distToRight = Dist(new PCalLocation (tokAtOrRightOfBeginning.getLine(), 
                                                     ((MappingObject.BeginTLAToken) obj).getColumn()),
                                    regEnd);
             }
             else {
                 distToRight = Dist(new PCalLocation (tokAtOrRightOfBeginning.getLine(), 
                                                      ((MappingObject.SourceToken) obj).getBeginColumn()),
                                    regEnd);
             }

             /*
              * If needed, we  set leftBegin to be location of the matching 
              * beginning of tokAtOrLeftEnd and rightEnd to be the matching
              * end of tokAtOrRightOfBeginning.
              */
             PCalLocation leftBegin = null;
             PCalLocation rightEnd = null;
             if (distToLeft >= distToRight) {
                  /*
                   * We need rightEnd.
                   */
                  rightEnd = tokAtOrRightOfBeginning;
                  notDone = true ;
                  while (rightEnd != null && notDone) {
                     // rightEnd should never equal null;  we'll get
                     // an exception if it is.  
                     int type = ObjectAt(rightEnd, spec).getType() ;
                     if (   (type == MappingObject.END_TLATOKEN)
                         || (type == MappingObject.SOURCE_TOKEN)) {
                         notDone = false; 
                     }
                     if (notDone) {
                         rightEnd = NextLocOf(rightEnd, spec);
                     }
                 }
             }
             
             if (distToLeft <= distToRight) {
                 /*
                  * We need leftBegin.
                  */
                 leftBegin = tokAtOrLeftOfEnd;
                 notDone = true ;
                 while (notDone) {
                    // leftBegin should never equal null;  we'll get
                    // an exception if it is.
                    int type = ObjectAt(leftBegin, spec).getType() ;
                    if (   (type == MappingObject.BEGIN_TLATOKEN)
                        || (type == MappingObject.SOURCE_TOKEN)) {
                        notDone = false; 
                    }
                    if (notDone) {
                        leftBegin = PrevLocOf(leftBegin, spec);
                    }
                }
            }
            
            if (distToLeft > distToRight) {
                return new Region(tokAtOrRightOfBeginning, rightEnd);
            } 
            else if (distToLeft < distToRight) {
                return new Region(leftBegin, tokAtOrLeftOfEnd);
            }
            else {
                return new Region(leftBegin, rightEnd);
            }
        }
    }
    else if (tokAtOrLeftOfEnd != null) {
        return new Region(tokAtOrLeftOfEnd, tokAtOrLeftOfEnd);
    }
    return null; // both are null, so spec contains no TLA translation tokens.

  }
  
  /**
   * Returns the MappingObject at the location in map indicated by loc.
   * @param loc
   * @param map
   * @return
   */
  private static MappingObject ObjectAt(PCalLocation loc, MappingObject[][] map) {
      return map[loc.getLine()][loc.getColumn()] ;
  }
  
  /**
   * Returns the position within map of the previous object after the one with
   * position loc.  It returns null if there is no previous  object in map.
   * @param loc
   * @param map
   * @return
   */
  private static PCalLocation PrevLocOf(PCalLocation loc, MappingObject[][] map) {
      if (loc.getColumn() > 0) {
          return new PCalLocation(loc.getLine(), loc.getColumn()-1) ;
      }
      for (int i = loc.getLine() - 1; i >= 0; i--) {
          if (map[i].length > 0) {
              return new PCalLocation(i, map[i].length - 1);
          }
      }
      return null;
  }
  
  /**
   * Returns the position within map of the next object after the one with
   * position loc.  It returns null if there is no further object in map.
   * @param loc
   * @param map
   * @return
   */
  private static PCalLocation NextLocOf(PCalLocation loc, MappingObject[][] map) {
      if (loc.getColumn() + 1 < map[loc.getLine()].length) {
          return new PCalLocation(loc.getLine(), loc.getColumn()+1) ;
      }
      for (int i = loc.getLine() + 1; i < map.length; i++) {
          if (map[i].length > 0) {
              return new PCalLocation(i, 0);
          }
      }
      return null;
  }
  
  /**
   * True iff location locA is before or equal to locB
   * @param locA
   * @param locB
   * @return
   */
  private static boolean LTEq(PCalLocation locA, PCalLocation locB) {
      if (locA.getLine() == locB.getLine()) {
          return locA.getColumn() <= locB.getColumn();
      }
      return locA.getLine() < locB.getLine();
  }
 
  /**
   * True iff location locA is before  locB
   * @param locA
   * @param locB
   * @return
   */
  private static boolean LT(PCalLocation locA, PCalLocation locB) {
      if (locA.getLine() == locB.getLine()) {
          return locA.getColumn() < locB.getColumn();
      }
      return locA.getLine() < locB.getLine();
  }

  /**
   * The distance between the two locations, where the distance from the end of 
   * one line to the beginning of the next is considered to be 9999 times as 
   * great as the distance between adjacent characters.
   * 
   * @param locA
   * @param locB
   * @return
   */
  private static int Dist(PCalLocation locA, PCalLocation locB) {
      return 9999 * Math.abs(locA.getLine() - locB.getLine())
              + Math.abs(locA.getColumn() - locB.getColumn());
  }
  
  /* --------------------------------------------------------------------*/
  
  /**
   * The line number of the source file that, when the file was translated,
   * corresponded to line 0 of {@link TLAtoPCalMapping#mapping}.  At that
   * time, it was the line immediately after the BEGIN TRANSLATION comment.
   */
  public int tlaStartLine;
  
  /**
   * The line containing the --algorithm or --fair that begins the
   * algorithm.
   */
  public int algLine ;
  
  /**
   * Should be the column of the beginning --algorithm or --fair that
   * begins the algorithm, but it's actually the column after that
   * token--which should make any difference.
   * 
   * I don't think this is needed.
   */
  public int algColumn ;
  
  /**
   * This removes redundant pairs of matching LeftParen, RightParen objects from
   * the mapping Vector mappingVec.  A redundant LeftParen, RightParen pair is
   * redundant if it comes immediately inside (with no intervening tokens) a matching
   * LeftParen, RightParen pair.  See the RemoveRedundantParens module, which will
   * be inserted as a comment at the end of this file, to see the algorithm on
   * which this implementation is based.  The `in' and `out' sequences of that
   * algorithm are implemented with the Vectors mappingVec and `out' of Vectors,
   * where element indices are represented as PCalLocation objects specifying
   * the "row" and "column" of the object.
   *  
   *
   * 
   * @param mappingVec
   * @return
   */
  public static Vector<Vector<MappingObject>> RemoveRedundantParens(Vector<Vector<MappingObject>> mappingVec) {
      Vector<Vector<MappingObject>> out = new Vector<Vector<MappingObject>>(); // Vector of Vectors of MappingObjects
      Vector<PCalLocation> unmatchedLeft = new Vector<PCalLocation>();  
         // Vector of PCalLocations in out of unmatched LeftParen objects
      PCalLocation lastMatchedLeft = null;
        // position in out of last LeftParen object that was matched by
        // a RightParen object
      PCalLocation lastAddedRight = null;
      int i = 0 ;
      while (i < mappingVec.size()) {
          Vector<MappingObject> inLine = mappingVec.elementAt(i);
          Vector<MappingObject> outLine = new Vector<MappingObject>();
          out.addElement(outLine);
          int j = 0 ;
          while (j < inLine.size()) {
              MappingObject inObj = inLine.elementAt(j); 
              if (inObj.getType() == MappingObject.LEFT_PAREN) {
                /*
                 * Bug in translating algorithm.  The following statement was
                 * originally coded as
                 *   
                 *   unmatchedLeft.addElement(new PCalLocation(i, j));
                 *   
                 * The algorithm clearly indicates it should have been.
                 */
                  unmatchedLeft.addElement(new PCalLocation(i, outLine.size()));
              }
              else if (inObj.getType() == MappingObject.RIGHT_PAREN) {
                  PCalLocation lastUnmatchedLeft = null ;
                  if (unmatchedLeft.size() != 0) {
                      lastUnmatchedLeft = 
                        unmatchedLeft.elementAt(unmatchedLeft.size()-1);
                  }
                  if (   IsNextIn(lastAddedRight, 
                                  new PCalLocation(i, j),
                                  mappingVec)
                      && IsNextIn(lastUnmatchedLeft, lastMatchedLeft,  out)    
                      ) {
                      (out.elementAt(lastMatchedLeft.getLine()))
                          .remove(lastMatchedLeft.getColumn());
                      /*
                       * Set lastLine to the last non-empty line of out, then
                       * delete its last element.
                       */
                      Vector<MappingObject> lastLine = outLine;
                      int lastLineNum = out.size()-1;
                      while (lastLine.size() == 0) {
                          lastLineNum--;
                          lastLine = out.elementAt(lastLineNum);
                      }
                      lastLine.remove(lastLine.size()-1);
                  }
                  lastMatchedLeft = 
                     unmatchedLeft.remove(unmatchedLeft.size()-1);
                  lastAddedRight = new PCalLocation(i, j);
              }
              
              outLine.addElement(inObj);
              j++;
          }
          
          i++;
      }
      return out;
  }
  
  /**
   * If vec is a vector of vectors, then it returns true iff locA and locB are
   * both non-null and locA and locB represent consecutive (line, column) locations
   * in vector vec (with locA preceding locB).  If non-null, then the line fields 
   * of locA and locB must both be less than vec.size().
   * 
   * @param locA
   * @param locB
   * @param vec
   * @return
   */
  private static boolean IsNextIn(PCalLocation locA, PCalLocation locB, Vector<Vector<MappingObject>> vec) {
      return     (locA != null)
              && (locB != null)
              && (   (   (locA.getLine() == locB.getLine())
                      && (locA.getColumn()+1 == locB.getColumn())
                     )
                  || (   (locA.getLine() == locB.getLine()-1)
                      && (locA.getColumn() == vec.elementAt(locA.getLine()).size())
                      && (locB.getColumn() == 0)
                     )
                 );
  }
  
}

/* ==================  Begin file TLAToPCal.tla  ========================

----------------------------- MODULE TLAToPCal -----------------------------
EXTENDS Integers, Sequences, TLC

(***************************************************************************)
(* We define the minimum and maximum of a nonempty set of numbers, and the *)
(* absolute value of a number.                                             *)
(***************************************************************************)
Min(S) == CHOOSE i \in S : \A j \in S : i =< j
Max(S) == CHOOSE i \in S : \A j \in S : i >= j
Abs(x) == Max({x, -x})

(***************************************************************************)
(* TP Mapping Specifiers               .                                   *)
(***************************************************************************)
Location == [line : Nat, column : Nat]
  (*************************************************************************)
  (* This is a location in the file, which might be in the TLA+ spec or in *)
  (* the PCal code.                                                        *)
  (*************************************************************************)

loc1 <: loc2 == 
  (*************************************************************************)
  (* This is the "equals or to the left of" relation on locations.         *)
  (*************************************************************************)
  \/ loc1.line < loc2.line
  \/ /\ loc1.line = loc2.line
     /\ loc1.column =< loc2.column

(***************************************************************************)
(* We define Dist(loc1, loc2) to be a natural number representing a        *)
(* distance between locations loc1 and loc2.  This distance is used only   *)
(* to determine which of two other locations a location is closer to.      *)
(* Thus, its magnitude doesn't matter.  I should make Dist a parameter of  *)
(* the spec, but it's less effort to give it some reasonable definition.   *)
(***************************************************************************)
Dist(loc1, loc2) == 
   10000 * Abs(loc2.line - loc1.line) + Abs(loc2.column - loc1.column)
   
Region == {r \in [begin : Location, end : Location] : r.begin <: r.end}
  (*************************************************************************)
  (* This describes a region within the file.  We say that region r1 is to *)
  (* the left of region r2 iff r1.end :< r2.begin                          *)
  (*************************************************************************)

(***************************************************************************)
(* TLA to PCal translation objects.                                        *)
(***************************************************************************)
TLAToken == [type : {"token"}, region  : Region, inExpr : BOOLEAN]
  (*************************************************************************)
  (* This represents a region of tokens in the TLA+ spec, with inExpr      *)
  (* being true iff that region lies within an expression.                 *)
  (*************************************************************************)
Paren    == [type : {"begin", "end"}, loc : Location]
  (*************************************************************************)
  (* This represents the beginning or end of a region in the PlusCal spec. *)
  (*************************************************************************)
Break    == [type : {"break"}, depth : Nat]
  (*************************************************************************)
  (* A Break comes between a right and left Paren at the same parenthesis  *)
  (* level (possibly with TLATokens also between them).  It indicates that *)
  (* there is some PlusCal code between the locations indicated by those   *)
  (* parentheses that should not be displayed when displaying the PlusCal  *)
  (* code for parenthesis levels between the current level lv and lv -     *)
  (* depth.                                                                *)
  (*************************************************************************)
TPObject == TLAToken \cup Paren \cup Break

RECURSIVE ParenDepth(_ , _)
ParenDepth(objSeq, pos) ==
  (*************************************************************************)
  (* Equals the parenthesis depth of the point in the TPObject sequence    *)
  (* objSeq just after element number pos, or at the beginning if pos = 0. *)
  (*************************************************************************)
  IF pos = 0 THEN 0
             ELSE LET obj == objSeq[pos]
                  IN  ParenDepth(objSeq, pos - 1) +
                        ( CASE obj.type = "begin" -> 1  []
                               obj.type = "end"   -> -1 []
                               OTHER              -> 0     )

\*CorrParenDepth(seq, pos) ==
\*  (*************************************************************************)
\*  (* Equals ParenDepth(seq, pos) unless seq[pos] is an expression token,   *)
\*  (* in which case it is one larger.                                       *)
\*  (*************************************************************************)
\*  LET dp ParenDepth(seq, pos)
\*  IN  IF seq[pos].type = "token" /\ seq[pos].inExpr THEN dp +1
\*               
\*                                     ELSE dp
(***************************************************************************)
(* WellFormed(seq) is true for a TPObject sequence iff it begins and ends  *)
(* with a parenthesis and all parentheses are properly matching.           *)
(***************************************************************************)
IsWellFormed(seq) ==  /\ seq # << >>
                      /\ seq[1].type = "begin"
                      /\ \A i \in 1..(Len(seq)-1) : ParenDepth(seq, i) >= 0
                      /\ ParenDepth(seq, Len(seq)) = 0

(***************************************************************************)
(* TokensInOrder(seq) is true for a TPObject sequence iff its TLAToken     *)
(* objects represent regions that are ordered properly--that is, if        *)
(* TLAToken T1 precedes TLAToken T2 in seq, then T1.region is to the left  *)
(* of T2.region.                                                           *)
(***************************************************************************)                      
TokensOf(seq) == {i \in 1..Len(seq) : seq[i].type = "token"}

TokensInOrder(seq) ==
  \A i \in TokensOf(seq) : 
     \A j \in { jj \in TokensOf(seq) : jj > i} : 
        (seq[i].region.end <: seq[j].region.begin)

MatchingParen(seq, pos) ==
  (*************************************************************************)
  (* If element number pos in TPObject sequence seq is a left paren, then  *)
  (* this equals the number n such that element number n is the matching   *)
  (* right paren.                                                          *)
  (*************************************************************************)
  CHOOSE i \in pos+1..Len(seq) :
     /\ ParenDepth(seq,i) = ParenDepth(seq, pos-1)
     /\ \A j \in (pos)..(i-1) : ParenDepth(seq, j) > ParenDepth(seq, pos-1)

(***************************************************************************)
(* A TPMap is a sequence of TPObject elements that has the following       *)
(* interpretation.  The regions of the TLA+ spec contained within its      *)
(* TLAToken elements contain the "important" text of the spec.  Text not   *)
(* in those regions can be treated as if it were white space when          *)
(* determining the PCal region that maps to a part of the TLA+ spec.       *)
(*                                                                         *)
(* Each pair of matching parentheses defines the smallest syntactic unit   *)
(* (e.g., expression or statement) whose translation contains the text in  *)
(* the TLATokens between them.  All the top level (lowest depth)           *)
(* parentheses between those matching parentheses describe successive      *)
(* regions in the same part of the PCal text.  (Code in a macro and code   *)
(* in a procedure is an example of two regions in completely different     *)
(* parts of the PCal code, and hence are not successive regions.) Two      *)
(* successive regions are adjacent if, to higlight both of them, one       *)
(* highlights those regions and the text between them.  If two successive  *)
(* regions represented by two pairs of matching parentheses are not        *)
(* adjacent, then the TPMap contains a Break between them.  The depth of a *)
(* break indicates the number of parenthesis levels containing the break   *)
(* that represent PCal code in which the region between the parenthesized  *)
(* regions on either side of the break should not be highlighted.          *)
(*                                                                         *)
(* The following predicate asserts that seq is a proper TPMap.             *)
(***************************************************************************)
IsTPMap(seq) ==
   (************************************************************************)
   (* There is at least one TLAToken between every matching pair of        *)
   (* parentheses.                                                         *)
   (************************************************************************)
   /\ \A i \in 1..Len(seq) :
         (seq[i].type = "begin") =>
            \E j \in (i+1)..(MatchingParen(seq,i)-1) : seq[j].type = "token"
   (************************************************************************)
   (* A token in an expression is surrounded by parentheses.               *)
   (************************************************************************)
   /\ \A i \in TokensOf(seq) : seq[i].inExpr =>  /\ seq[i-1].type = "begin"
                                                 /\ seq[i+1].type = "end"
   /\ IsWellFormed(seq)
   /\ TokensInOrder(seq)
   (************************************************************************)
   (* The following conjunct asserts that a Break comes between a right    *)
   (* and a left parenthesis at its level, perhaps with intervening        *)
   (* tokens.                                                              *)
   (************************************************************************) 
   /\ \A i \in 1..Len(seq) :
         (seq[i].type = "break") => 
            /\ \E j \in 1..(i-1) : 
                  /\ seq[j].type = "end"
                  /\ \A k \in (j+1)..(i-1) : seq[j].type # "begin"
            /\  \E j \in (i+1)..Len(seq) : 
                  /\ seq[j].type = "begin"
                  /\ \A k \in (i+1)..(j-1) : seq[j].type # "end"
   (************************************************************************)
   (* The following conjunct asserts that matching parentheses have        *)
   (* non-decreasing locations, and that within a pair of matched          *)
   (* parentheses, the regions represented by the top-level matching       *)
   (* parentheses are properly ordered.                                    *)
   (************************************************************************)
   /\ \A i \in 1..Len(seq) :
         (seq[i].type = "begin") =>
            LET j  == MatchingParen(seq, i)
                dp == ParenDepth(seq, i-1) + 1
            IN  /\ seq[i].loc <: seq[j].loc
                /\ \A k \in (i+1)..(j-1) :
                     /\ seq[k].type = "end"
                     /\ ParenDepth(seq, k) = dp
                     => \A m \in (k+1)..(j-1) :
                          /\ seq[m].type = "begin"
                          /\ ParenDepth(seq, m-1) = dp
                          => seq[k].loc <: seq[m].loc

TPMap == {s \in Seq(TPObject) : IsTPMap(s)}           
-----------------------------------------------------------------------------
(***************************************************************************)
(* The Region in the PCal code specified by a Region in the TLA+ spec.     *)
(***************************************************************************)

RegionToTokPair(spec, reg) ==
  (*************************************************************************)
  (* A pair of integers that are the positions of the pair of TLATokens in *)
  (* spec such that they and the TLATokens between them are the ones that  *)
  (* the user has chosen if she has highlighted the region specified by    *)
  (* reg.  (Both tokens could be the same.)                                *)
  (*                                                                       *)
  (* If the region reg does not intersect with the region of any TLAToken  *)
  (* (so it lies entirely inside "white space"), then the value is <<t,    *)
  (* t>> for the token t that lies either to the left or the right of reg. *)
  (*************************************************************************)
  LET TokensContaining(loc) == 
         (******************************************************************)
         (* The set of positions of tokens in spec containing loc.  (It    *)
         (* contains 0 or 1 element.)                                      *)
         (******************************************************************)
         {i \in TokensOf(spec) : /\ spec[i].region.begin <: loc
                                 /\ spec[i].region.begin # loc
                                 /\ loc <: spec[i].region.end
                                 /\ loc # spec[i].region.end  }
                          
      TokensToLeft(loc) == 
        (*******************************************************************)
        (* The set of positions of tokens in spec at or to the left of     *)
        (* loc.                                                            *)
        (*******************************************************************)
        {i \in TokensOf(spec) : spec[i].region.end <: loc}

      TokensToRight(loc) ==
        (*******************************************************************)
        (* The set of positions of tokens in spec at or to the right of    *)
        (* loc.                                                            *)
        (*******************************************************************)
        {i \in TokensOf(spec) : loc <: spec[i].region.begin}

      TokensInRegion == 
        (*******************************************************************)
        (* The set of tokens whose regions lie within reg.                 *)
        (*******************************************************************)
        TokensToRight(reg.begin) \cap TokensToLeft(reg.end)

      S == TokensInRegion \cup TokensContaining(reg.begin) 
            \cup TokensContaining(reg.end)
      
  IN  IF S # {}
        THEN <<Min(S), Max(S)>>
        ELSE LET LeftOfReg  == TokensToLeft(reg.begin)
                 LeftTok == Max(LeftOfReg)
                 RightOfReg == TokensToRight(reg.end)
                 RightTok == Min(RightOfReg)
             IN  CASE LeftOfReg = {}  -> <<RightTok, RightTok>> []
                      RightOfReg = {} -> <<LeftTok, LeftTok>>   []
                      OTHER ->
                        LET dl == Dist(spec[LeftTok].region.end, reg.begin)
                            dr == Dist(spec[RightTok].region.begin, reg.end)
                        IN  CASE dl < dr -> <<LeftTok, LeftTok>>   []
                                 dl > dr -> <<RightTok, RightTok>> []
                                 dl = dr -> <<LeftTok, RightTok>>
               
TokPairToParens(spec, ltok, rtok) ==
  (*************************************************************************)
  (* Assumes ltok and rtok are the positions of TLAToken elements of the   *)
  (* TPMap spec with ltok equal to or to the left of rtok.  It equals the  *)
  (* pair <<lparen, rparen>> where lparen is the position of the           *)
  (* right-most left paren to the left of ltok that enters level dp and    *)
  (* rparen is the position of the left-most right paren to the right of   *)
  (* rtok that leaves level dp, where dp is defined as follows:            *)
  (*                                                                       *)
  (* Let d be the minimum paren depth any token from ltok and rtok.  If    *)
  (* ltok # rtok and every TLAToken element from positions ltok through    *)
  (* rtok is an expression token, then dp = d+1.  Otherwise, dp = d.       *)
  (*************************************************************************)
  LET d == Min ( {ParenDepth(spec, i) : i \in ltok..rtok} )
      dp == IF /\ ltok # rtok 
               /\ \A i \in ltok..rtok : (spec[i].type = "token") =>
                                          spec[i].inExpr 
              THEN d + 1
              ELSE d
      lp == Max ( {i \in 1..ltok : /\ spec[i].type = "begin"
                                   /\ ParenDepth(spec,i) = dp} )
      rp == Min ( {i \in rtok..Len(spec) : /\ spec[i].type = "end"
                                           /\ ParenDepth(spec,i-1) = dp} )
  IN  <<lp, rp>>
-----------------------------------------------------------------------------
(***************************************************************************)
(* For Debugging                                                           *)
(*                                                                         *)
(* To simplify debugging, we assume that locations are all on the same     *)
(* line.                                                                   *)
(***************************************************************************)
Loc(pos) == [line |-> 0, column |-> pos]
Reg(beg, end) == [begin |-> Loc(beg), end |-> Loc(end)]
T(beg, end) == [type |->"token", region |-> Reg(beg, end), inExpr |-> FALSE]
TE(beg, end) == [type |->"token", region |-> Reg(beg, end), inExpr |-> TRUE]
L(pos) == [type |-> "begin", loc |-> Loc(pos)]
R(pos) == [type |-> "end", loc |-> Loc(pos)]
B(dep) == [type |-> "break", depth |-> dep]

tpMap_1 == << L(-5), T(2,3), L(11), T(3, 4), L(12), T(4,5), R(13), 
              T(6,7), R(14), T(8, 9), R(42) >>
tpRegion_1 == Reg(5,20)      
              
tpMap_2 == <<L(10), T(1,2), L(11), T(3,4), L(12), T(5,6), L(13), T(7,8), R(14),
             (* 10 *)T(9,10),  R(15), B(1), L(16), T(11,12), L(17), T(13,14), R(18), 
             (* 18 *) R(19), T(15,16), R(20), R(21)>>
\*        ( lbl : ( (  x[1] := ( 2 + 2 ) ) || y := 3  || ( x[2] := ( 3 ) )  )  )
\*        10     11 12         13     14 15              16        17 18 19 20 21
\*        ( lbl == ( x' = [x EXCEPT ( ![1] = ( 2 + 2 ) , ) ^^ ( ![2] = ( 3 ) ) ] ) )
\*          1-2      3 -----------4   5 ----6  7----8  9-10     11---12  13-14 15-16
tpRegion1 == Reg(0,16)

tpMap1 == << L(1), L(2), TE(1,2), R(3), L(4), TE(2,3), 
             R(5), T(4, 5), L(6), TE(5,6), R(7), R(8)>>

SpecToRegions(spec) ==
  (*************************************************************************)
  (* The set of all regions whose endpoints are in the smallest region     *)
  (* containing all the tokens of spec.                                    *)
  (*************************************************************************)
  LET TT == TokensOf(spec)
      left == Min({spec[i].region.begin.column : i \in TT})
      right == Max({spec[i].region.end.column : i \in TT})
  IN  { Reg(r[1], r[2]) : 
          r \in {rr \in (left..right) \X (left..right) : rr[1] =< rr[2]} }
-----------------------------------------------------------------------------
(***************************************************************************)
(* Declare tpMap to be the TPMap and tpLoc the Location that are the       *)
(* inputs to the algorithm.                                                *)
(***************************************************************************)
CONSTANT tpMap, tpRegion
  
(***************************************************************************
                          The Mapping Algorithm

This algorithm sets the variable `result' to the sequence of regions in
the PCal code that, according to the mapping specification tpMap,
should be highlighted when the user selects the region that is the
value of variable tpregion.  (Variable tpregion is initialized to
tpRegion to test a single region, and to SpecToRegions(tpMap) to test
all subregions.) In the initial Java implementation, I expect that
result will be set to a sequence containing only a single region.
                          
--fair algorithm Map {
    variables  
        tpregion \* = tpRegion ,             
                 \in SpecToRegions(tpMap),  
        ltok,      \* <<ltok, rtok>> is set to 
        rtok,      \*   RegionToTokPair(tpMap, tpregion)
        rtokDepth, \* The paren depth of rtok relative to ltok
        minDepth,  \* The depth of the minimum paren depth TLAToken 
        allExpr,   \* Set to true iff all tokens from ltok to rtok are
                   \*   expression tokens.             
        bParen,    \* <<bParen, eParen>> is set to 
        eParen,    \*   TokPairToParens(tpMap, ltok, rtok)
        result,    \* Set to the sequence of Regions that is the translation.
        curBegin,  \* Used to construct the result
        lastRparen,\*  "    
        i,         \* For loop variable
        curDepth ; \* Temporary variable for holding the paren depth

    (***********************************************************************)
    (* If var is the parenthesis depth of the token at position pos, then  *)
    (* the following macro sets var to the parenthesis depth of the token  *)
    (* at position pos + 1 if movingForward = TRUE, else the depth at pos  *)
    (* - 1 if movingForward = FALSE.                                       *)
    (***********************************************************************)
    macro ModifyDepth(var, pos, movingForward) {
      with (amt = CASE tpMap[pos].type = "begin" ->  1  []
                        tpMap[pos].type = "end"   -> -1 []
                        OTHER                    -> 0     ) {
           var := var + IF movingForward THEN amt ELSE -amt
        }
      }
      
    { with (tp = RegionToTokPair(tpMap, tpregion)) {
         ltok := tp[1];
         rtok := tp[2]
       } ;

      (*********************************************************************)
      (* If d is the depth of ltok, then set rtokDepth and minDepth such   *)
      (* that d + rtokDepth is the depth of rtok, d + minDepth is the      *)
      (* minimum depth of tokens, and allExpr is true iff all tokens in    *)
      (* positions ltok to rtok are expression tokens.                     *)
      (*********************************************************************)
      rtokDepth := 0;
      minDepth := 0 ;
      allExpr := tpMap[ltok].inExpr ;
      i := ltok+1;
      while (i =< rtok) {
         ModifyDepth(rtokDepth, i, TRUE);
         if (rtokDepth < minDepth) {minDepth := rtokDepth} ;
         if (tpMap[i].type = "token") {
           allExpr := allExpr /\ tpMap[i].inExpr
          } ;
         i := i+1
       };
       
      assert /\ ParenDepth(tpMap, rtok) = ParenDepth(tpMap, ltok) + rtokDepth
             /\ minDepth + ParenDepth(tpMap, ltok) =
                  Min({ParenDepth(tpMap, k) : k \in ltok..rtok}) 
             /\ allExpr = \A k \in ltok..rtok : 
                             (tpMap[k].type = "token") => tpMap[k].inExpr ;
                             
      (*********************************************************************)
      (* Increment minDepth if ltok # rtok and allExpr is true.            *)
      (*                                                                   *)
      (* This appears to be an error, because the implementation works     *)
      (* properly without the ltok # rtok conjunct in the `if' test.  I    *)
      (* probably didn't test the spec adequately.  However, it's also     *)
      (* possible that the spec is correct and for some subtle reason, the *)
      (* obvious implementation of the `if' test doesn't actually          *)
      (* implement the spec.  As long as the implementation seems to be    *)
      (* working, I don't want to spend the time figuring out what's going *)
      (* on.                                                               *)
      (*********************************************************************)
      if (ltok # rtok /\ allExpr) {minDepth := minDepth + 1} ;
      
      (*********************************************************************)
      (* Set bParen to first left paren to left of ltok that descends to   *)
      (* relative paren depth minDepth.                                    *)
      (*********************************************************************)
      curDepth := 0;
      i := ltok - 1;
      while (~ /\ tpMap[i].type = "begin"
               /\ curDepth = minDepth ) {
        ModifyDepth(curDepth, i, FALSE) ;
        i := i-1
       } ;
      bParen := i ;
      
      (*********************************************************************)
      (* Set eParen to first right paren to the right of rtok that rises   *)
      (* from relative paren depth minDepth.                               *)
      (*********************************************************************)
      curDepth := rtokDepth;
      i := rtok + 1;
      while (~ /\ tpMap[i].type = "end"
               /\ curDepth = minDepth ) {
        ModifyDepth(curDepth, i, TRUE) ;
        i := i+1
       } ;
      eParen := i ;
      
      assert <<bParen, eParen>> = TokPairToParens(tpMap, ltok, rtok);
      
      (*********************************************************************)
      (* Construct the final result.                                       *)
      (*********************************************************************)
      result := << >> ; 
      curBegin := tpMap[bParen].loc ;
      curDepth := 0 ;
      lastRparen := -1 ;
      i := bParen + 1 ;
      while (i < eParen) {
        if (tpMap[i].type = "end") {
          lastRparen := i
          } ;
        if ( /\ tpMap[i].type = "break"
             /\ tpMap[i].depth - curDepth >= 0 ) {
             assert lastRparen # -1 ;
      
             (**************************************************************)
             (* The following statement will be eliminated in the initial  *)
             (* implementation.                                            *)
             (**************************************************************)
             result := Append(result, 
                              [begin |-> curBegin, end |-> tpMap[lastRparen].loc]);

             lastRparen := -1 ;
             while (tpMap[i].type # "begin") {
               ModifyDepth(curDepth, i, TRUE) ;
               i := i+1;
              } ;
             curBegin := tpMap[i].loc ;         
           } ;
        ModifyDepth(curDepth, i, TRUE) ;
        i := i+1;
       } ;
      result := Append(result, 
                       [begin |-> curBegin, end |-> tpMap[eParen].loc]);
      
      \* debugging output
      print <<tpregion.begin.column, tpregion.end.column>> ;
      print [j \in 1..Len(result) |-> <<result[j].begin.column,
                                        result[j].end.column>>];
      print << "lrtok", ltok, rtok>>
    }
}
 ***************************************************************************)
\* BEGIN TRANSLATION
CONSTANT defaultInitValue
VARIABLES tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, bParen, eParen, 
          result, curBegin, lastRparen, i, curDepth, pc

vars == << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, bParen, eParen, 
           result, curBegin, lastRparen, i, curDepth, pc >>

Init == (* Global variables *)
        /\ tpregion \in SpecToRegions(tpMap)
        /\ ltok = defaultInitValue
        /\ rtok = defaultInitValue
        /\ rtokDepth = defaultInitValue
        /\ minDepth = defaultInitValue
        /\ allExpr = defaultInitValue
        /\ bParen = defaultInitValue
        /\ eParen = defaultInitValue
        /\ result = defaultInitValue
        /\ curBegin = defaultInitValue
        /\ lastRparen = defaultInitValue
        /\ i = defaultInitValue
        /\ curDepth = defaultInitValue
        /\ pc = "Lbl_1"

Lbl_1 == /\ pc = "Lbl_1"
         /\ LET tp == RegionToTokPair(tpMap, tpregion) IN
              /\ ltok' = tp[1]
              /\ rtok' = tp[2]
         /\ rtokDepth' = 0
         /\ minDepth' = 0
         /\ allExpr' = tpMap[ltok'].inExpr
         /\ i' = ltok'+1
         /\ pc' = "Lbl_2"
         /\ UNCHANGED << tpregion, bParen, eParen, result, curBegin, 
                         lastRparen, curDepth >>

Lbl_2 == /\ pc = "Lbl_2"
         /\ IF i =< rtok
               THEN /\ LET amt == CASE tpMap[i].type = "begin" ->  1  []
                                        tpMap[i].type = "end"   -> -1 []
                                        OTHER                    -> 0 IN
                         rtokDepth' = rtokDepth + IF TRUE THEN amt ELSE -amt
                    /\ IF rtokDepth' < minDepth
                          THEN /\ minDepth' = rtokDepth'
                          ELSE /\ TRUE
                               /\ UNCHANGED minDepth
                    /\ IF tpMap[i].type = "token"
                          THEN /\ allExpr' = (allExpr /\ tpMap[i].inExpr)
                          ELSE /\ TRUE
                               /\ UNCHANGED allExpr
                    /\ i' = i+1
                    /\ pc' = "Lbl_2"
                    /\ UNCHANGED curDepth
               ELSE /\ Assert(/\ ParenDepth(tpMap, rtok) = ParenDepth(tpMap, ltok) + rtokDepth
                              /\ minDepth + ParenDepth(tpMap, ltok) =
                                   Min({ParenDepth(tpMap, k) : k \in ltok..rtok})
                              /\ allExpr = \A k \in ltok..rtok :
                                              (tpMap[k].type = "token") => tpMap[k].inExpr, 
                              "Failure of assertion at line 397, column 7.")
                    /\ IF ltok # rtok /\ allExpr
                          THEN /\ minDepth' = minDepth + 1
                          ELSE /\ TRUE
                               /\ UNCHANGED minDepth
                    /\ curDepth' = 0
                    /\ i' = ltok - 1
                    /\ pc' = "Lbl_3"
                    /\ UNCHANGED << rtokDepth, allExpr >>
         /\ UNCHANGED << tpregion, ltok, rtok, bParen, eParen, result, 
                         curBegin, lastRparen >>

Lbl_3 == /\ pc = "Lbl_3"
         /\ IF ~ /\ tpMap[i].type = "begin"
                 /\ curDepth = minDepth
               THEN /\ LET amt == CASE tpMap[i].type = "begin" ->  1  []
                                        tpMap[i].type = "end"   -> -1 []
                                        OTHER                    -> 0 IN
                         curDepth' = curDepth + IF FALSE THEN amt ELSE -amt
                    /\ i' = i-1
                    /\ pc' = "Lbl_3"
                    /\ UNCHANGED bParen
               ELSE /\ bParen' = i
                    /\ curDepth' = rtokDepth
                    /\ i' = rtok + 1
                    /\ pc' = "Lbl_4"
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         eParen, result, curBegin, lastRparen >>

Lbl_4 == /\ pc = "Lbl_4"
         /\ IF ~ /\ tpMap[i].type = "end"
                 /\ curDepth = minDepth
               THEN /\ LET amt == CASE tpMap[i].type = "begin" ->  1  []
                                        tpMap[i].type = "end"   -> -1 []
                                        OTHER                    -> 0 IN
                         curDepth' = curDepth + IF TRUE THEN amt ELSE -amt
                    /\ i' = i+1
                    /\ pc' = "Lbl_4"
                    /\ UNCHANGED << eParen, result, curBegin, lastRparen >>
               ELSE /\ eParen' = i
                    /\ Assert(<<bParen, eParen'>> = TokPairToParens(tpMap, ltok, rtok), 
                              "Failure of assertion at line 434, column 7.")
                    /\ result' = << >>
                    /\ curBegin' = tpMap[bParen].loc
                    /\ curDepth' = 0
                    /\ lastRparen' = -1
                    /\ i' = bParen + 1
                    /\ pc' = "Lbl_5"
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         bParen >>

Lbl_5 == /\ pc = "Lbl_5"
         /\ IF i < eParen
               THEN /\ IF tpMap[i].type = "end"
                          THEN /\ lastRparen' = i
                          ELSE /\ TRUE
                               /\ UNCHANGED lastRparen
                    /\ IF /\ tpMap[i].type = "break"
                          /\ tpMap[i].depth - curDepth >= 0
                          THEN /\ Assert(lastRparen' # -1, 
                                         "Failure of assertion at line 450, column 14.")
                               /\ result' = Append(result,
                                                   [begin |-> curBegin, end |-> tpMap[lastRparen'].loc])
                               /\ pc' = "Lbl_6"
                          ELSE /\ pc' = "Lbl_8"
                               /\ UNCHANGED result
               ELSE /\ result' = Append(result,
                                        [begin |-> curBegin, end |-> tpMap[eParen].loc])
                    /\ PrintT(<<tpregion.begin.column, tpregion.end.column>>)
                    /\ PrintT([j \in 1..Len(result') |-> <<result'[j].begin.column,
                                                           result'[j].end.column>>])
                    /\ PrintT(<< "lrtok", ltok, rtok>>)
                    /\ pc' = "Done"
                    /\ UNCHANGED lastRparen
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         bParen, eParen, curBegin, i, curDepth >>

Lbl_8 == /\ pc = "Lbl_8"
         /\ LET amt == CASE tpMap[i].type = "begin" ->  1  []
                             tpMap[i].type = "end"   -> -1 []
                             OTHER                    -> 0 IN
              curDepth' = curDepth + IF TRUE THEN amt ELSE -amt
         /\ i' = i+1
         /\ pc' = "Lbl_5"
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         bParen, eParen, result, curBegin, lastRparen >>

Lbl_6 == /\ pc = "Lbl_6"
         /\ lastRparen' = -1
         /\ pc' = "Lbl_7"
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         bParen, eParen, result, curBegin, i, curDepth >>

Lbl_7 == /\ pc = "Lbl_7"
         /\ IF tpMap[i].type # "begin"
               THEN /\ LET amt == CASE tpMap[i].type = "begin" ->  1  []
                                        tpMap[i].type = "end"   -> -1 []
                                        OTHER                    -> 0 IN
                         curDepth' = curDepth + IF TRUE THEN amt ELSE -amt
                    /\ i' = i+1
                    /\ pc' = "Lbl_7"
                    /\ UNCHANGED curBegin
               ELSE /\ curBegin' = tpMap[i].loc
                    /\ pc' = "Lbl_8"
                    /\ UNCHANGED << i, curDepth >>
         /\ UNCHANGED << tpregion, ltok, rtok, rtokDepth, minDepth, allExpr, 
                         bParen, eParen, result, lastRparen >>

Next == Lbl_1 \/ Lbl_2 \/ Lbl_3 \/ Lbl_4 \/ Lbl_5 \/ Lbl_8 \/ Lbl_6
           \/ Lbl_7
           \/ (* Disjunct to prevent deadlock on termination *)
              (pc = "Done" /\ UNCHANGED vars)

Spec == /\ Init /\ [][Next]_vars
        /\ WF_vars(Next)

Termination == <>(pc = "Done")

\* END TRANSLATION
=============================================================================
\* Modification History
\* Last modified Tue Dec 13 10:12:16 PST 2011 by lamport
\* Created Thu Dec 01 16:51:23 PST 2011 by lamport

 ==================  End file TLAToPCal.tla  ======================== */

/*==================  Begin file RemoveRedundantParens.tla  ================

----------------------- MODULE RemoveRedundantParens -----------------------
(***************************************************************************)
(* Let an expression be a sequence of tokens, some of which are left and   *)
(* right parenthesis tokens, in which parentheses are balanced.  The goal  *)
(* is an algorithm that removes redundant parentheses from the expression. *)
(* A pair of matching left and right parentheses (a( and )b) are redundant *)
(* if they occur immediately inside another pair of matching parentheses,  *)
(* as in                                                                   *)
(*                                                                         *)
(*   (p( (a( xxx (u( xxx )v) xxx )b) )q)                                   *)
(***************************************************************************)
EXTENDS Integers, Sequences, TLC

(***************************************************************************)
(* A Token has a type, which is "left", "right", or "other" and an id,     *)
(* which is an element of the set TokId                                    *)
(***************************************************************************)
CONSTANT TokId
Token == [type : {"left", "right", "other"}, id : TokId]
----------------------------------------------------------------------------
(***************************************************************************)
(* We now define Result(seq) to be the output that the algorithm is        *)
(* supposed to produce.  It's defined recursively to keep removing         *)
(* matching redundant parentheses until there are no left.  We make some   *)
(* preliminary definitions, some of which are used in the algorithm as     *)
(* well.                                                                   *)
(***************************************************************************)

(***************************************************************************)
(* ParenDepth(seq, i) is the parenthesis depth in the expression seq just  *)
(* after the i-th token in seq, where ParenDepth(seq, 0) = 0.              *)
(***************************************************************************)
RECURSIVE ParenDepth(_, _)
ParenDepth(seq, i) == 
  IF i = 0 
    THEN 0  
    ELSE CASE seq[i].type = "left"  -> ParenDepth(seq, i-1) + 1
           [] seq[i].type = "right" -> ParenDepth(seq, i-1) - 1
           [] seq[i].type = "other" -> ParenDepth(seq, i-1)

(***************************************************************************)
(* IsWellFormed(seq) is true iff all parentheses in seq are properly       *)
(* matched.                                                                *)
(***************************************************************************)
IsWellFormed(seq) == /\ \A i \in 1..Len(seq) : ParenDepth(seq, i) >= 0
                     /\ ParenDepth(seq, Len(seq)) = 0
                                
(***************************************************************************)
(* For m < n, this is true iff the m-th and n-th elements of seq are       *)
(* matching parentheses.                                                   *)
(***************************************************************************)
AreMatching(seq, m, n) == /\ seq[m].type = "left"
                          /\ seq[n].type = "right"
                          /\ LET sseq == SubSeq(seq, m, n)
                             IN  /\ ParenDepth(sseq, n-m+1) = 0
                                 /\ \A i \in 1..(n-m) :
                                       ParenDepth(sseq, i) > 0

(***************************************************************************)
(* We now define some useful operators on sequences.                       *)
(***************************************************************************)
RemoveElement(seq, i) == 
  [j \in 1..(Len(seq)-1) |-> IF j < i THEN seq[j] ELSE seq[j+1]]

Last(seq) == seq[Len(seq)]

RemoveLast(seq) == RemoveElement(seq, Len(seq))
                  
RECURSIVE Result(_)
Result(seq) ==
  IF \E r \in (2..(Len(seq)-2)) \X (3..(Len(seq)-1)) : 
       /\ r[1] < r[2]
       /\ AreMatching(seq, r[1], r[2])
       /\ AreMatching(seq, r[1]-1, r[2]+1)
    THEN LET r == 
              CHOOSE r \in (2..(Len(seq)-2)) \X (3..(Len(seq)-1)) : 
               /\ r[1] < r[2]
               /\ AreMatching(seq, r[1], r[2])
               /\ AreMatching(seq, r[1]-1, r[2]+1)
         IN Result(RemoveElement(RemoveElement(seq, r[2]), r[1]))
    ELSE seq
----------------------------------------------------------------------------
(***************************************************************************)
(* The following are some operators useful for writing and debugging the   *)
(* algorithm.  ExprOfMaxLen(n) is the set of all expressions of length at  *)
(* most n.  The algorithm has been checked for all expressions in          *)
(* ExprOfMaxLen(9).  For ExprOfMaxLen(10), there are too many initial      *)
(* states.                                                                 *)
(***************************************************************************)
ExprOfMaxLen(n) == 
  UNION {{s \in [1..i -> Token] : IsWellFormed(s)} : i \in 0..n}

(***************************************************************************)
(* Pr(seq) is a value that, when printed, provides a compact               *)
(* representation of the expression seq.                                   *)
(***************************************************************************)
PrT(tok) == CASE tok.type = "left" -> <<"(", tok.id>> []
                 tok.type = "right" -> <<tok.id, ")">> []
                 tok.type = "other" -> tok.id
     
Pr(seq) == [i \in 1..Len(seq) |-> PrT(seq[i])]            

(***************************************************************************)
(* Some operators for writing expressions compactly.                       *)
(***************************************************************************)
L(i) == [type |-> "left", id |-> i]
R(i) == [type |-> "right", id |-> i]
O(i) == [type |-> "other", id |-> i]
----------------------------------------------------------------------------
(****************************************************************************

--algorithm Remove {
  variables 
    in \in ExprOfMaxLen(9), 
             \* The input.  
     
    out = << >>,           \* The output
    unmatchedLeft = << >>, \* Sequence of indices in `out' of unmatched "("s in out
    lastMatchedLeft = -1,  \* Index in `out' of "(" matched by last ")" in `out'.
                           \* A value of -1 means there is none.
    lastAddedRight = -1,   \* Index in `in' of last ")"  added to `out'.
                           \* A value of -1 means there is none.
    i = 1,                 \* Next element of `in' to examine.
            
 { while (i =< Len(in)) {
      if (in[i].type = "left") {
        unmatchedLeft := Append(unmatchedLeft, Len(out)+1)
      }
      else if (in[i].type = "right") {
        if ( /\ i = lastAddedRight + 1
             /\ lastMatchedLeft = unmatchedLeft[Len(unmatchedLeft)]+1 ) {
          out := RemoveLast(RemoveElement(out, lastMatchedLeft));
        };
        lastMatchedLeft := Last(unmatchedLeft);
        unmatchedLeft := RemoveLast(unmatchedLeft);
        lastAddedRight := i
      } ;
      out := Append(out, in[i]);
      i := i+1;
    };
    \* If out is not the correct result, print in, out and the
    \* correct result and report an error.
    if ( out # Result(in)) {
       print <<"in:", Pr(in)>>;
       print <<"out;", Pr(out)>>;
       print <<"res:",Pr(Result(in))>>;
       assert FALSE
    } 
 }

}
****************************************************************************)
\* BEGIN TRANSLATION
VARIABLES in, out, unmatchedLeft, lastMatchedLeft, lastAddedRight, i, pc

vars == << in, out, unmatchedLeft, lastMatchedLeft, lastAddedRight, i, pc >>

Init == (* Global variables *)
        /\ in \in ExprOfMaxLen(10)
        /\ out = << >>
        /\ unmatchedLeft = << >>
        /\ lastMatchedLeft = -1
        /\ lastAddedRight = -1
        /\ i = 1
        /\ pc = "Lbl_1"

Lbl_1 == /\ pc = "Lbl_1"
         /\ IF i =< Len(in)
               THEN /\ IF in[i].type = "left"
                          THEN /\ unmatchedLeft' = Append(unmatchedLeft, Len(out)+1)
                               /\ UNCHANGED << out, lastMatchedLeft, 
                                               lastAddedRight >>
                          ELSE /\ IF in[i].type = "right"
                                     THEN /\ IF /\ i = lastAddedRight + 1
                                                /\ lastMatchedLeft = unmatchedLeft[Len(unmatchedLeft)]+1
                                                THEN /\ out' = RemoveLast(RemoveElement(out, lastMatchedLeft))
                                                ELSE /\ TRUE
                                                     /\ out' = out
                                          /\ lastMatchedLeft' = Last(unmatchedLeft)
                                          /\ unmatchedLeft' = RemoveLast(unmatchedLeft)
                                          /\ lastAddedRight' = i
                                     ELSE /\ TRUE
                                          /\ UNCHANGED << out, unmatchedLeft, 
                                                          lastMatchedLeft, 
                                                          lastAddedRight >>
                    /\ pc' = "Lbl_2"
               ELSE /\ IF out # Result(in)
                          THEN /\ PrintT(<<"in:", Pr(in)>>)
                               /\ PrintT(<<"out;", Pr(out)>>)
                               /\ PrintT(<<"res:",Pr(Result(in))>>)
                               /\ Assert(FALSE, 
                                         "Failure of assertion at line 136, column 8.")
                          ELSE /\ TRUE
                    /\ pc' = "Done"
                    /\ UNCHANGED << out, unmatchedLeft, lastMatchedLeft, 
                                    lastAddedRight >>
         /\ UNCHANGED << in, i >>

Lbl_2 == /\ pc = "Lbl_2"
         /\ out' = Append(out, in[i])
         /\ i' = i+1
         /\ pc' = "Lbl_1"
         /\ UNCHANGED << in, unmatchedLeft, lastMatchedLeft, lastAddedRight >>

Next == Lbl_1 \/ Lbl_2
           \/ (* Disjunct to prevent deadlock on termination *)
              (pc = "Done" /\ UNCHANGED vars)

Spec == Init /\ [][Next]_vars

Termination == <>(pc = "Done")

\* END TRANSLATION

=============================================================================
\* Modification History
\* Last modified Tue Dec 20 15:29:06 PST 2011 by lamport
\* Created Mon Dec 19 17:20:10 PST 2011 by lamport

=========================  End file RemoveRedundantParens.tla  =======================*/


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/DirtyMarkingListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.ui.forms.AbstractFormPart;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.part.IValidateble;

/**
 * Implementation of a bunch of listener interfaces. All the methods call the perform method, which will cause the part to become
 * "dirty" and if the part is validateable to re-validate the part. The ignore input change is a flag which causes to ignore the input
 * change, and is used to switch on and off the listener. This listener is used on the model editor pages. 
 * @author <NAME>
 * @version $Id$
 */
public class DirtyMarkingListener implements ITextInputListener, ITextListener, SelectionListener, ModifyListener,
        IgnoringListener
{
    private final AbstractFormPart part;
    private boolean ignoreInputChange;

    public DirtyMarkingListener(AbstractFormPart part, boolean ignoreInputChange)
    {
        this.part = part;
        this.ignoreInputChange = ignoreInputChange;
    }

    /**
     * Switches the listner on/off
     * @param ignoreInputChange if true, the listener is deactivated
     */
    public void setIgnoreInput(boolean ignoreInputChange)
    {
        this.ignoreInputChange = ignoreInputChange;
    }

    public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput)
    {
    }

    public void inputDocumentChanged(IDocument oldInput, IDocument newInput)
    {
        perform();
    }

    public void textChanged(TextEvent event)
    {
        perform();
    }

    public void widgetDefaultSelected(SelectionEvent e)
    {
    }

    public void widgetSelected(SelectionEvent e)
    {
        perform();
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
     */
    public void modifyText(ModifyEvent e)
    {
        perform();
    }

    private void perform()
    {
        if (!ignoreInputChange)
        {
            part.markDirty();
            if (part instanceof IValidateble)
            {
                ((IValidateble) part).validate();
            }
        }
    }
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/WorkerValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.impl;

import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tlc2.TLCGlobals;
import tlc2.tool.IWorker;
import tlc2.tool.TLCState;
import tlc2.tool.coverage.CostModel;
import tlc2.util.Context;
import tlc2.value.IValue;

/*
Root Cause:
---------

1) [Values](https://github.com/tlaplus/tlaplus/blob/master/tlatools/src/tlc2/value/impl/Value.java) can be (deeply) nested.

1) Values transition through the following sequence of states:  New (instantiated), normalized, and fingerprinted.  Transitioning from one state to another is not thread-safe.  Non-technical speaking, a value is both the symbolic and the explicit entity.

2) Normalization of an (enumerable) value causes its elements to be sorted and duplicates to be removed.  It does not cause new elements to be  generated/enumerated. For example, normalizing the [SetPredValue](https://github.com/tlaplus/tlaplus/blob/master/tlatools/src/tlc2/value/impl/SetPredValue.java), corresponding to the expression ```tla { s \in SUBSET S : s # {} }```, causes ```S``` to be sorted and any duplicate elements to be removed.

3) Fingerprinting an enumerable value causes its elements to be explicitly enumerated.  For example, the SetPredValue from before causes all subsets ```s``` to be enumerated.

4) At startup, TLC eagerly evaluates zero-arity constant definitions and operators which involves creating values.  These values are normalized but not fingerprinted!  For example, the operator ```NonEmptySubsS == { s \in SUBSET S : s # {} }``` will be evaluated to a SetPredValue that is stored in the ```NonEmptySubsS``` node of the semantic graph.  We denote the set of values in the semantic graph with V<sub>SG</sub>.

5) Generating a [TLCState](https://github.com/tlaplus/tlaplus/blob/master/tlatools/src/tlc2/tool/TLCTrace.java) during the evaluation of the next-state relation, assigns newly created values to variables.  Before a TLCState is enqueued in the [StateQueue](https://github.com/tlaplus/tlaplus/blob/master/tlatools/src/tlc2/tool/queue/StateQueue.java), its values are fingerprinted.  Thus, values of TLCStates can safely be shared across [Workers](https://github.com/tlaplus/tlaplus/blob/master/tlatools/src/tlc2/tool/Worker.java).

Lets assume a spec with one variable ```x``` whose value - in all states - is some set.  Furthermore, let ```P``` be the property ```[](x \in NonEmptySubsS)```.  For simplicity reasons,  we assume:

1)  ```P``` is not checked on the initial states
2) Two Workers check next states simultaneously

Under these two assumptions, both Workers will race to enumerate (fingerprint) ```NonEmptySubsS```.

Note that the fact that we had to assume 1) and 2) explains why this race condition didn't surfaced earlier.  However, the assumptions are true in real-world executions of TLC.  For example, the evaluation of a more complex NonEmptySubsS, with a deeply nested hierarchy of values, may not require the evaluation of nested values in the initial states.

---------------

@xxyzzn came up with another scenario that might lead to the calculation of bogus fingerprints:

```tla
EXTENDS Integers, Sequences
VARIABLE x, y

Foo == { s \in SUBSET {1,2,3,4} : s # {} }

Init == x = << >> /\ y \in 1..2

Next == x' \in {<<i, Foo>> : i \in 1..2} /\ UNCHANGED y
```

Variable ```y``` only exists so that the state-graph has two initial states (sequentially generated).  A single initial state would restrict the first evaluation of Next to a single Worker (only a single initial state to dequeue from the ```StateQueue```) and thus fingerprinting cannot occur concurrently.

Attempted Fix A:
---------------------

[At startup](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/tool/impl/SpecProcessor.java#L202-L281), (eagerly) fingerprint all values of V<sub>SG</sub>.

Problem: Not all values in V<sub>SG</sub> need not be fingerprinted to completely check a spec.  For some specs such as [CarTalkPuzzle](https://github.com/tlaplus/tlaplus/issues/361#issuecomment-543256201), this is even prohibitive because explicit enumeration is infeasible: TLC will hang at startup.

Deferring fingerprinting of V<sub>SG</sub> until after the assumptions have been checked, such as when the initial states are (atomically) generated, is no general solution.

Proposed Fix A:
--------------------

Properly synchronize values such that no race conditions are possible if two or more Workers enumerate them concurrently.  

Disadvantages:  
1) It creates a scalability bottleneck: Workers will content for the synchronized ```NonEmptySubs```on every state that is generated.
2) Engineering effort to correctly synchronize the Value type hierarchy without introducing dead-locks.

Proposed Fix B:
--------------------

For each worker, create a copy of V<sub>SG</sub> (technically borrows from the concept of  a ```ThreadLocal```).

Disadvantages:  
1) Requires a type check (and potentially cast) on every [lookup](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/tool/impl/Spec.java#L448-L497) that occurrs during the [evaluation of the next-state relation](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/tool/impl/Tool.java#L782-L814).  An optimization would be to [eventually](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/tool/AbstractChecker.java#L496) garbage-collect the copies of V<sub>SG</sub> to at least skip the type cast once one copy is completely fingerprinted.
2) [Value#deepCopy](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/value/IValue.java#L104)  - required to create the copies of V<sub>SG</sub> - is [broken for most value types](https://github.com/tlaplus/tlaplus/blob/63bab42e79e750b7ac033cfe7196d8f0b53e861e/tlatools/src/tlc2/value/impl/SubsetValue.java#L232) (can probably be fixed).
*/
public class WorkerValue {
	
	/*
	 * Demuxing is supposed to be called only once per sn/opDef whereas muxing is called many many times.
	 */
	
    public static Object demux(final OpDefEvaluator spec, final OpDefNode opDef) {
    	return demux(spec, opDef, opDef);
    }
    
    public static Object demux(final OpDefEvaluator spec, final SemanticNode sn, final OpDefNode opDef) {
    	final IValue defVal = spec.eval(opDef.getBody(), Context.Empty, TLCState.Empty, CostModel.DO_NOT_RECORD);
    	defVal.deepNormalize();
    	
    	if (defVal.mutates() && TLCGlobals.getNumWorkers() > 1) {
    		final IValue[] values = new IValue[TLCGlobals.getNumWorkers()];
    		values[0] = defVal;

    		for (int i = 1; i < values.length; i++) {
    			// Ideally, we could invoke IValue#deepCopy here instead of evaluating opDef again.  However,
    			// IValue#deepCopy doesn't create copies for most values.
    			values[i] = spec.eval(opDef.getBody(), Context.Empty, TLCState.Empty, CostModel.DO_NOT_RECORD);
    			values[i].deepNormalize();
    		}
    		
    		return new WorkerValue(values);
    	} else {
    		return defVal;
    	}
    }
    
	public static Object mux(final Object result) {
		if (!(result instanceof WorkerValue)) {
			return result;
		}
		
		final WorkerValue vp = (WorkerValue) result;
		final Thread t = Thread.currentThread();
		if (t instanceof IWorker) {
			final IWorker w = (IWorker) t;
			return vp.values[w.myGetId()];
		} else {
			return vp.values[0];
		}
	}
	
	private final IValue[] values;

	private WorkerValue(IValue[] values) {
		this.values = values;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/module/Json.java<|end_filename|>
package tlc2.module;
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;

import tlc2.overrides.TLAPlusOperator;
import tlc2.value.IValue;
import tlc2.value.impl.BoolValue;
import tlc2.value.impl.FcnLambdaValue;
import tlc2.value.impl.FcnRcdValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.ModelValue;
import tlc2.value.impl.RecordValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.SetOfFcnsValue;
import tlc2.value.impl.SetOfRcdsValue;
import tlc2.value.impl.SetOfTuplesValue;
import tlc2.value.impl.StringValue;
import tlc2.value.impl.SubsetValue;
import tlc2.value.impl.TupleValue;
import tlc2.value.impl.Value;
import util.UniqueString;

/**
 * Module overrides for operators to read and write JSON.
 */
public class Json {
	
	public static final long serialVersionUID = 20210223L;

  /**
   * Encodes the given value as a JSON string.
   *
   * @param value the value to encode
   * @return the JSON string value
   */
  @TLAPlusOperator(identifier = "ToJson", module = "Json", warn = false)
  public static StringValue toJson(final IValue value) throws IOException {
    return new StringValue(getNode(value).toString());
  }

  /**
   * Encodes the given value as a JSON array string.
   *
   * @param value the value to encode
   * @return the JSON array string value
   */
  @TLAPlusOperator(identifier = "ToJsonArray", module = "Json", warn = false)
  public static StringValue toJsonArray(final IValue value) throws IOException {
    return new StringValue(getArrayNode(value).toString());
  }

  /**
   * Encodes the given value as a JSON object string.
   *
   * @param value the value to encode
   * @return the JSON object string value
   */
  @TLAPlusOperator(identifier = "ToJsonObject", module = "Json", warn = false)
  public static StringValue toJsonObject(final IValue value) throws IOException {
    return new StringValue(getObjectNode(value).toString());
  }

  /**
   * Deserializes a tuple of newline delimited JSON values from the given path.
   *
   * @param path the JSON file path
   * @return a tuple of JSON values
   */
  @TLAPlusOperator(identifier = "ndJsonDeserialize", module = "Json", warn = false)
  public static IValue ndDeserialize(final StringValue path) throws IOException {
    List<Value> values = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new FileReader(new File(path.val.toString())))) {
      String line = reader.readLine();
      while (line != null) {
        JsonElement node = JsonParser.parseString(line);
        values.add(getValue(node));
        line = reader.readLine();
      }
    }
    return new TupleValue(values.toArray(new Value[0]));
  }

  /**
   * Deserializes a tuple of *plain* JSON values from the given path.
   *
   * @param path the JSON file path
   * @return a tuple of JSON values
   */
  @TLAPlusOperator(identifier = "JsonDeserialize", module = "Json", warn = false)
  public static IValue deserialize(final StringValue path) throws IOException {
    JsonElement node = JsonParser.parseReader(new FileReader(new File(path.val.toString())));
    return getValue(node);
  }

  /**
   * Serializes a tuple of values to newline delimited JSON.
   *
   * @param path  the file to which to write the values
   * @param value the values to write
   * @return a boolean value indicating whether the serialization was successful
   */
  @TLAPlusOperator(identifier = "ndJsonSerialize", module = "Json", warn = false)
  public synchronized static BoolValue ndSerialize(final StringValue path, final TupleValue value) throws IOException {
    File file = new File(path.val.toString());
    if (file.getParentFile() != null) {file.getParentFile().mkdirs();} // Cannot create parent dir for relative path.
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(path.val.toString())))) {
        for (int i = 0; i < value.elems.length; i++) {
            writer.write(getNode(value.elems[i]).toString() + "\n");
          }
    }
    return BoolValue.ValTrue;
  }

  /**
   * Serializes a tuple of values to newline delimited JSON.
   *
   * @param path  the file to which to write the values
   * @param value the values to write
   * @return a boolean value indicating whether the serialization was successful
   */
  @TLAPlusOperator(identifier = "JsonSerialize", module = "Json", warn = false)
  public synchronized static BoolValue serialize(final StringValue path, final TupleValue value) throws IOException {
    File file = new File(path.val.toString());
    if (file.getParentFile() != null) {file.getParentFile().mkdirs();} // Cannot create parent dir for relative path.
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(path.val.toString())))) {
    	writer.write("[\n");
		for (int i = 0; i < value.elems.length; i++) {
			writer.write(getNode(value.elems[i]).toString());
			if (i < value.elems.length - 1) {
				// No dangling "," after last element.
				writer.write(",\n");
			}
		}
    	writer.write("\n]\n");
    }
    return BoolValue.ValTrue;
  }

  /**
   * Recursively converts the given value to a {@code JsonElement}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getNode(IValue value) throws IOException {
    if (value instanceof RecordValue) {
      return getObjectNode((RecordValue) value);
    } else if (value instanceof TupleValue) {
      return getArrayNode((TupleValue) value);
    } else if (value instanceof StringValue) {
      return new JsonPrimitive(((StringValue) value).val.toString());
    } else if (value instanceof ModelValue) {
      return new JsonPrimitive(((ModelValue) value).val.toString());
    } else if (value instanceof IntValue) {
      return new JsonPrimitive(((IntValue) value).val);
    } else if (value instanceof BoolValue) {
      return new JsonPrimitive(((BoolValue) value).val);
    } else if (value instanceof FcnRcdValue) {
      return getObjectNode((FcnRcdValue) value);
    } else if (value instanceof FcnLambdaValue) {
      return getObjectNode((FcnRcdValue) ((FcnLambdaValue) value).toFcnRcd());
    } else if (value instanceof SetEnumValue) {
      return getArrayNode((SetEnumValue) value);
    } else if (value instanceof SetOfRcdsValue) {
      return getArrayNode((SetEnumValue) ((SetOfRcdsValue) value).toSetEnum());
    } else if (value instanceof SetOfTuplesValue) {
      return getArrayNode((SetEnumValue) ((SetOfTuplesValue) value).toSetEnum());
    } else if (value instanceof SetOfFcnsValue) {
      return getArrayNode((SetEnumValue) ((SetOfFcnsValue) value).toSetEnum());
    } else if (value instanceof SubsetValue) {
      return getArrayNode((SetEnumValue) ((SubsetValue) value).toSetEnum());
    } else if (value instanceof IntervalValue) {
      return getArrayNode((SetEnumValue) ((IntervalValue) value).toSetEnum());
    } else {
      throw new IOException("Cannot convert value: unsupported value type " + value.getClass().getName());
    }
  }

  /**
   * Returns a boolean indicating whether the given value is a valid sequence.
   *
   * @param value the value to check
   * @return indicates whether the value is a valid sequence
   */
  private static boolean isValidSequence(FcnRcdValue value) {
    final Value[] domain = value.getDomainAsValues();
    for (Value d : domain) {
      if (!(d instanceof IntValue)) {
        return false;
      }
    }
    value.normalize();
    for (int i = 0; i < domain.length; i++) {
      if (((IntValue) domain[i]).val != (i + 1)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Recursively converts the given value to an {@code JsonObject}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getObjectNode(IValue value) throws IOException {
    if (value instanceof RecordValue) {
      return getObjectNode((RecordValue) value);
    } else if (value instanceof TupleValue) {
      return getObjectNode((TupleValue) value);
    } else if (value instanceof FcnRcdValue) {
      return getObjectNode((FcnRcdValue) value);
    } else if (value instanceof FcnLambdaValue) {
      return getObjectNode((FcnRcdValue) ((FcnLambdaValue) value).toFcnRcd());
    } else {
      throw new IOException("Cannot convert value: unsupported value type " + value.getClass().getName());
    }
  }

  /**
   * Converts the given record value to a {@code JsonObject}, recursively converting values.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getObjectNode(FcnRcdValue value) throws IOException {
    if (isValidSequence(value)) {
      return getArrayNode(value);
    }

    final Value[] domain = value.getDomainAsValues();
    JsonObject jsonObject = new JsonObject();
    for (int i = 0; i < domain.length; i++) {
      Value domainValue = domain[i];
      if (domainValue instanceof StringValue) {
        jsonObject.add(((StringValue) domainValue).val.toString(), getNode(value.values[i]));
      } else {
        jsonObject.add(domainValue.toString(), getNode(value.values[i]));
      }
    }
    return jsonObject;
  }

  /**
   * Converts the given record value to an {@code JsonObject}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getObjectNode(RecordValue value) throws IOException {
    JsonObject jsonObject = new JsonObject();
    for (int i = 0; i < value.names.length; i++) {
      jsonObject.add(value.names[i].toString(), getNode(value.values[i]));
    }
    return jsonObject;
  }

  /**
   * Converts the given tuple value to an {@code JsonObject}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getObjectNode(TupleValue value) throws IOException {
    JsonObject jsonObject = new JsonObject();
    for (int i = 0; i < value.elems.length; i++) {
      jsonObject.add(String.valueOf(i), getNode(value.elems[i]));
    }
    return jsonObject;
  }

  /**
   * Recursively converts the given value to an {@code JsonArray}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getArrayNode(IValue value) throws IOException {
    if (value instanceof TupleValue) {
      return getArrayNode((TupleValue) value);
    } else if (value instanceof FcnRcdValue) {
      return getArrayNode((FcnRcdValue) value);
    } else if (value instanceof FcnLambdaValue) {
      return getArrayNode((FcnRcdValue) ((FcnLambdaValue) value).toFcnRcd());
    } else if (value instanceof SetEnumValue) {
      return getArrayNode((SetEnumValue) value);
    } else if (value instanceof SetOfRcdsValue) {
      return getArrayNode((SetEnumValue) ((SetOfRcdsValue) value).toSetEnum());
    } else if (value instanceof SetOfTuplesValue) {
      return getArrayNode((SetEnumValue) ((SetOfTuplesValue) value).toSetEnum());
    } else if (value instanceof SetOfFcnsValue) {
      return getArrayNode((SetEnumValue) ((SetOfFcnsValue) value).toSetEnum());
    } else if (value instanceof SubsetValue) {
      return getArrayNode((SetEnumValue) ((SubsetValue) value).toSetEnum());
    } else if (value instanceof IntervalValue) {
      return getArrayNode((SetEnumValue) ((IntervalValue) value).toSetEnum());
    } else {
      throw new IOException("Cannot convert value: unsupported value type " + value.getClass().getName());
    }
  }

  /**
   * Converts the given tuple value to an {@code JsonArray}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getArrayNode(TupleValue value) throws IOException {
    JsonArray jsonArray = new JsonArray(value.elems.length);
    for (int i = 0; i < value.elems.length; i++) {
      jsonArray.add(getNode(value.elems[i]));
    }
    return jsonArray;
  }

  /**
   * Converts the given record value to an {@code JsonArray}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getArrayNode(FcnRcdValue value) throws IOException {
    if (!isValidSequence(value)) {
      return getObjectNode(value);
    }

    value.normalize();
    JsonArray jsonArray = new JsonArray(value.values.length);
    for (int i = 0; i < value.values.length; i++) {
      jsonArray.add(getNode(value.values[i]));
    }
    return jsonArray;
  }

  /**
   * Converts the given tuple value to an {@code JsonArray}.
   *
   * @param value the value to convert
   * @return the converted {@code JsonElement}
   */
  private static JsonElement getArrayNode(SetEnumValue value) throws IOException {
    value.normalize();
    Value[] values = value.elems.toArray();
    JsonArray jsonArray = new JsonArray(values.length);
    for (int i = 0; i < values.length; i++) {
      jsonArray.add(getNode(values[i]));
    }
    return jsonArray;
  }

  /**
   * Recursively converts the given {@code JsonElement} to a TLC value.
   *
   * @param node the {@code JsonElement} to convert
   * @return the converted value
   */
  private static Value getValue(JsonElement node) throws IOException {
    if (node.isJsonArray()) {
      return getTupleValue(node);
    }
    else if (node.isJsonObject()) {
      return getRecordValue(node);
    }
    else if (node.isJsonPrimitive()) {
      JsonPrimitive primitive = node.getAsJsonPrimitive();
      if (primitive.isNumber()) {
        return IntValue.gen(primitive.getAsInt());
      }
      else if (primitive.isBoolean()) {
        return new BoolValue(primitive.getAsBoolean());
      }
      else if (primitive.isString()) {
        return new StringValue(primitive.getAsString());
      }
    }
    else if (node.isJsonNull()) {
      return null;
    }
    throw new IOException("Cannot convert value: unsupported JSON value " + node.toString());
  }

  /**
   * Converts the given {@code JsonElement} to a tuple.
   *
   * @param node the {@code JsonElement} to convert
   * @return the tuple value
   */
  private static TupleValue getTupleValue(JsonElement node) throws IOException {
    List<Value> values = new ArrayList<>();
    JsonArray jsonArray = node.getAsJsonArray();
    for (int i = 0; i < jsonArray.size(); i++) {
      values.add(getValue(jsonArray.get(i)));
    }
    return new TupleValue(values.toArray(new Value[0]));
  }

  /**
   * Converts the given {@code JsonElement} to a record.
   *
   * @param node the {@code JsonElement} to convert
   * @return the record value
   */
  private static RecordValue getRecordValue(JsonElement node) throws IOException {
    List<UniqueString> keys = new ArrayList<>();
    List<Value> values = new ArrayList<>();
    Iterator<Map.Entry<String, JsonElement>> iterator = node.getAsJsonObject().entrySet().iterator();
    while (iterator.hasNext()) {
      Map.Entry<String, JsonElement> entry = iterator.next();
      keys.add(UniqueString.uniqueStringOf(entry.getKey()));
      values.add(getValue(entry.getValue()));
    }
    return new RecordValue(keys.toArray(new UniqueString[0]), values.toArray(new Value[0]), false);
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/LSBDiskFPSet.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.fp;

import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.rmi.RemoteException;
import java.util.Arrays;

import tlc2.output.EC;
import tlc2.util.BufferedRandomAccessFile;
import util.Assert;

@SuppressWarnings("serial")
public class LSBDiskFPSet extends HeapBasedDiskFPSet {

	protected LSBDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);
		this.flusher = new LSBFlusher();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getAuxiliaryStorageRequirement()
	 */
	protected double getAuxiliaryStorageRequirement() {
		return 2.5d;
	}
	
	public class LSBFlusher extends Flusher {

		private long[] buff;
		
		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet.Flusher#prepareTable()
		 */
		@Override
		protected void prepareTable() {
			// Verify tblCnt is still within positive Integer.MAX_VALUE bounds
			int cnt = (int) getTblCnt();
			Assert.check(cnt > 0, EC.GENERAL);
			
			// Why not sort this.tbl in-place rather than doubling memory
			// requirements by copying to clone array and subsequently sorting it?
			// - disk written fps are marked disk written by changing msb to 1
			// - next time such a fp from the in-memory this.tlb is converted on the
			// fly back and again used to do an in-memory lookup
			//
			// - this.tbl bucket assignment (hashing) is done on least significant bits,
			// which makes in-place sort with overlay index infeasible
			// - erasing this.tbl means we will loose the in-memory cache completely until it fills up again
			// - new fps overwrite disk flushed fps in-memory
			// see MSBDiskFPSet for an implementation that doesn't have the
			// requirement to sort in a clone array.
	
			// copy table contents into a buffer array buff; do not erase tbl
			buff = new long[cnt];
			int idx = 0;
			for (int j = 0; j < tbl.length; j++) {
				long[] bucket = tbl[j];
				if (bucket != null) {
					int blen = bucket.length;
					// for all bucket positions and non-null values
					for (int k = 0; k < blen && bucket[k] > 0; k++) {
						buff[idx++] = bucket[k];
						// indicate fp has been flushed to disk
						bucket[k] |= 0x8000000000000000L;
					}
				}
			}
			
			// sort in-memory entries
			Arrays.sort(buff, 0, buff.length);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet.Flusher#mergeNewEntries(java.io.RandomAccessFile, java.io.RandomAccessFile)
		 */
		@Override
		protected void mergeNewEntries(BufferedRandomAccessFile[] inRAFs, RandomAccessFile outRAF) throws IOException {
			final int buffLen = buff.length;

			// Precompute the maximum value of the new file
			long maxVal = buff[buffLen - 1];
			if (index != null) {
				maxVal = Math.max(maxVal, index[index.length - 1]);
			}

			int indexLen = calculateIndexLen(buffLen);
			index = new long[indexLen];
			index[indexLen - 1] = maxVal;
			currIndex = 0;
			counter = 0;

			// initialize positions in "buff" and "inRAF"
			int i = 0;
			long value = 0L; // initialize only to make compiler happy
			boolean eof = false;
			if (fileCnt > 0) {
				try {
					value = inRAFs[0].readLong();
				} catch (EOFException e) {
					eof = true;
				}
			} else {
				eof = true;
			}

			// merge while both lists still have elements remaining
			while (!eof && i < buffLen) {
				if (value < buff[i]) {
					writeFP(outRAF, value);
					try {
						value = inRAFs[0].readLong();
					} catch (EOFException e) {
						eof = true;
					}
				} else {
					// prevent converting every long to String when assertion holds (this is expensive)
					if(value == buff[i]) {
						Assert.check(false, EC.TLC_FP_VALUE_ALREADY_ON_DISK,
								String.valueOf(value));
					}
					writeFP(outRAF, buff[i++]);
				}
			}

			// write elements of remaining list
			if (eof) {
				while (i < buffLen) {
					writeFP(outRAF, buff[i++]);
				}
			} else {
				do {
					writeFP(outRAF, value);
					try {
						value = inRAFs[0].readLong();
					} catch (EOFException e) {
						eof = true;
					}
				} while (!eof);
			}
			Assert.check(currIndex == indexLen - 1, EC.SYSTEM_INDEX_ERROR);

			// maintain object invariants
			fileCnt += buffLen;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/TokenizeComment.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS TokenizeComment                                                    *
*                                                                          *
* This class contains a a single method, Tokenize, that takes as argument  *
* a multiline comment represented as a Vector whose elements are strings.  *
* Its result is an array of arrays of CTokens obtained by tokenizing the   *
* comment.  Each element of the vector produces one row of the array.      *
*                                                                          *
* Note: in formatting comments, we don't treat PlusCal built-in tokens     *
* specially because they are mostly strings like "if", "with", and "while" *
* that are very common English words.  As a result, we don't try to format *
* PlusCal code as such in comments.                                        *
*                                                                          *
* The tokenizing algorithm is described below.  The description has the    *
* following BNF syntax:                                                    *
*                                                                          *
*    <Description> ::=                                                     *
*        <State_Action> | <State_Action> <Description>                     *
*                                                                          *
*    <State_Action>    ::=  <State_Name> ":" <Action_Sequence>             *
*                                                                          *
*    <Action_Sequence> ::=  <Action> | <Action> <Action_Sequence>          *
*                                                                          *
*    <Action> ::=                                                          *
*         <Precondition> <Step_Sequence> "-->" <State_Name>                *
*                                                                          *
*    <Step_Sequence> ::= <Step> | <Step> ";" <StepSequence>                *
*                                                                          *
* The algorithm has a current state, which is initially START. When in     *
* a state S, the algorithm executes the <Action_Sequence> for the          *
* <State_Action> whose <State_Name> is S. It executes an                   *
* <Action_Sequence> by going through its actions in order until it         *
* finds one whose <Precondition> is true.  It then executes the <Step>s    *
* in that <Action>'s <Step_Sequence>, and then sets the current state      *
* to the <Action>'s <State_Name>.  However, the special <State_Name>s      *
* DONE and ERROR indicate that the algorithm is finished, either           *
* normally or with an error.                                               *
*                                                                          *
* The algorithm uses the following variables:                              *
*                                                                          *
*    token :    The part of the token found so far.                        *
*                                                                          *
*    nextChar : The next character from the input stream                   *
*                                                                          *
*    inDQuote : True iff left double-quote has been encountered            *
*               and the matching right double-quote has not                *
*               been.                                                      *
*    inSQuote : True iff a left single-quote has been encountered          *
*               and the matching right single-quote has not                *
*               been.                                                      *
*                                                                          *
* A <Precondition> has the form [exp], where exp is an ordinary            *
* expression, except the following conventions are used in it:             *
*                                                                          *
*   (S) asserts that nextChar equals S if S is a character, or             *
*     that nextChar is an element of S if S is a set of characters.        *
*     LegalStringChar is the set of all legal non-escaped characters       *
*     in a TLA+ string.                                                    *
*                                                                          *
*   token+ is the string obtained by appending nextChar to token.          *
*                                                                          *
*   BuiltIns is the set of all strings that are recognized by              *
*     TLA+ as operators or keywords.                                       *
*                                                                          *
*   BuiltInPrefix is the set of prefixes of all strings in                 *
*     BuiltIns except all-letter strings or strings consisting             *
*     of a "\\" (a backslash) followed by a sequence of letters.           *
*                                                                          *
*   OTHER equals TRUE.                                                     *
*                                                                          *
* I write (S) instead of [(S)].                                            *
*                                                                          *
* The following notation for steps is used.                                *
*                                                                          *
*   + means to append nextChar to token and set nextChar to the            *
*     next character in the input stream.                                  *
*                                                                          *
*   - means to set nextChar to the next character in the input             *
*     stream.                                                              *
*                                                                          *
*   CTokenOut(type) outputs  token as a CToken of the indicated            *
*   type and resets token to the empty string.                             *
*                                                                          *
* Here is the algorithm.                                                   *
*                                                                          *
* START:                                                                   *
*   (Space_Char)        -                      --> START                   *
*   (Letter)            +                      --> ID                      *
*   (Digit)             +                      --> NUM_OR_ID               *
*   ("\n")              -                      --> START                   *
*   ("\\")              +                      --> BS                      *
*   (\in RepeatChars)   repChar = nextChar; +                              *
*                       repMin  = min repetition number                    *
*                                 of nextChar;                             *
*                                              --> REPEAT_CHAR             *
*   ("\"" /\ ~inDQuote) -                      --> STRING                  *
*   ("\"")              +                      --> RIGHT_DQUOTE            *
*   ("`")               +                      --> LEFT_SQUOTE             *
*   ("'" /\ inSQuote)   - ; inSQuote = false   --> START                   *
*   ("'")               +                      --> RIGHT_SQUOTE            *
*   (BuiltInPrefix)     +                      --> BUILT_IN                *
*   ("\t")                                     --> DONE                    *
*   [OTHER]             + ; CTokenOut(OTHER)   --> START                   *
*                                                                          *
* ID:                                                                      *
*   [token = "WF_" or "SF_"]  CTokenOut(BUILTIN)    --> START              *
*   (Letter or Digit)         +                     --> ID                 *
*   [token \in BuiltIns]      CTokenOut(BUILTIN)    --> START              *
*   [OTHER]                   CTokenOut(IDENT)      --> START              *
*                                                                          *
* NUM_OR_ID:                                                               *
*   (Digit)   +                  --> NUM_OR_ID                             *
*   (Letter)  +                  --> ID                                    *
*   [OTHER]   CTokenOut(NUMBER)  --> START                                 *
*                                                                          *
* BS:                                                                      *
*   ("b", "B", "o", "O", "h", or "H") +                --> NUM_OR_BI       *
*   (Letter)                                           --> BSBUILT_IN      *
*   [OTHER]                                            --> BUILT_IN        *
*                                                                          *
* NUM_OR_BI                                                                *
*   (Digit)   --> NUM                                                      *
*   [OTHER]   --> BSBUILT_IN                                               *
*                                                                          *
* NUM:                                                                     *
*   (Digit)  +                       --> NUM                               *
*   (Letter /\ token[1] != '\')  +   --> ID                                *
*   [OTHER]  CTokenOut(NUMBER)       --> START                             *
*                                                                          *
* BSBUILT_IN:                                                              *
*   (Letter)              +                   --> BSBUILT_IN               *
*   [token \in BuiltIns]  CTokenOut(BUILTIN)  --> START                    *
*   [OTHER]               CTokenOut(OTHER)    --> START                    *
*                                                                          *
* BUILT_IN:                                                                *
*   [token+ \in BuiltInPrefix]  +                  --> BUILT_IN            *
*   [OTHER]   while (token \notin BuiltIn)                                 *
*               {move last char in token back                              *
*                to the CharReader};                                       *
*             CTokenOut(BUILTIN)                   --> START               *
*                                                                          *
* REPEAT_CHAR:                                                             *
*   (repChar)   +                                  --> REPEAT_CHAR         *
*   [Len(token) \geq getRepeatCharMin(repChar)]                            *
*                  CTokenOut(REP_CHAR)             --> START               *
*   [OTHER]                                        --> BUILT_IN            *
*                                                                          *
* (**********************************************************)             *
* (* Note that we leave in the string the "\" of an escape  *)             *
* (* character like "\n".                                   *)             *
* (**********************************************************)             *
* STRING:                                                                  *
*   ("\\")             +                           --> ESC_STRING          *
*   ("\"" /\ (token in stringHashTable \/ inSQuote)                        *
*                   (*****************************************)            *
*                   (* Note: `\/ inSQuote' added 30 Jan 2001 *)
*                   (*****************************************)            *
*                     - ; CTokenOut(STRING)         --> START              *
*   (LegalStringChar)  +                           --> STRING              *
*   [OTHER]  --> LEFT_DQUOTE                                               *
*                                                                          *
* ESC_STRING:                                                              *
*   ("\"", "\\", "t", "n", "f", or "r")  +        --> STRING               *
*   [OTHER] --> LEFT_DQUOTE                                                *
*                                                                          *
* LEFT_DQUOTE:                                                             *
*   [OTHER] Backspace(Len(token)+1); token = "\"";                         *
*           CTokenOut(LEFT_DQUOTE); inDQuote = true --> START              *
*                                                                          *
* RIGHT_DQUOTE:                                                            *
*   [OTHER] CTokenOut(RIGHT_DQUOTE); inDQuote = false --> START            *
*                                                                          *
* LEFT_SQUOTE:                                                             *
*   (`)  + CTokenOut(OTHER);                --> START                      *
*   (^)  - ; token = "" ;                   --> TEX                        *
*   (~)  - ; token = "" ;                   --> THROW_AWAY                 *
*   (.)  - ; token = "  "                   --> VERB                       *
*       (************************************************************)     *
*       (* Note: we replace the "`." by spaces in first VERB token. *)     *
*       (************************************************************)     *
*   [OTHER]  token = ""; inSQuote = true    --> START                      *
*         (************************************************************)   *
*         (* Note: we add a hack here to decrement col so, if there   *)   *
*         (* is no space between the "`" and the next token, then the *)   *
*         (* starting column of that token is the column of the "`".  *)   *
*         (* This gets alignments right if a line in a multi-line     *)   *
*         (* comment begins with `token'.  However, it introduces the *)   *
*         (* following bug: if the ' is immediately followed by a     *)   *
*         (* character, as in "`token'.", then it will appear as if   *)   *
*         (* there is a space before the ".", so TLATeX inserts a     *)   *
*         (* spurious space in the output.  One way to fix this is to *)   *
*         (* add 1 to the length of a token immediately following a ` *)   *
*         (* and add 1 to the length of a token immediately preceding *)   *
*         (* a '.  The latter requires some kludgery.                 *)   *
*         (************************************************************)   *
*                                                                          *
* RIGHT_SQUOTE:                                                            *
*   (')      + ; CTokenOut(OTHER)   --> START                              *
*   [OTHER]                         --> BUILT_IN                           *
*                                                                          *
* TEX:                                                                     *
*   (^)      -                        ---> TEX_CARET                       *
*   ("\n")   IF token = ""                                                 *
*              THEN token = " " ;                                          *
*            CTokenOut(TEX);                                               *
*            token = ""               ---> TEX                             *
*   ("\t")   IF token nonblank                                             *
*              THEN CTokenOut(TEX)    ---> DONE                            *
*   [OTHER]  +                        ---> TEX                             *
*                                                                          *
* TEX_CARET :                                                              *
*   (')     - ; IF token nonblank                                          *
*                 THEN CTokenOut(TEX)     ---> START                       *
*   [OTHER] token = token + ".";          ---> TEX                         *
*                                                                          *
* THROW_AWAY:                                                              *
*   (~)      -    ---> THROW_AWAY_TILDE                                    *
*   (\n)     -    ---> THROW_AWAY                                          *
*   ("\t")   -    ---> DONE                                                *
*   [OTHER]  -    ---> THROW_AWAY                                          *
*                                                                          *
* THROW_AWAY_TILDE:                                                        *
*   (')      -    ---> START                                               *
*   [OTHER]  -    ---> THROW_AWAY                                          *
*                                                                          *
* VERB:                                                                    *
*   (.)      -                        ---> VERB_DOT                        *
*   ("\n")   IF token nonblank                                             *
*              THEN CTokenOut(VERB);                                       *
*            token = ""               ---> VERB                            *
*   ("\t")   IF token nonblank                                             *
*              THEN CTokenOut(VERB)   ---> DONE                            *
*   [OTHER]  +                        ---> VERB                            *
*                                                                          *
* VERB_DOT:                                                                *
*   (')     - ; CTokenOut(VERB)    ---> START                              *
*   [OTHER] token = token + ".";   ---> VERB                               *
***************************************************************************/


package tla2tex;
import java.util.Vector;

public class TokenizeComment
  { private static Vector vspec = new Vector(50, 50) ;
      /*********************************************************************
      * The vector that will eventually be turned into the array returned  *
      * by the Tokenize method.                                            *
      *********************************************************************/
      
    /***********************************************************************
    * The following private class variables are used in the                *
    * implementation of the Tokenize method.  They are made class          *
    * variables so they can be accessed in procedures used by Tokenize     *
    * (which are defined as private class methods).                        *
    ***********************************************************************/

    private static Vector linev = new Vector(40, 40) ;
          /*****************************************************************
          * Vector linev contains the tokens found so far on the current   *
          * line.                                                          *
          *****************************************************************/

    private static Vector argVec ;
      /*********************************************************************
      * The argument with which the Tokenize method is called, "exposed"   *
      * so that other methods, which are actually subprocedures of         *
      * Tokenize, can access it.  This hackery is needed because Java      *
      * apparently doesn't support static methods within a static method.  *
      * As someone once said, "I always program in the same language,      *
      * regardless of the compiler I happen to be using."                  *
      *********************************************************************/
      
    private static char nextChar ;
          /*****************************************************************
          * nextChar is the next input character to be processed.          *
          *****************************************************************/

    private static String token  = "" ;
          /*****************************************************************
          * token is the string containing the part of the current token   *
          * found so far.                                                  *
          *****************************************************************/

    private static boolean inDQuote = false ;
      /*********************************************************************
      * True iff have found the first of a presumed pair of '"'            *
      * characters.                                                        *
      *********************************************************************/
      
    private static boolean inSQuote = false ;
      /*********************************************************************
      * True iff have found the first of a presumed "`...'" expression,    *
      * which indicates that the expression is to be parsed as part of a   *
      * TLA spec.                                                          *
      *********************************************************************/
      
    private static int col ;
    private static int ncol = 0;
          /*****************************************************************
          * col is the column from which the first character of token      *
          * came.                                                          *
          *                                                                *
          * ncol is the column from which nextChar came.                   *
          *****************************************************************/
    private static int line = 0;
      /*********************************************************************
      * The line of comment (the element of the Vector argument of         *
      * Tokenize) currently being processed.                               *
      *********************************************************************/
      
    private static String curString = "";
      /*********************************************************************
      * This is the line of the comment currently being processed.  It     *
      * equals vec.elementAt(line), where vec is the argument to           *
      * Tokenize.                                                          *
      *********************************************************************/

    /***********************************************************************
    * Here are all the states for the tokenizing algorithm.                *
    ***********************************************************************/
      private static final int START            = 1 ;
      private static final int ID               = 2 ;
      private static final int NUM_OR_ID        = 3 ;
      private static final int BS               = 4 ;
      private static final int NUM_OR_BI        = 5 ;  
      private static final int NUM              = 6 ;
      private static final int BSBUILT_IN       = 7 ;  
      private static final int BUILT_IN         = 8 ;
      private static final int REPEAT_CHAR      = 9 ;
      private static final int STRING           = 10 ;
      private static final int ESC_STRING       = 11 ;
      private static final int LEFT_DQUOTE      = 12 ;
      private static final int RIGHT_DQUOTE     = 13 ;
      private static final int LEFT_SQUOTE      = 14 ;
      private static final int RIGHT_SQUOTE     = 15 ;
      private static final int TEX              = 16 ;
      private static final int TEX_CARET        = 17 ;
      private static final int THROW_AWAY       = 18 ;
      private static final int THROW_AWAY_TILDE = 19 ;
      private static final int VERB             = 20 ;
      private static final int VERB_DOT         = 21 ;
      private static final int DONE             = 22 ;
      
    private static int state = START ;
          /*****************************************************************
          * The state in the tokenizing algorithm.                         *
          *****************************************************************/
          
    /***********************************************************************
    * The following private methods are all procedures for use by the      *
    * Tokenize method.                                                     *
    ***********************************************************************/

    private static boolean isAllUnderscores()
      /*********************************************************************
      * True iff token is a string consisting only of "_" characters.      *
      *********************************************************************/
      { int i = 0 ;
        boolean result = true ;
        while ( result && (i < token.length()))
         { if (token.charAt(i) != '_') { result = false;} ;
           i=i+1;
         };
        return result;
      } ;

    private static void skipNextChar()
      /*********************************************************************
      * Sets nextChar to the next character in the input stream, and sets  *
      * ncol to its column.                                                *
      *********************************************************************/
      { ncol = ncol + 1;
        if (ncol < curString.length())
          {nextChar = curString.charAt(ncol);}
        else if (ncol == curString.length())
          {nextChar = '\n';}
        else
          { line = line + 1;
            if (line < argVec.size())
              { curString = (String) argVec.elementAt(line); 
                if (curString == null) {curString = "";}
              }
            else
             { curString = "\t"; } ;
            ncol = 0 ;
            if (curString.length() == 0)
             { nextChar = '\n';}
            else
             { nextChar = curString.charAt(0);} ;
          };
      } ;

    private static void addNextChar()
      /*********************************************************************
      * Appends nextChar to token, sets nextChar to the next character in  *
      * the input stream, and sets ncol to its column.                     *
      *********************************************************************/
      { token = token + nextChar ;
        skipNextChar() ;
      } ;

    private static void Backspace(int n) 
      /*********************************************************************
      * Decrements ncol by n.  (The result should be non-negative.)        *
      *********************************************************************/
      { ncol = ncol - n ;
        if (ncol < 0) 
          { Debug.ReportBug("TokenizeComment: Backspacing off end of line"); };
      }

    private static void gotoStart()
      /*********************************************************************
      * Set the state to START. Since this means that we are at or before  *
      * the beginning of the next token, we set col equal to ncol.         *
      *********************************************************************/
      { state = START ;
        col = ncol ;
      }

    private static void CTokenOut(int type)
      /*********************************************************************
      * Add the token to linev and reset token to the empty string.        *
      *********************************************************************/
      { if (   (! token.equals(""))
            || (type == CToken.STRING))
          /*****************************************************************
          * CTokenOut can be called with a null argument if the user       *
          * types "", or if she types ".'" at the beginning of a line or   *
          * immediately after "`.".  I'm not sure if there are other       *
          * cases as well.                                                 *
          *****************************************************************/
          { boolean tla = false ;
            boolean amb = false ;
            if ( (inSQuote) && (type != CToken.VERB))
             { tla = true ;
             }
            else
             { switch(type)
                { case CToken.BUILTIN :
                    if (FormatComments.isAmbiguous(token))
                      { /***************************************************
                        * We set the isAmbiguous flag for an ambiguous     *
                        * token only if that token actually appears in     *
                        * the spec.  This may be overly pessimistic,       *
                        * since it causes TLATeX to mess up the            *
                        * typesetting of a symbol fairly often.  Perhaps   *
                        * one should add an additional table for           *
                        * ambiguous tokens that should be considered       *
                        * ambiguous even if they don't appear in the spec  *
                        * because they're still more likely than not to    *
                        * be TLA symbols.  That table include "#".         *
                        ***************************************************/
                        if (TokenizeSpec.isUsedBuiltin(token))
                          {amb = true;};
                      }
                    else
                      { tla = true; }
                    break;
                  case CToken.NUMBER :
                    if (token.charAt(0) == '\\')
                      { tla = true ;}
                    else
                      { amb = true ;}
                    break;
                  case CToken.STRING :
                    tla = true;
                    break;
                  case CToken.IDENT :
                    if (FormatComments.IsWord(token))
                      { if (TokenizeSpec.isIdent(token))
                         { amb = true ;} ;
                      }
                    else
                      { if (TokenizeSpec.isIdent(token))
                              //   || (token.length() == 1)
                              // At first, it seemed like a good idea
                              // to consider any 1-character non-word 
                              // IDENT like "i" to be a symbol.  However, 
                              // a comment could include something like 
                              //   "There are two cases: (i)..."
                         { tla = true ;
                         }
                        else
                         { amb = true;
                         }
                      } ;
                    break;
                  case CToken.VERB :
                    if (token.indexOf("\\end{verbatim}") != -1)
                      /*****************************************************
                      * This is highly unlikely, but I discovered the      *
                      * problem when testing, so ...                       *
                      *****************************************************/
                     { Debug.ReportError(
                        "Sorry, but you can't put the string\n\n" +
                        "       \\end{verbatim}\n\n" +
                        "    between `. and .' ");
                     };
                    break;
                  case CToken.OTHER :
                  case CToken.REP_CHAR :
                  case CToken.LEFT_DQUOTE :
                  case CToken.RIGHT_DQUOTE :
                  case CToken.TEX :
                    break;
                  default :
                    Debug.ReportBug(
                     "TokenizeComment.CTokenOut called with illegal type"); 
                }
             }
            linev.addElement(new CToken(token, col, type, tla, amb)); 
          } ;
        token = "" ;
      } ;

    private static void startNewLine()
      /*********************************************************************
      * Append linev to vspec, reset linev, and set curString to the next  *
      * line of input.  This should be called whenever a \n character is   *
      * removed from the input stream.                                     *
      *********************************************************************/
      { vspec.addElement(linev)    ;
        linev = new Vector(30, 30) ;
        col = 0 ;
        ncol = 0 ;
      } ;

    private static CToken[][] vspecToArray() 
      /*********************************************************************
      * Turns vspec into an array, and re-initializes it.                  *
      *********************************************************************/
      { CToken[][] aspec = new CToken[vspec.size()][] ;
        int n = 0 ;                                                       
        while (n < vspec.size())                                          
          { aspec[n] =                                                     
               new CToken [ ((Vector) vspec.elementAt(n)) . size() ] ;     
            int m = 0 ;                                                   
            while (m < aspec[n].length)                                    
              {aspec[n][m] =                                               
                (CToken) ((Vector) vspec.elementAt(n)) . elementAt(m);     
               m = m+1;                                                   
              };                                                          
            n = n+1 ;                                                     
          };                                                              
        vspec = new Vector(50, 50) ;
        return aspec;
      } ;

    public static CToken[][] Tokenize(Vector vec)
      /*********************************************************************
      * Tokenize the comment represented by vec, which must be a vector    *
      * of strings.                                                        *
      *********************************************************************/
      { if ((vec == null) || (vec.size() == 0)) {return null ;} ;
          /*****************************************************************
          * A zero-length or null vector returns null.  Any caller who     *
          * provides such an argument had better be ready to deal with     *
          * the null result.                                               *
          *****************************************************************/

        argVec = vec;
          /*****************************************************************
          * Expose the argument to all the innocent methods in the         *
          * neighborhood.                                                  *
          *****************************************************************/

        line = 0 ;
        
        /*******************************************************************
        * Initialize curString and nextChar, col, and ncol.                *
        *******************************************************************/
        if (argVec.elementAt(line) == null)
          { curString = "" ;
          }
        else 
          { curString = (String) argVec.elementAt(line) ;
          } ;
        if (curString.equals(""))
          { nextChar  = '\n';}
        else
          { nextChar = curString.charAt(0) ;};
        col = 0 ;
        ncol = 0;

        char repChar = ' ';
          /*****************************************************************
          * The current repetition character.  (It is initialized only to  *
          * avoid a compiler warning.)                                     *
          *****************************************************************/

        state = START ;

        while (state != DONE)
          { // BEGIN while (state != DONE)
            /***************************************************************
            * Set linev to the vector of tokens in the current line.       *
            ***************************************************************/
            switch (state) 
              /*************************************************************
              * The following code is a direct translation of the          *
              * description given in the comments above, with only minor   *
              * optimizations that are local to a particular case clause.  *
              *************************************************************/
              { case START :
                  if (Misc.IsSpace(nextChar))
                    { skipNextChar() ;
                      gotoStart(); 
                    }
                  else if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      state = ID;  
                    }
                  else if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM_OR_ID; 
                    }
                  else if (nextChar == '\n')
                    { skipNextChar() ;
                      startNewLine() ;
                      gotoStart(); 
                    }
                  else if (nextChar == '\\')
                    { addNextChar();
                      state = BS;    
                    }
                  else if (FormatComments.isRepeatChar(nextChar))
                    { repChar = nextChar;
                      addNextChar();
                      state = REPEAT_CHAR ;
                    }
                  else if (nextChar == '"')   // " )
                    { if (inDQuote)
                        { addNextChar();
                          state = RIGHT_DQUOTE;}
                      else
                        { skipNextChar();
                          state = STRING;};
                    }
                  else if (nextChar == '`')
                    { addNextChar();
                      state = LEFT_SQUOTE; 
                    }                              
                  else if (nextChar == '\'')
                    { if (inSQuote)
                        { skipNextChar();
                          inSQuote = false;
                          gotoStart();
                        }
                      else
                        { addNextChar();
                          state = RIGHT_SQUOTE; 
                        } ;
                    }                              
                  else if (BuiltInSymbols.IsBuiltInPrefix("" + nextChar))
                    { addNextChar();
                      state = BUILT_IN ;
                    }
                  else if (nextChar == '\t')
                    { state = DONE ;
                    }
                  else 
                    { addNextChar();
                      CTokenOut(CToken.OTHER);
                      gotoStart() ;
                    } ;
                  break;

                case ID :
                  if (   (token.length() == 3)
                      && (token.equals("WF_") || token.equals("SF_")))
                    { CTokenOut(CToken.BUILTIN) ;
                      gotoStart(); 
                    }
                  else if (Misc.IsLetter(nextChar) || Misc.IsDigit(nextChar))
                    { addNextChar();
                      // state = ID ;
                    }  
                  else if (BuiltInSymbols.IsBuiltInSymbol(token))
                            // don't want to handle PCal tokens specially
                    { CTokenOut(CToken.BUILTIN) ;
                      gotoStart();
                    }
                  else 
                    { if (isAllUnderscores())
                        { CTokenOut(CToken.REP_CHAR); }
                      else 
                        { CTokenOut(CToken.IDENT) ; };
                      gotoStart();
                    };
                  break;          

                case NUM_OR_ID :
                  if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM_OR_ID; 
                    }
                  else if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      state = ID; 
                    }
                  else 
                    { CTokenOut(CToken.NUMBER) ;
                      gotoStart();
                    }
                  break;

                case BS :
                  if (    (nextChar == 'b') 
                       || (nextChar == 'B') 
                       || (nextChar == 'o') 
                       || (nextChar == 'O') 
                       || (nextChar == 'h') 
                       || (nextChar == 'H') )
                    { addNextChar();
                      state = NUM_OR_BI ;
                    }
                  else if (Misc.IsLetter(nextChar))
                    { state = BSBUILT_IN ; 
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case NUM_OR_BI :
                  if (Misc.IsDigit(nextChar))
                    { state = NUM;
                    }
                  else 
                    { state = BSBUILT_IN;
                    };
                  break;

                case NUM :
                  if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM;
                    }
                  else if (Misc.IsLetter(nextChar) && (token.charAt(0) != '\\'))
                    { addNextChar();
                      state = ID;
                    }
                  else 
                    { CTokenOut(CToken.NUMBER) ;
                      gotoStart();
                    }
                  break;

                case BSBUILT_IN :
                  if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      state = BSBUILT_IN;
                    }
                  else if (BuiltInSymbols.IsBuiltInSymbol(token))
                            // "\" built-in never a PCal symbol
                    { CTokenOut(CToken.BUILTIN) ;
                      gotoStart();
                    }
                  else 
                    { CTokenOut(CToken.OTHER) ;
                      gotoStart();
                    } ;
                   break;

                case BUILT_IN :
                  if (BuiltInSymbols.IsBuiltInPrefix(token + nextChar))
                    { addNextChar();
                      // state = BUILT_IN;
                    }
                  else 
                    { 
                     if (! BuiltInSymbols.IsBuiltInSymbol(token))
                         // don't want to handle PCal tokens specially
                      { 
                        while (! BuiltInSymbols.IsBuiltInSymbol(token))
                            // don't want to handle PCal tokens specially
                        { Backspace(1);
                          if (token.length() == 0)
                            { Debug.ReportBug(
                                 "Error tokenizing built-in symbol");
                            };
                          token = token.substring(0, token.length()-1);
                        } ;
                        nextChar = curString.charAt(ncol); 
                      } ;
                      CTokenOut(CToken.BUILTIN) ;
                      gotoStart();
                    }
                   break;

                case REPEAT_CHAR:
                  if (nextChar == repChar)
                    { addNextChar();
                      // state = REPEAT_CHAR ;
                    }
                  else if (token.length() >= 
                          FormatComments.getRepeatCharMin(repChar))
                    { CTokenOut(CToken.REP_CHAR);
                      state = START ;
                    }
                  else
                    { state = BUILT_IN ;
                    }
                  break;

                case STRING :
                  if (nextChar == '\\')
                    { addNextChar();
                      state = ESC_STRING ;
                    }
                  else if (BuiltInSymbols.IsStringChar(nextChar))
                    { addNextChar();
                      state = STRING ;
                    }
                  else if (  (nextChar == '"') // " )
                          && (   TokenizeSpec.isString(token)
                              || inSQuote ))
                    { 
                      skipNextChar();
                      CTokenOut(CToken.STRING) ;
                      gotoStart();
                    }
                  else
                    { state = LEFT_DQUOTE;
                    }
                   break;

                case ESC_STRING :
                  if (   (nextChar == '\"')
                      || (nextChar == '\\')
                      || (nextChar == 't')
                      || (nextChar == 'n')
                      || (nextChar == 'f')
                      || (nextChar == 'r') )
                    { addNextChar();
                      state = STRING ;
                    }
                  else
                    { state = LEFT_DQUOTE;
                    };
                  break;

                case LEFT_DQUOTE :
                  Backspace(token.length()+1);
                  token = "\"" ; 
                  CTokenOut(CToken.LEFT_DQUOTE);
                  inDQuote = true;
                  skipNextChar();
                  gotoStart();    
                  break;

                case RIGHT_DQUOTE :
                  CTokenOut(CToken.RIGHT_DQUOTE) ;
                  inDQuote = false ;
                  gotoStart();    
                  break;

                case LEFT_SQUOTE :
                  if (nextChar == '`')
                   { addNextChar();
                     CTokenOut(CToken.OTHER);
                     gotoStart();    
                   }
                  else if (nextChar == '^' )
                   { skipNextChar();
                     token = "  " ;
                     state = TEX ;
                   }
                  else if (nextChar == '~' )
                   { skipNextChar();
                     token = "  " ;
                     state = THROW_AWAY ;
                   }
                  else if (nextChar == '.' )
                   { skipNextChar();
                     token = "  " ;
                     state = VERB ;
                   }
                  else 
                   { token = "" ;
                     inSQuote = true;
                     // gotoStart();
                     col = ncol - 1;
                     state = START ;
                   }
                  break;

                case RIGHT_SQUOTE :
                  if (nextChar == '\'')
                    { addNextChar() ;
                      CTokenOut(CToken.OTHER) ;
                      gotoStart();
                    }
                  else
                    { state = BUILT_IN ;
                    }
                  break;

                case TEX :
                  if (nextChar == '^')
                   { skipNextChar();
                     state = TEX_CARET ;
                   }
                  else if (nextChar == '\n' )
                   { skipNextChar();
                     if (token.equals(""))
                       { token = " "; }
                     CTokenOut(CToken.TEX);
                     startNewLine();
                     // state = TEX
                   }
                  else if (nextChar == '\t' )
                   { if (! Misc.isBlank(token))
                       {CTokenOut(CToken.TEX);} ;
                     token = "";
                     state = DONE ;
                   }
                  else 
                   { addNextChar();
                     // state = TEX ;
                   }
                  break;

                case TEX_CARET :
                  if (nextChar == '\'')
                   { skipNextChar();
                     if (! Misc.isBlank(token))
                       {CTokenOut(CToken.TEX);} ;
                     token = "";
                     gotoStart();
                   }
                   else 
                   { token = token + "^";
                     state = TEX ;
                   }
                  break;

                case THROW_AWAY :
                  if (nextChar == '~')
                   { skipNextChar();
                     state = THROW_AWAY_TILDE ;
                   }
                  else if (nextChar == '\n' )
                   { skipNextChar();
                     if (linev.size() != 0) 
                       /****************************************************
                       * Start new line iff there is some actual output    *
                       * on the line.                                      *
                       ****************************************************/
                       { startNewLine(); }
                     col = 0 ;
                     ncol = 0 ;
                     // state = THROW_AWAY
                   }
                  else if (nextChar == '\t' )
                   { state = DONE ;
                   }
                  else 
                   { addNextChar();
                     // state = THROW_AWAY ;
                   }
                  break;

                case THROW_AWAY_TILDE :
                  if (nextChar == '\'')
                   { skipNextChar();
                     token = "";
                     gotoStart();
                   }
                   else 
                   { skipNextChar();
                     state = THROW_AWAY ;
                   }
                  break;

                case VERB :
                  if (nextChar == '.')
                   { skipNextChar();
                     state = VERB_DOT;
                   }
                  else if (nextChar == '\n' )
                   { skipNextChar();
                     if (! Misc.isBlank(token))
                       {CTokenOut(CToken.VERB);} ;
                     token = "";
                     startNewLine();
                     // state = VERB ;
                   }
                  else if (nextChar == '\t' )
                   { if (! Misc.isBlank(token))
                       {CTokenOut(CToken.VERB);} ;
                     state = DONE ;
                   }
                  else 
                   { addNextChar();
                     // state = VERB ;
                   }
                  break;

                case VERB_DOT :
                  if (nextChar == '\'')
                   { skipNextChar();
                     CTokenOut(CToken.VERB) ;
                     gotoStart();
                   }
                   else 
                   { token = token + ".";
                     state = VERB ;
                   }
                  break;

                default :
                  Debug.ReportBug(
                    "Unexpected state in comment-parsing algorithm");
                  // break;

              } ;  // END switch (state)
         } ; // END while (state != DONE)

        /*******************************************************************
        * Return the contents of vspec, converted to an array.             *
        *******************************************************************/
        return vspecToArray();
      }

    public static CToken[][] TeXTokenize(Vector vec)
      /*********************************************************************
      * Tokenize the comment represented by vec, which must be a vector of *
      * strings, turning each line into a TeX token.                       *
      *********************************************************************/
      { if ((vec == null) || (vec.size() == 0)) {return null ;} ;
          /*****************************************************************
          * A zero-length or null vector returns null.  Any caller who     *
          * provides such an argument had better be ready to deal with     *
          * the null result.                                               *
          *****************************************************************/
        CToken[][] result = new CToken[vec.size()][];
        line = 0 ;
        while (line < vec.size())
         {String curString = "" ;
          if (vec.elementAt(line) != null)
           {curString = (String) vec.elementAt(line) ;
           } ;
          result[line] = new CToken[1];
          result[line][0] = new CToken(curString,0,CToken.TEX, false, false);
          line = line + 1;
         } ;
        return result ;
      }
 }

/* last modified on Wed  1 Nov 2006 at 11:29:38 PST by lamport */
/*      modified on Mon Dec 11 14:21:46 PT 2000 by unknown */


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/IParseResultListener.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

/**
 * Interface that must be implemented by classes that want
 * to be notified when a new parse result is returned by
 * the parser.
 * 
 * @author <NAME>
 *
 */
public interface IParseResultListener
{

    /**
     * This method is called when a new {@link ParseResult} is created by
     * a call to SANY. The object parseResult is that new {@link ParseResult}.
     * 
     * @param parseResult
     */
    public void newParseResult(ParseResult parseResult);

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/SANY.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

package tla2sany;

/**
 * SANY is a shell class to call the main driver method of SANY
 */

public class SANY {

  public static final void main(String[] args) {
    tla2sany.drivers.SANY.SANYmain(args);
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/property/SpecPropertyPage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.property;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.preference.LibraryPathComposite;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * Represents specification properties
 * 
 * @author <NAME>
 * @version $Id$
 */
public class SpecPropertyPage extends GenericFieldEditorPropertyPage {
	private StringFieldEditor rootFileEditor;
	private StringFieldEditor directorySizeEditor;
	private LibraryPathComposite libraryPathComposite;

	protected Control createContents(Composite parent) {
		Control control = super.createContents(parent);

		// ensure the page has no special buttons
		noDefaultAndApplyButton();

		UIHelper.setHelp(control, IHelpConstants.SPEC_PROPERTY_PAGE);
		return control;
	}

	public void createFieldEditors(Composite composite) {
		// TODO change root file
		rootFileEditor = new StringFieldEditor(
				IPreferenceConstants.P_PROJECT_ROOT_FILE,
				"Specification root module", composite);
		addEditor(rootFileEditor);
		rootFileEditor.getTextControl(composite).setEditable(false);

		StringFieldEditor pcalParamEditor = new StringFieldEditor(
				IPreferenceConstants.PCAL_CAL_PARAMS, "PlusCal call arguments",
				composite);
		addEditor(pcalParamEditor);

		directorySizeEditor = new StringFieldEditor(
				"DoesNotExistIsIrrelevant",
				"Size of .toolbox directory in kbytes", composite);
		addEditor(directorySizeEditor);
		directorySizeEditor.getTextControl(composite).setEditable(false);

		libraryPathComposite = new LibraryPathComposite(this);

	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.ui.property.GenericFieldEditorPropertyPage#initialize()
	 */
	protected void initialize() {
		super.initialize();	
		
		/*
		 * The preference store keeps an Eclipse specific relative file path. It
		 * has to be resolved to the OS specific path.
		 * 
		 * @see PreferenceStoreHelper#storeRootFilename(..)
		 */
		final IPreferenceStore preferenceStore = getPreferenceStore();

		final Spec spec = (Spec) getElement();
		final IProject project = spec.getProject();

		final String relativePath = preferenceStore.getString(IPreferenceConstants.P_PROJECT_ROOT_FILE);
		final IFile resolvedFile = project.getFile(new Path(relativePath).lastSegment());
		rootFileEditor.setStringValue(resolvedFile.getLocation().toOSString());
		
		directorySizeEditor.setStringValue(Long.toString(spec.getSize() / 1000L)); // convert to KB
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
	 */
	protected IPreferenceStore doGetPreferenceStore() {
		Spec spec = (Spec) getElement();
		return PreferenceStoreHelper.getProjectPreferenceStore(spec
				.getProject());
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.ui.property.GenericFieldEditorPropertyPage#performDefaults()
	 */
	protected void performDefaults() {
		libraryPathComposite.performInit();
		super.performDefaults();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.ui.property.GenericFieldEditorPropertyPage#performOk()
	 */
	public boolean performOk() {
		libraryPathComposite.applyChanges();
		return super.performOk();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/OpenParseErrorViewHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.HashMap;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.services.IEvaluationService;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.ui.expression.ParseErrorTester;
import org.lamport.tla.toolbox.ui.view.ProblemView;
import org.lamport.tla.toolbox.util.UIHelper;

public class OpenParseErrorViewHandler extends AbstractHandler implements IHandler {

	private final SpecLifecycleParticipant specLifecycleParticipant = new SpecLifecycleParticipant() {
		public boolean eventOccured(SpecEvent event) {
			if (event.getType() == SpecEvent.TYPE_PARSE) {
				final IEvaluationService evalService = (IEvaluationService) PlatformUI.getWorkbench().getService(
						IEvaluationService.class);
				evalService.requestEvaluation(ParseErrorTester.PROPERTY_ID);
			}
			return false;
		}
	};

	public OpenParseErrorViewHandler() {
		// Various (Eclipse foundation) UIs react to the parse status of the
		// currently active spec, but can't register as
		// SpecLifecycleParticipants (SLP is a Toolbox, not Eclipse foundation
		// concept). Thus, we have to let those UIs know about the status of a
		// spec.
		// It is created and registered here in the ToolboxExplorer because this
		// UI is always instantiated when the Toolbox starts.
		Activator.getSpecManager().addSpecLifecycleParticipant(specLifecycleParticipant);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.commands.AbstractHandler#dispose()
	 */
	public void dispose() {
		super.dispose();
		Activator.getSpecManager().removeSpecLifecycleParticipant(specLifecycleParticipant);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
	 */
	public Object execute(ExecutionEvent event) throws ExecutionException {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put(OpenViewHandler.PARAM_VIEW_NAME, ProblemView.ID);
		UIHelper.runCommand(OpenViewHandler.COMMAND_ID, params);

		return null;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/LongArrays.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.fp;

public class LongArrays {

	/**
	 * Sorts the specified range [left,right] of the array. In other words,
	 * sorts the elements from the array index <code>left</code> to index
	 * <code>right</code>.
	 */
	public static void sort(final LongArray a, final long left, final long right, final LongComparator cmp) {
		final long size = a.size();
		if (size == 0) {
			return;
		}

		//+++++++ Insertions sort +++++++//
		for (long i = left, j = i; i < right; j = ++i) {
			final long lo = (i + 1) % size;
			final long ai = a.get(lo);
			while (cmp.compare(ai, lo, a.get(j % size), j % size) <= -1) {
				a.set((j + 1) % size, a.get(j % size));
				if (j-- == left) {
					break;
				}
			}
			a.set((j + 1) % size, ai);
		}
	}
	
	public static class LongComparator {
		public int compare(long lo, long loPos, long hi, long hiPos) {
			// The default comparator ignores the positions.
			return Long.compare(lo, hi);
		}
	}
	
	public static void sort(final LongArray a, final long left, final long right) {
		sort(a, left, right, new LongComparator());
	}

	public static void sort(final LongArray a) {
		sort(a, 0, a.size() - 1L, new LongComparator());
	}
	
	/**
	 * DOES NOT HANDLE LONG ARRAYS LARGER THAN INTEGER.MAX_VALUE
	 */
	public static long[] toArray(final LongArray array) {
		final long[] res = new long[(int) array.size()];
		for (int i = 0; i < array.size(); i++) {
			long l = array.get(i);
			res[i] = l;
		}
		return res;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/util/ZipUtil.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ZipUtil {

	public static boolean isArchive(final String filePath) {
		final File file = new File(filePath);
		try {
			final String probeContentType = Files.probeContentType(file.toPath());
			if (probeContentType != null && probeContentType.equals("application/zip")) {
				return true;
			}
		} catch (final IOException intentionallyIgnored) {
		}
		return false;
	}

	public static File unzip(final File zipFilePath, File destDir, boolean unique) throws IOException {
		return unzip(new FileInputStream(zipFilePath), destDir, unique);
	}

	public static File unzip(final InputStream zip, File destDir, boolean unique) throws IOException {
		if (unique) {
			while (destDir.exists()) {
				// append suffix if another spec in the same directory already exists. This might append it multiple times.
				destDir = new File(destDir + "_" + System.currentTimeMillis());
			}
			destDir.mkdirs();
		}
		final ZipInputStream zipIn = new ZipInputStream(zip);

		ZipEntry entry = zipIn.getNextEntry();
		while (entry != null) {
			final String filePath = destDir + File.separator + entry.getName();
			final File file = new File(filePath);
			if (entry.isDirectory()) {
				file.mkdir();
			} else {
				if (file.getParentFile() != null && !file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}
				// Better use Apache Commons IOUtils similar to PayloadHelper
				final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
				final byte[] bytesIn = new byte[4096];
				int read = 0;
				while ((read = zipIn.read(bytesIn)) != -1) {
					bos.write(bytesIn, 0, read);
				}
				bos.close();
			}
			zipIn.closeEntry();
			entry = zipIn.getNextEntry();
		}
		
		zipIn.close();
		
		return destDir;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.uitest/src/org/lamport/tla/toolbox/tool/tlc/ui/test/ModelEditorOpenCondition.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.test;

import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.ui.IEditorPart;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Checks if the workbench shows an editor with the given name
 */
public class ModelEditorOpenCondition extends DefaultCondition {

	private final String prefix;
	
	public ModelEditorOpenCondition(String aPrefix) {
		this.prefix = aPrefix;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#test()
	 */
	public boolean test() throws Exception {
		final IEditorPart activeEditor = UIHelper.getActiveEditor();
		if(activeEditor instanceof ModelEditor) {
			final String aTitle = activeEditor.getTitle();
			return aTitle.startsWith(prefix);
		} 
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#getFailureMessage()
	 */
	public String getFailureMessage() {
		return String.format("Timed out waiting for editor with %s to open", prefix);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/StaticBlockSelector.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.TLCState;
import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.TLCWorkerRMI;
import tlc2.tool.queue.IStateQueue;

public class StaticBlockSelector extends BlockSelector {
	/**
	 * System property to set a fixed block size
	 */
	private static final String BLOCK_SIZE = "tlc2.tool.distributed.TLCServerThread.BlockSize";
	/**
	 * TLC server threads manage the set of existing TLC workers.
	 */
	private final static int BlockSize = Integer.getInteger(BLOCK_SIZE, 1024);

	StaticBlockSelector(final TLCServer aTLCServer) {
		super(aTLCServer);
		averageBlockCnt = BlockSize;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.BlockSelector#getBlocks(tlc2.tool.queue.StateQueue, tlc2.tool.distributed.TLCWorkerRMI)
	 */
	public TLCState[] getBlocks(IStateQueue stateQueue, TLCWorkerRMI worker) {
		return stateQueue.sDequeue(BlockSize);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.selector.BlockSelector#setAverageBlockCnt(long)
	 */
	protected void setAverageBlockCnt(long blockCnt) {
		// nop
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/pref/ResourceBasedPreferenceStore.java<|end_filename|>
package org.lamport.tla.toolbox.util.pref;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.lamport.tla.toolbox.Activator;

/**
 * @author <NAME>
 * @version $Id$
 */
public class ResourceBasedPreferenceStore implements IPreferenceStore
{
    private IResource resource;
    private ListenerList listeners = new ListenerList();

    public ResourceBasedPreferenceStore(IResource resource)
    {
        this.resource = resource;
    }

    public boolean contains(String name)
    {
        try
        {
            return resource.getPersistentProperties().containsKey(name);
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
    }

    public String getString(String name)
    {
        String value = null;
        try
        {
            value = resource.getPersistentProperty(new QualifiedName(Activator.PLUGIN_ID, name));
            if (value == null) 
            {
                value = "";
            }
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return value;
    }
    
    public void setValue(String name, String value)
    {
        try
        {
            if (value == null) 
            {
                value = "";
            }
            resource.setPersistentProperty(new QualifiedName(Activator.PLUGIN_ID, name), value);
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public boolean needsSaving()
    {
        return false;
    }

    public void putValue(String name, String value)
    {
        setValue(name, value);
    }

    public boolean getBoolean(String name)
    {
        return Boolean.parseBoolean(getString(name));
    }

    public double getDouble(String name)
    {
        return Double.parseDouble(getString(name));
    }

    public float getFloat(String name)
    {
        return Float.parseFloat(getString(name));
    }

    public int getInt(String name)
    {
        return Integer.parseInt(getString(name));
    }

    public long getLong(String name)
    {
        return Long.parseLong(getString(name));
    }

    public void setValue(String name, double value)
    {
        setValue(name, new Double(value).toString());
    }

    public void setValue(String name, float value)
    {
        setValue(name, new Float(value).toString());
    }

    public void setValue(String name, int value)
    {
        setValue(name, new Integer(value).toString());
    }

    public void setValue(String name, long value)
    {
        setValue(name, new Long(value).toString());
    }

    public void setValue(String name, boolean value)
    {
        setValue(name, new Boolean(value).toString());
    }

    public void addPropertyChangeListener(IPropertyChangeListener listener)
    {
        listeners.add(listener);
    }

    public void removePropertyChangeListener(IPropertyChangeListener listener)
    {
        listeners.remove(listener);
    }

    public void firePropertyChangeEvent(String name, Object oldValue, Object newValue)
    {

    }

    
    /* -------------------------------------------------- */
    public void setDefault(String name, double value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public void setDefault(String name, float value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public void setDefault(String name, int value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public void setDefault(String name, long value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public void setDefault(String name, String value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public void setDefault(String name, boolean value)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    /* -------------------------------------------------- */
    public boolean getDefaultBoolean(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public double getDefaultDouble(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public float getDefaultFloat(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public int getDefaultInt(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public long getDefaultLong(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    public String getDefaultString(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }
    /* -------------------------------------------------- */
    public void setToDefault(String name)
    {
        throw new UnsupportedOperationException("Not implemented yet");
    }

    public boolean isDefault(String name)
    {
        return false;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/ExternalSortable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public interface ExternalSortable /* extends Comparable -- eliminated 12 Jan 09 because it creates an error in Java 1.6 */ {
  public BigInt read(InputStream in) throws IOException;
  public void write(OutputStream out) throws IOException;
}



<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/model-editor-preferences.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/model-editor-preferences.html  -->


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Model Editor Preferences</title>
</head>

<body>
<h1>Model Editor Preferences</h1>

<h3>Show Evaluate Constant Expression in its own tab</h3>
<p>
By default, the user can enter constant expressions to evaluate in a section on the Model Checking
Results page; by selecting this option, this section will be moved to its own page
within the Model Editor.
</p>

<h3>Definition Override display style</h3>
<p>
The Definition Override display on the Spec Options tab of the model editor can display definitions
referenced from the primary specification in either the display format of:
<ul>
	<li style="font-family: monospace;">Definition [Module Name]</li>
	<li style="font-family: monospace;">InstanceVariable!Definition</li>
</ul>
where, in the latter, <span style="font-family: monospace;">InstanceVariable</span>
is defined in specification such as
<span style="font-family: monospace;">InstanceVariable == INSTANCE ModuleName WITH ...</span>
<br/>
This style definition also carries over to the display shown when adding a new override in
this section.
</p>

<hr>
<a href = "model.html">&uarr; Model Checking</a>
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/StringVectorToFileException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class StringVectorToFileException extends UnrecoverableException
{

    /**
     * @param string
     */
    public StringVectorToFileException(String string)
    {
        super(string);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/TLA2TexException.java<|end_filename|>
package tla2tex;

/**
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLA2TexException extends RuntimeException
{

    private String error_message;

    /**
     * 
     */
    private static final long serialVersionUID = 6158929578245645265L;

    public TLA2TexException(String message)
    {
        error_message = message;
    }

    public String getMessage()
    {
        return error_message;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools.impl.distributed/src/org/lamport/tlatools/impl/distributed/TLCWorkerWrapper.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package org.lamport.tlatools.impl.distributed;

import java.net.URI;

import tlc2.ITLCWorker;
import tlc2.tool.distributed.TLCWorker;

public class TLCWorkerWrapper extends TLCWrapper implements ITLCWorker {

	/* (non-Javadoc)
	 * @see tlc2.ITLCWorker#connect(java.net.URI)
	 */
	public boolean connect(final URI uri) {
		super.connect("TLCWorker");
		try {
			TLCWorker.main(new String[] { uri.getHost() });
		} catch(Exception e) {
			// not expected to happen
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see tlc2.ITLCWorker#disconnect()
	 */
	public boolean disconnect() {
		try {
			TLCWorker.shutdown();
		} catch (Exception e) {
			// not expected to happen
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public void awaitTermination() {
		try {
			TLCWorker.awaitTermination();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/help-us/help-us.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/help-us/help-us.html  -->


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Please Help Us</title>
</head>
<!-- a comment here -->

<body>
<h1>Please Help Us</h1>

<p>
Leslie Lamport has mentored the development of the TLA<sup>+</sup> Toolbox continually,
while it has been developed by a small number of people over the years. The initial
version was designed and implemented almost entirely by <NAME> in less
than a year; followed by work done by <NAME>; followed by <NAME> and
others.
</p>

<p>
The Toolbox is written as an Eclipse RCP (Rich Client Platform)
application.&nbsp;  This has made it possible to implement a great deal of functionality
in a fairly short time.&nbsp;  It has also led to compromises.&nbsp;  There are things
we would like the Toolbox to do that it doesn't.&nbsp;  Some of the inadequacies
are due to a lack of time; others are because we have been unable to
figure out how to implement them in Eclipse--either because Eclipse
lacks the necessary functionality, or because we don't know how to do them
in Eclipse.
</p>

<p>
We can use your help.&nbsp;  Let us know about problems you encounter
or about any aspect
of the Toolbox that you don't like.&nbsp;  We also want to know
what important features you feel the Toolbox lacks.&nbsp;  Below is
a list of some of the features we are thinking of adding.&nbsp;
We probably won't have time to add them all, so we want
to know which of them you would most like.&nbsp;  And we would
love your help in debugging and developing the Toolbox.&nbsp;
Contact us on the <a href="https://groups.google.com/forum/#!forum/tlaplus">Google
Groups forum</a> or open a new issue <a href="https://github.com/tlaplus/tlaplus/issues">at
GitHub.</a>
</p>

<h2>Some Features We May Add</h2>

<h3>A TLA<sup>+</sup> Tutorial</h3>

A tutorial on specifying systems with TLA<sup>+</sup>
and checking the specifications with the TLA<sup>+</sup> tools is being written.&nbsp;
It is based on the Toolbox.&nbsp;  The current, incomplete version, is available;
see the <a href="http://research.microsoft.com/en-us/um/people/lamport/tla/tla.html">TLA+ web site</a>.
We do not know whether
the tutorial will be incorporated within the Toolbox itself.

<h3>Better Support for PlusCal</h3>

<p>
Errors in expressions in a PlusCal algorithm are manifest
as parsing errors or TLC errors in the corresponding expressions
of the algorithm's TLA<sup>+</sup> translation.&nbsp;  We would like
to have the Toolbox mark the locations of those errors in the
PlusCal code.
</p>

<p>The pretty-printer does not yet properly format PlusCal algorithms.&nbsp;  We would like
it to.</p>

<h3>Support for the TLA<sup>+</sup> Proof System</h3>

A TLA<sup>+</sup> proof checker is under development at the
<a href="http://www.msr-inria.inria.fr/Projects/tools-for-formal-specs">Microsoft Research-Inria Joint Centre</a>.&nbsp;
We expect to add at least a basic level of support for writing and checking proofs within the Toolbox.

<hr>
<a href = "../contents.html">&uarr; TLA+ Toolbox User's Guide</a>
</hr>

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ToolboxWelcomeView.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.view;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.lamport.tla.toolbox.ui.intro.ToolboxIntroPart;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * The toolbox view that is shown when no spec is loaded.
 * @author <NAME>
 */
public class ToolboxWelcomeView extends ViewPart
{

    private Composite parentComposite;

    public static final String ID = "toolbox.view.ToolboxWelcomeView";

    public void createPartControl(Composite parent)
    {
        parentComposite = parent;

        ToolboxIntroPart.createControl(parent);
        
        UIHelper.setHelp(parent, "WelcomeView");
    }

    public void setFocus()
    {
        if (parentComposite != null)
        {
        	parentComposite.setFocus();
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/SimpleCache.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.util;

import java.text.DecimalFormat;

public class SimpleCache implements Cache {

	private volatile long cacheHit = 1L;
	private volatile long cacheMiss = 1L;
	
	private final long mask;
	private final long[] cache;
	
	/**
	 * A {@link SimpleCache} with room for 2^10 (1024) fingerprints
	 */
	public SimpleCache() {
		this(10); 
	}

	/**
	 * A {@link SimpleCache} with room for 2^size fingerprints
	 * @param size Room for 2^size fps 
	 */
	public SimpleCache(final int size) {
		final int capacity = 1 << size;
		this.mask = capacity - 1;
		this.cache = new long[capacity];
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.Cache#hit(long)
	 */
	public boolean hit(final long fp) {
	    final int index = (int)(fp & this.mask);
	    long hit = this.cache[index];
	    if (hit == fp) {
	    	cacheHit++;
	    	return true;
	    } else {
	    	cacheMiss++;
	    	this.cache[index] = fp;
	    	return false;
	    }
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.Cache#getHitRatio()
	 */
	public double getHitRatio() {
		return cacheHit / (double) cacheMiss;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.Cache#getHitRatioAsString()
	 */
	public String getHitRatioAsString() {
		DecimalFormat df = new DecimalFormat("###,###.###");
		return df.format(getHitRatio());
	}

	/* (non-Javadoc)
	 * @see tlc2.util.Cache#getHitRate()
	 */
	public long getHitRate() {
		return cacheHit;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/prover/old-decompose.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/prover/prover.html -->
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

    <title>The Decompose Proof Command</title>
</head>
<!-- a comment -->

<body>


<h1>The Old Decompose Proof Command</h1>

<b> This command has been replaced with a new version.</b>

<p>

The Decompose Proof command is executed by placing the cursor in a proof obligation, either a proof step or
a theorem, and either typing <code>Ctl+G&nbsp;Ctl+D</code> or right-clicking and selecting
the command.

<p>
There are two basic ways to decompose a proof obligation
into simpler obligtions:
<DL> <DT> <b><code>/\</code> decomposition</b> </DT>
<DD>If &nbsp;<code>P</code>&nbsp; equals 
   &nbsp;<code>P1 /\ ... /\ Pn</code>&nbsp;,
then the proof of &nbsp;<code>P</code>&nbsp; can be broken into the
proof of the &nbsp;<code>n</code>&nbsp; formulas 
  &nbsp;<code>P1, ... , Pn</code>&nbsp;.
</DD>

<BR> </BR>
 <DT><b><code>\/</code> decomposition &nbsp; (case split) </b>
 </DT>
<DD> 
If &nbsp;<code>P</code>&nbsp; equals 
   &nbsp;<code>P1&nbsp;\/ ... \/&nbsp;Pn</code>&nbsp;,
then the proof of &nbsp;<code>ASSUME&nbsp;P&nbsp;PROVE&nbsp;Q</code>&nbsp;
can be broken into the
proof of the &nbsp;<code>n</code>&nbsp; obligations
  &nbsp;<code>ASSUME&nbsp;P1&nbsp;PROVE&nbsp;Q,&nbsp;...,&nbsp;ASSUME&nbsp;Pn&nbsp;PROVE&nbsp;Q</code>&nbsp;.
</DD>
</DL>
</p>

<p>
Often, a proof obligation must be transformed into an equivalent one in order to be decomposed
by <code>/\</code> or <code>\/</code> decomposition.  There are two transformations that can be
applied to the goal of an obligation.  (The goal is the <code>PROVE</code> formula of an <code>ASSUME</code>/<code>PROVE</code>
obligation or the entire obligation, if it is a single formula.)

<DL> <DT> <b><code>=></code> splitting</b> </DT>
<DD>A goal &nbsp;<code>P => Q</code>&nbsp; is equivalent to the assumption &nbsp;<code>P</code>&nbsp;
and the goal &nbsp;<code>Q</code>&nbsp;.
</DD>

<BR> </BR>
 <DT><b><code>\A</code> splitting</b>
 </DT>
<DD>A goal &nbsp;<code>\A x \in S : P</code>&nbsp; is equivalent to the assumption &nbsp;<code>NEW&nbsp;x&nbsp;\in&nbsp;S</code>&nbsp;
and the goal &nbsp;<code>P</code>&nbsp;.&nbsp;  The goal &nbsp;<code>\A x&nbsp;:&nbsp;P</code>&nbsp; is similarly split.

</DD>
</DL>

There are two transformations that can be applied to an assumption of an <code>ASSUME</code>/<code>PROVE</code> obligation:

<DL> <DT> <b><code>/\</code> splitting</b> </DT>
<DD>An assumption &nbsp;<code>P1 /\ ... /\ Pn</code>&nbsp;, is equivalent to the &nbsp;<code>n</code>&nbsp; assumptions
&nbsp;P1,&nbsp;...,&nbsp;Pn</code>&nbsp;.
</DD>

<BR> </BR>
 <DT><b><code>\E</code> splitting</b>
 </DT>
<DD>An assumption &nbsp;<code>\E x \in S : P</code>&nbsp; is equivalent to the two assumptions 
 &nbsp;<code>NEW&nbsp;x&nbsp;\in&nbsp;S,&nbsp;P</code>&nbsp;.

The goal &nbsp;<code>\E x&nbsp;:&nbsp;P</code>&nbsp; is similarly split.
</DD>
</DL>

These splittings are effected by clicking on the appropriately labeled buttons.&nbsp;  (<code>\/</code> and <code>\E</code>
splittings can be combined hierarchically.)&nbsp;
</P>

<p>
The proof is generated by clicking a button that is either labeled by <font size=+1><b>P</b></font> or (for an <code>/\</code>
decomposition) by a button with <font size=+1><b>P</b></font> next to it.&nbsp;
</p>

<p>
Instead of generating an <code>/\</code> or <code>\/</code> decomposition, the button labeled <font size=+1><b>P</b></font>
at the top of the command's dialog window generates a proof consisting of only a 
  &nbsp;<code>SUFFICES&nbsp;ASSUME&nbsp;...&nbsp;PROVE</code>&nbsp;
step constructed by splitting the original obligation and a &nbsp;<code>QED</code>&nbsp; step.

For example, starting from the obligation &nbsp;<code>P&nbsp;=>&nbsp;\E&nbsp;x&nbsp;\in&nbsp;S&nbsp;:&nbsp;Q</code>, performing
a &nbsp;<code>=></code>&nbsp; split followed by a &nbsp;<code>\A</code> split on the goal and then clicking on this
button produces a proof like this:
<pre>
   <3> SUFFICES ASSUME P, NEW x \in S
                PROVE  Q
     OBVIOUS
   <3> QED
</pre>
</p>

<p>  The obligation to which you apply the Decompose Proof command must have either no proof or else a 
leaf proof, such as a <code>BY</code> proof or the proof <code>OBVIOUS</code>).&nbsp;  If it has a leaf proof, that proof
is made the proof of each of the simpler obligations into which the proof is decomposed.&nbsp;  For a proof generated by
the top  <font size=+1><b>P</b></font> button (which does no decomposing), the obligation's leaf proof becomes the 
<code>QED</code> step's proof.
</p>

<h2>Options</h2>

There are two options that you can select.

<DL> <DT> <b>Use <code>SUFFICES</code></b> </DT>
<DD>Splitting the goal or a <code>\E</code> assumption generates new assumptions.&nbsp;
Selecting this option causes those assumptions to be asserted by a 
  &nbsp;<code>SUFFICES&nbsp;ASSUME/PROVE</code>&nbsp;
step.&nbsp;  Otherwise, these assumption are added to each of the decomposed proof steps.&nbsp;
</DD>

<BR> </BR>
 <DT><b>Use <code>CASE</code></b>
 </DT>
<DD>This selection determines whether, in the created substeps of the proof of an <code>\/</code>
decomposition, <code>CASE</code> steps should be used instead of <code>ASSUME/PROVE</code>
steps when possible.&nbsp;  One reason not to choose this option is that
the Decompose Command does not decompose <code>CASE</code> steps.
</DD>

<!-- COMMENT
<BR> </BR>
 <DT><b>Use subexpression names</b>
 </DT>
<DD>The command looks at the expansions of definitions when looking for splittings and decompositions.&nbsp;
For example, you can do an <code>/\</code> decomposition if the goal is    &nbsp;<code>P</code>&nbsp;, where
&nbsp;<code>P</code>&nbsp; is defined to equal a conjunction of formulas.&nbsp;  Normally, this decomposition
will produce steps that prove each of the conjuncts as they appear in the definition of &nbsp;<code>P</code>&nbsp;.
However, if you select this option, the generated steps will contain the goals &nbsp;<code>P!1,&nbsp;P!2,&nbsp;...</code>&nbsp;.
</DD>
END COMMENT -->
</DL>

<h2>Limitations</h2>

The following are the known problems and limitations of the command.
<ul>

<li> The command will not expand definitions that come from a different module.
</li>

<BR></BR>

<li> Decomposing a proof step may require renaming of bound identifiers
to avoid name clashes.&nbsp; This renaming is not done for clashes with names
defined by <code>LET</code> definitions within the step.&nbsp; This can cause parsing
errors in the decomposed proof.

</li>
</ul>
<hr>
<a href = "reading.html">&uarr; Viewing and Editing Structured Proofs</a>
</hr>

</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/provider/SpecContentProvider.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.provider;

import java.util.Hashtable;
import java.util.Vector;

import org.eclipse.core.resources.IResource;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * Content provider listing the specifications
 */
public class SpecContentProvider implements ITreeContentProvider {
	private static final Object[] EMPTY_ARRAY = new Object[0];
	
	private final Hashtable<Module, Group> reverseLookup;
	
	public SpecContentProvider() {
		reverseLookup = new Hashtable<Module, Group>();
	}

	/**
	 * Retrieves the children
	 */
	public Object[] getChildren(Object parentElement) {
		if (parentElement instanceof WorkspaceSpecManager) {
			return ((WorkspaceSpecManager) parentElement).getRecentlyOpened();
		} else if (parentElement instanceof Spec) {
			final Spec spec = (Spec) parentElement;
			if (Activator.getSpecManager().isSpecLoaded(spec)) {
				final Module[] constructModules = constructModules(spec);
				final Group group = new Group(spec, constructModules);
				for (int i = 0; i < constructModules.length; i++) {
					final Module module = constructModules[i];
					reverseLookup.put(module, group);
				}
				return new Group[] {group};
			}
			return EMPTY_ARRAY;
		} else if (parentElement instanceof Group) {
			return ((Group) parentElement).getModules();
		} else {
			return EMPTY_ARRAY;
		}
	}

	public Object getParent(Object element) {
		if (element instanceof Spec) {
			return Activator.getSpecManager(); // ResourcesPlugin.getWorkspace().getRoot();
		} else if (element instanceof Group) {
			return Activator.getSpecManager().isSpecLoaded(((Group) element).getSpec());
		} else if (element instanceof Module) {
			return reverseLookup.get(element);
		}
		return null;
	}

	public boolean hasChildren(Object element) {
		// A Spec only has children (visually indicated by a triangle in the
		// Spec Explorer) if it is open.
		if (element instanceof Spec) {
			return Activator.getSpecManager().isSpecLoaded((Spec) element);
		} else if (element instanceof Group) {
			Group group = (Group) element;
			if (Activator.getSpecManager().isSpecLoaded(group.getSpec())) {
				return group.getModules().length > 0;
			}
		}
		return (element instanceof WorkspaceSpecManager
		/* || element instanceof Spec */);
	}

	public Object[] getElements(Object inputElement) {
		return getChildren(inputElement);
	}

	public void dispose() {
		reverseLookup.clear();
	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		// no-op
	}

	protected Module[] constructModules(Spec spec) {
		final Vector<Module> modules = new Vector<Module>();
		final IResource[] moduleResources = spec.getModuleResources();
		for (int i = 0; i < moduleResources.length; i++) {
			// skip non-modules
			if (!ResourceHelper.isModule(moduleResources[i])) {
				continue;
			}
			final Module module = new Module(moduleResources[i]);
			modules.add(module);
		}
		return (Module[]) modules.toArray(new Module[modules.size()]);
	}
	
	public static class Group implements IGroup {
		private final Module[] modules;
		private final Spec spec;

		public Group(Spec spec, Module[] modules) {
			this.spec = spec;
			this.modules = modules;
		}
		/**
		 * @return the spec
		 */
		public Spec getSpec() {
			return spec;
		}
		/**
		 * @return the modules
		 */
		public Module[] getModules() {
			return modules;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#toString()
		 */
		public String toString() {
			return "modules";
		}
		
		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((spec == null) ? 0 : spec.hashCode());
			return result;
		}
		
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Group other = (Group) obj;
			if (spec == null) {
				if (other.spec != null)
					return false;
			} else if (!spec.equals(other.spec))
				return false;
			return true;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/ACoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME>
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class ACoverageTest extends AbstractCoverageTest {

    public ACoverageTest () {
        super("A");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "2"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "7", "3", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
		assertCoverage("<Init line 7, col 1 to line 7, col 4 of module A>: 1:1\n" + 
				"  line 7, col 12 to line 7, col 16 of module A: 1\n" + 
				"  line 8, col 12 to line 8, col 21 of module A: 1\n" + 
				"  |line 5, col 11 to line 5, col 49 of module A: 1\n" + 
				"  ||line 5, col 31 to line 5, col 49 of module A: 131072\n" + 
				"  ||line 5, col 20 to line 5, col 27 of module A: 1\n" + // This used to be a level deeper and value 131072
				"  |line 8, col 16 to line 8, col 20 of module A: 1\n" + 
				"<A line 13, col 1 to line 13, col 4 of module A>: 1:3\n" + 
				"  line 13, col 9 to line 13, col 19 of module A: 3\n" + 
				"  |line 13, col 14 to line 13, col 19 of module A: 3\n" + 
				"  ||line 11, col 11 to line 11, col 61 of module A: 3\n" + 
				"  |||line 11, col 31 to line 11, col 61 of module A: 30\n" + 
				"  ||||line 11, col 57 to line 11, col 61 of module A: 162\n" + 
				"  ||||line 11, col 41 to line 11, col 52 of module A: 30\n" + 
				"  |||line 11, col 24 to line 11, col 27 of module A: 3\n" + 
				"  ||line 13, col 18 to line 13, col 18 of module A: 3\n" + 
				"<B line 15, col 1 to line 15, col 4 of module A>: 1:3\n" + 
				"  line 15, col 9 to line 15, col 19 of module A: 3\n" + 
				"  |line 15, col 14 to line 15, col 19 of module A: 3\n" + 
				"  ||line 11, col 11 to line 11, col 61 of module A: 3\n" + 
				"  |||line 11, col 31 to line 11, col 61 of module A: 9\n" + 
				"  ||||line 11, col 57 to line 11, col 61 of module A: 15\n" + 
				"  ||||line 11, col 41 to line 11, col 52 of module A: 9\n" + 
				"  |||line 11, col 24 to line 11, col 27 of module A: 3\n" + 
				"  ||line 15, col 18 to line 15, col 18 of module A: 3");
    }
}


<|start_filename|>general/tests/test.cmd<|end_filename|>
testlist.cmd > out.txt 2>&1

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/LeafProofNode.java<|end_filename|>
// Copyright (c) 2007 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.xml.SymbolContext;

/***************************************************************************
* This class represents a leaf proof.  It is of kind LeafProffKind         *
***************************************************************************/
public class LeafProofNode extends ProofNode {

  /*************************************************************************
  * The fields.                                                            *
  *                                                                        *
  * A leaf proof has the syntax                                            *
  *                                                                        *
  *   [PROOF]   BY [ONLY] [facts] [DEF[S] defs].                           *
  *           | OBVIOUS                                                    *
  *           | OMITTED                                                    *
  *                                                                        *
  * The following two fields are the semantic nodes for the facts and      *
  * defs.                                                                  *
  *************************************************************************/
  LevelNode[]  facts = null ;
    /***********************************************************************
    * For each i, facts[i] will be either an ExprNode, a ModuleNode, or    *
    * an OpDefNode of type ModuleInstanceKind (with no parameters).  A     *
    * proof management tool will probably put restrictions on the class    *
    * of expressions that can be used as facts.                            *
    ***********************************************************************/
  SymbolNode[] defs  = null ;
    /***********************************************************************
    * For each i, defs[i] should be a UserDefinedOpDefKind or              *
    * ModuleInstanceKind OpDefNode or a ThmOrAssumpDefNode                 *
    ***********************************************************************/
  boolean omitted ;
    /***********************************************************************
    * True iff this is a "[PROOF] OMITTED" statement.  In this case, the   *
    * facts and defs field will be null.  But that is also the case for    *
    * an "OBVIOUS" proof.                                                  *
    ***********************************************************************/
  boolean isOnly ;
    /***********************************************************************
    * True iff this is a "BY ONLY" proof.                                  *
    ***********************************************************************/

  /*************************************************************************
  * The constructor.                                                       *
  *************************************************************************/
  public LeafProofNode(TreeNode stn, LevelNode[] theFacts,
                   SymbolNode[] theDefs, boolean omit, boolean only) {
    super(LeafProofKind, stn) ;
    this.facts   = theFacts ;
    this.defs    = theDefs ;
    this.omitted = omit ;
    this.isOnly = only ;
   } ;


  /*************************************************************************
  * Methods that return the values of the fields.                          *
  *************************************************************************/
  public LevelNode[]  getFacts() {return facts ; } ;
  public SymbolNode[] getDefs() {return defs ;} ;
  public boolean getOmitted() {return omitted ;} ;
  public boolean getOnlyFlag() {return isOnly ;} ;

  @Override
  public boolean levelCheck(int iter) {
    /***********************************************************************
    * Level checking is performed by level-checking the facts.  Since the  *
    * defs should be defined operators, they have already been level       *
    * checked.                                                             *
    ***********************************************************************/
    if (this.levelChecked >= iter) return this.levelCorrect;
    return this.levelCheckSubnodes(iter, facts) ;
   }

  /*
   * The children are the facts.
   * @see tla2sany.semantic.SemanticNode#getChildren()
   */
  @Override
  public SemanticNode[] getChildren() {
      if (this.facts == null || this.facts.length == 0) {
          return null;
      }
      SemanticNode[] res = new SemanticNode[this.facts.length];
      for (int i = 0; i < facts.length; i++) {
          res[i] = facts[i];
      }
      return res;
   }

  @Override
  public void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    for (int  i = 0; i < facts.length; i++) {
      facts[i].walkGraph(semNodesTable, visitor);
      } ;
    /***********************************************************************
    * Note: there's no need to walk the defs array because all the nodes   *
    * on it are walked from the nodes under which they appear.             *
    ***********************************************************************/
      visitor.postVisit(this);
   }

  @Override
  public String toString(int depth) {
    if (depth <= 0) return "";
    String ret = "\n*LeafProofNode:\n"
                  + super.toString(depth)
                  + Strings.indent(2, "\nfacts:") ;
    for (int i = 0 ; i < this.facts.length; i++) {
        ret += Strings.indent(4, this.facts[i].toString(depth-1)) ;
      } ;
    ret += Strings.indent(2, "\ndefs:") ;
    for (int i = 0 ; i < this.defs.length; i++) {
        ret += Strings.indent(4, this.defs[i].toString(depth-1)) ;
      } ;
    ret += Strings.indent(2, "\nomitted: " + this.omitted)
            + Strings.indent(2, "\nonlyFlag: " + this.isOnly);
    return ret;
   }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
    Element e;

    if (getOmitted()) {
      e = doc.createElement("omitted");
    }
    else if (getFacts().length == 0 && getDefs().length == 0) {
      e = doc.createElement("obvious");
    }
    else {
      //SemanticNode.SymbolContext context = new SemanticNode.SymbolContext(context2);
      e = doc.createElement("by");

      Element factse = doc.createElement("facts");
      Element definitions = doc.createElement("defs");

      for (int i=0; i<facts.length; i++) factse.appendChild(facts[i].export(doc,context));
      for (int i=0; i<defs.length; i++) definitions.appendChild(defs[i].export(doc,context));

      e.appendChild(factse);
      e.appendChild(definitions);
      if(getOnlyFlag()) e.appendChild(doc.createElement("only"));
      // at the end, we append the context of the symbols used in this node
      //e.appendChild(context.getContextElement(doc));
    }

    return e;
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/TeX.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS TeX                                                                *
*                                                                          *
* THINGS TO DO:                                                            *
*  - Change Parameters.latexwidth to be a float.  This requires            *
*    rewriting a bunch of code.  (Should do Parameters.latexheight as      *
*    well.)                                                                *
*                                                                          *
*  - Fix the following bug: the program always reports "More tla           *
*    environments than the last time file run through LaTeX" if            *
*    there is a tla environment after the \end{document}, though           *
*    it hardly seems worth it.                                             *
*                                                                          *
*  - Bug: TLATeX has an unrecoverable error "I/O error: null" if           *
*    it encounters a tla environment containing only a single blank        *
*    line.
*                                                                          *
* Modified on 19 Sep 2007 for TLA+2.  See the comments in TLA.java to see  *
* how.  However, the formatting of proof steps in a tla environment isn't  *
* working right.  If the formula for a step is continued on one or more    *
* subsequent lines, those lines are indented too much.                     *
*                                                                          *
* The `main' method is the TLATeX.TeX program.  It calls other methods to  *
* do the work as follows.                                                  *
*                                                                          *
* BuiltInSymbols.Initialize                                                *
*    Initializes tables containing information about TLA's built-in        *
*    symbols.                                                              *
*                                                                          *
* FormatComments.Initialize                                                *
*    Initializes tables used for formatting comments.  One table           *
*    contains common English words, which are read from the file           *
*    Parameters.WordFile                                                   *
*                                                                          *
* ReadLogFile                                                              *
*    Reads the log file created the last time LaTeX was run on the         *
*    input file.  It returns an array of floats, representing the          *
*    values in points of the \linewidth in effect at each tla              *
*    environment.                                                          *
*                                                                          *
* It next copies the input file to the new version, through the            *
* \begin{document}, and saves it as a vector of lines in the variable      *
* preamble.  It then copies the rest of the file to the new version.       *
* However, after it copies a tla environment, the program skips an         *
* immediately following tlatex environment if one exists.  It then writes  *
* out a new tlatex environment by calling the following sequence of        *
* methods.  It continues doing this until it finds an \end{document}.      *
*                                                                          *
*  TokenizeSpec.Tokenize                                                   *
*    Reads the input file and turns it into an array of array of Token     *
*    objects `spec', where spec[i][j] is item j on line i.  Each line of   *
*    a comment is a single token.  (In the Java program, all numbering     *
*    starts from 0.  The error messages translate into the numbering       *
*    system used by most humans, in which the first object is object       *
*    number 1.)                                                            *
*                                                                          *
*  CommentToken.ProcessComments                                            *
*    Determines which comment tokens are part of a single multi-line       *
*    comment, and indicates this by setting the subtype field of           *
*    comment tokens.                                                       *
*                                                                          *
*  FindAlignments.FindAlignment                                            *
*    Determines what tokens should be aligned with what other tokens.      *
*    This is indicated by setting the tokens' belowAlign and aboveAlign    *
*    fields.  It also sets the isAlignmentPoint flag for each token        *
*    whose left-hand edge is a point used by some other token for its      *
*    alignment.                                                            *
*                                                                          *
*  LaTeXOutput.WriteAlignmentFile                                          *
*    Writes the -alignOut file.                                            *
*                                                                          *
*  LaTeXOutput.RunLaTeX                                                    *
*    Runs LaTeX on the -alignOut file.  This aux file produced by LaTeX    *
*    contains the information about the typeset widths of text that        *
*    TLATeX needs to perform the alignment.                                *
*                                                                          *
*  LaTeXOutput.SetDimensions                                               *
*    Reads the LaTeX aux file and determines how much space it needs to    *
*    add for alignment, setting the information in the tokens'             *
*    distFromMargin and preSpace fields.                                   *
*                                                                          *
*  LaTeXOutput.WriteTLATeXEnvironment                                      *
*    Actually writes the tlatex environment.                               *
*                                                                          *
* When it encounters an \end{document}, the program stops looking for tla  *
* environments and just copies the rest of the input to the new file.      *
* Finally, it renames the files to give the input the extension .old, and  *
* the new version the extension .tex.                                      *
***************************************************************************/
package tla2tex ;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Vector;

import util.ToolIO;

class TeX
 {                                            // BEGIN class

  static final String lastModified = 
    /***********************************************************************
    * The following string is inserted by an Emacs macro when a new        *
    * version is saved.                                                    *
    ***********************************************************************/
    "last modified on Wed 12 Apr 2013 at 16:08:49 PST by lamport";

  static String modDate = lastModified.substring(21, 33) ;
    /***********************************************************************
    * The modification date.                                               *
    ***********************************************************************/

  static String version = 
    "tla2tex.TeX Version 1.0 created " + modDate ;

    public static void main(String[] args) 
    { /*********************************************************************
      * Get the command-line arguments.                                    *
      *********************************************************************/
      long startTime = Debug.now();
      ToolIO.out.println(version) ;
      GetArguments(args);

      /*********************************************************************
      * Initialize class BuiltInSymbols.                                   *
      *********************************************************************/
      Starting("BuiltInSymbols.Initialize") ;
      BuiltInSymbols.Initialize();
      Finished("BuiltInSymbols.Initialize") ;

      /*********************************************************************
      * Initialize class FormatComments.                                   *
      *********************************************************************/
      Starting("FormatComments.Initialize");
      FormatComments.Initialize();
      Finished("FormatComments.Initialize");

      /*********************************************************************
      * Obtain the linewidths from the log file.                           *
      *********************************************************************/
      float[] lineWidths = ReadLogFile();

      /*********************************************************************
      * Open the input and output files.                                   *
      *********************************************************************/
      BufferedReader infile = null ;
      try 
       { infile = new BufferedReader(new FileReader(Parameters.TLAInputFile));
       }
      catch (Exception e)
       { Debug.ReportError(
          "Can't open input file " + Parameters.TLAInputFile);
       }

      OutputFileWriter outfile = null ;
      try      
       { outfile = new OutputFileWriter(Parameters.LaTeXOutputFile + ".new");
       }
      catch (Exception e)
       { Debug.ReportError(
          "Can't open output file " + Parameters.LaTeXOutputFile + ".new");
       }

      int lineNum = 0 ;
        /*******************************************************************
        * The number of lines read from the input file.                    *
        *******************************************************************/
        
      /*********************************************************************
      * Copy the preamble (everything through the line containing          *
      * \begin{document}, and save everything except the                   *
      * \begin{document} in the Vector preamble.                           *
      *********************************************************************/
      Vector preamble = new Vector(200);
      String line = "" ;
      try
       { line = infile.readLine();
         while (   (line != null)
                && (line.indexOf("\\begin{document}") == -1))
          { lineNum = lineNum + 1 ;
            outfile.putLine(line) ;
            preamble.addElement(line);
            line = infile.readLine();
          }
       }
      catch (Exception e)
       { Debug.ReportError("I/O error: " + e.getMessage());
       }
      if (line == null)
       { Debug.ReportError("Input file has no \\begin{document}"); }
      lineNum = lineNum + 1 ;

      /*********************************************************************
      * Write out the \begin{document} line                                *
      *********************************************************************/
      outfile.putLine(line) ;


      /*********************************************************************
      * If there's something before the \begin{document} on the line, add  *
      * it to preamble.                                                    *
      *********************************************************************/
      int begindocPos = line.indexOf("\\begin{document}") ;
      if (begindocPos != 0)
       { preamble.addElement(line.substring(0, begindocPos));
       }
        
      /*********************************************************************
      * Process the body of the input file.                                *
      *********************************************************************/
      try
       { line = infile.readLine();
         int envNum = 0 ;
           /****************************************************************
           * The number of tla, pcal, or ppcal environments processed so   *
           * far.                                                          *
           ****************************************************************/

         while (line != null)
          {                                   // BEGIN while (line != null)
           lineNum = lineNum + 1 ;
           outfile.putLine(line) ;
           
           /*
            * If this line begins a tla, pcal, or ppcal environment, set
            * mode to the correct mode for calling TokenizeSpec and set
            * envName to "tla", "pcal", or "ppcal"
            */
           int mode = -1 ;
           String envName = "" ;
           if (line.indexOf("\\begin{tla}") != -1) {
               mode = TokenizeSpec.TLA ;
               envName = "tla" ;
           }
           else if (line.indexOf("\\begin{pcal}") != -1) {
               mode = TokenizeSpec.PLUSCAL ;
               envName = "pcal" ;
           }
           else if (line.indexOf("\\begin{ppcal}") != -1) {
               mode = TokenizeSpec.P_PLUSCAL ;
               envName = "ppcal" ;
           }       
           if (mode != -1)
            {        // BEGIN then OF if (mode != -1)
             /**************************************************************
             * Process the tla/pcal/ppcal environment and set line to the  *
             * line immediately after it or the following tlatex           *
             * environment.                                                *
             *                                                             *
             * Start by copying the environment and also putting it in     *
             * the vector tla.                                             *
             *                                                             *
             * Note: Nothing on the same line may follow a \begin{tla} or  *
             * precede an \end{tla}, and similarly for pcal and ppcal.     *
             **************************************************************/
             Starting(envName + " environment number " + (envNum + 1) 
                         + " on line " + (lineNum + 1));
             Vector tla = new Vector(100);
             int tlaLineNum = lineNum ;
             line = infile.readLine();
             while (   (line != null) 
                    && (line.indexOf("\\end{" + envName + "}") == -1))
              { lineNum = lineNum + 1 ;
                outfile.putLine(line) ;
                tla.addElement(line);
                line = infile.readLine();
              }

             if (line == null)
              { Debug.ReportError( "Unmatched \\begin{" + envName + "} on line " 
                                    + (tlaLineNum + 1)); 
              }
             lineNum = lineNum + 1 ;

             /**************************************************************
             * Write out the \end{tla} line                                *
             **************************************************************/
             outfile.putLine(line) ;

             /**************************************************************
             * Read next line, reporting an error if there is none.        *
             **************************************************************/
             line = infile.readLine();
             if (line == null)
              { Debug.ReportError("Missing \\end{document}"); }

             /**************************************************************
             * If next line begins a tlatex environment, then skip over    *
             * that environment and read the line beyond it.               *
             **************************************************************/
             if (line.indexOf("\\begin{tlatex}") != -1)
              { lineNum = lineNum + 1 ;
                line = infile.readLine();
                while (   (line != null) 
                       && (line.indexOf("\\end{tlatex}") == -1))
                 { lineNum = lineNum + 1 ;
                   line = infile.readLine();
                 }
                if (line == null)
                 { Debug.ReportError( "Unmatched \\begin{tlatex} on line " 
                                    + (tlaLineNum + tla.size() + 2)); 
                 }
                lineNum = lineNum + 1 ;
                line = infile.readLine();
                
              }     

            /***************************************************************
            * Tokenize the spec.                                           *
            ***************************************************************/
            CharReader tlaRdr = new VectorCharReader(tla, tlaLineNum);
            Token[][] spec = TokenizeSpec.Tokenize(tlaRdr, mode);

            /***************************************************************
            * Finish the tokenization by converting sequences of tokens    *
            * that represent proof-step numbers to PF_STEP tokens.         *
            ***************************************************************/
            Token.FindPfStepTokens(spec) ;
            
            /*********************************************************************
            * Really finish the tokenization by parentheses and braces that are  *
            * part of the PlusCal C-syntax to tokens that are printed            *
            * appropriately.                                                     *
            *********************************************************************/
            TokenizeSpec.FixPlusCal(spec, true) ;
             
            /***************************************************************
            * Process the comment tokens.                                  *
            ***************************************************************/
            CommentToken.ProcessComments(spec);

            /***************************************************************
            * Add the alignment pointers to spec.                          *
            ***************************************************************/
            FindAlignments.FindAlignments(spec);      
            // Debug.print2DArray(spec, "spec"); 

            /***************************************************************
            * Find the linewidth for this tla/pcal/ppcal environment.      *
            ***************************************************************/
            float linewidth = -1 ;
            if (envNum < lineWidths.length)
             { linewidth = lineWidths[envNum];
             }
            else
             { if (envNum == lineWidths.length)
                 { ToolIO.out.println(
                      "More tla/pcal/ppcal environments than the last time file\n"
                    + "    run through LaTeX");
                 }
             }

            /***************************************************************
            * Set the LaTeXtextwidth parameter.  This parameter should     *
            * probably be changed to a float, but hopefully doing things   *
            * to the nearest point is good enough.                         *
            ***************************************************************/
            Parameters.LaTeXtextwidth = (int) linewidth;

            /***************************************************************
            * Write the alignment file, run it through LaTeX, and set the  *
            * dimension information in spec based on the log file          *
            * produced by LaTeX.                                           *
            ***************************************************************/
            LaTeXOutput.WriteTeXAlignmentFile(spec, preamble, linewidth);
            Starting("to LaTeX alignment file.");
            LaTeXOutput.RunLaTeX(Parameters.LaTeXAlignmentFile);
            Finished("LaTeXing alignment file");
            LaTeXOutput.SetDimensions(spec) ;
            // Debug.print2DArray(spec, "");

            /***************************************************************
            * Write the tlatex environment.                                *
            ***************************************************************/
            LaTeXOutput.WriteTLATeXEnvironment(spec, outfile) ;
            Finished("tla/pcal/ppcal environment number " + (envNum + 1));
            envNum = envNum + 1;
            }  // END then OF if (mode != -1)
           else
            {/**************************************************************
             * This line did not begin a tla, pcal, or ppcal environment.  *
             **************************************************************/
             line = infile.readLine();
            }
          }                                  // END while (line != null)
        if (envNum < lineWidths.length)
           { ToolIO.out.println(
               "Fewer tla/pcal/ppcal environments than the last time file\n"
                    + "    run through LaTeX");
           };
        /*******************************************************************
        * Close and rename the files.                                      *
        *******************************************************************/
        infile.close() ;
        outfile.close() ;
        File iFile = new File(Parameters.LaTeXOutputFile + ".tex") ;
        File oFile = new File(Parameters.LaTeXOutputFile + ".new") ;

        /*******************************************************************
        * Delete the old version of the .old file, if there is one.        *
        *******************************************************************/
        (new File(Parameters.LaTeXOutputFile + ".old")).delete();

        if (   !iFile.renameTo(new File(Parameters.LaTeXOutputFile + ".old"))
            || !oFile.renameTo(new File(Parameters.LaTeXOutputFile + ".tex")))
         { Debug.ReportError("Error while renaming files"); }
       }
      catch (Exception e)
       { Debug.ReportError("I/O error: " + e.getMessage());
       }
      
      Debug.printElapsedTime(startTime, "Total execution time:");
    }  // END main


  private static void GetArguments(String[] args)
     /**********************************************************************
     * Get the command-line arguments and set the appropriate parameters.  *
     **********************************************************************/
     { /********************************************************************
       * The following flags are set if the indicated option is present.   *
       ********************************************************************/
       boolean outOption = false;
       boolean alignOutOption = false;
       boolean psOption = false ;
       boolean nopsOption = false ;
       int nextArg = 0 ;
         /******************************************************************
         * The number of the argument being processed.                     *
         ******************************************************************/
       int maxArg = args.length - 1;
         /******************************************************************
         * The number of the final argument, which is the input file name. *
         ******************************************************************/
       if (maxArg < 0)
        { CommandLineError("No arguments specified");
        } ;

       if (   (args[maxArg].length() != 0)
           && (args[maxArg].charAt(0) == '-'))
         /******************************************************************
         * If the last argument begins with "-", then no file has been     *
         * specified.  This should mean that the user has typed "-help"    *
         * or "-info", but it could be another mistake.                    *
         ******************************************************************/
         { maxArg = maxArg + 1 ;
         } ;

       while (nextArg < maxArg)
        /*******************************************************************
        * Process all the arguments, except for the last (unless it's a    *
        * "-" argument).                                                   *
        *******************************************************************/
        { String option = args[nextArg] ;
          if (option.equals("-help"))
            { OutputMessageFile(Parameters.TeXHelpFile) ;
              System.exit(0);
            }
          else if (option.equals("-info"))
            { OutputMessageFile(Parameters.TeXInfoFile) ;
              System.exit(0);
            }
// We're not going to run the output through TeX or dvips.  The
// user can do that.
//          else if (option.equals("-ps"))
//            { psOption = true ; 
//            }
//          else if (option.equals("-nops"))
//            { nopsOption = true ; 
//            }
//          else if (option.equals("-psCommand"))
//            { nextArg = nextArg + 1;
//              if (nextArg >= args.length) 
//                {CommandLineError("No input file specified") ;} ;
//              Parameters.PSCommand = args[nextArg];
//            }
          else if (option.equals("-latexCommand"))
            { nextArg = nextArg + 1;
              if (nextArg >= args.length) 
                {CommandLineError("No input file specified") ;} ;
              Parameters.LaTeXCommand = args[nextArg];
            }
          else if (option.equals("-out"))
            { /*************************************************************
              * The LaTeX output file.                                     *
              *************************************************************/
              outOption = true ;
              nextArg = nextArg + 1;
              if (nextArg >= args.length) 
                {CommandLineError("No input file specified") ;} ;
              Parameters.LaTeXOutputFile = RemoveExtension(args[nextArg]);
              if (HasPathPrefix(Parameters.LaTeXOutputFile))
               { CommandLineError(
                    "-out file contains a path specifier.\n"
                  + "It must be a file in the current directory.");
               };
            }
          else if (option.equals("-alignOut"))
            { /*************************************************************
              * The alignment file.  The default is "tlatex".              *
              *************************************************************/
              alignOutOption = true ;
              nextArg = nextArg + 1;
              if (nextArg >= args.length) 
                {CommandLineError("No input file specified") ;} ;
              Parameters.LaTeXAlignmentFile = RemoveExtension(args[nextArg]);
              if (HasPathPrefix(Parameters.LaTeXAlignmentFile))
               { CommandLineError(
                    "-alignOut file contains a path specifier.\n"
                  + "It must be a file in the current directory.") ;
               };
            } 
          else if (option.equals("-debug"))
            { Parameters.Debug = true;
            }
// Should probably change the way the -number option is implemented
// so numbering is controlled by a LaTeX command, so the user 
// of tlatex.TeX can get lines numbered.
//
//          else if (option.equals("-number"))
//            { Parameters.PrintLineNumbers = true;
//            }
          else 
            { CommandLineError("Unknown option: " + option);
            } ;
          nextArg = nextArg + 1;
        }                      // END while (nextArg < maxArg)

       if (nextArg > maxArg)
         /******************************************************************
         * The last option took an argument that was the last              *
         * command-line argument.                                          *
         ******************************************************************/
         { CommandLineError("No input file specified") ;
         } ;

       /********************************************************************
       * Set Parameters.TLAInputFile to the last argument, adding ".tex"   *
       * if it has no extension already.                                   *
       ********************************************************************/
       if (args[maxArg].indexOf(".") == -1)
         { Parameters.TLAInputFile = args[maxArg] + ".tex";}
       else       
         { Parameters.TLAInputFile = args[maxArg];};

       /********************************************************************
       * Set default options.                                              *
       ********************************************************************/
       if (! outOption)
         { Parameters.LaTeXOutputFile = 
             RemoveExtension(RemovePathPrefix(Parameters.TLAInputFile));
           if (HasPathPrefix(Parameters.TLAInputFile))
             ToolIO.out.println(
              "Warning: Output file being written to a different directory\n"
            + "         than input file.");
         } ;
       if (! alignOutOption)
         { Parameters.LaTeXAlignmentFile = "tlatex" ;
         } ;

       /********************************************************************
       * Produce Postscript output if either                               *
       *   (i) -ps, or                                                     *
       *  (ii) -shade but not -nops                                        *
       * was specified.                                                    *
       ********************************************************************/
       if (   psOption 
           || (Parameters.CommentShading && ! nopsOption))

        { Parameters.PSOutput = true;
        }
     }   

    private static int GetIntArg(String str, String option)
      /*********************************************************************
      * Returns str interpreted as an integer, or generates an error       *
      * message for the indicated option.                                  *
      *********************************************************************/
      {int val = 0; 
       try { val = Integer.parseInt(str) ; }
       catch (NumberFormatException e)
        { CommandLineError(option + " option must specify an integer value");
        };
       return val ;
      }

    private static String RemoveExtension(String fileName)
      /*********************************************************************
      * The string fileName with any extensions removed.                   *
      *********************************************************************/
      { if (fileName.indexOf(".") == -1)
          { return fileName ;}
        else
          { return fileName.substring(0, fileName.indexOf(".")); }
      }      

   private static String RemovePathPrefix(String str)
    /***********************************************************************
    * Returns str with all any leading path specifiers removed.  For       *
    * example, calling it on "c:frob\bar\name.txt" or "~/frob/bar/name.txt"  *
    * will return "name.txt".                                              *
    ***********************************************************************/
    { String result = str;
      if (result.indexOf(":") != -1)
        { result = result.substring(result.lastIndexOf(":")+1) ; } ;
      if (result.indexOf("/") != -1)
        { result = result.substring(result.lastIndexOf("/")+1) ; } ;
      if (result.indexOf("\\") != -1)
        { result = result.substring(result.lastIndexOf("\\")+1) ; } ;
      return result;
    }    

   private static boolean HasPathPrefix(String str)
    /***********************************************************************
    * True iff str has a leading path specifier--that is, if it contains   *
    * a ":", "/" or "\".                                                   *
    ***********************************************************************/
    { return    (str.indexOf(":") != -1)
             || (str.indexOf("/") != -1)
             || (str.indexOf("\\") != -1) ;
    }    

    private static void CommandLineError(String msg)
      /*********************************************************************
      * Announce a command line error with the string indicating the       *
      * explanation, write the help message, and halt.                     *
      *********************************************************************/
      { ToolIO.out.println("TLATeX command-line error: " + msg + ".");
        ToolIO.out.println("Use -help option for more information.");
        // OutputMessageFile(Parameters.HelpFile) ;
        throw new TLA2TexException("TLATeX command-line error: " + msg + "." + "Use -help option for more information.");
      }

    private static void OutputMessageFile(String fileName)
     /**********************************************************************
     * Write the resource file named fileName to stdout.                   *
     **********************************************************************/
     { ResourceFileReader input = new ResourceFileReader(fileName) ;
       String line = input.getLine();
       while (line != null)
         { ToolIO.out.println(line) ;
           line = input.getLine() ;
         } ;
      input.close();
     } ;

    private static long start = Debug.now() ;

    /***********************************************************************
    * Starting / Finished used to print debugging information.            *
    ***********************************************************************/
    private static void Starting(String name)
     { if (Parameters.Debug)
         { start = Debug.now() ;
           ToolIO.out.println("Starting " + name);
         }
     }
    private static void Finished(String name)
     { if (Parameters.Debug)
         { Debug.printElapsedTime(start, name + " finished in");
         }
     }

/*
   private static void MakePSFile()
    { int errorCode = -77;
      String Command =     Parameters.PSCommand + " " 
                         + Parameters.LaTeXOutputFile + ".dvi" ; 
      try { Runtime rt = Runtime.getRuntime() ;
            Process proc = null ;
            proc = rt.exec(Command);
            errorCode = proc.waitFor();
          }
      catch (Exception e)
       { Debug.ReportError(
              "Trying to run the command `" + Command
            + "' produced the following error\n    " + e.getMessage());
       } ;
      if (errorCode < 0)
        { Debug.ReportError(
            "Running the command `" + Command 
          + "' produced an error");
        }
    }    
*/

   private static float[] ReadLogFile()
    /***********************************************************************
    * Reads the log file to obtain the linewidths for the tla              *
    * environments, and returns them as an array of floats.  Each          *
    * linewidth is written to the log file as a separate line such as      *
    *                   \%{123.456}                                        *
    ***********************************************************************/
    { BufferedReader logfile = null ;
      try 
       { logfile = new BufferedReader(
                    new FileReader(Parameters.LaTeXOutputFile + ".log"));
       }
      catch (Exception e)
       { ToolIO.out.println(
               "No file " + Parameters.LaTeXOutputFile + ".log");
         return new float[0];
       }
      Vector resultVec = new Vector(50);
        /*******************************************************************
        * A vector of the strings representing the linewidths.             *
        *******************************************************************/
        
      try
       {String inputLine = logfile.readLine();
        while (inputLine != null)
         { if (   (inputLine.length() > 2)
               && (inputLine.substring(0,3).equals("\\%{")))
            { int start = 3 ;
              int after = inputLine.indexOf("}",start)-2 ;
              resultVec.addElement(inputLine.substring(start, after));
            }; 
           inputLine = logfile.readLine();
         } 
       }
      catch (Exception e)
       { Debug.ReportError(
           "Error reading file " + Parameters.LaTeXOutputFile + ".log");
       }

      float[] result = new float[resultVec.size()];
      int i = 0;
      while (i < result.length)
       { result[i] = Misc.stringToFloat((String) resultVec.elementAt(i));
        i = i+1;
       }
      return result ;
    }
 } 




<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/ObjectStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:35 PST by lamport
//      modified on Tue Feb 13 18:38:24 PST 2001 by yuanyu

package tlc2.util;

import java.io.IOException;

public abstract class ObjectStack {
  /* A stack of objects. */

  protected int len = 0;            // the queue length

  /* Enqueues the state. It is not thread-safe. */
  public final void push(Object state) {
    this.enqueueInner(state);
    this.len++;
  }

  /**
   * Returns the first element in the queue. It returns null if the
   * queue is empty. It is not thread-safe.
   */
  public final Object pop() {
    if (this.len == 0) return null;
    Object state = this.dequeueInner();
    this.len--;
    return state;
  }

  /* Enqueues a state. Wake up any waiting thread. */
  public final synchronized void spush(Object state) {
    this.enqueueInner(state);
    this.len++;
  }

  /* Enqueues a list of states. Wake up any waiting thread. */
  public final synchronized void spush(Object states[]) {
    for (int i = 0; i < states.length; i++) {
      this.enqueueInner(states[i]);
    }
    this.len += states.length;
  }

  /* Return the first element in the queue.  Wait if empty. */
  public final synchronized Object spop() {
    Object state = this.dequeueInner();
    this.len--;
    return state;
  }

  /* Return (up to) the first cnt elements in the queue. Wait if empty. */  
  public final synchronized Object[] spop(int cnt) {
    Object states[] = new Object[cnt];
    int idx;
    for (idx = 0; idx < cnt && this.len > 0; idx++) {
      states[idx] = this.dequeueInner();
      this.len--;
    }
    if (idx == cnt) return states;
      
    Object res[] = new Object[idx];
    for (int i = 0; i < idx; i++) {
      res[i] = states[i];
    }
    return res;
  }

  /* This method returns the size of the state queue. */
  public final int size() { return this.len; }

  /* This method must be implemented in the subclass. */
  abstract void enqueueInner(Object state);

  /* This method must be implemented in the subclass. */
  abstract Object dequeueInner();

  /* Checkpoint. */
  public abstract void beginChkpt() throws IOException;
  public abstract void commitChkpt() throws IOException;
  public abstract void recover() throws IOException;
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/model/MCStateTest.java<|end_filename|>
package tlc2.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.List;

import org.junit.Test;

import util.TLAConstants;

public class MCStateTest {
	
	@Test
	public void testParseRoundTrips()
	{
		testParseRoundTrip(1, "Initial predicate", "", "x = 8", "y = 7");
		testParseRoundTrip(2, "YIncr", "line 8, col 10 to line 10, col 26 of module Bla", "x = 8", "y = 15");
		testParseRoundTrip(1, "Initial predicate", "", "x = 1", "y = FALSE");
		testParseRoundTrip(2, "Next", "line 7, col 9 to line 11, col 23 of module Alias", "x = 2", "y = TRUE");
		testParseRoundTrip(3, "Next", "line 7, col 9 to line 11, col 23 of module Alias", "x = 3", "y = FALSE");
		testParseRoundTrip(4, "Next", "line 7, col 9 to line 11, col 23 of module Alias", "x = 4", "y = TRUE");
	}
	
	@Test
	public void testSimpleRecordPrinter()
	{
		final MCState input = Utils.buildState(1, "Initial predicate", "", "x = 8", "y = 7");
		final String actual = input.asSimpleRecord();
		final String[] expectedTokens = new String[] {
				TLAConstants.L_SQUARE_BRACKET,
				"x", TLAConstants.RECORD_ARROW.trim(), "8",
				TLAConstants.COMMA,
				"y", TLAConstants.RECORD_ARROW.trim(), "7",
				TLAConstants.R_SQUARE_BRACKET
		};

		String remaining = actual.trim();
		for (String expectedToken : expectedTokens)
		{
			if (remaining.startsWith(expectedToken))
			{
				remaining = remaining.substring(expectedToken.length()).trim();
			}
			else
			{
				fail(String.format("Required token [%s]; received [%s]", expectedToken, remaining));
			}
		}
	}
	
	private static void testParseRoundTrip(
			int ordinal,
			String name,
			String location,
			String ...assignments)
	{
		final MCState expected = Utils.buildState(ordinal, name, location, assignments);
		final List<String> inputLines = Utils.toTlcOutputFormat(expected);
		final String input = String.join(TLAConstants.CR, inputLines);
		final MCState actual = MCState.parseState(input);
		MCStateTest.compareStates(expected, actual);
	}
	
	private static void compareStates(final MCState expected, final MCState actual)
	{
		assertEquals(expected.getName(), actual.getName());
		// The label is not trimmed in parsing; we are maintaining backward compatibility
		assertEquals(" " + expected.getLabel(), actual.getLabel());
		assertEquals(expected.isStuttering(), actual.isStuttering());
		assertEquals(expected.isBackToState(), actual.isBackToState());
		assertEquals(expected.getStateNumber(), actual.getStateNumber());
		
		MCVariable[] expectedVars = expected.getVariables();
		MCVariable[] actualVars = actual.getVariables();
		assertEquals(expectedVars.length, actualVars.length);
		for (int i = 0; i < expectedVars.length; i++)
		{
			assertEquals(expectedVars[i].getName(), actualVars[i].getName());
			assertEquals(expectedVars[i].getValueAsString(), actualVars[i].getValueAsString());
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/debug/StandaloneConstExpressionDebugger.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.debug;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

import org.eclipse.lsp4j.debug.OutputEventArguments;
import org.eclipse.lsp4j.debug.launch.DSPLauncher;

import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpDefNode;
import tlc2.TLCGlobals;
import tlc2.tool.impl.DebugTool;
import tlc2.tool.impl.Tool;
import tlc2.util.FP64;
import util.SimpleFilenameToStream;
import util.ToolIO;

/*
 * This debugger waits for a front-end to connect with a path to a spec.  This spec has to define a "debugMe" const-level operator that this debugger will evaluate and debug 
 */
public class StandaloneConstExpressionDebugger extends TLCDebugger {

	// THIS SCED HASN'T BEEN UPDATED TO REFLECT WHAT IS GOING ON IN TLCDEBUGGER AND,
	// THUS, PROBABLY DOESN'T WORK ANYMORE!!!
	
	public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
		new StandaloneConstExpressionDebugger();
	}

	public StandaloneConstExpressionDebugger() {
		super();
	}

	@Override
	public CompletableFuture<Void> launch(Map<String, Object> args) {
		LOGGER.finer("launch");

		final Path p = Paths.get((String) args.get("program"));
		final String specPath = p.getParent().toAbsolutePath().toString();
		final String specName = p.getFileName().toFile().toString();
		final String moduleName = specName.replaceFirst(".tla$", "");

		// IValue#hashCode calls below require fingerprints to be correctly initialized.
		// TODO: Investigate if this is still needed since Variable and its related
		// classes were changed to not trigger Value#hashCode as a side-effect.
		FP64.Init();

		// Listen to that SANY and TLC have to say, and what gets written with TLC!Print*.
		ToolIO.out = new PrintStream(ToolIO.out) {
			// See tlc2.debug.AttachingDebugger.AttachingDebugger(...).new PrintStream() {...}
			@Override
			public void println(String str) {
				((PrintStream) out).println(str);
				sendOutput(str + "\n");
			}

			@Override
			public void print(String str) {
				((PrintStream) out).print(str);
				sendOutput(str);
			}

			private void sendOutput(String str) {
				final OutputEventArguments oea = new OutputEventArguments();
				oea.setOutput(str);
				if (launcher != null) {
					launcher.getRemoteProxy().output(oea);
				}
			}
		};
		ToolIO.reset();
		
		final Tool tool = new DebugTool(moduleName, specName, new SimpleFilenameToStream(specPath), this);
		final ModuleNode module = tool.getSpecProcessor().getRootModule();
		// The spec has to have an "debugMe" operator.
		final OpDefNode valueNode = module.getOpDef("debugMe");

		// Kick off the evaluation of the expression in Tool in a different thread.
		Executors.newSingleThreadExecutor().submit(() -> {
			// Expanding values causes them to be un-lazied/enumerated, which we don't want
			// as a side-effect of the debugger.
			TLCGlobals.expand = false;
			
			tool.eval(valueNode.getBody());
		});

		return CompletableFuture.completedFuture(null);
	}

	@Override
	public TLCDebugger listen(int debugPort) {
		throw new UnsupportedOperationException("implement me!");
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/output/internal/BroadcastStreamListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.internal;

import java.util.Vector;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink;

/**
 * A listener broadcasting the stream appending to extensions 
 * @author <NAME>
 */
public class BroadcastStreamListener implements IStreamListener
{
    private IProcessOutputSink[] listeners = null;

    /**
     * 
     * @param model
     * @param kind, see constants {@link IProcessOutputSink#TYPE_DEBUG}, {@link IProcessOutputSink#TYPE_ERROR}, {@link IProcessOutputSink#TYPE_OUT}
     */
    public BroadcastStreamListener(Model model, int kind)
    {
        this.listeners = getRegisteredStreamManagers(model, kind);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.core.IStreamListener#streamAppended(java.lang.String, org.eclipse.debug.core.model.IStreamMonitor)
     */
    public synchronized void streamAppended(String text, IStreamMonitor monitor)
    {
        // broadcast the message
        for (int i = 0; i < listeners.length; i++)
        {
            if (listeners[i] != null)
            {
                try
                {
                    listeners[i].appendText(text);
                } catch (Exception e)
                {
                    TLCActivator.logError("Error broadcasting the message", e);
                }
            }
        }
    }

    /**
     * Called to inform us that it has been completed.
     */
    public synchronized void streamClosed()
    {
        // broadcast the message
        for (int i = 0; i < listeners.length; i++)
        {
            try
            {

                if (listeners[i] != null)
                {
                    listeners[i].processFinished();
                }
            } catch (Exception e)
            {
                TLCActivator.logError("Error broadcasting the stream closed event", e);
            }
        }
    }

    /**
     * Retrieves all registered listener managers
     * @return 
     */
    private IProcessOutputSink[] getRegisteredStreamManagers(Model model, int type)
    {
        IConfigurationElement[] decls = Platform.getExtensionRegistry().getConfigurationElementsFor(
                IProcessOutputSink.EXTENSION_ID);

        Vector<IProcessOutputSink> validExtensions = new Vector<IProcessOutputSink>();
        for (int i = 0; i < decls.length; i++)
        {
            try
            {
                IProcessOutputSink extension = (IProcessOutputSink) decls[i].createExecutableExtension("class");
                extension.initializeSink(model, type);
                validExtensions.add(extension);
            } catch (CoreException e)
            {
                TLCActivator.logError("Error instatiating the IProcessSink extension", e);
            }
        }
        return (IProcessOutputSink[]) validExtensions.toArray(new IProcessOutputSink[validExtensions.size()]);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/RefreshSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

public class RefreshSpecHandler extends AbstractHandler {

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
	 */
	public Object execute(final ExecutionEvent event) throws ExecutionException {
		final IWorkbenchPage activePage = UIHelper.getActivePage();
		if (activePage != null) {
			final ISelection selection = activePage.getSelection(ToolboxExplorer.VIEW_ID);
			if (selection != null && selection instanceof IStructuredSelection
					&& !((IStructuredSelection) selection).isEmpty()) {

				final Job job = new ToolboxJob("Refreshing spec...") {
					/* (non-Javadoc)
					 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
					 */
					protected IStatus run(IProgressMonitor monitor) {
						final Iterator<Spec> selectionIterator = ((IStructuredSelection) selection).iterator();
						while (selectionIterator.hasNext()) {
							ResourceHelper.refreshSpec(selectionIterator.next(), monitor);
						}
						return Status.OK_STATUS;
					}
				};
				job.schedule();
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActivePage() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/ActionItemListExt.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.impl;

import tla2sany.semantic.SemanticNode;
import tlc2.tool.Action;
import tlc2.tool.IActionItemList;
import tlc2.tool.coverage.CostModel;
import tlc2.util.Context;

public class ActionItemListExt extends ActionItemList {

	public final static ActionItemList Empty = new ActionItemListExt(null, null, 0, null, null);

	private ActionItemListExt prev;

	private Action action;

	protected ActionItemListExt(SemanticNode pred, Context con, int kind, ActionItemList next, CostModel cm) {
		super(pred, con, kind, next, cm);
	}

	@Override
	public IActionItemList cons(SemanticNode pred, Context con, CostModel cm, int kind) {
		ActionItemListExt actionItemListExt = new ActionItemListExt(pred, con, kind, this, coverage ? cm.get(pred) : cm);
		actionItemListExt.action = getAction();
		return actionItemListExt;
	}

	@Override
	public ActionItemList cons(final Action act, final int kind) {
		final ActionItemListExt actionItemListExt = new ActionItemListExt(act.pred, act.con, kind, this, coverage ? act.cm.get(pred) : act.cm);
		actionItemListExt.action = act;
		return actionItemListExt;
	}

	@Override
	public ActionItemList cdr() {
		final ActionItemListExt cdr = (ActionItemListExt) super.cdr();
		cdr.prev = this;
		return cdr;
	}

	@Override
	public boolean isEmpty() {
		return this == Empty;
	}

	@Override
	public void setAction(final Action action) {
		this.action = action;
	}

	@Override
	public Action getAction() {
		if (this.prev != null) {
			return this.prev.action;
		}
		return action;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/EvalControlTest.java<|end_filename|>
package tlc2.tool;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class EvalControlTest {

	@Test
	public void test() {
		int control = EvalControl.Clear;

		assertFalse(EvalControl.isEnabled(control));
		assertFalse(EvalControl.isKeepLazy(control));
		assertFalse(EvalControl.isPrimed(control));

		control = EvalControl.setEnabled(control);
		assertTrue(EvalControl.isEnabled(control));
		assertFalse(EvalControl.isKeepLazy(control));
		assertFalse(EvalControl.isPrimed(control));
		
		control = EvalControl.setKeepLazy(control);
		assertTrue(EvalControl.isEnabled(control));
		assertTrue(EvalControl.isKeepLazy(control));
		assertFalse(EvalControl.isPrimed(control));

		control = EvalControl.setPrimed(control);
		assertTrue(EvalControl.isEnabled(control));
		assertTrue(EvalControl.isKeepLazy(control));
		assertTrue(EvalControl.isPrimed(control));
	}

	@Test
	public void testIfEnabled() {
		int control = EvalControl.Clear;
		
		assertFalse(EvalControl.isPrimed(EvalControl.setPrimedIfEnabled(control)));
		
		control = EvalControl.setEnabled(control);
		assertTrue(EvalControl.isEnabled(control));
		assertTrue(EvalControl.isPrimed(EvalControl.setPrimedIfEnabled(control)));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TableauDiskGraph.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import java.io.IOException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.ITool;
import tlc2.util.LongVec;
import tlc2.util.MemIntQueue;
import tlc2.util.statistics.IBucketStatistics;

public class TableauDiskGraph extends AbstractDiskGraph {
	
	private static final long INIT_STATE = MAX_PTR + 1;

	private TableauNodePtrTable nodePtrTbl;
	
	public TableauDiskGraph(String metadir, int soln, IBucketStatistics graphStats) throws IOException {
		super(metadir, soln, graphStats);
		this.nodePtrTbl = new TableauNodePtrTable(255);
	}
	
	public final long getPtr(long fp, int tidx) {
		return this.nodePtrTbl.get(fp, tidx);
	}
	
	public int getElemLength() {
		return this.nodePtrTbl.getElemLength();
	}

	/**
	 * @param fp The fingerprint which should be checked for its done state. 
	 * @return true iff the node is done, false otherwise.
	 *  
	 * @see TableauDiskGraph#setDone(long)
	 * @see TableauDiskGraph#recordNode(long, int)
	 */
	public final boolean isDone(final long fp) {
		return this.nodePtrTbl.isDone(fp);
	}
	
	/**
	 * Mark the fingerprint fp as being done. A fingerprint is undone for as
	 * long as it has been recorded with recordNode().
	 * <p>
	 * A node is logically undone when it's an initial state and added via
	 * {@link LiveCheck#addInitState(ITool, tlc2.tool.TLCState, long)} but not yet
	 * added via
	 * {@link LiveCheck#addNextState(tlc2.tool.TLCState, long, tlc2.tool.StateVec, LongVec)}
	 * . A second case is when a successor node in the behavior graph is added
	 * via
	 * {@link LiveCheck#addNextState(tlc2.tool.TLCState, long, tlc2.tool.StateVec, LongVec)}
	 * . However, in this case it can happen that the successor in fact has
	 * already been done. Then adding the successor node requires computing the
	 * children (see private TableauLiveChecker#addNextNode(..)).
	 * 
	 * @param fp
	 *            The fingerprint to mark as done
	 * @return The location at which the corresponding node can be looked up
	 *         with {@link TableauDiskGraph#getNodesByLoc(int)}.
	 * 
	 * @see TableauDiskGraph#recordNode(long, int)
	 * @see TableauDiskGraph#isDone(long)
	 * @see TableauDiskGraph#getNodesByLoc(int)
	 */
	public final int setDone(final long fp) {
		return this.nodePtrTbl.setDone(fp);
	}
	
	/**
	 * This method records that the node, whose fingerprint is fp, is reachable.
	 * The node itself is not added into the graph (see
	 * {@link LiveCheck#addNextState(tlc2.tool.TLCState, long, tlc2.tool.StateVec, LongVec)}.
	 * 
	 * @see TableauDiskGraph#isDone(long)
	 * @see TableauDiskGraph#setDone(long)
	 */
	public final void recordNode(final long fp, final int tidx) {
		this.nodePtrTbl.put(fp, tidx, TableauNodePtrTable.UNDONE);
	}

	/**
	 * @see TableauDiskGraph#setDone(long) 
	 */
	public final int[] getNodesByLoc(final int loc) {
		return this.nodePtrTbl.getNodesByLoc(loc);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#putNode(tlc2.tool.liveness.GraphNode, long)
	 */
	protected void putNode(GraphNode node, long ptr) {
		this.nodePtrTbl.put(node.stateFP, node.tindex, ptr);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#checkDuplicate(tlc2.tool.liveness.GraphNode)
	 */
	protected boolean checkDuplicate(final GraphNode node) {
		return this.nodePtrTbl.get(node.stateFP, node.tindex) != -1;
	}

	/**
	 * Get the graph node. Returns a new GraphNode if the node is not in this.
	 * 
	 * @param fp
	 * @param tidx
	 * @return A new GraphNode instance or an existing GraphNode instance read
	 *         from the graph (technically either cache or disk).
	 *         <p>
	 *         The latter case is only used in simulation mode to add a new
	 *         (outgoing) transition to an existing GraphNode. In simulation
	 *         mode a trace can be such that the same state occurs multiple
	 *         times (due to random selection of next state), but each time with
	 *         a different successor. This is not possible in regular model
	 *         checking, because the complete set of successors is calculated
	 *         the first time a state is generated.
	 *         <p>
	 *         For an GraphNode update to produce a valid result, the nodePtr
	 *         files have to be read from start to end to make sure the
	 *         reconstruction correctly updates the GraphNode data in the
	 *         nodeptrtbl. //TODO Add test case to TableauDiskGraph that adds
	 *         the same GraphNode multiple times with different outgoing
	 *         transitions.
	 * 
	 * @throws IOException
	 */
	public final GraphNode getNode(long fp, int tidx) throws IOException {
		long ptr = this.nodePtrTbl.get(fp, tidx);
		if (ptr < 0) {
			return new GraphNode(fp, tidx);
		}
		if (gnodes == null) {
			// No cache, get directly from disk.
			return this.getNodeFromDisk(fp, tidx, ptr);
		}
		return this.getNode(fp, tidx, ptr);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#getLink(long, int)
	 */
	public long getLink(long state, int tidx) {
		return this.nodePtrTbl.get(state, tidx);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#putLink(long, int, long)
	 */
	public long putLink(long state, int tidx, long link) {
		assert MAX_PTR <= link && link < MAX_LINK; 
		int[] node = this.nodePtrTbl.getNodes(state);
		int cloc = this.nodePtrTbl.getIdx(node, tidx);
		long oldLink = TableauNodePtrTable.getElem(node, cloc);
		if (!isFilePointer(oldLink)) {
			return oldLink;
		}
		TableauNodePtrTable.putElem(node, link, cloc);
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#setMaxLink(long, int)
	 */
	public void setMaxLink(long state, int tidx) {
		this.nodePtrTbl.put(state, tidx, MAX_LINK);
	}

	public final void reset() throws IOException {
		this.nodePtrRAF.setLength(0);
		this.nodeRAF.setLength(0);
		this.nodePtrTbl = new TableauNodePtrTable(255);
	 }

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#size()
	 */
	public long size() {
		return this.nodePtrTbl.size();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#makeNodePtrTbl(long)
	 */
	protected void makeNodePtrTbl(final long ptr) throws IOException  {
		makeNodePtrTbl(ptr, nodePtrTbl);
	}
	
	protected void makeNodePtrTbl(final long ptr, final TableauNodePtrTable aTable) throws IOException  {
		this.nodePtrRAF.seek(0);
		while (this.nodePtrRAF.getFilePointer() < ptr) {
			long fp = this.nodePtrRAF.readLong();
			int tidx = this.nodePtrRAF.readInt();
			long loc = this.nodePtrRAF.readLongNat();
			aTable.put(fp, tidx, loc);
		}
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public final String toString() {

		// The following code relies on gnodes not being null, thus safeguard
		// against accidental invocations.
		// Essentially one has to wrap the toString call with
		// createCache/destroyCache
		// for gnodes to be initialized.
		if (this.gnodes == null) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		try {
			long nodePtr = this.nodeRAF.getFilePointer();
			long nodePtrPtr = this.nodePtrRAF.getFilePointer();
			long len = this.nodePtrRAF.length();
			this.nodePtrRAF.seek(0);
			while (this.nodePtrRAF.getFilePointer() < len) {
				long fp = nodePtrRAF.readLong();
				int tidx = nodePtrRAF.readInt();
				long loc = nodePtrRAF.readLongNat();
				sb.append("<" + fp + "," + tidx + "> -> ");
				GraphNode gnode = this.getNode(fp, tidx, loc);
				int sz = gnode.succSize();
				for (int i = 0; i < sz; i++) {
					sb.append("<" + gnode.getStateFP(i) + "," + gnode.getTidx(i) + "> ");
				}
				sb.append("\n");
			}
			this.nodeRAF.seek(nodePtr);
			this.nodePtrRAF.seek(nodePtrPtr);
		} catch (IOException e) {
			MP.printError(EC.SYSTEM_DISKGRAPH_ACCESS, e);

			System.exit(1);
		}
		return sb.toString();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#toDotViz(tlc2.tool.liveness.OrderOfSolution)
	 */
	public final String toDotViz(final OrderOfSolution oos) {
		final int slen = oos.getCheckState().length;
		final int alen = oos.getCheckAction().length;

		// The following code relies on gnodes not being null, thus safeguard
		// against accidental invocations.
		// Essentially one has to wrap the toDotViz call with
		// createCache/destroyCache
		// for gnodes to be initialized.
		if (this.gnodes == null) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		try {
			sb.append("digraph DiskGraph {\n");
			sb.append("nodesep = 0.7\n");
			sb.append("rankdir=LR;\n"); // Left to right rather than top to bottom
			sb.append(toDotVizLegend(oos));
			sb.append("subgraph cluster_graph {\n"); 
	        sb.append("color=\"white\";\n"); // no border.
			//TODO Reading the file front to end potentially yields node duplicates in the output. Better to create a (temporary) nodeptrtable and traverse it instead.
			long nodePtr = this.nodeRAF.getFilePointer();
			long nodePtrPtr = this.nodePtrRAF.getFilePointer();
			long len = this.nodePtrRAF.length();
			this.nodePtrRAF.seek(0);
			while (this.nodePtrRAF.getFilePointer() < len) {
				long fp = nodePtrRAF.readLong();
				int tidx = nodePtrRAF.readInt();
				long loc = nodePtrRAF.readLongNat();
				GraphNode gnode = this.getNode(fp, tidx, loc);
				sb.append(gnode.toDotViz(isInitState(gnode), true, slen, alen));
			}
			sb.append("}}");
			this.nodeRAF.seek(nodePtr);
			this.nodePtrRAF.seek(nodePtrPtr);
		} catch (IOException e) {
			MP.printError(EC.SYSTEM_DISKGRAPH_ACCESS, e);

			System.exit(1);
		}
		return sb.toString();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#getPath(long, int)
	 */
	public final LongVec getPath(final long state, final int tidx) throws IOException {
		// If path requested just consists of an init node, return the single
		// init node. This is the trivial case.
		final int numOfInits = this.initNodes.size();
		for (int i = 0; i < numOfInits; i += 2) {
			final long state0 = this.initNodes.elementAt(i);
			// Comparing the tidx here makes sure we only return a path iff the
			// node matches what is actually requested (the returned path of
			// just the initial state's fingerprint would be indistinguishable
			// anyway).
			final int tidx0 = (int) this.initNodes.elementAt(i + 1);
			if (state0 == state && tidx0 == tidx) {
				final LongVec res = new LongVec(1);
				res.addElement(state0);
				return res;
			}
		}
		// ...the path consists of more than just a single init node:

		// Restore the nodePtrTbl. The implementation uses the efficient
		// NodePtrTable because it is doing a breadth-first search and thus
		// potentially traversing many many nodes:
		// Restoring/Resetting the NodePtrTable is crucial as we are going to
		// store elements exclusively used for the reverse path reconstruction.
		// They are incompatible with the way other parts of the code use the
		// NodePtrTable.
		final TableauNodePtrTable reversablePtrTable = new ReverseTraversableTableauNodePtrTable(255);
		this.makeNodePtrTbl(this.nodePtrRAF.length(), reversablePtrTable);

		// Do breadth-first search (BFS guarantees we find the *shortest* path
		// which is most comprehensible):
		final MemIntQueue queue = new MemIntQueue(this.metadir, null);

		// Add all init states to nodePtrTable (some might already be in
		// nodePtrTable) and mark all init states in nodePtrTable as such. Note
		// that a nodes init state property does not solely depend on its
		// fingerprint. It depends on the fingerprint *and* tableau idx.:
		for (int i = 0; i < numOfInits; i += 2) {
			final long state0 = this.initNodes.elementAt(i);
			final int tidx0 = (int) this.initNodes.elementAt(i + 1);
			// Can get from reversablePtrTable because at this point it is an
			// exact copy of nodePtrTable
			final long ptr = reversablePtrTable.get(state0, tidx0);
			// Skip initial states without successors:
			// An initial state with a -1 (disk) pointer means that is has *no*
			// successors. Thus, it can safely be omitted from the path search
			// below. If the init state is the very state searched for, the
			// previous for loop will have caught it already.
			// Adding an init with negative pointer to the queue manifests in
			// an exception in the while loop below. This is because the
			// DiskGraph won't be able to return a GraphNode instance.
			if (ptr != -1) {
				queue.enqueueLong(state0);
				queue.enqueueInt(tidx0);
				queue.enqueueLong(ptr);
				// Marker the node as an init state in nodePtrTable. This is used
				// below when the reverse path gets reconstructed as a termination
				// condition.
				reversablePtrTable.put(state0, tidx0, MAX_PTR);
			}
		}

		// While queue has elements, but not longer! while(true)... can get stuck 
		while (queue.hasElements()) {
			final long curState = queue.dequeueLong();
			final int curTidx = queue.dequeueInt();
			final long curPtr = queue.dequeueLong();
			final GraphNode curNode = this.getNode(curState, curTidx, curPtr);
			final int succCnt = curNode.succSize();

			for (int i = 0; i < succCnt; i++) {
				final long nextState = curNode.getStateFP(i);
				final int nextTidx = curNode.getTidx(i);
				if (nextState == curState && nextTidx == curTidx) {
					// No point to explore a successor state
					// that is the current state. It is a successor
					// due to a direct cycle in the graph.
					continue;
				}
				if (nextState == state && nextTidx == tidx) {
					// Stop BFS (see MemIntQUEUE above), we found a path to
					// state. The path might not necessarily be the shortest one
					// possible. A non-optimal path is returned if the BFS
					// search happens to produce a path <<fp1, fp2, fp3>> first
					// before it finds <<fp1, fp1, fp2>> (the first two elements
					// share the same fingerprint and only differ in the
					// discarded tableau id). The caller LiveWorker#printTrace
					// collapses contiguous segments (identical fingerprint) in
					// the path into a single state. E.g. the second example
					// above will be printed as two states: <<State(fp1),
					// State(fp2)>>. Hence, it is shorter than <<State(fp1),
					// State(fp2), State(fp3)>>. Note that the search does *not*
					// stop after the second node from the end in <<fp1, fp1, fp2>>
					// because this node - due to its tableau id - does not
					// correspond to an initial state in reversablePtrTable.
					return reconstructReversePath(reversablePtrTable, curState, curTidx, nextState, nextTidx);
				}

				// Lookup the successor nodes of nextState (curState -> nextState ->
				// successor nodes).
				final int nextLoc = reversablePtrTable.getNodesLoc(nextState);
				if (nextLoc == -1) {
					// nextState is not on disk.
					//
					// Iff nextState itself is not on disk, it's successor nodes
					// won't be either (or we don't know its successors yet).
					// This scenario occurs when liveness checking is executed
					// on a *partial* graph only. The model checker has added
					// curState with nextState as its successor, nextState has
					// not been added yet though. Basically this is where the
					// partial graph has its border to the unknown.
					//
					// Continuing the for loop is fine. But we might as well add
					// nextState to the queue. Once it gets picked up by the outer
					// while loop, it will be skipped anyway as its succCnt is 0.
					//
					// If this case happens when LiveCheck is doing its
					// finalCheck (complete graph), it is most probably a bug.
					// Unfortunately, I don't know a proper assertion to check.
					continue;
				}
				final int[] nextNodes = reversablePtrTable.getNodesByLoc(nextLoc);
				final int cloc = reversablePtrTable.getIdx(nextNodes, nextTidx);
				final long nextPtr = TableauNodePtrTable.getElem(nextNodes, cloc);

				// Add nextState to the queue if its successor node are still on disk.
				if (isFilePointer(nextPtr)) {
					// nextState is not visited: enqueue it, mark it
					// visited, and memorize its parent.
					queue.enqueueLong(nextState);
					queue.enqueueInt(nextTidx);
					queue.enqueueLong(nextPtr);
					final int curLoc = reversablePtrTable.getNodesLoc(curState);
					// Add extra information to the back-pointer pointing to the
					// predecessor to not just map to the state, but
					// additionally to the specific tableau idx.
					reversablePtrTable.putElem(nextNodes, INIT_STATE + curLoc, curTidx, cloc);
				}
			}
		}
		return super.getPath(state, tidx);
	}

	private LongVec reconstructReversePath(final TableauNodePtrTable reversablePtrTable, final long startState,
			final int startTidx, final long finalState, final int finalTidx) {
		// Add the target/final state to the result. Reverse path construction
		// does not start at the final state that the getPath(..) is searching
		// for, but at its immediate predecessor alias startState. 
		final LongVec res = new LongVec(2);
		res.addElement(finalState);
		
		// Traverse the graph backwards from currentState using
		// the NodePtrTable. The NodePtrTable contains the back
		// pointers from a successor to its predecessor.
		int lastTidx = finalTidx;
		long currentState = startState;
		int currentTidx = startTidx;
		int currentLoc = reversablePtrTable.getNodesLoc(currentState);
		int[] nodes = reversablePtrTable.getNodesByLoc(currentLoc);
		while (true) {
			// res never empty due to addElement call with final
			// state.
			// The tableau index has to be taken into account if the predecessor
			// of res.lastElement() happens to be a state with an identical
			// fingerprint and only differ in the tableau idx.
			if (res.lastElement() == currentState && lastTidx == currentTidx) {
				// The new state is the last state in res, we are about
				// to follow a cycle, thus exit.
				throw new RuntimeException("Self loop in trace path reconstruction");
			}
			res.addElement(currentState);
			lastTidx = currentTidx;
			long predecessorLocation = -1;
			int predecessorTidx = -1;
			for (int j = 2; j < nodes.length; j += reversablePtrTable.getElemLength()) {
				// a) The node's tableau idx has to match the one we
				// are interested in.
				// b) All nodes have been read from disk during the
				// outer BFS. If the node is still on disk, it can't
				// be part of the path, thus ignore.
				final long candidateLocation = TableauNodePtrTable.getElem(nodes, j);
				final int candidateTidx = TableauNodePtrTable.getTidx(nodes, j);
				if (currentTidx == candidateTidx && !isFilePointer(candidateLocation)) {
					predecessorLocation = candidateLocation;
					predecessorTidx = reversablePtrTable.getElemTidx(nodes, j);
					if (candidateLocation == MAX_PTR) {
						// The predecessor is an init state and thus the best
						// match (on our search for the shortest path) out of
						// all possible predecessors. No need to continue the
						// search...
						break;
					}
					// ...else we continue looping over all predecessors
					// returning the last match (not an init state though).
				}
				// Ignore the else case, because the outer while
				// loop would have read the node from disk if it
				// came across it in the BFS. Since it didn't read
				// during BFS, it won't be part of the path anyway.
			}
			// MAX_PTR indicates that this is an init state. Since
			// getPath is looking for the shortest path from the
			// given state back to *an* initial state, we are done.
			if (predecessorLocation == MAX_PTR) {
				break;
			}
			// Lookup the predecessor in the ptr table. (ploc -
			// offset) is the index of the predecessor in the
			// nodePtrTbl. See offset below at putByLoc(..).
			currentLoc = (int) (predecessorLocation - INIT_STATE);
			nodes = reversablePtrTable.getNodesByLoc(currentLoc);
			currentState = TableauNodePtrTable.getKey(nodes);
			currentTidx = predecessorTidx;
		}
		return res;
	}
	
	/**
	 * This implementation extends {@link TableauNodePtrTable} to additionally
	 * store the tableau index of the predecessor node. It is needed to traverse
	 * the {@link ReverseTraversableTableauNodePtrTable} backwards once a error
	 * trace path has been created.
	 */
	private class ReverseTraversableTableauNodePtrTable extends TableauNodePtrTable {

		public ReverseTraversableTableauNodePtrTable(final int size) {
			super(size);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.TableauNodePtrTable#getElemTidx(int[], int)
		 */
		public int getElemTidx(final int[] node, final int loc) {
			return node[loc + 3];
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.TableauNodePtrTable#putElem(int[], long, int, int)
		 */
		public void putElem(final int[] node, final long elem, final int tableauIdx, final int loc) {
			super.putElem(node, elem, tableauIdx, loc);
			node[loc + 3] = tableauIdx;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.TableauNodePtrTable#getElemLength()
		 */
		public int getElemLength() {
			// This implementation stores the predecessor's tableau index
			// additionally to its location in this ptr table.
			return super.getElemLength() + 1;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.TableauNodePtrTable#addElem(long, int, long)
		 */
		protected int[] addElem(final long key, final int tidx, final long elem) {
			final int[] node = super.addElem(key, tidx, elem);
			node[5] = -1; // later updated to store predecessor's tidx
			return node;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.TableauNodePtrTable#appendElem(int[], int, long)
		 */
		protected int[] appendElem(final int[] node, final int tidx, final long elem) {
			int len = node.length;
			int[] newNode = new int[len + getElemLength()];
			System.arraycopy(node, 0, newNode, 0, len);
			newNode[len] = tidx;
			newNode[len + 1] = (int) (elem >>> 32);
			newNode[len + 2] = (int) (elem & 0xFFFFFFFFL);
			newNode[len + 3] = -1; // later used to store predecessor's tidx
			return newNode;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAEditorReadOnly.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import org.eclipse.jface.action.IMenuManager;

/**
 * A read-only version of the {@link TLAEditor}.
 * Simply overrides the necessary methods to make
 * it read-only.
 * 
 * I created this class for opening read-only versions
 * of modules that are saved when a TLC model is run.
 * I could have written a new read-only source viewer for
 * this, but extending {@link TLAEditor} is the easiest
 * way to immediately get all of the features that the
 * editor already offers : syntax coloring, folding, etc.
 * 
 * @author <NAME>
 *
 */
public class TLAEditorReadOnly extends TLAEditor
{

    public static final String ID = "org.lamport.tla.toolbox.editor.basic.TLAEditorReadOnly";

    public boolean isEditable()
    {
        return false;
    }

    public boolean isEditorInputReadOnly()
    {
        return true;
    }

    public boolean isEditorInputModifiable()
    {
        return false;
    }

    /**
     * TODO Remove items from the context menu that don't make sense
     * for a read-only version of the module.
     */
    protected void editorContextMenuAboutToShow(IMenuManager menuManager)
    {
        menuManager.removeAll();
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/SaveDirtyEditorAbstractHandler.java<|end_filename|>
// Copyright (c) Jan 25, 2012 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * @author <NAME>
 */
public abstract class SaveDirtyEditorAbstractHandler extends AbstractHandler {

	protected IEditorPart activeEditor;

	/**
	 * @param event
	 * @return true iff the dirty editor has been saved, false otherwise
	 */
	public boolean saveDirtyEditor(final ExecutionEvent event) {
		activeEditor = UIHelper.getActiveEditor();
		if (activeEditor.isDirty()) {
			getPrefs().setDefault(this.getClass() + ".dontBother", false);
			if (getPrefs().getBoolean(this.getClass() + ".dontBother")) {
				// TODO decouple from ui thread
				// Use NullProgressMonitor instead of newly created monitor. The
				// parent ProgressMonitorDialog would need to be properly
				// initialized first.
				// @see Bug #256 in general/bugzilla/index.html
				//
				// Generally though, saving a resource involves I/O which should be
				// decoupled from the UI thread in the first place. Properly doing
				// this, would be from inside a Job which provides a ProgressMonitor
				activeEditor.doSave(new NullProgressMonitor());
			} else {
				final Shell shell = HandlerUtil.getActiveShell(event);
				final MessageDialog dialog = new SaveMessageDialog(shell, getDialogTitle(), getDialogMessage());
				int res = dialog.open();
				if (res == 2) { // 2 is index of button in string[] below
					// User doesn't want to be warned about a dirty editor any longer.
					// Remember it for this handler (this.getClass).
					getPrefs().setValue(this.getClass() + ".dontBother", true);
					res = MessageDialog.OK;
				}
				if (res == MessageDialog.OK || res == MessageDialog.CONFIRM) {
					// TODO decouple from ui thread
					// Use NullProgressMonitor instead of newly created monitor. The
					// parent ProgressMonitorDialog would need to be properly
					// initialized first.
					// @see Bug #256 in general/bugzilla/index.html
					//
					// Generally though, saving a resource involves I/O which should be
					// decoupled from the UI thread in the first place. Properly doing
					// this, would be from inside a Job which provides a ProgressMonitor
					activeEditor.doSave(new NullProgressMonitor());
				} else {
					return false;
				}
			}
		}
		return true;
	}

	private IPreferenceStore getPrefs() {
		return Activator.getDefault().getPreferenceStore();
	}

	protected String getDialogMessage() {
		return "The current editor has not been saved, should the editor be saved first?";
	}

	protected String getDialogTitle() {
		return "Save " + activeEditor.getTitle() + " editor?";
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActiveEditor() == null) {
			return false;
		}
		return super.isEnabled();
	}

	/**
	 * A {@link MessageDialog#QUESTION} style dialog with special save/cancel buttons
	 */
	private class SaveMessageDialog extends MessageDialog {

		public SaveMessageDialog(Shell parentShell, String dialogTitle, String dialogMessage) {
			super(parentShell, dialogTitle, null, dialogMessage, QUESTION,
					new String[] { "&Save", "&Cancel", "Save and &never ask again" }, 0);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/modelexplorer/ModelContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.handlers.OpenModelHandler;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Contributes a list of models
 * @author <NAME>
 */
public class ModelContributionItem extends CompoundContributionItem
{
    private ImageDescriptor modelIcon = TLCUIActivator.getImageDescriptor("icons/full/choice_sc_obj.gif");

    /**
     * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
     */
    protected IContributionItem[] getContributionItems()
    {
        final Vector<CommandContributionItem> modelContributions = new Vector<CommandContributionItem>();

        Spec currentSpec = ToolboxHandle.getCurrentSpec();
        if (currentSpec == null) {
        	return new IContributionItem[0];
        }
		// First, search for all models for the given spec.
		final Set<String> modelNames = currentSpec.getAdapter(TLCSpec.class).getModels().keySet();
		for (String modelName : modelNames) {

            Map<String, String> parameters = new HashMap<String, String>();

            // fill the model name for the handler
            parameters.put(OpenModelHandler.PARAM_MODEL_NAME, modelName);

            // create the contribution item
            CommandContributionItemParameter param = new CommandContributionItemParameter(UIHelper
                    .getActiveWindow(), "toolbox.command.model.open." + modelName, OpenModelHandler.COMMAND_ID,
                    parameters, modelIcon, null, null, modelName, null, "Opens " + modelName,
                    CommandContributionItem.STYLE_PUSH, null, true);

            // add contribution item to the list
            modelContributions.add(new CommandContributionItem(param));
        }
        return modelContributions.toArray(new IContributionItem[modelContributions.size()]);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/StandardModules.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tla2sany.semantic;

import java.util.HashSet;
import java.util.Set;

public class StandardModules {
	private static final Set<String> STANDARD_MODULES = new HashSet<>();
	
	static {
		// Quick'n'Dirty hack! This breaks if any one of the operators is override by
		// the model or a complete standard module has been replaced by a user-defined
		// module with the same name.
		STANDARD_MODULES.add("FiniteSets");
		STANDARD_MODULES.add("Sequences");
		STANDARD_MODULES.add("Bags");
		STANDARD_MODULES.add("Naturals");
		STANDARD_MODULES.add("Integers");
		STANDARD_MODULES.add("Reals");
		STANDARD_MODULES.add("RealTime");
		STANDARD_MODULES.add("Randomization");
		STANDARD_MODULES.add("TLC");
	}

	private StandardModules() {
		// no instances
	}
	
	public static boolean isDefinedInStandardModule(SemanticNode sn) {
		if ((sn != null) && (sn.getLocation() != null)) {
			return isDefinedInStandardModule(sn.getLocation().source()); // source might be null
		}
		return false;
	}
	
	public static boolean isDefinedInStandardModule(final String moduleName) {
		return STANDARD_MODULES.contains(moduleName);
	}
	
	public static void filterNonStandardModulesFromSet(final Set<String> listOfModules) {
		listOfModules.retainAll(STANDARD_MODULES);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MSBDiskFPSet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.

package tlc2.tool.fp;

import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.NoSuchElementException;

import tlc2.output.EC;
import tlc2.util.BufferedRandomAccessFile;
import util.Assert;

@SuppressWarnings("serial")
public class MSBDiskFPSet extends HeapBasedDiskFPSet {

	/**
	 * Number of bits to right shift bits during index calculation
	 */
	protected final int moveBy;
	
	/**
	 * Construct a new <code>DiskFPSet2</code> object whose internal memory
	 * buffer of new fingerprints can contain up to
	 * <code>DefaultMaxTblCnt</code> entries. When the buffer fills up, its
	 * entries are atomically flushed to the FPSet's backing disk file.
	 * 
	 * @param maxInMemoryCapacity The number of fingerprints (not memory) this DiskFPSet should maximally store in-memory.
	 * @param preBits Take the amount of DiskFPSet instance into account to move the index bits further to the right
	 * @throws RemoteException
	 */
	protected MSBDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);

		// To pre-sort fingerprints in memory, use n MSB fp bits for the
		// index. However, we cannot use the 32st bit, because it is used to
		// indicate if a fp has been flushed to disk. Hence we use the first n
		// bits starting from the second most significant bit.
		Assert.check(fpSetConfig.getFpBits() > 0, EC.GENERAL);
		this.moveBy = (32 - fpSetConfig.getFpBits()) - (logMaxMemCnt - LogMaxLoad);
		this.mask = (capacity - 1) << moveBy;
		
		this.flusher = new MSBFlusher();
	}


	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getAuxiliaryStorageRequirement()
	 */
	@Override
	protected double getAuxiliaryStorageRequirement() {
		// Need auxiliary storage for the disk file index which needs approx.
		// 1/3 of the overall memory.
		return 1.5d;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#index(long, int)
	 */
	@Override
	protected long index(long fp, long aMask) {
		// calculate hash value (just n most significant bits of fp) which is
		// used as an index address
		// 1) Right shift by 32 bits and cast to int (upper 32 bits are zeroed)
		// 2) Zero the lower n bits according to mask
		// 3) Right shift by moveBy (the bits which have previously been zeroed because of mask.
		return ((int) (fp >>> 32) & aMask) >> moveBy;
	}
	
	public class MSBFlusher extends Flusher {

		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet.Flusher#preFlushTable()
		 */
		protected void prepareTable() {
			
			// copy table contents into a buffer array buff; do not erase tbl, but 1
			// msb of each fp to indicate it has been flushed to disk
			for (int j = 0; j < tbl.length; j++) {
				long[] bucket = tbl[j];
				if (bucket != null) {
					int blen = bucket.length;
					// for all bucket positions and non-null values
					int k = 0;
					for (; k < blen && bucket[k] > 0; k++) {
						continue;
					}
					// * Postconditions:
					// * - Zero/0 Element(s) remains at the end
					// * - Negative elements maintain their position (remain untouched) 
					Arrays.sort(bucket, 0, k);
				}
			}
	
			// At this point this.tbl should be fully sorted modulo the fps which
			// had been flush in a previous flush operation and zero/0 (which is invalid anyway).
		}
		
		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet#mergeNewEntries(long[], int, java.io.RandomAccessFile, java.io.RandomAccessFile)
		 */
		protected void mergeNewEntries(BufferedRandomAccessFile[] inRAFs, RandomAccessFile outRAF) throws IOException {
			final long buffLen = getTblCnt();
			final TLCIterator itr = new TLCIterator(tbl);

			// Precompute the maximum value of the new file.
			// If this isn't the first merge, the index has
			// the last element of the disk file. In that case
			// the new maxVal is the larger element of the two
			// in-memory and on-disk elements.
			long maxVal = itr.getLast();
			if (index != null) {
				maxVal = Math.max(maxVal, index[index.length - 1]);
			}
	
			int indexLen = calculateIndexLen(buffLen);
			index = new long[indexLen];
			index[indexLen - 1] = maxVal;
			currIndex = 0;
			counter = 0;
	
			// initialize positions in "buff" and "inRAF"
			long value = 0L; // initialize only to make compiler happy
			boolean eof = false;
			if (fileCnt > 0) {
				try {
					value = inRAFs[0].readLong();
				} catch (EOFException e) {
					eof = true;
				}
			} else {
				eof = true;
			}
	
			// merge while both lists still have elements remaining
			boolean eol = false;
			long fp = itr.next();
			while (!eof || !eol) {
				if ((value < fp || eol) && !eof) {
					writeFP(outRAF, value);
					try {
						value = inRAFs[0].readLong();
					} catch (EOFException e) {
						eof = true;
					}
				} else {
					// prevent converting every long to String when assertion holds (this is expensive)
					if (value == fp) {
						Assert.check(false, EC.TLC_FP_VALUE_ALREADY_ON_DISK,
								String.valueOf(value));
						
					}
					writeFP(outRAF, fp);
					// we used one fp up, thus move to next one
					try {
						fp = itr.next();
					} catch (NoSuchElementException e) {
						// has read all elements?
						Assert.check(!itr.hasNext(), EC.GENERAL);
						Assert.check(itr.reads() == buffLen, EC.GENERAL);
						eol = true;
					}
				}
			}
			
			// both sets used up completely
			Assert.check(eof && eol, EC.GENERAL);
	
			// currIndex is amount of disk writes
			Assert.check(currIndex == indexLen - 1, EC.SYSTEM_INDEX_ERROR);
	
			// maintain object invariants
			fileCnt += buffLen;
		}
	}

	/**
	 * A TLCIterator wraps the buff given to it from its outer MSBDiskFPSet and
	 * provides convenience methods to traverse the elements in buff, namely:
	 * Check if there is a next element and get it as well as obtaining the
	 * largest element.
	 */
	public static class TLCIterator {
		/**
		 * The underlying buffer this {@link TLCIterator} is iterating on.
		 */
		private final long[][] buff;
		/**
		 * Index pointing to the current bucket in the first level of
		 * {@link TLCIterator#buff}
		 */
		private int firstIdx = 0;
		/**
		 * Index pointing to the current element in the current bucket which is the
		 * second level of {@link TLCIterator#buff}
		 */
		private int secondIdx = 0;
		/**
		 * Used to verify that the elements we hand out are strictly monotonic
		 * increasing.
		 */
		private long previous = -1l;
		/**
		 * Number of elements read with next()
		 */
		private long readElements = 0L;

		/**
		 * @param buff an [][] with null elements on the second level.
		 */
		public TLCIterator(final long[][] buff) {
			this.buff = buff;
		}

	    /**
	     * Returns <tt>true</tt> if the iteration has more elements. (In other
	     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
	     * rather than throwing an exception.)
	     *
	     * @return <tt>true</tt> if the iterator has more elements.
	     */
		public boolean hasNext() {
			// hasNext does not move the indices at all!
			
			// firstIdx within buff[].length
			if (firstIdx < buff.length) {
				long[] bucket = buff[firstIdx];
				// secondIdx within bucket[].length and with valid elements in current bucket 
				if (bucket != null && secondIdx < bucket.length && bucket[secondIdx] > 0) {
					return true;
				// we might have reached a null or negative range in buff[] -> skip it until
				// we reach a non-null and non negative bucket or we get to the end of buff[]
				} else {
					for (int i = firstIdx + 1; i < buff.length; i++) {
						if (buff[i] != null && buff[i].length > 0 && buff[i][0] > 0) {
							return true;
						}
					}
				}
			}
			return false;
		}

	    /**
	     * Returns the next element in the iteration.
	     *
	     * @return the next element in the iteration.
	     * @exception NoSuchElementException iteration has no more elements.
	     */
		public long next() {
			long result = -1l;
			
			// at least one more element in current bucket
			if (firstIdx < buff.length) {
				long[] bucket = buff[firstIdx];
				if (bucket != null && secondIdx < bucket.length && bucket[secondIdx] > 0) {
					result = bucket[secondIdx];
					bucket[secondIdx] |= 0x8000000000000000L;
					secondIdx++;
				} else {
					for (int i = firstIdx + 1; i < buff.length && result == -1L; i++) {
						if (buff[i] != null && buff[i].length > 0 && buff[i][0] > 0) {
							firstIdx = i;
							secondIdx = 0;
							result = buff[firstIdx][secondIdx];
							buff[firstIdx][secondIdx] |= 0x8000000000000000L;
							secondIdx++;
							break; // redundant to "result == -1L" in for loop
						}
					}
				}
			}
			
			// adhere to the general Iterator contract to fail fast and not hand out
			// meaningless values
			if (result == -1L) {
				throw new NoSuchElementException();
			}
			
			// hand out strictly monotonic increasing elements
			Assert.check(previous < result, EC.GENERAL);
			previous = result;
			
			// maintain read statistics
			readElements++;
			
			return result;
		}

		/**
		 * @return The last (largest) element in the iteration (aka the
		 *         underlying buff of buckets).
		 * @exception NoSuchElementException
		 *                if iteration is empty.
		 * 
		 *                Pre-condition: Each bucket is sorted in ascending
		 *                order!
		 */
		public long getLast() {
			int len = buff.length;

			// Walk from the end of buff to the beginning. Each bucket that is
			// found and non-null (null if no fingerprint for such an index has
			// been added to the DiskFPSet) is checked for a valid fingerprint.
			// A fp is valid iff it is larger zero. A zero fingerprint slot
			// indicates an unoccupied slot, while a negative one corresponds to
			// a fp that has already been flushed to disk.
			while (len > 0) {
				long[] bucket = buff[--len];

				// Find last element > 0 in bucket (negative elements have already
				// been flushed to disk, zero indicates an unoccupied slot).
				if (bucket != null) {
					for (int i = bucket.length - 1; i >= 0; i--) {
						if (bucket[i] > 0) {
							return bucket[i];
						}
					}
				}
			}
			// At this point we have scanned the complete buff, but haven't
			// found a single fingerprint that hasn't been flushed to disk
			// already.
			throw new NoSuchElementException();
		}
		
		/**
		 * @return The number of element read with {@link TLCIterator#next()} since
		 *         the creation of this instance.
		 */
		public long reads() {
			return readElements;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/preference/ITLA2TeXPreferenceConstants.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.preference;

/**
 * TLA2TeX preferences
 * 
 * @author <NAME>
 */
public interface ITLA2TeXPreferenceConstants
{
    /**
     * Automatically regenerate the pretty-printed PDF when the
     * corresponding spec is saved.
     */
    public static final String AUTO_REGENERATE = "autoRegenerateOnSave";
    
    /**
     * Shade comments in tla2tex output file
     */
    public static final String SHADE_COMMENTS = "shadeComments";

    /**
     * Do not shade PlusCal algorithm in tla2tex output file
     */
    public static final String NO_PCAL_SHADE = "noPcalShade";

    /**
     * Number lines in tla2tex output file
     */
    public static final String NUMBER_LINES = "numberLines";

    /**
     * Specify latex command to be used
     */
    public static final String LATEX_COMMAND = "latexCommand";

    /**
     * Specify grey level
     */
    public static final String GRAY_LEVEL = "greyLevel";

    /**
     * True if embedded viewer is to be used
     */
    public static final String EMBEDDED_VIEWER = "embeddedViewer";

    /**
     * True if the operating system should open the PDF - currently only used on macOS
     */
    public static final String HAVE_OS_OPEN_PDF = "osHandlesPDF";

	/**
	 * Specify the full qualified path to GraphViz's dot executable.
	 */
	public static final String DOT_COMMAND = "dotCommand";
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/TLCUIActivator.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;
import org.lamport.tla.toolbox.AbstractTLCActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.util.ExecutionStatisticsDialog;
import org.lamport.tla.toolbox.util.UIHelper;
import org.osgi.framework.BundleContext;

import util.ExecutionStatisticsCollector;

/**
 * The activator class controls the plug-in life cycle
 */
public class TLCUIActivator extends AbstractTLCActivator
{
    // The plug-in ID
    public static final String PLUGIN_ID = "org.lamport.tla.toolbox.tool.tlc.ui";

    // The shared instance
    private static TLCUIActivator plugin;

    private Font courierFont;
    private Font outputFont;

    /*
     * The colors used for trace row highlighting. These should be in some
     * central location containing all colors and fonts to make it easy to
     * make them changeable by preferences.
     */
    private Color changedColor;
    private Color addedColor;
    private Color deletedColor;

    // update the CNF content
    /*
    private PerspectiveAdapter perspectiveAdapter = new PerspectiveAdapter() 
    {
        public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective)
        {
            if (TLCPerspective.ID.equals(perspective.getId()))
            {
                ToolboxHandle.setToolboxNCEActive(ModelContentProvider.TLC_NCE, true);
            }
        }

        public void perspectiveDeactivated(IWorkbenchPage page, IPerspectiveDescriptor perspective)
        {
            if (TLCPerspective.ID.equals(perspective.getId()))
            {
                ToolboxHandle.setToolboxNCEActive(ModelContentProvider.TLC_NCE, false);
            }
        }
    };
    */

    /**
     * The constructor
     */
    public TLCUIActivator()
    {
    	super(PLUGIN_ID);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext context) throws Exception
    {
        super.start(context);
        plugin = this;

        changedColor = new Color(null, 255, 200, 200);
        addedColor = new Color(null, 255, 255, 200);
        deletedColor = new Color(null, 240, 240, 255);
        

		if (Display.getCurrent() != null && ExecutionStatisticsCollector.promptUser()) { // Display is null during unit test execution.
			final UIJob j = new UIJob(Display.getCurrent(), "TLA+ execution statistics approval.") {
				@Override
				public IStatus runInUIThread(final IProgressMonitor monitor) {
					new ExecutionStatisticsDialog(false, PlatformUI.createDisplay().getActiveShell()).open();
					return Status.OK_STATUS;
				}
			};
			j.schedule(5 * 60 * 1000L);
		}
    }

    public Color getChangedColor()
    {
        return changedColor;
    }


    public Color getAddedColor()
    {
        return addedColor;
    }


    public Color getDeletedColor()
    {
        return deletedColor;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext context) throws Exception
    {
        // IWorkbenchWindow window = UIHelper.getActiveWindow();
        /*
        if (window != null)
        {
            window.removePerspectiveListener(perspectiveAdapter);
        }*/
        if (courierFont != null)
        {
            courierFont.dispose();
        }
        if (outputFont != null)
        {
            outputFont.dispose();
        }
        
        /*
         * Remove the colors
         */
        addedColor.dispose();
        changedColor.dispose();
        deletedColor.dispose();

        
        plugin = null;
        super.stop(context);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static TLCUIActivator getDefault()
    {
        return plugin;
    }

    public synchronized Font getCourierFont()
    {
        if (courierFont == null)
        {
            courierFont = new Font(UIHelper.getShellProvider().getShell().getDisplay(), "Courier New", 11, SWT.NORMAL);
        }
        return courierFont;
    }

    /**
     * @return
     */
    public Font getOutputFont()
    {
        if (outputFont == null)
        {
            outputFont = new Font(UIHelper.getShellProvider().getShell().getDisplay(), "Courier New", 8, SWT.NORMAL);
        }
        return outputFont;
    }

    /**
     * Returns an image descriptor for the image file at the given
     * plug-in relative path
     *
     * @param path the path
     * @return the image descriptor
     */
    public static ImageDescriptor getImageDescriptor(String path)
    {
        return imageDescriptorFromPlugin(PLUGIN_ID, path);
    }

    /**
     * @param colorRed
     * @return
     */
    public static Color getColor(int color)
    {
        return UIHelper.getShellProvider().getShell().getDisplay().getSystemColor(color);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/StandaloneActivator.java<|end_filename|>
// Copyright (c) Feb 13, 2012 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * @author <NAME>
 */
public class StandaloneActivator extends AbstractUIPlugin {

	private static final int DEBUG_SEVERITY = -1;
	public static final String PLUGIN_ID = "org.lamport.tla.toolbox.product.standalone";
	private static StandaloneActivator plugin;
	
	public StandaloneActivator() {
		plugin = this;
	}

	/**
	 * Returns the shared instance
	 * 
	 * @return the shared instance
	 */
	public static StandaloneActivator getDefault() {
		return plugin;
	}

	/**
	 * Writes a string and a cause into the error category of the log
	 * 
	 * @param string
	 */
	public void logError(String message) {
		getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, message));
	}
	
	/**
	 * Writes a string and a cause into the error category of the log
	 * 
	 * @param string
	 * @param e
	 */
	public void logError(String message, Throwable cause) {
		getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, message, cause));
	}

	/**
	 * Writes a string and a cause into the warning category of the log
	 * 
	 * @param string
	 */
	public void logWarning(String message) {
		getLog().log(new Status(IStatus.WARNING, PLUGIN_ID, message));
	}

	/**
	 * Writes a string and a cause into the warning category of the log
	 * 
	 * @param string
	 */
	public void logWarning(String message, Throwable cause) {
		getLog().log(new Status(IStatus.WARNING, PLUGIN_ID, message, cause));
	}

	/**
	 * Writes a string into some debugging place
	 */
	public void logDebug(String message) {
		logDebug(message, null);
	}

	/**
	 * Writes a string into some debugging place
	 */
	public void logDebug(String message, Throwable cause) {
		getLog().log(new Status(IStatus.INFO, PLUGIN_ID, DEBUG_SEVERITY, message, cause));
	}

	/**
	 * Writes a string into the info category of the log
	 * 
	 * @param string
	 */
	public void logInfo(String message) {
		getLog().log(new Status(IStatus.INFO, PLUGIN_ID, message));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/TLAPMMessage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.output.TagBasedTLAPMOutputIncrementalParser;

import tla2sany.st.Location;
import util.UniqueString;

/**
 * Abstract class for the data in a message of output
 * of the TLAPM.
 * 
 * A message of output consists of field name-value
 * pairs. This class provides a common type to be extended
 * by all objects representing TLAPM messages.
 * 
 * It also contains a static method
 * {@link TLAPMMessage#parseMessage(String, String)} for parsing
 * a single message output by the TLAPM. It returns the appropriate
 * subtype of this class that represents the message.
 * 
 * @author <NAME>
 *
 */
public abstract class TLAPMMessage
{
    public static final String TYPE_FIELD = "type";
    public static final String LOC_FIELD = "loc";
    public static final String STATUS_FIELD = "status";

    /**
     * String that separates the field name from
     * its values, as in
     * 
     * <field-name>:<field-value>
     */
    public static final String FIELD_PAIR_SPLIT = ":";

    /**
     * Type of message containing information
     * on the status of an obligation.
     */
    public static final String OB_STATUS_TYPE = "obligation";
    /**
     * Type of message containing information on the
     * status of a proof step.
     */
    public static final String STEP_STATUS_TYPE = "proof-step";
    /**
     * Type of message containing information on the status
     * of a theorem.
     */
    public static final String THEOREM_STATUS_TYPE = "theorem";
    /**
     * Type of message containing the number of obligations
     * in the region being proved or checked.
     */
    public static final String OB_NUMBER_TYPE = "obligationsnumber";
    /**
     * Type of message containing some sort of warning message.
     */
    public static final String WARNING_TYPE = "warning";
    /**
     * Type of message containing some sort of error message.
     */
    public static final String ERROR_TYPE = "error";

    /**
     * Returns a {@link TLAPMMessage} representing the information
     * contained in proverMessage. The String proverMessage
     * should be the String between the tags @!!BEGIN and @!!END.
     * It can include these tags.
     * 
     * This returns null if no data can be parsed from
     * proverMessage.
     * 
     * @param proverMessage
     * @return
     */
    public static TLAPMMessage parseMessage(String proverMessage, String moduleName)
    {
        // ProverUIActivator.getDefault().logDebug("New message to be parsed : \n" + proverMessage);
        /*
         * The String proverMessage should be of the form
         * 
         * @!!<field-name>:<field-value>
         * @!!<field-name>:<field-value>
         * .
         * .
         * .
         * 
         * One of the field names should be "type".
         * 
         * This method parses the type of the message,
         * then delegates the remaining parsing to the
         * subclass of TLAPM message that corresponds
         * to this type. It delegates this parsing
         * by passing a set of field-name,field-value
         * pairs to a static method of the subclass.
         */

        /*
         * First, we get all field-name, field-value pairs.
         * 
         * We split the string around all occurrences
         * of the delimiter @!!. Trim all strings
         * in between the delimiter and try to parse
         * field names and values.
         */
        String[] fieldStrings = proverMessage.split(TagBasedTLAPMOutputIncrementalParser.DELIM);

        String type = null;

        Map fieldPairs = new HashMap();

        for (int i = 0; i < fieldStrings.length; i++)
        {
            /*
             * The first element of the array may be the empty string.
             */
            if (!(fieldStrings[i].trim().length() == 0))
            {
                /*
                 * The trimmed field string should be of the form
                 * <field-name>:<field-value>
                 * 
                 * Split the field string around the first
                 * occurrence of ":".
                 */
                String[] nameValPair = fieldStrings[i].trim().split(FIELD_PAIR_SPLIT, 2);
                Assert.isTrue(nameValPair.length == 2, "Encountered a flawed field name-value string : "
                        + fieldStrings[i] + "\n in message :" + proverMessage);

                String fieldName = nameValPair[0];
                String fieldValue = nameValPair[1];
                if (fieldName != null && fieldValue != null)
                {
                    if (fieldName.equals(TYPE_FIELD))
                    {
                        type = fieldValue;
                    } else
                    {
                        /*
                         * Put all name,value pairs that
                         * are not the message type into the map.
                         */
                        fieldPairs.put(fieldName, fieldValue);
                    }
                } else
                {
                    ProverUIActivator.getDefault()
                            .logDebug("Null field name or value when parsing message. This is a bug. Message:");
                    ProverUIActivator.getDefault().logDebug(proverMessage);
                }
            }
        }

        if (type != null)
        {
            /*
             * Delegate the remaining parsing to the appropriate
             * subclass.
             */
            if (type.equals(OB_STATUS_TYPE))
            {
                ObligationStatusMessage message = ObligationStatusMessage.getObMessage(fieldPairs.entrySet(),
                        moduleName);
                return message;
            } else if (type.equals(STEP_STATUS_TYPE) || type.equals(THEOREM_STATUS_TYPE))
            {
                StepStatusMessage message = StepStatusMessage.getStepMessage(fieldPairs.entrySet(), moduleName);
                return message;
            } else if (type.equals(OB_NUMBER_TYPE))
            {
                ObligationNumberMessage message = ObligationNumberMessage.getObNumMessage(fieldPairs.entrySet(),
                        moduleName);
                return message;
            } else if (type.equals(WARNING_TYPE))
            {
                WarningMessage message = WarningMessage.getWarningMessage(fieldPairs.entrySet(), moduleName);
                return message;
            } else if (type.equals(ERROR_TYPE))
            {
                ErrorMessage message = ErrorMessage.getErrorMessage(fieldPairs.entrySet(), moduleName);
                return message;
            } else
            {
                ProverUIActivator.getDefault().logDebug("Unsuppported message type " + type);
            }
        } else
        {
            ProverUIActivator.getDefault().logDebug("Type field not found in TLAPM message. The message follows.");
            ProverUIActivator.getDefault().logDebug(proverMessage);
        }
        return null;

        /*
         * This first bad implementations of this method.
         */
        // TLAPMMessage message = new TLAPMMessage();
        //
        // /*
        // * We split the string around all occurrences
        // * of the delimiter @!!. Trim all strings
        // * in between the delimiter and try to parse
        // * field names and values.
        // */
        // String[] fieldStrings = proverMessage.split(TagBasedTLAPMOutputIncrementalParser2.DELIM);
        //
        // // flag indicating if the type field has been found
        // // in the message
        // boolean typeFieldFound = false;
        //
        // String type = null;
        //
        // Map fieldPairs = new HashMap();
        //
        // for (int i = 0; i < fieldStrings.length; i++)
        // {
        // /*
        // * The first element of the array may be the empty string.
        // */
        // if (!fieldStrings[i].trim().isEmpty())
        // {
        // /*
        // * The trimmed field string should be of the form
        // * <field-name>:<field-value>
        // *
        // * Split the field string around the first
        // * occurrence of ":".
        // */
        // String[] nameValPair = fieldStrings[i].trim().split(FIELD_PAIR_SPLIT, 2);
        // Assert.isTrue(nameValPair.length == 2, "Encountered a flawed field name-value string : "
        // + fieldStrings[i]);
        //
        // String fieldName = nameValPair[0];
        // String fieldValue = nameValPair[1];
        // if (fieldName != null && fieldValue != null)
        // {
        // fieldPairs.put(fieldName, fieldValue);
        // if (fieldName.equals(TYPE_FIELD))
        // {
        // typeFieldFound = true;
        // message.type = fieldValue;
        // type = fieldValue;
        // } else if (fieldName.equals(LOC_FIELD))
        // {
        // try
        // {
        // /*
        // * Attempt to parse bl, bc, el, ec from
        // * the field value.
        // *
        // * fieldValue should be of the form:
        // *
        // * "bl:bc:el:ec"
        // *
        // */
        // String[] coordinates = fieldValue.split(":");
        // Assert.isTrue(coordinates.length >= 4, "Not enough coordinates found in location string "
        // + fieldName);
        // message.location = new Location(UniqueString.uniqueStringOf(moduleName), Integer
        // .parseInt(coordinates[0]), Integer.parseInt(coordinates[1]), Integer
        // .parseInt(coordinates[2]), Integer.parseInt(coordinates[3]));
        // } catch (NumberFormatException e)
        // {
        // ProverUIActivator.getDefault().logError("Error parsing location from TLAPM message. Location string : "
        // + fieldValue, e);
        // }
        // } else if (fieldName.equals(OBL_FIELD))
        // {
        // message.obligation = fieldValue;
        // } else if (fieldName.equals(STATUS_FIELD))
        // {
        // message.status = fieldValue;
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("Unknown field name : " + fieldName + ".");
        // }
        // } else
        // {
        // ProverUIActivator
        // .logDebug("Null field name or value when parsing message. This is a bug. Message:");
        // ProverUIActivator.getDefault().logDebug(proverMessage);
        // }
        // }
        // }
        //
        // if (typeFieldFound)
        // {
        // ProverUIActivator.getDefault().logDebug("New message parsed : ");
        // ProverUIActivator.getDefault().logDebug(message.toString());
        // return message;
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("Type field not found in TLAPM message. The message follows.");
        // ProverUIActivator.getDefault().logDebug(proverMessage);
        // }
        //
        // return null;

        // // flag indicating if the type field has been found
        // // in the message
        // boolean typeFieldFound = false;
        //
        // while (matcher.find())
        // {
        // String fieldName = matcher.group(1);
        // String fieldValue = matcher.group(2);
        // if (fieldName != null && fieldValue != null)
        // {
        // if (fieldName.equals(TYPE_FIELD))
        // {
        // typeFieldFound = true;
        // message.type = fieldValue;
        // } else if (fieldName.equals(LOC_FIELD))
        // {
        // try
        // {
        // /*
        // * Attempt to parse bl, bc, el, ec from
        // * the field value.
        // *
        // * fieldValue should be of the form:
        // *
        // * "bl:bc:el:ec"
        // *
        // */
        // String[] coordinates = fieldValue.split(":");
        // Assert.isTrue(coordinates.length >= 4, "Not enough coordinates found in location string "
        // + fieldName);
        // message.location = new Location(UniqueString.uniqueStringOf(moduleName), Integer
        // .parseInt(coordinates[0]), Integer.parseInt(coordinates[1]), Integer
        // .parseInt(coordinates[2]), Integer.parseInt(coordinates[3]));
        // } catch (NumberFormatException e)
        // {
        // ProverUIActivator.getDefault().logError("Error parsing location from TLAPM message. Location string : "
        // + fieldValue, e);
        // }
        // } else if (fieldName.equals(OBL_FIELD))
        // {
        // message.obligation = fieldValue;
        // } else if (fieldName.equals(STATUS_FIELD))
        // {
        // message.status = fieldValue;
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("Unknown field name : " + fieldName + ".");
        // }
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("Null field name or value when parsing message. This is a bug. Message:");
        // ProverUIActivator.getDefault().logDebug(proverMessage);
        // }
        //
        // matcher.region(matcher.end() - TagBasedTLAPMOutputIncrementalParser2.DELIM.length(), matcher.regionEnd());
        // }
        //
        // if (typeFieldFound)
        // {
        // ProverUIActivator.getDefault().logDebug("New message parsed : ");
        // ProverUIActivator.getDefault().logDebug(message.toString());
        // return message;
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("Type field not found in TLAPM message. The message follows.");
        // ProverUIActivator.getDefault().logDebug(proverMessage);
        // }
        //
        // return null;
    }

    /**
     * Parses the location string returned by the prover
     * into an instance of {@link Location}. Null
     * if parsing is unsuccessful.
     * 
     * @param locString
     * @return
     */
    protected static Location parseLocation(String locString, String moduleName)
    {

        try
        {
            /*
             * Attempt to parse bl, bc, el, ec from
             * the locString.
             * 
             * locString should be of the form:
             * 
             * "bl:bc:el:ec"
             * 
             * For tlapm messages, ec corresponds to the
             * column after the last character in the location.
             * For example, if the location described the string
             * "ab", then bc would be n and ec would be n+2.
             * 
             * This is not consistent with SANY Locations, in which
             * the end column corresponds to the column before the last
             * character in the location. In the previous example, bc
             * would be n and ec would be n+1. We want the Locations to be
             * consistent in the Toolbox, so we subtract 1 from the ec
             * reported by the tlapm. 
             */
            String[] coordinates = locString.split(":");
            Assert.isTrue(coordinates.length >= 4, "Not enough coordinates found in location string : " + locString);
            return new Location(UniqueString.uniqueStringOf(moduleName), Integer.parseInt(coordinates[0]), Integer
                    .parseInt(coordinates[1]), Integer.parseInt(coordinates[2]), Integer.parseInt(coordinates[3]) - 1);
        } catch (NumberFormatException e)
        {
            ProverUIActivator.getDefault().logError("Error parsing location from TLAPM message. Location string : " + locString, e);
        }
        return null;

    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/ITLCOutputListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output;

import org.eclipse.jface.text.ITypedRegion;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCRegion;

/**
 * A listener interested in TLC Output status changes for a particular TLC process
 * <br>
 * This class is not intended to be implemented by the clients.<br>
 * This class is not intended to be subclassed by the clients.<br>
 * 
 * @author <NAME>
 */
public interface ITLCOutputListener
{
    /**
     * Retrieves the process name of TLC 
     * @return the name to identify the TLC instance
     */
    public Model getModel();

    /**
     * Reports new output.
     * 
     * The new output comes in the form
     * of an {@link ITypedRegion} and the text represented by the region. The region
     * was originally created to point to a document. using the region's offset and
     * length when the region was created. However, the document may have changed
     * since the region was created, so its offset and length may not correspond to
     * anything useful. For this reason, the text originally pointed to by the region
     * is passed in.
     * 
     * The type of the region is useful, and if it is a {@link TLCRegion}, then it could contain other
     * useful information.
     */
    public void onOutput(ITypedRegion region, String text);

    /**
     * Reports end of output
     */
    public void onDone();

    /**
     * Informs the listener that a new source has replaced an existing source.
     */
    public void onNewSource();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/HelpHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Handles the help 
 * @author <NAME>
 * @version $Id$
 */
public class HelpHandler extends AbstractHandler implements IHandler
{

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        UIHelper.showDynamicHelp();
        /*// This may take a while, so use the busy indicator
        BusyIndicator.showWhile(null, new Runnable() {
            public void run()
            {
                UIHelper.getActiveWindow().getWorkbench().getHelpSystem().displayDynamicHelp();
                // the following ensure that the help view receives focus
                // prior to adding this, it would not receive focus if
                // it was opened into a folder or was already
                // open in a folder in which another part had focus
                IViewPart helpView = UIHelper.findView("org.eclipse.help.ui.HelpView");
                if (helpView != null && UIHelper.getActiveWindow() != null
                        && UIHelper.getActiveWindow().getActivePage() != null)
                {
                    UIHelper.getActiveWindow().getActivePage().activate(helpView);
                }
            }
        });*/
        return null;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/DistApp.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:25:56 PST by lamport
//      modified on Thu May 31 13:22:22 PDT 2001 by yuanyu

package tlc2.tool.distributed;

import java.rmi.RemoteException;

import tlc2.tool.IStateFunctor;
import tlc2.tool.TLCState;
import tlc2.tool.TLCStateInfo;
import tlc2.tool.TraceApp;
import tlc2.tool.WorkerException;

/**
 * @author <NAME>
 */
public abstract class DistApp implements TraceApp {

	// TLCServer
	public abstract Boolean getCheckDeadlock();

	// TLCServer
	public abstract Boolean getPreprocess();

	// TLCServer
	public abstract String getFileName();

	// TLCServer
	public abstract String getMetadir();

	// TLCServer
	public abstract boolean canRecover();

	// Returns a list of initial states.
	// TLCServer
	public abstract void getInitStates(IStateFunctor functor);

	// Returns a list of successor states of the state s. /
	// TLCServer
	public abstract TLCState[] getNextStates(TLCState s) throws WorkerException, RemoteException;

	// Checks if the state is a valid state.
	// TLCServer, TLCWorker
	public abstract void checkState(TLCState s1, TLCState s2)
			throws WorkerException;

	// Checks if the state satisfies the state constraints.
	// TLCServer, TLCWorker
	public abstract boolean isInModel(TLCState s);

	// Checks if a pair of states satisfy the action constraints.
	// TLCWorker
	public abstract boolean isInActions(TLCState s1, TLCState s2);

	// Reconstruct the initial state whose fingerprint is fp.
	// TLCTrace
	/* (non-Javadoc)
	 * @see tlc2.tool.TraceApp#getState(long)
	 */
	public abstract TLCStateInfo getState(long fp);

	// Reconstruct the next state of state s whose fingerprint is fp.
	// TLCTrace
	/* (non-Javadoc)
	 * @see tlc2.tool.TraceApp#getState(long, tlc2.tool.TLCState)
	 */
	public abstract TLCStateInfo getState(long fp, TLCState s);

	// Reconstruct the info for the transition from s to s1. /
	// TLCTrace
	/* (non-Javadoc)
	 * @see tlc2.tool.TraceApp#getState(tlc2.tool.TLCState, tlc2.tool.TLCState)
	 */
	public abstract TLCStateInfo getState(TLCState s1, TLCState s);

	// Enables call stack tracing.
	// TLCServer
	public abstract void setCallStack();

	// Prints call stack.
	// TLCServer
	public abstract String printCallStack();

	/**
	 * @return The specification root directory
	 */
	// TLCServer
	public abstract String getSpecDir();

	/**
	 * @return The (qualified) configuration file name
	 */
	// TLCServer
	public abstract String getConfigName();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/concepts/subspec1.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
	<title>SubConceptText</title>
</head>

<body>
<h1>Sub Concept number 1</h1>
Please enter your text here. this is ..doc/html/concepts/subspec1.html.

<p>

Here is a pointer to <A href = "subspec2.html">subspec2</a>.

<p>

Here is a pointer to <A href = "../gettingstarted/maintopic.html">something else</a>.
</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/FontPreferenceChangeListener.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.util.Vector;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Control;

/**
 * This should be used by editors or views that need to update the font of controls
 * when a user changes a font preference.
 * 
 * The class should be instantiated with a list of controls whose font should be updated
 * with the font named fontName. The font name may be found in the plug-in if the font
 * definition is declared in that way or in the name of the field in a preference page
 * if the font preference is added that way.
 * 
 * Additional controls can be added to the list of controls to be updated by calling
 * {@link FontPreferenceChangeListener#addControl(Control)}.
 * 
 * This should be added as a listener to {@link JFaceResources#getFontRegistry()}.
 * 
 * @author <NAME>
 *
 */
public class FontPreferenceChangeListener implements IPropertyChangeListener
{
    private Vector controls;
    private String preferenceName;

    /**
     * Constructor.
     * 
     * @param controls list of controls whose font should be set when the preference corresponding to
     * preferenceName is changed. If null, then no controls will be notified until added using addControl().
     * @param fontName name of the font that the controls to which the controls should be set
     */
    public FontPreferenceChangeListener(Vector controls, String fontName)
    {
        if (controls != null)
        {
            this.controls = controls;
        } else
        {
            this.controls = new Vector();
        }
        this.preferenceName = fontName;
    }

    public void propertyChange(PropertyChangeEvent event)
    {
        if (event.getProperty().equals(preferenceName))
        {
            for (int i = 0; i < controls.size(); i++)
            {
                ((Control) controls.get(i)).setFont(JFaceResources.getFont(preferenceName));
            }
        }
    }

    /**
     * Adds a control to the set of controls whose font should be
     * set when the preference corresponding to preferenceName is changed
     * 
     * @param control
     */
    public void addControl(Control control)
    {
        controls.add(control);
    }

    /**
     * Removes a control from the set of controls whose font should be
     * set when the preference corresponding to preferenceName is changed
     * 
     * @param control
     */
    public void removeControl(Control control)
    {
        controls.remove(control);
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/PDFViewingPage.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;

/**
 * Contains a browser for viewing pdf files. Used as a page in
 * TLAEditorAndPDFViewer.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class PDFViewingPage extends FormPage
{

    Browser browser;
    Composite body;

    public PDFViewingPage(FormEditor editor, String id, String title)
    {
        super(editor, id, title);
    }

    protected void createFormContent(IManagedForm managedForm)
    {
        body = managedForm.getForm().getBody();
        body.setLayout(new FillLayout());
        browser = new Browser(body, SWT.NONE);

        super.createFormContent(managedForm);
    }

    public Browser getBrowser()
    {
        return browser;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools.impl.distributed/src/org/lamport/tlatools/impl/distributed/OSGiPrintStream.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tlatools.impl.distributed;

import java.io.PipedOutputStream;
import java.io.PrintStream;

import util.ToolIO;

public class OSGiPrintStream extends PrintStream {

	private final String prefix;

	public OSGiPrintStream(final String prefix) {
		super(new PipedOutputStream());
		this.prefix = prefix + ": ";
		ToolIO.out = this;
		ToolIO.err = this;
	}

	/* (non-Javadoc)
	 * @see java.io.PrintStream#print(java.lang.String)
	 */
	public void print(String str) {
		System.out.print(prefix + str);
	}

	/* (non-Javadoc)
	 * @see java.io.PrintStream#println(java.lang.String)
	 */
	public void println(String str) {
		System.out.println(prefix + str);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MultiFPSet.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:16:00 PST by lamport
//      modified on Tue May 15 11:44:57 PDT 2001 by yuanyu

package tlc2.tool.fp;

import java.io.IOException;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

import tlc2.output.EC;
import tlc2.tool.TLCTrace;
import tlc2.tool.TLCTrace.Enumerator;
import util.Assert;

/**
 * An <code>MultiFPSet</code> is a set of 64-bit fingerprints.
 */
@SuppressWarnings("serial")
public class MultiFPSet extends FPSet {

	/**
	 * Indicates that child {@link FPSet} should allocate the built-in amount of memory
	 */
	private static final int MEM_DEFAULT = -1;

	public static final int MAX_FPBITS = 30;
	public static final int MIN_FPBITS = 0;

	/**
	 * Contains all nested {@link FPSet}s 
	 */
	protected final List<FPSet> sets;

	/**
	 * Amount of leftmost bits used to determine nested {@link FPSet}
	 */
	protected int fpbits;

	/**
	 * Create a MultiFPSet with 2^bits FPSets.
	 * @param bits [1,30]
	 */
	public MultiFPSet(final FPSetConfiguration fpSetConfiguration) throws RemoteException {
		super(fpSetConfiguration);

		int bits = fpSetConfiguration.getFpBits();
		long fpMemSize = fpSetConfiguration.getMemoryInBytes();
		
	    // LL modified error message on 7 April 2012
		Assert.check(bits > 0 && bits <= MAX_FPBITS, "Illegal number of FPSets found.");
		
		if (fpMemSize == MEM_DEFAULT) {
			fpMemSize = HeapBasedDiskFPSet.DefaultMaxTblCnt / 20;
		}

		this.sets = getNestedFPSets(fpSetConfiguration);
		this.fpbits = 64 - bits;
	}

	protected List<FPSet> getNestedFPSets(final FPSetConfiguration fpSetConfiguration) throws RemoteException {
		final List<FPSet> s = new ArrayList<>(fpSetConfiguration.getMultiFPSetCnt());
		for (int i = 0; i < fpSetConfiguration.getMultiFPSetCnt(); i++) {
			s.add(FPSetFactory.getFPSet(new MultiFPSetConfiguration(fpSetConfiguration)));
		}
		return s;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#init(int, java.lang.String, java.lang.String)
	 */
	public final FPSet init(final int numThreads, final String metadir, final String filename) throws IOException {
		IntStream.range(0, this.sets.size()).parallel().forEach(i -> {
			try {
				sets.get(i).init(numThreads, metadir, filename + "_" + i);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		});
		return this;
	}

	
	@Override
	public void incWorkers(final int num) {
		sets.stream().forEach(s -> s.incWorkers(num) );
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#size()
	 */
	public final long size() {
		/* Returns the number of fingerprints in this set. */
		return sets.parallelStream().mapToLong(FPSet::size).sum();
	}
	
	/**
	 * @param fp
	 * @return Partition given fp into the {@link FPSet} space 
	 */
	protected FPSet getFPSet(long fp) {
		// determine corresponding fpset (using unsigned right shift)
		// shifts a zero into the leftmost (msb) position of the first operand for right operand times
		// and cast it to int loosing the leftmost 32 bit
		final int idx = (int) (fp >>> this.fpbits);
		return this.sets.get(idx);
	}

	/**
	 * Returns <code>true</code> iff the fingerprint <code>fp</code> is in this
	 * set. If the fingerprint is not in the set, it is added to the set as a
	 * side-effect.
	 * 
	 * @see tlc2.tool.fp.FPSet#put(long)
	 */
	public final boolean put(long fp) throws IOException {
		return getFPSet(fp).put(fp);
	}

	/**
	 * Returns <code>true</code> iff the fingerprint <code>fp</code> is in this
	 * set.
	 * 
	 * @see tlc2.tool.fp.FPSet#contains(long)
	 */
	public final boolean contains(long fp) throws IOException {
		return getFPSet(fp).contains(fp);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#close()
	 */
	public final void close() {
		for (FPSet fpSet : sets) {
			fpSet.close();
		}
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#unexportObject(boolean)
	 */
	public void unexportObject(boolean force) throws NoSuchObjectException {
		for (FPSet fpSet : sets) {
			fpSet.unexportObject(force);
		}
		UnicastRemoteObject.unexportObject(this, force);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#checkFPs()
	 */
	public final long checkFPs() throws IOException {
		return sets.parallelStream().mapToLong(s -> {
			try {
				return s.checkFPs();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}).min().orElse(Long.MAX_VALUE);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#checkInvariant()
	 */
	public boolean checkInvariant() throws IOException {
		return sets.parallelStream().allMatch(s -> {
			try {
				return s.checkInvariant();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		});
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#exit(boolean)
	 */
	public final void exit(boolean cleanup) throws IOException {
	    super.exit(cleanup);
		for (FPSet fpSet : sets) {
			fpSet.exit(cleanup);
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#beginChkpt()
	 */
	public final void beginChkpt() throws IOException {
		for (FPSet fpSet : sets) {
			fpSet.beginChkpt();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#commitChkpt()
	 */
	public final void commitChkpt() throws IOException {
		for (FPSet fpSet : sets) {
			fpSet.commitChkpt();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recover()
	 */
	public final void recover(TLCTrace trace) throws IOException {
		final Enumerator elements = trace.elements();
		while (elements.nextPos() != -1) {
			long fp = elements.nextFP();
			getFPSet(fp).recoverFP(fp);
		}
		elements.close();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recoverFP(long)
	 */
	public final void recoverFP(long fp) throws IOException {
		Assert.check(!this.put(fp), EC.TLC_FP_NOT_IN_SET);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#beginChkpt(java.lang.String)
	 */
	public final void beginChkpt(String filename) throws IOException {
		IntStream.range(0, this.sets.size()).parallel().forEach(i -> {
			try {
				sets.get(i).beginChkpt(filename + "_" + i);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		});
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#commitChkpt(java.lang.String)
	 */
	public final void commitChkpt(String filename) throws IOException {
		IntStream.range(0, this.sets.size()).parallel().forEach(i -> {
			try {
				sets.get(i).commitChkpt(filename + "_" + i);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		});
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recover(java.lang.String)
	 */
	public final void recover(String filename) throws IOException {
		IntStream.range(0, this.sets.size()).parallel().forEach(i -> {
			try {
				sets.get(i).recover(filename + "_" + i);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		});
	}

	public FPSet[] getFPSets() {
		return sets.toArray(new FPSet[sets.size()]);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/tool/SpecRenameEvent.java<|end_filename|>
package org.lamport.tla.toolbox.tool;

import org.eclipse.core.runtime.Assert;
import org.lamport.tla.toolbox.spec.Spec;

public class SpecRenameEvent extends SpecEvent {

	private final Spec newSpec;

	public SpecRenameEvent(final Spec spec, final Spec newSpec) {
		super(spec, SpecEvent.TYPE_RENAME);
		Assert.isNotNull(newSpec);
		this.newSpec = newSpec;
	}

	public Spec getNewSpec() {
		return newSpec;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ProofFoldCommandHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;

/**
 * Abstract base handler for fold command handling.
 * 
 * Subclasses can extend by implementing the {@link ProofFoldCommandHandler#setEnabled(Object)} method
 * to enable and disable the handler. This has the effect of graying out any menu items for the
 * command if the handler is disabled. The {@link ProofFoldCommandHandler#setEnabled(Object)}
 * method seems to be called just before such menu items are rendered in the UI and
 * just before the handler is executed.
 * 
 * @author <NAME>
 *
 */
public abstract class ProofFoldCommandHandler extends AbstractHandler
{

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();

        if (editor != null)
        {
            editor.runFoldOperation(event.getCommand().getId());
        }

        return null;
    }
	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (EditorUtil.getTLAEditorWithFocus() == null) {
			return false;
		}
		return super.isEnabled();
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/update/update-preferences.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<HEAD>

<meta name="copyright" content="Copyright (c) IBM Corporation and others 2008. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." >

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="../style.css" rel="stylesheet" CHARSET="ISO-8859-1" TYPE="text/css">
<title>Scheduling automatic updates</title>
</HEAD>

<BODY BGCOLOR="#ffffff">
<h1>Scheduling automatic updates</h1>
<p>
You can configure the Toolbox update installer to automatically search for updates 
on a periodic basis.&nbsp; 

You can configure how these updates
are scheduled and performed from the 
<b>Automatic Update</b> <a href="../gettingstarted/preferences.html">preferences page</a>.&nbsp;

Checking the box at the top of the page enables automatic searching for and notification of available
updates.&nbsp;  
<p>
You can also opt-in to receive experimental features of the TLA Toolbox and TLC. Note though, that 
experimental features might not work as intended and can lead to bogus behavior. Not for the faint-hearted.</p>

The rest of the preference page then allows you to schedule the search and notification.
</p>
<h3>Update schedule</h3>
<p>You can choose among the following
schedules for checking for updates:</p>
<ul>
  <li>No automatic search</li>
  <li>On each startup (default)</li>
  <li>Every day at a specific time (e.g., 3:00PM)</li>
  <li>On a scheduled day of the week at a specific time (e.g., Monday 8:00AM)</li>
</ul>
<p>If the Toolbox is not running at the
scheduled time, the search will be done when the Toolbox is next started. 

</p>
<h3>Download options</h3>
<p>If you schedule for updates to be checked, you can choose whether or not
  to download (but not install) the new updates before notifying you.
</p>

<h3>When updates are found</h3>

<p>When a notification popup appears, you have the choice of either updating or deferring.&nbsp;
 
If you  defer the update, a preference determines if the notification pops up
again and, if so, when.

<!-- Some content reused from https://help.eclipse.org/oxygen/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Freference%2Fref-net-preferences.htm -->

<h3>Network Connections</h3>
If your network environment requires you to setup proxy servers to connect to the internet, you can do so on the
Network Connections preference page found under <strong>General > Network Connections</strong>.

The <i>Active Provider</i> instructs the Toolbox to use no proxy server (Direct), use the system's proxy server 
(Native) or the manually defined ones (Manual). 

<ul>
  <li>Choosing the <i>Direct</i> provider causes all the connections to be opened without the use of a proxy server.</li>
  <li><i>Native</i> causes settings that were discovered in the operating system to be used (does not work on macOS).</li>
  <li>Selecting <i>Manual</i> causes settings defined in the <i>Proxy entries</i> table below to be used.</li>
</ul>

<p>
When using the Manual provider there are three predefined schemas to set settings for: HTTP, HTTPS and SOCKS.
Configuration for each schema is displayed in the <i>Proxy entries</i> table. To edit settings for a particular
schema double-click the entry or select the entry and click Edit... button.
</p>

<p>
The <i>Proxy bypass</i> table is only relevant for advanced use cases when different proxies need to be configured
to access different computers on the internet. Most users can ignore the <i>Proxy bypass</i> table.
</p>

Please ask your network administrator if the Toolbox fails to access the internet and you do not know what to enter.

<hr>
<a href="run-update.html">&uarr; Updating the Toolbox</a>
</hr>

</BODY>
</HTML>


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/AddModuleHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tlc2.output.SpecWriterUtilities;

/**
 * Command handler for adding new modules (opening non-existing modules or modules in the directory of the root module)
 * 
 * @author <NAME>
 * @version $Id$
 * 
 */
public class AddModuleHandler extends AbstractHandler implements IHandler
{
    public static final String[] ACCEPTED_EXTENSIONS = { "*.tla", "*.*" };
    public static final String COMMAND_ID = "toolbox.command.module.add";

    /**
     * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);

        Spec spec = Activator.getSpecManager().getSpecLoaded();

        FileDialog openFileDialog = UIHelper.getFileDialog(window.getShell());
        openFileDialog.setText("Add TLA+ module to the spec");
        openFileDialog.setFilterPath(ResourceHelper.getParentDirName(spec.getRootFile()));

        openFileDialog.setFilterExtensions(ACCEPTED_EXTENSIONS);
        String moduleFileName = openFileDialog.open();
        if (moduleFileName != null)
        {
            IFile module = ResourceHelper.getLinkedFile(spec.getProject(), moduleFileName, false);

            // add .tla extension is the file does not have any extension
            if (module != null && module.getFileExtension() == null)
            {
                moduleFileName = ResourceHelper.getModuleFileName(moduleFileName);
                module = ResourceHelper.getLinkedFile(spec.getProject(), moduleFileName, false);
            }

            // check if it a TLA file
            if (!ResourceHelper.isModule(module))
            {
                // selected non-TLA file
                // module exists and is already registered in the spec
                MessageDialog.openInformation(window.getShell(), "The selected file is not a TLA+ file",
                        "The provided file " + module.getName()
                                + " is not a TLA+ file.\n Please select a file with .tla extension.");
                return null;

            } else
            {
                if (module.isLinked())
                {
                    // module exists and is already registered in the spec
                    MessageDialog.openInformation(window.getShell(), "TLA+ Module is part of the spec",
                            "The provided module " + module.getName()
                                    + " has already been added to the specification previously.");
                } else
                {
                    IPath modulePath = new Path(moduleFileName);
                    // check the folder we are in
                    if (!ResourceHelper.isProjectParent(modulePath.removeLastSegments(1), spec.getProject()))
                    {
						// the selected resource is not in the same directory as
						// the root file
						MessageDialog.openInformation(window.getShell(), "TLA+ Module is not part of the current spec.",
								"The provided module " + module.getName()
										+ " is not part of the spec which is currently open. It will therefore be opened in read-only mode.\n"
										+ "If you want to make changes to this file, you will have to open the corresponding spec first.");

						// Open TLA's read-only editor on a .tla file that does
						// *not* belong to the current spec. It is opened
						// read-only, because we want to allow any changes,
						// because we couldn't parse the spec anyway. The reason
						// why this functionality is offered, is to allow users
						// to look at .tla files of closed spec.
						// http://wiki.eclipse.org/FAQ_How_do_I_open_an_editor_on_a_file_outside_the_workspace%3F
						final IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(moduleFileName));
						if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) {
							UIHelper.openEditor("org.lamport.tla.toolbox.editor.basic.TLAEditorReadOnly",
									new FileStoreEditorInput(fileStore));
						} else {
							throw new ExecutionException(moduleFileName
									+ " cannot be opened in read-only mode because its file content could not be obtained.");
						}
                        return null;
                    }

                    // !module.exists()
                    if (!modulePath.toFile().exists())
                    {
                        // the provided file does not exist
                        boolean createNew = MessageDialog.openQuestion(window.getShell(), "TLA+ Module is not found",
                                "The provided module " + module.getName()
                                        + " does not exist. Should the new file be created?");
                        if (createNew)
                        {
                            // the module point to a virtual path /WS_ROOT/SPEC_NAME/module_name.tla
                            // assuming the fact that the root file is located in directory /ROOT_DIR/SPEC_NAME.tla
                            // and the Spec's project name is /ROOT_DIR/SPEC_NAME.project
                            // the file should be created in /ROOT_DIR/module_name.tla and linked to the virtual path.

                            try
                            {
                                ResourcesPlugin.getWorkspace().run(
                                        ResourceHelper.createTLAModuleCreationOperation(modulePath), null);
                            } catch (CoreException e)
                            {
                                e.printStackTrace();
                                // exception, no chance to recover
                                return null;
                            }
                        } else
                        {
                            return null;
                        }
                    }
                    // adding the file to the spec
					module = createModuleFile(spec, moduleFileName, modulePath);
                }

                // create parameters for the handler
                Map<String, String> parameters = new HashMap<String, String>();
                parameters.put(OpenModuleHandler.PARAM_MODULE, SpecWriterUtilities.getModuleNameChecked(module.getName(),
                        false));

                // runs the command and opens the module in the editor
                UIHelper.runCommand(OpenModuleHandler.COMMAND_ID, parameters);
            }
        }

        return null;
    }

	public IFile createModuleFile(final Spec spec, String moduleFileName, final IPath modulePath) {
		// Convert the OS specific absolute path to an Eclipse
		// specific relative one that is portable iff the resource
		// is in the project's folder hierarchy.
		// Technically this will always evaluate to true. One of the
		// checks above makes sure that one can only add modules
		// residing in the project's parent.
		if (ResourceHelper.isProjectParent(modulePath.removeLastSegments(1), spec.getProject())) {
			moduleFileName = ResourceHelper.PARENT_ONE_PROJECT_LOC + modulePath.lastSegment();
		}
		// adding the file to the spec
		return ResourceHelper.getLinkedFile(spec.getProject(), moduleFileName, true);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (Activator.getSpecManager().getSpecLoaded() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/drivers/FrontEndException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.drivers;

/**
 * Exception thrown by SANY on errors
 * @author <NAME>
 */
public class FrontEndException extends Exception {
    // SZ Feb 20, 2009: fixed the exception chaining
    // instead of having the cause as a member, the 
    // exception now has it in trace
    // also changed the visibility to public
	public FrontEndException(final Exception cause) {
		super(cause);
    }
    
    public FrontEndException(final String msg) {
    	super(msg);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/queue/StateQueue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:27 PST by lamport
//      modified on Tue Feb 13 18:38:24 PST 2001 by yuanyu

package tlc2.tool.queue;

import java.io.IOException;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.StateVec;
import tlc2.tool.TLCState;
import tlc2.tool.Worker;

/**
 * 
 */
// TODO-MAK - Why do consumer/producer game on StateQueue when workers could
// maintain thread local StateQueue until it gets empty?
public abstract class StateQueue implements IStateQueue {
	/**
	 * In model checking, this is the sequence of states waiting to be explored
	 * further. When the queue is empty, the checking is completed.
	 */
	protected long len = 0; // the queue length
	private int numWaiting = 0; // the number of waiting threads
	private volatile boolean finish = false; // terminate
	/**
	 * Signals {@link Worker} that checkpointing is going happen next.
	 */
	private boolean stop = false; // suspend all workers.
	/**
	 * Synchronizes between workers and checkpointing. More precisely it is used
	 * to notify (wake up) the checkpointing thread once the last worker is
	 * done.
	 */
	private Object mu = new Object();

	/* Enqueues the state. It is not thread-safe. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#enqueue(tlc2.tool.TLCState)
	 */
	public final void enqueue(final TLCState state) {
		this.enqueueInner(state);
		this.len++;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#dequeue()
	 */
	public final TLCState dequeue() {
		if (isEmpty()) {
			return null;
		}
		final TLCState state = this.dequeueInner();
		this.len--;
		return state;
	}

	/* Enqueues a state. Wake up any waiting thread. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#sEnqueue(tlc2.tool.TLCState)
	 */
	public final synchronized void sEnqueue(final TLCState state) {
		this.enqueueInner(state);
		this.len++;
		if (this.numWaiting > 0 && !this.stop) {
			this.notifyAll();
		}
	}

	/* Enqueues a list of states. Wake up any waiting thread. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#sEnqueue(tlc2.tool.TLCState[])
	 */
	public final synchronized void sEnqueue(final TLCState states[]) {
		for (int i = 0; i < states.length; i++) {
			this.enqueueInner(states[i]);
		}
		this.len += states.length;
		if (this.numWaiting > 0 && !this.stop) {
			this.notifyAll();
		}
	}
	
	public final synchronized void sEnqueue(final StateVec stateVec) {
		int cnt = 0;
		for (int j = 0; j < stateVec.size(); j++) {
			TLCState state = stateVec.elementAt(j);
			if (state != null) {
				this.enqueueInner(state);
				cnt++;
			}
		}
		this.len += cnt;
		if (this.numWaiting > 0 && !this.stop) {
			this.notifyAll();
		}
	}


	public final synchronized TLCState sPeek() {
		if (this.isAvail()) {
			return this.peekInner();
		}
		return null;
	}

	/* Return the first element in the queue. Wait if empty. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#sDequeue()
	 */
	public final synchronized TLCState sDequeue() {
		if (this.isAvail()) {
			final TLCState state = this.dequeueInner();
			// LL modified error message on 7 April 2012
			assert state != null : "Null state found on queue";
			this.len--;
			return state;
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#sDequeue(int)
	 */
	public final synchronized TLCState[] sDequeue(int cnt) {
		assert cnt > 0 : "Nonpositive number of states requested.";
		if (this.isAvail()) {
			if (cnt > len) {
				// in this case, casting len to int is safe 
				cnt = (int) len;
			}
			final TLCState states[] = new TLCState[cnt];
			int idx;
			for (idx = 0; idx < cnt && this.len > 0; idx++) {
				states[idx] = this.dequeueInner();
				this.len--;
			}
			if (idx == cnt) {
				return states;
			}

			// cnt >= index, shrink resulting array
			// dead code due to resetting cnt == len if cnt > len
			final TLCState res[] = new TLCState[idx];
			for (int i = 0; i < idx; i++) {
				res[i] = states[i];
			}
			return res;
		}
		return null;
	}

	/**
	 * Checks if states are available. If no states are available, the callee
	 * will be put to sleep until new states are available or another callee
	 * signals work done. This is determined by the fact, that all other workers
	 * are waiting for states.
	 * 
	 * @return true if states are available in the queue.
	 */
	private final boolean isAvail() {
		/*
		 * isAvail is only called from within sDequeue() and sDequeue(..) and
		 * thus is always synchronized on this.
		 */
		
		if (this.finish) {
			return false;
		}
		while (isEmpty() || this.stop) {
			this.numWaiting++;
			// the last worker accessing notices that all other workers are
			// waiting. This indicates that all work is done.
			if (this.numWaiting >= TLCGlobals.getNumWorkers()) {
				if (isEmpty()) {
					this.numWaiting--;
					return false;
				}
				// TODO what happens if control flow exits without ever
				// notifying the checkpoint (mu.wait()) thread? In case
				// of distributed TLC, this is the main thread of
				// TLCServer.
				synchronized (this.mu) {
					this.mu.notify();
				}
			}
			try {
				this.wait();
			} catch (Exception e) {
				MP.printError(EC.GENERAL, "making a worker wait for a state from the queue", e);  // LL changed call 7 April 2012
				System.exit(1);
			}
			this.numWaiting--;
			if (this.finish) {
				return false;
			}
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#finishAll()
	 */
	public synchronized void finishAll() {
		this.finish = true;
		// Notify all other worker threads.
		this.notifyAll();
		// Need to wake main thread that waits (mu.wait()) to suspend access to
		// the squeue (see suspendAll). The main thread might attempt to do its
		// periodic work (tlc2.tool.ModelChecker.doPeriodicWork()) the moment
		// all worker threads finish. Since suspendAll assumes the main thread
		// is woken up (potentially) multiple times from sleeping indefinitely
		// in the while loop before it finally returns after locking the
		// StateQueue, we have to live up to this assumption.
		//
		// synchronized(this.mu) does not block when the main thread waits on
		// this.mu in suspend all. We merely have to follow proper thread access.
		synchronized (this.mu) {
			// Technically notify() would do.
			this.mu.notify();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#suspendAll()
	 */
	public final boolean suspendAll() {
		boolean needWait = false;
		synchronized (this) {
			if (this.finish) {
				return false;
			}
			this.stop = true;
			needWait = needsWaiting();
		}
		// Wait for all worker threads to stop.
		while (needWait) {
			synchronized (this.mu) {
				try {
					// finishAll & suspendAll race:
					//
					// suspendAll from main is on the heels of finishAll, but
					// not quite as fast. SuspendAll's synchronized(this.mu)
					// is executed one clock tick after finishAll's thus waiting
					// for finishAll() to notify all waiters of this.mu.
					// With main being the only potential waiter in the system
					// nobody gets notified and the lock on this released
					// subsequently.
					// Now it's suspendAll's turn. It acquires the lock on
					// this.mu and immediately after goes to wait on it
					// (this.mu) to be waken by worker threads eventually.
					// Unfortunately, there are none left in the system. All
					// have long finishedAll.
					//
					// The fix is to check the this.finish variable one more
					// time directly after suspendAll acquires the lock this.mu,
					// it checks if it still has to wait for workers. To make
					// sure it reads the most recent value, it's declared
					// volatile to establish a happens-before relation (since
					// Java5's memory model) between workers and main. Otherwise
					// the VM might decide to let main read a cached value of
					// false of this.finish.
					if (this.finish) {
						return false;
					}
					// waiting here assumes that subsequently a worker
					// is going to wake us up by calling isAvail() or
					// this.mu.notify*()
					this.mu.wait();
				} catch (Exception e) {
					MP.printError(EC.GENERAL, "waiting for a worker to wake up", e);  // LL changed call 7 April 2012
					System.exit(1);
				}
			}
			synchronized (this) {
				if (this.finish) {
					return false;
				}
				needWait = needsWaiting();
			}
		}
		return true;
	}
	
	/**
	 * @return
	 */
	private boolean needsWaiting() {
		//MAK 04/2012: Commented to fix an EOFException when liveness checking is enabled 
//		// no need to wait without workers present
//		if (this.numWaiting < 1) {
//			return false;
//		}
		// if all workers wait at once, it indicates that all work is
		// done and suspending all workers can happen right away without
		// waiting.
		return this.numWaiting < TLCGlobals.getNumWorkers();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#resumeAll()
	 */
	public final synchronized void resumeAll() {
		this.stop = false;
		this.notifyAll();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#resumeAllStuck()
	 */
	public void resumeAllStuck() {
		// needsWaiting() read might have been incorrect if a TLCWorkerRMI dies
		// unexpectedly, thus this recovers a potentially stuck checkpointing
		// run.
		if (stop) {
			synchronized (mu) {
				mu.notifyAll();
			}
		}
		// 
		if (!stop && !isEmpty() && this.numWaiting > 0) {
			synchronized (this) {
				this.notifyAll();
			}
		}
	}

	/* This method returns the size of the state queue. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#size()
	 */
	public final long size() {
		return this.len;
	}

	/**
	 * @return true iff the inner queue does not contain states
	 */
	public boolean isEmpty() {
		return len < 1;
	}

	/* This method must be implemented in the subclass. */
	abstract void enqueueInner(TLCState state);

	/* This method must be implemented in the subclass. */
	abstract TLCState dequeueInner();

	/* This method must be implemented in the subclass. */
	abstract TLCState peekInner();
	
	/* Checkpoint. */
	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#beginChkpt()
	 */
	public abstract void beginChkpt() throws IOException;

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#commitChkpt()
	 */
	public abstract void commitChkpt() throws IOException;

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#recover()
	 */
	public abstract void recover() throws IOException;
	
	@Override
	public void delete() throws IOException {
		// no-op
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/OffHeapDiskFPSet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.ToLongFunction;
import java.util.logging.Level;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.fp.LongArrays.LongComparator;
import tlc2.tool.fp.management.DiskFPSetMXWrapper;
import tlc2.util.BufferedRandomAccessFile;
import util.Assert;

/**
 * see OpenAddressing.tla
 */
@SuppressWarnings({ "serial" })
public final class OffHeapDiskFPSet extends NonCheckpointableDiskFPSet implements FPSetStatistic {
	
	private static class OffHeapSynchronizer {
		
		private final Set<OffHeapDiskFPSet> sets = new HashSet<OffHeapDiskFPSet>();
		
		private final AtomicBoolean flusherChosen = new AtomicBoolean();
		
		// This barrier gets run after one thread signals the need to suspend
		// put and contains operations to evict to secondary. Signaling is done
		// via the flusherChoosen AtomicBoolean. All threads (numThreads) will
		// then await on the barrier and the Runnable be executed when the
		// last of numThreads arrives.
		// Compared to an AtomicBoolean, the barrier operation use locks and
		// are thus comparably expensive.
		private final Phaser phaser = new Phaser(1) {

			@Override
			protected boolean onAdvance(int phase, int registeredParties) {
				// Atomically evict and reset flusherChosen to make sure no
				// thread re-read flusherChosen=true after an eviction and
				// waits again.
				for (OffHeapDiskFPSet set : sets) {
					set.evict();
				}

				// Release exclusive access. It has to be done by the runnable
				// before workers waiting on the barrier wake up again.
				Assert.check(flusherChosen.compareAndSet(true, false), EC.GENERAL);
				
				return super.onAdvance(phase, registeredParties);
			}
		};
		
		private OffHeapSynchronizer() {
			// Don't want any copies.
		}
		
		public final void add(final OffHeapDiskFPSet aSet) {
			this.sets.add(aSet);
		}
		
		public final void incWorkers(final int numWorkers) {
			final int parties = phaser.getRegisteredParties();
			if (parties < numWorkers) {
				phaser.bulkRegister(numWorkers - parties);
			}
		}
		
		public final boolean evictPending() {
			return flusherChosen.get();
		}
		
		public final void evict() {
			flusherChosen.compareAndSet(false, true);
		}
		
		public final void awaitEviction() {
			phaser.arriveAndAwaitAdvance();
		}
		
		public AtomicBoolean getFlusherChosen() {
			return flusherChosen;
		}
	}

	// We require a singleton here, because if TLC is run with multiple instances
	// of FPSets - the default - workers will call evict and awaitEvict on 
	// all FPSet instances. Thus, an individual synchronization internal to each
	// FPSet would never see the complete set of waiting workers. TLC would thus
	// deadlock. This is why SYNC is a singleton and shared by all FPSet instances.
	private static final OffHeapSynchronizer SYNC = new OffHeapSynchronizer();
	
	private static final int PROBE_LIMIT = Integer.getInteger(OffHeapDiskFPSet.class.getName() + ".probeLimit", 1024);
	static final long EMPTY = 0L;
	

	/**
	 * @see LongArray#isSupported()
	 */
	public static boolean isSupported() {
		return LongArray.isSupported();
	}

	private final transient LongArray array;
	
	/**
	 * The indexer maps a fingerprint to a in-memory bucket and the associated lock
	 */
	private final transient Indexer indexer;

	private int numThreads;

	protected OffHeapDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);
		
		final long positions = fpSetConfig.getMemoryInFingerprintCnt();
		
		// Determine base address which varies depending on machine architecture.
		this.array = new LongArray(positions);
		
		// If Hamming weight is 1, the logical index address can be calculated
		// significantly faster by bit-shifting. However, with large memory
		// sizes, only supporting increments of 2^n sizes would waste memory
		// (e.g. either 32GiB or 64Gib). Hence, we check if the bitCount allows
		// us to use bit-shifting. If not, we fall back to less efficient
		// calculations.
		if (Long.bitCount(positions) == 1) {
			this.indexer = new BitshiftingIndexer(positions, fpSetConfig.getFpBits());
		} else {
			// non 2^n buckets cannot use a bit shifting indexer
			this.indexer = new Indexer(positions, fpSetConfig.getFpBits());
		}
		
		// Use the non-concurrent flusher as the default. Will be replaced by
		// the CyclicBarrier-Runnable later. Just set to prevent NPEs when
		// eviction/flush is called before init.
		this.flusher = new OffHeapMSBFlusher(array);
		
		this.flusherChosen = SYNC.getFlusherChosen();
		SYNC.add(this);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#init(int, java.lang.String, java.lang.String)
	 */
	@Override
	public FPSet init(final int numThreads, String aMetadir, String filename)
			throws IOException {
		super.init(numThreads, aMetadir, filename);
		this.numThreads = numThreads;
		
		array.zeroMemory(numThreads);
		return this;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#incWorkers(int)
	 */
	public void incWorkers(int numWorkers) {
		assert numWorkers == this.numThreads;
		SYNC.incWorkers(numWorkers);
	}

	public void evict() {
		// statistics
		growDiskMark++;
		final long timestamp = System.currentTimeMillis();
		final long insertions = tblCnt.longValue();
		final double lf = tblCnt.doubleValue() / (double) maxTblCnt;
		
		LOGGER.log(Level.FINE,
				"Started eviction of disk {0} the {1}. time at {2} after {3} insertions, load factor {4} and reprobe of {5}.",
				new Object[] { ((DiskFPSetMXWrapper) diskFPSetMXWrapper).getObjectName(), getGrowDiskMark(),
						timestamp, insertions, lf, PROBE_LIMIT });
		
		// Check that the table adheres to our invariant. Otherwise, we
		// can't hope to successfully evict it.
		assert checkInput(array, indexer, PROBE_LIMIT) : "Table violates invariants prior to eviction: "
				+ array.toString();
		
		// Only pay the price of creating threads when array is
		// sufficiently large and the array size is large enough to
		// partition it for multiple threads.
		flusher = getFlusher(numThreads, insertions);
		
		try {
			flusher.flushTable(); // Evict()
		} catch (IOException e) {
			// wrap in unchecked.
			throw new OffHeapRuntimeException(e);
		}

		// statistics and logging again.
		final long l = System.currentTimeMillis() - timestamp;
		flushTime += l;
		LOGGER.log(Level.FINE,
				"Finished eviction of disk {0} the {1}. time at {2}, in {3} sec after {4} insertions, load factor {5} and reprobe of {6}.",
				new Object[] { ((DiskFPSetMXWrapper) diskFPSetMXWrapper).getObjectName(), getGrowDiskMark(), l,
						System.currentTimeMillis(), insertions, lf, PROBE_LIMIT });
	}

	private Flusher getFlusher(final int numThreads, final long insertions) {
		if (array.size() >= 8192 && Math.floor(array.size() / (double) numThreads) > 2 * PROBE_LIMIT) {
			return new ConcurrentOffHeapMSBFlusher(array, PROBE_LIMIT, numThreads, insertions);
		} else {
			return this.flusher;
		}
	}

	private boolean checkEvictPending() {
		if (SYNC.evictPending()) {
			SYNC.awaitEviction();
			return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#sizeof()
	 */
	public long sizeof() {
		long size = 44; // approx size of this DiskFPSet object
		size += maxTblCnt * LongSize;
		size += getIndexCapacity() * 4;
		return size;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#needsDiskFlush()
	 */
	@Override
	protected final boolean needsDiskFlush() {
		return loadFactorExceeds(1d) || forceFlush;
	}
	
	/**
	 * This limits the (primary) in-memory hash table to grow beyond the given
	 * limit.
	 * 
	 * @param limit
	 *            A limit in the domain [0, 1] which restricts the hash table
	 *            from growing past it.
	 * @return true iff the current hash table load exceeds the given limit
	 */
	private final boolean loadFactorExceeds(final double limit) {
		final double d = (this.tblCnt.doubleValue()) / (double) this.maxTblCnt;
		return d >= limit;
	}
    
	private static final int FOUND = -1;
    
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#memLookup(long)
	 */
	final boolean memLookup(final long fp0) {
		return memLookup0(fp0) == FOUND;
	}

	final int memLookup0(final long fp0) {
		int free = PROBE_LIMIT;
		for (int i = 0; i <= PROBE_LIMIT; i++) {
			final long position = indexer.getIdx(fp0, i);
			final long l = array.get(position);
			if (fp0 == (l & FLUSHED_MASK)) {
				// zero the long msb (which is 1 if fp has been flushed to disk)
				return FOUND;
			} else if (l == EMPTY) {
				return Math.min(i, free);
			} else if (l < EMPTY && free == PROBE_LIMIT) {
				free = i;
			}
		}

		return free;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#memInsert(long)
	 */
	final boolean memInsert(final long fp0) throws IOException {
		return memInsert0(fp0, 0);
	}

	final boolean memInsert0(final long fp0, final int start) throws IOException {
		// See OffHeapDiskFPSetJPFTest for a (verbatim) version that has
		// additionally been verified with JPF.
		for (int i = start; i < PROBE_LIMIT; i++) {
			final long position = indexer.getIdx(fp0, i);
			final long expected = array.get(position);
			if (expected == EMPTY || (expected < 0 && fp0 != (expected & FLUSHED_MASK))) {
				// Try to CAS the new fingerprint.
				if (array.trySet(position, expected, fp0)) {
					this.tblCnt.increment();
					return false;
				} else {
					// Retry at current position because another thread wrote a
					// value concurrently (possibly the same one this thread is
					// trying to write).
					i = i - 1;
					continue;
				}
			}
			
			// Expected is the fingerprint to be inserted.
			if ((expected & FLUSHED_MASK) == fp0) {
				return true;
			}
		}

		
		// We failed to insert into primary. Consequently, lets try and make
		// some room by signaling all threads to wait for eviction.
		forceFlush();
		// We've signaled for eviction to start or failed because some other
		// thread beat us to it. Actual eviction and setting flusherChosen back
		// to false is done by the Barrier's Runnable. We cannot set
		// flusherChosen back to false after barrier.awaits returns because it
		// leaves a window during which other threads read the old true value of
		// flusherChosen a second time and immediately wait again.
		
		return put(fp0);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#put(long)
	 */
	public final boolean put(final long fp) throws IOException {
		if (checkEvictPending()) {
			return put(fp);
		}

		// zeros the msb
		final long fp0 = fp & FLUSHED_MASK;

		// Only check primary and disk iff there exists a disk file. index is
		// created when we wait and thus cannot race.
		int start = 0;
		if (index != null) {
			// Lookup primary memory
			if ((start = memLookup0(fp0)) == FOUND) {
				this.memHitCnt.increment();
				return true;
			}
			
			// Lookup on disk
			if (this.diskLookup(fp0)) {
				this.diskHitCnt.increment();
				return true;
			}
		}
		
		// Lastly, try to insert into memory.
		return memInsert0(fp0, start);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#contains(long)
	 */
	public final boolean contains(final long fp) throws IOException {
		// maintains happen-before with regards to successful put
		
		if (checkEvictPending()) {
			return contains(fp);
		}

		// zeros the msb
		final long fp0 = fp & FLUSHED_MASK;
		
		// Lookup in primary
		if (memLookup(fp0)) {
			return true;
		}
		
		// Lookup on secondary/disk
		if (this.diskLookup(fp0)) {
			diskHitCnt.increment();
			return true;
		}
		
		return false;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#forceFlush()
	 */
	public void forceFlush() {
		SYNC.evict();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#acquireTblWriteLock()
	 */
	void acquireTblWriteLock() {
		// no-op for now
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#releaseTblWriteLock()
	 */
	void releaseTblWriteLock() {
		// no-op for now
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getTblCapacity()
	 */
	public long getTblCapacity() {
		return maxTblCnt;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getTblLoad()
	 */
	public long getTblLoad() {
		return getTblCnt();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getOverallCapacity()
	 */
	public long getOverallCapacity() {
		return array.size();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#getBucketCapacity()
	 */
	public long getBucketCapacity() {
		// A misnomer, but bucketCapacity is obviously not applicable with open
		// addressing.
		return PROBE_LIMIT;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#checkFPs()
	 */
	@Override
	public long checkFPs() throws IOException {
		if (getTblCnt() <= 0) {
			return Long.MAX_VALUE;
		}
		// The superclass implementation provides insufficient performance and
		// scalability. These problems get more pronounced with large arrays.
		// In order to provide a faster solution to the closest pair problem in
		// one-dimensional space, we cheat and determine the minimum distance
		// between fingerprints only on a subset of fingerprints. The subset are
		// those fingerprints which happen to be in main memory and have not yet
		// been evicted to disk. We believe this to be a sufficient approximation.
		// The algorithm to find the closest pair in one-dimensional space is:
		// 1) Sort all fingerprints.
		// 2) Perform a linear scan/search
		// => O(n log n)
		// Scalability is achieved by partitioning the array for 1) and 2),
		// which is possible due to the bounded disorder in array.
		
		// One can think of two shortcuts to approximate of the closest pair:
		// a) Track the minimum distance during the 1) step in prepareTable. A possible
		// implementation can pass something similar to a BinaryOpeartor to the
		// LongComparator. Due to the bounded disorder, this generally works except for
		// the corner case where the closest pair are two fingerprints in two
		// non-adjacent partitions, i.e. [,,,fp23],[],...,[],[,,fp42,,,]. This is
		// frequently the case for very sparsely populated arrays. 
		// b) For low load factors (thus low collision rates) simply skip step 1) and do
		// not sort the array at all. A zero collision rate implies that the array
		// is sorted (except for first PROBE_LIMIT slots) if fingerprints wrapped around.
		// c) Select just 1..N partitions out of the set of all array partitions
		// for which the closest pair gets calculated. This is a more extreme variant
		// of the current approximation which skips fingerprints on disk.
		
		// 1) Sort all fingerprints, either with a sequential or concurrent
		// flusher depending on the size of the array.
		final int numThreads = TLCGlobals.getNumWorkers();
		this.flusher = getFlusher(numThreads, getTblCnt());
		this.flusher.prepareTable();
		
		// 2) A task finds the pair with the minimum distance in an ordered
		// subrange of array. Each task is assigned an id. This id determines
		// which subrange of array (partition) it searches.
		final Collection<Callable<Long>> tasks = new ArrayList<Callable<Long>>(numThreads);
		final long length = (long) Math.floor(array.size() / (double) numThreads);
		for (int i = 0; i < numThreads; i++) {
			final int id = i;
			tasks.add(new Callable<Long>() {
				@Override
				public Long call() throws Exception {
					final boolean isLast = id == numThreads - 1;
					final long start = id * length;
					// Partitions overlap in case the two fingerprints with
					// minimum distance are in two adjacent partitions.
					final long end = (isLast ? array.size() - 1L : start + length) + 1L;
					
					long distance = Long.MAX_VALUE;
					
					// Reuse Iterator implementation which already handles the
					// various cases related to the cyclic table layout. Pass it
					// getTblCnt to make sure next does not keep going forever
					// if the array is empty. Instead, check the itr's position.
					final Iterator itr = new Iterator(array, getTblCnt(), start, indexer,
							isLast && id != 0 ? Iterator.WRAP.FORBIDDEN : Iterator.WRAP.ALLOWED);
					try {
						// If the partition is empty, next throws a NSEE.
						long x = itr.next();
						long y = 0;
						while ((y = itr.next(end)) != EMPTY) {
							long d = y - x;
							// d < 0 indicates that the array is not sorted.
							// d == 0 indicates two identical elements in the
							// fingerprint set. Iff this is the last partition,
							// itr.next might have returned the first element of the
							// first partition.
							assert d > 0 ^ (d < 0 && itr.getPos() > end && isLast);
							distance = Math.min(distance, d);
							x = y;
						}
						return distance;
					} catch (NoSuchElementException e) {
						return distance;
					}
				}
			});
		}
		
		// Start as many tasks as we have workers. Afterwards, collect the
		// minimum distance out of the set of results provided by the workers.
		final ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
		try {
			final long distance = executorService.invokeAll(tasks).stream().min(new Comparator<Future<Long>>() {
				public int compare(Future<Long> o1, Future<Long> o2) {
					try {
						return Long.compare(o1.get(), o2.get());
					} catch (InterruptedException e) {
						Thread.currentThread().interrupt();
						throw new OffHeapRuntimeException(e);
					} catch (ExecutionException e) {
						throw new OffHeapRuntimeException(e);
					}
				}
			}).get().get();
			return distance;
		} catch (InterruptedException ie) {
			Thread.currentThread().interrupt();
			throw new OffHeapRuntimeException(ie);
		} catch (ExecutionException e) {
			throw new OffHeapRuntimeException(e);
		} finally {
			executorService.shutdown();
		}
		
		
		// Dynamic variant to maintain closest pair:
		// The dynamic (during insertions and not on static data) variant of the closest
		// pair problem also provides an approximation of the actual closest pair. It
		// can be maintained with little overhead in runtime and space and returned in
		// constant time O(1). Contrary to the current implementation, it does not skip
		// fingerprints on disk but observes all fingerprints.
		// For that, we observe the minimum distance OD of the fingerprint to be inserted
		// and all fingerprints it collides with in the method memInsert0. Before
		// returning from memInsert0, the global minimum distance GD gets updated to the
		// observed distance OD iff OD < GD (for scalability reasons we want to use a
		// java.util.concurrent.atomic.LongAccumulator).
		// This provides a sufficient approximation iff the collision rate is
		// sufficiently high. Under a low collision rate, the number of comparisons in
		// memInsert0 will be low. But even under a high collision rate, the
		// approximation GD does not necessarily converge with the real minimum distance:
		// Let f1 differs from f2 in just the lowest significant bit (LSB) and let f1 <
		// f2. Depending on the size of the array, it is possible that f1 and f2 are
		// indexed to two adjacent positions. If both positions for f1 and f2 are empty
		// by the time f1 and f2 get inserted, no distance for f1 and f2 will be
		// calculated.
		// For low hash table/array collision rates (small load factors), we could
		// simply report "insufficient data". Users will still have the optimistic FP64
		// collision probability, which will also be very small.
	}

	//**************************** Indexer ****************************//
	
	public static class Indexer {

		private static final long minFingerprint = 1L; //Minimum possible fingerprint (0L marks an empty position)

		private final double tblScalingFactor;
		private final long maxFingerprint;
		protected final long positions;
		
		public Indexer(final long positions, final int fpBits) {
			this(positions, fpBits, 0xFFFFFFFFFFFFFFFFL >>> fpBits);
			assert fpBits > 0;
		}

		public Indexer(final long positions, final int fpBits, final long maxValue) {
			this.positions = positions;
			this.maxFingerprint = maxValue;
			// (position-1L) because array is zero indexed.
			this.tblScalingFactor = (positions - 1L) / ((maxFingerprint - minFingerprint) * 1f);
		}
		
		protected long getIdx(final long fp) {
			return getIdx(fp, 0);
		}
		
		protected long getIdx(final long fp, final int probe) {
			long idx = Math.round(tblScalingFactor * (fp - minFingerprint)) + probe;
			return idx % positions;
		}
	}
	
	public static class BitshiftingIndexer extends Indexer {
		private final long prefixMask;
		private final int rShift;

		public BitshiftingIndexer(final long positions, final int fpBits) throws RemoteException {
			super(positions, fpBits);
			
			this.prefixMask = 0xFFFFFFFFFFFFFFFFL >>> fpBits;
			
			long n = (0xFFFFFFFFFFFFFFFFL >>> fpBits) - (positions - 1);
			int moveBy = 0;
			while (n >= positions) {
				moveBy++;
				n = n >>> 1; // == (n/2)
			}
			this.rShift = moveBy;
		}
		
		@Override
		protected long getIdx(final long fp) {
			return (fp & prefixMask) >>> rShift;
		}
		
		@Override
		protected long getIdx(final long fp, int probe) {
			// Have to mod positions because probe might cause us to overshoot.
			return (((fp & prefixMask) >>> rShift) + probe) % positions; 
		}
	}

	//**************************** Flusher ****************************//
	
	private LongComparator getLongComparator() {
		return new LongComparator() {
			@Override
			public int compare(long fpA, long posA, long fpB, long posB) {
				
				// Elements not in Nat \ {0} remain at their current
				// position.
				if (fpA <= EMPTY || fpB <= EMPTY) {
					return 0;
				}
				
				final boolean wrappedA = indexer.getIdx(fpA) > posA;
				final boolean wrappedB = indexer.getIdx(fpB) > posB;
				
				if (wrappedA == wrappedB && posA > posB) {
					return fpA < fpB ? -1 : 1;
				} else if (wrappedA ^ wrappedB) {
					if (posA < posB && fpA < fpB) {
						return -1;
					}
					if (posA > posB && fpA > fpB) {
						return -1;
					}
				}
				return 0;
			}
		};
	}

	/**
	 * Returns the number of fingerprints stored in table/array in the range
	 * [start,limit].
	 */
	private long getTableOffset(final LongArray a, final long reprobe, final Indexer indexer, final long start,
			final long limit) {
		long occupied = 0L;
		for (long pos = start; pos < limit; pos++) {
			final long fp = a.get(pos % a.size());
			if (fp <= EMPTY) {
				continue;
			}
			final long idx = indexer.getIdx(fp);
			if (idx > pos) {
				// Ignore the elements that wrapped around the
				// end when scanning the first partition.
				continue;
			}
			if (idx + reprobe < pos) {
				// Ignore the elements of the first partition
				// when wrapping around for the last partition.
				continue;
			}
			occupied = occupied + 1L;
		}
		return occupied;
	}
	
	private long getNextLower(long idx) {
		// Reverse to the next non-evicted/empty fp that belongs to this partition.
		long fp = array.get(idx);
		while (fp <= EMPTY || indexer.getIdx(fp) > idx) {
			fp = array.get(--idx);
		}
		return fp;
	}
	
	/**
	 * The number of fingerprints stored on disk smaller than fp.
	 */
	private long getDiskOffset(final int id, final long fp) throws IOException {
		if (this.index == null) {
			return 0L;
		}
		
		final int indexLength = this.index.length;
		int loPage = 0;
		int hiPage = indexLength - 1;
		long loVal = this.index[loPage];
		long hiVal = this.index[hiPage];

		if (fp <= loVal) {
			return 0L;
		}
		if (fp >= hiVal) {
			return this.braf[id].length() / FPSet.LongSize;
		}
		// See DiskFPSet#diskLookup for comments.
		
		// Lookup the corresponding disk page in index.
		final double dfp = (double) fp;
		while (loPage < hiPage - 1) {
			final double dhi = (double) hiPage;
			final double dlo = (double) loPage;
			final double dhiVal = (double) hiVal;
			final double dloVal = (double) loVal;
			int midPage = (loPage + 1) + (int) ((dhi - dlo - 1.0) * (dfp - dloVal) / (dhiVal - dloVal));
			if (midPage == hiPage) {
				midPage--;
			}
			final long v = this.index[midPage];
			if (fp < v) {
				hiPage = midPage;
				hiVal = v;
			} else if (fp > v) {
				loPage = midPage;
				loVal = v;
			} else {
				return (midPage * 1L) * (NumEntriesPerPage * 1L);
			}
		}
		// no page is in between loPage and hiPage at this point
		Assert.check(hiPage == loPage + 1, EC.SYSTEM_INDEX_ERROR);
		assert this.index[loPage] < fp && fp < this.index[hiPage];
		
		// Read the disk page and try to find the given fingerprint or the next
		// smaller one. Calculate its offset in file.
		long midEntry = -1L;
		long loEntry = ((long) loPage) * NumEntriesPerPage;
		long hiEntry = ((loPage == indexLength - 2) ? this.fileCnt - 1 : ((long) hiPage) * NumEntriesPerPage);
		final BufferedRandomAccessFile raf = this.braf[id];
		while (loEntry < hiEntry) {
			midEntry = calculateMidEntry(loVal, hiVal, dfp, loEntry, hiEntry);
			raf.seek(midEntry * LongSize);
			final long v = raf.readLong();

			if (fp < v) {
				hiEntry = midEntry;
				hiVal = v;
			} else if (fp > v) {
				loEntry = midEntry + 1;
				loVal = v;
				midEntry = loEntry;
			} else {
				break;
			}
		}
		
		assert isHigher(midEntry, fp, raf);
		return midEntry;
	}

	public boolean isHigher(long midEntry, long fp, BufferedRandomAccessFile raf) throws IOException {
		raf.seek((midEntry - 1L) * LongSize);
		final long low = raf.readLong();
		final long high = raf.readLong();
		if (low < fp && fp < high) {
			return true;
		}
		return false;
	}

	public class ConcurrentOffHeapMSBFlusher extends OffHeapMSBFlusher {
		
		private final int numThreads;
		private final ExecutorService executorService;
		private final int r; 
		private final long insertions;
		/**
		 * The length of a single partition.
		 */
		private final long length;
		private List<Result> offsets; 

		public ConcurrentOffHeapMSBFlusher(final LongArray array, final int r, final int numThreads,
				final long insertions) {
			super(array);
			this.r = r;
			this.numThreads = numThreads;
			this.insertions = insertions;

			this.length = (long) Math.floor(a.size() / (double) numThreads);
			this.executorService = Executors.newFixedThreadPool(numThreads);
		}
		
		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet.Flusher#prepareTable()
		 */
		@Override
		protected void prepareTable() {
			final long now = System.currentTimeMillis();
			final CyclicBarrier phase = new CyclicBarrier(this.numThreads);
			final Collection<Callable<Result>> tasks = new ArrayList<Callable<Result>>(numThreads);
			for (int i = 0; i < numThreads; i++) {
				final int id = i;
				tasks.add(new Callable<Result>() {
					@Override
					public Result call() throws Exception {
						final boolean isFirst = id == 0;
						final boolean isLast = id == numThreads - 1;
						final long start = id * length;
						final long end = isLast ? a.size() - 1L : start + length;
						
						// Sort partition p_n. We have exclusive access.
						LongArrays.sort(a, isFirst ? 0L : start + 1L, end, getLongComparator());
						assert checkSorted(a, indexer, r, isFirst ? 0L : start + 1L, end) == -1L : String.format(
								"Array %s not fully sorted at index %s and reprobe %s in range [%s,%s].", a.toString(),
								checkSorted(array, indexer, r, start, end), r, start, end);
						
						// Wait for the other threads sorting p_n+1 to be done
						// before we stitch together p_n and p_n+1.
						phase.await();

						// Sort the range between partition p_n and
						// p_n+1 bounded by reprobe.
						LongArrays.sort(a, end - r+1L, end + r+1L, getLongComparator());
						
						// Wait for table to be fully sorted before we calculate
						// the offsets. Offsets can only be correctly calculated
						// on a sorted table.
						phase.await();
						
						// Count the occupied positions for this
						// partition. Occupied positions are those which
						// get evicted (written to disk).
						// This could be done as part of (insertion) sort
						// above at the price of higher complexity. Thus,
						// it's done here until it becomes a bottleneck.
						final long limit = isLast ? a.size() + r : end;
						final long occupied = getTableOffset(a, r, indexer, start, limit);
						assert occupied <= limit - start;
						
						if (index == null) {
							// No index, no need to calculate a disk offset.
							return new Result(occupied, 0L);
						}
						
						// Determine number of elements in the old/current file.
						if (isFirst && isLast) {
							return new Result(occupied, fileCnt);
						} else if (isFirst) {
							return new Result(occupied, getDiskOffset(id, getNextLower(end)));
						} else if (isLast) {
							return new Result(occupied, fileCnt - getDiskOffset(id, getNextLower(start)));
						} else {
							return new Result(occupied,
									getDiskOffset(id, getNextLower(end)) - getDiskOffset(id, getNextLower(start)));
						}
					}
				});
			}
			try {
				offsets = futuresToResults(executorService.invokeAll(tasks));
			} catch (InterruptedException ie) {
				Thread.currentThread().interrupt();
				throw new OffHeapRuntimeException(ie);
			} catch (ExecutionException notExpectedToHappen) {
				throw new OffHeapRuntimeException(notExpectedToHappen);
			}

			assert checkSorted(a, indexer, r) == -1L : String.format(
					"Array %s not fully sorted at index %s and reprobe %s.", a.toString(),
					checkSorted(array, indexer, r), r);
			
			LOGGER.log(Level.FINE, "Sorted in-memory table with {0} workers and reprobe {1} in {2} ms.",
					new Object[] { numThreads, r, System.currentTimeMillis() - now });
		}
		
		private List<Result> futuresToResults(List<Future<Result>> futures) throws InterruptedException, ExecutionException {
			final List<Result> res = new ArrayList<Result>(futures.size());
			for (Future<Result> future : futures) {
				res.add(future.get());
			}
			return res;
		}

		@Override
		protected void mergeNewEntries(final BufferedRandomAccessFile[] inRAFs, final RandomAccessFile outRAF, final Iterator ignored) throws IOException {
			final long now = System.currentTimeMillis();
			assert offsets.stream().mapToLong(new ToLongFunction<Result>() {
				public long applyAsLong(Result result) {
					return result.getTable();
				}
			}).sum() == insertions : "Missing inserted elements during eviction.";
			assert offsets.stream().mapToLong(new ToLongFunction<Result>() {
				public long applyAsLong(Result result) {
					return result.getDisk();
				}
			}).sum() == fileCnt : "Missing disk elements during eviction.";

			// Calculate offsets for in and the out file, i.e. sum up the
			// combined number of elements in lower partitions.
			for (int id = 1; id < numThreads; id++) {
				final Result prev = offsets.get(id - 1);
				final Result result = offsets.get(id);
				result.setInOffset(prev.getInOffset() + prev.getDisk());
				result.setOutOffSet(prev.getOutOffset() + prev.getTotal());
			}

			final long outLength = outRAF.length();
			final Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>>(numThreads);
			final BufferedRandomAccessFile[] tmpRAFs = new BufferedRandomAccessFile[numThreads];
			for (int i = 0; i < numThreads; i++) {
				final int id = i;
				
				// Create a new RAF instance. The outRAF instance is
				// otherwise shared by multiple writers leading to race
				// conditions and inconsistent fingerprint set files.
				tmpRAFs[id] = new BufferedRandomAccessFile(new File(tmpFilename), "rw");
				tmpRAFs[id].setLength(outLength);

				// Set offsets into the out (tmp) file.
				final Result result = offsets.get(id);
				tmpRAFs[id].seekAndMark(result.getOutOffset() * FPSet.LongSize);

				// Set offset and the number of elements the
				// iterator is supposed to return.
				final Iterator itr = new Iterator(a, result.getTable(), id * length, indexer,
						id == 0 ? Iterator.WRAP.ALLOWED : Iterator.WRAP.FORBIDDEN);
				
				final BufferedRandomAccessFile inRAF = inRAFs[id];
				assert (result.getInOffset() + result.getDisk()) * FPSet.LongSize <= inRAF.length();
				inRAF.seekAndMark(result.getInOffset() * FPSet.LongSize);

				// Stop reading after diskReads elements (after
				// which the next thread continues) except for the
				// last thread which reads until EOF. Pass 0 when
				// nothing can be read from disk.
				final long diskReads = id == numThreads - 1 ? fileCnt - result.getInOffset() : result.getDisk();
				
				tasks.add(new Callable<Void>() {
					public Void call() throws Exception {
						ConcurrentOffHeapMSBFlusher.super.mergeNewEntries(inRAF, tmpRAFs[id], itr, diskReads);
						assert tmpRAFs[id].getFilePointer() == (result.getOutOffset() + result.getTotal()) * FPSet.LongSize : id
								+ " writer did not write expected amount of fingerprints to disk.";
						return null;
					}
				});
			}
			// Combine the callable results.
			try {
				executorService.invokeAll(tasks);
				executorService.shutdown();
				executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
				assert checkRAFs(tmpRAFs);
			} catch (InterruptedException ie) {
				Thread.currentThread().interrupt();
				throw new OffHeapRuntimeException(ie);
			} finally {
				executorService.shutdown();
			}
			
			// Finally close the out rafs after all tasks have finished. On
			// Linux, closing an instance of the tmpRAFs appears to be racy when
			// other tasks still execute.
			for (int i = 0; i < tmpRAFs.length; i++) {
				tmpRAFs[i].close();
			}

			assert checkRAFs(inRAFs);
			assert checkTable(a) : "Missed element during eviction.";
			
			LOGGER.log(Level.FINE, "Wrote table to disk with {0} workers in {1} ms.",
					new Object[] { numThreads, (System.currentTimeMillis() - now) });
		}

		private class Result {
			private final long occupiedTable;
			private final long occupiedDisk;
			private long outOffset;
			private long inOffset;
			
			public Result(long occupiedTable, long occupiedDisk) {
				this.occupiedTable = occupiedTable;
				this.occupiedDisk = occupiedDisk;
			}
			public long getDisk() {
				return occupiedDisk;
			}
			public long getTable() {
				return occupiedTable;
			}
			public long getTotal() {
				return occupiedDisk + occupiedTable;
			}
			public void setOutOffSet(long offset) {
				this.outOffset = offset;
			}
			public void setInOffset(long offset) {
				this.inOffset = offset;
			}
			public long getInOffset() {
				return this.inOffset;
			}
			public long getOutOffset() {
				return this.outOffset;
			}
		}
	}
	
	public class OffHeapMSBFlusher extends Flusher {
		
		protected final LongArray a;

		public OffHeapMSBFlusher(LongArray array) {
			a = array;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.fp.DiskFPSet.Flusher#prepareTable()
		 */
		@Override
		protected void prepareTable() {
			super.prepareTable();
			final int r = PROBE_LIMIT;
			
			assert checkInput(array, indexer, r) : "Table violates invariants prior to eviction";
			
			// Sort with a single thread.
			LongArrays.sort(a, 0, a.size() - 1L + r, getLongComparator());

			assert checkSorted(a, indexer, r) == -1L : String.format(
					"Array %s not fully sorted at index %s and reprobe %s.", a.toString(),
					checkSorted(array, indexer, r), r);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.fp.MSBDiskFPSet#mergeNewEntries(java.io.RandomAccessFile, java.io.RandomAccessFile)
		 */
		@Override
		protected void mergeNewEntries(BufferedRandomAccessFile[] inRAFs, RandomAccessFile outRAF) throws IOException {
			final long buffLen = tblCnt.sum();
			final Iterator itr = new Iterator(array, buffLen, indexer);

			final int indexLen = calculateIndexLen(buffLen);
			index = new long[indexLen];
			mergeNewEntries(inRAFs, outRAF, itr);

			final long length = (outRAF.length() / LongSize) - 1L;
			writeIndex(index, outRAF, length);
			assert checkIndex(index) : "Broken disk index.";
			assert checkIndex(index, outRAF, length) : "Misaligned disk index.";
			
			// maintain object invariants
			fileCnt += buffLen;
		}

		protected void mergeNewEntries(BufferedRandomAccessFile[] inRAFs, RandomAccessFile outRAF, Iterator itr)
				throws IOException {
			inRAFs[0].seek(0);
			mergeNewEntries(inRAFs[0], outRAF, itr, inRAFs[0].length() / FPSet.LongSize);
		}

		/*
		 * See PlusCal spec OpenAddressing.ConcurrentFlusher.tla which has been checked for Nat == 0..6.
		 */
		protected void mergeNewEntries(BufferedRandomAccessFile inRAF, RandomAccessFile outRAF, final Iterator itr,
				long diskReads) throws IOException {
			
			// Disk might be empty.
			long value = 0L;
			if (diskReads > 0) {
				value = inRAF.readLong();
			} else {
				assert fileCnt == 0L;
			}
			
			long tableReads = itr.elements;
			long fp = itr.markNext();
			
			do {
				if (value == fp) {
					MP.printWarning(EC.TLC_FP_VALUE_ALREADY_ON_DISK, String.valueOf(value));
				}
				assert fp > EMPTY : "Wrote an invalid fingerprint to disk.";
				
				// From memory/table
		        if (tableReads > 0 && (fp < value || diskReads == 0)) {
					outRAF.writeLong(fp);
					tableReads--;
					diskWriteCnt.increment();
					// Read next value if any.
		            if (tableReads > 0) {
						final long nextFP = itr.markNext();
						assert nextFP > fp : nextFP + " > " + fp + " from table at pos " + itr.pos + " "
								+ a.toString(itr.pos - 10L, itr.pos + 10L);
						fp = nextFP;
		            }
		         }
		         
		         // From file/disk
				if (diskReads > 0 && (value < fp || tableReads == 0)) {
					outRAF.writeLong(value);
					diskReads--;
					diskWriteCnt.increment();
					// Read next value if any.
					if (diskReads > 0) {
						final long nextValue = inRAF.readLong();
						assert value < nextValue;
						value = nextValue;
					}
				}

			} while (diskReads > 0 || tableReads > 0);
			
			// both sets used up completely
			Assert.check(diskReads == 0L && tableReads == 0L, EC.GENERAL);
			assert !itr.hasNext();
		}
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.DiskFPSet#calculateIndexLen(long)
	 */
	@Override
	protected int calculateIndexLen(final long tblcnt) {
		int indexLen = super.calculateIndexLen(tblcnt);
		if ((tblcnt + fileCnt - 1L) % NumEntriesPerPage == 0L) {
			// This is the special case where the largest fingerprint
			// happened is going to end up on the last entry of the previous
			// page. Thus, we won't need the last extra index cell.
			indexLen--;
		}
		return indexLen;
	}

	protected void writeIndex(long[] index, final RandomAccessFile raf, long length) throws IOException {
		for (int i = 0; i < index.length; i++) {
			long pos = Math.min(((long) i) * NumEntriesPerPage, length);
			raf.seek(pos * LongSize);
			final long value = raf.readLong();
			index[i] = value;
		}
	}
	
	/**
	 * A non-thread safe Iterator whose next method returns the next largest
	 * element.
	 */
	public static class Iterator {

		private enum WRAP {
			ALLOWED, FORBIDDEN;
		}

		private final long elements;
		private final LongArray array;
		private final Indexer indexer;
		private final WRAP canWrap;

		private long pos = 0;
		private long elementsRead = 0L;
		
		public Iterator(final LongArray array, final long elements, final Indexer indexer) {
			this(array, elements, 0L, indexer, WRAP.ALLOWED);
		}

		public Iterator(final LongArray array, final long elements, final long start, final Indexer indexer) {
			this(array, elements, start, indexer, WRAP.FORBIDDEN);
		}

		public Iterator(final LongArray array, final long elements, final long start, final Indexer indexer,
				final WRAP canWrap) {
			this.array = array;
			this.elements = elements;
			this.indexer = indexer;
			this.pos = start;
			this.canWrap = canWrap;
		}

		public long getPos() {
			return pos;
		}

		/**
		 * Returns the next element in the iteration that is not EMPTY nor
		 * marked evicted.
		 *
		 * @return the next element in the iteration that is not EMPTY nor
		 *         marked evicted.
		 * @exception NoSuchElementException
		 *                iteration has no more elements.
		 */
		public long next() {
			return next0(false, Long.MAX_VALUE);
		}
		
		long next(long maxPos) {
			if (pos >= maxPos) {
				return EMPTY;
			}
			return next0(false, maxPos);
		}
		
		/**
		 * Returns the next element in the iteration that is not EMPTY nor
		 * marked evicted and marks it to be evicted.
		 * <p>
		 * THIS IS NOT SIDEEFFECT FREE. AFTERWARDS, THE ELEMENT WILL BE MARKED
		 * EVICTED.
		 *
		 * @return the next element in the iteration that is not EMPTY nor
		 *         marked evicted.
		 * @exception NoSuchElementException
		 *                iteration has no more elements.
		 */
		public long markNext() {
			return next0(true, Long.MAX_VALUE);
		}

		private long next0(final boolean mark, final long maxPos) {
			long elem;
			do {
				final long position = pos % array.size();
				elem = array.get(position);
				if (elem == EMPTY) {
					pos = pos + 1L;
					continue;
				}
				if (elem < EMPTY) {
					pos = pos + 1L;
					continue;
				}
				final long baseIdx = indexer.getIdx(elem);
				if (baseIdx > pos) {
					// This branch should only be active for thread with id 0.
					assert canWrap == WRAP.ALLOWED;
					pos = pos + 1L;
					continue;
				}
				pos = pos + 1L;
				// mark elem in array as being evicted.
				if (mark) {array.set(position, elem | MARK_FLUSHED);}
				elementsRead = elementsRead + 1L;
				return elem;
			} while (hasNext() && pos < maxPos);
			if (pos >= maxPos) {
				return EMPTY;
			}
			throw new NoSuchElementException();
		}
		
	    /**
	     * Returns <tt>true</tt> if the iteration has more elements. (In other
	     * words, returns <tt>true</tt> if <tt>next</tt> would return an element
	     * rather than throwing an exception.)
	     *
	     * @return <tt>true</tt> if the iterator has more elements.
	     */
		public boolean hasNext() {
			return elementsRead < elements;
		}
	}

	public static class OffHeapRuntimeException extends RuntimeException {

		public OffHeapRuntimeException(Exception ie) {
			super(ie);
		}
	}
	
	// ***************** assertion helpers *******************//

	private static boolean checkInput(final LongArray array, final Indexer indexer, final int reprobe) {
		for (long pos = 0; pos <= array.size() + reprobe - 1L; pos++) {
			long tmp = array.get(pos % array.size());
			if (tmp == EMPTY) {
				continue;
			}
			if (tmp < EMPTY) {
				// Convert evicted fps back.
				tmp = tmp & FLUSHED_MASK;
			}
			final long idx = indexer.getIdx(tmp);
			// Accept wrapped elements.
			if (pos < reprobe && idx > (array.size() - 1L - pos - reprobe)) {
				continue;
			}
			// Accept non-wrapped elements when pos > array.size
			if (pos > array.size() - 1L && idx + reprobe < pos) {
				continue;
			}
			// Accept any other valid elements where pos is within the range
			// given by [idx,idx + reprobe].
			if (idx <= pos && pos <= idx + reprobe) {
				continue;
			}
			System.err.println(String.format("%s with idx %s at pos %s (reprobe: %s).", tmp, idx, pos, reprobe));
			return false;
		}
		return true;
	}

	/**
	 * @return -1L iff array is sorted, index/position of the element that violates otherwise in the range [start, end].
	 */
	private static long checkSorted(final LongArray array, final Indexer indexer, int reprobe, long start, long end) {
		if (reprobe >= array.size()) {
			// When the array is smaller than the number of positions/slots, the
			// loop below will run past its bounds. If this happens, it compares
			// elements the element at the start with the element at the end.
			reprobe = (int) (array.size() - 1);
		}
		long e = 0L;
		for (long pos = start; pos <= end; pos++) {
			final long tmp = array.get(pos % array.size());
			if (tmp <= EMPTY) {
				continue;
			}
			final long idx = indexer.getIdx(tmp);
			if (idx > pos) {
				continue;
			}
			if (idx + reprobe < pos) {
				continue;
			}
			if (e == 0L) {
				// Initialize e with the first element that is not <=EMPTY
				// or has wrapped.
				e = tmp;
				continue;
			}
			if (e >= tmp) {
				System.err.println(String.format("%s >= %s at pos %s.", e, tmp, pos));
				return pos;
			}
			e = tmp;
		}
		return -1L;
	}

	/**
	 * @return -1L iff array is sorted, index/position of the element that violates otherwise.
	 */
	private static long checkSorted(final LongArray array, final Indexer indexer, final int reprobe) {
		return checkSorted(array, indexer, reprobe, 0, array.size() - 1L + reprobe);
	}

	private static boolean checkRAFs(final BufferedRandomAccessFile[] rafs) throws IOException {
		for (int i = 0; i < rafs.length - 1; i++) {
			final long end = rafs[i].getFilePointer();
			final long start = rafs[i + 1].getMark();
			if (end != start) {
				return false;
			}
		}
		return true;
	}
	
	private static boolean checkTable(LongArray array) {
		for (long i = 0L; i < array.size(); i++) {
			long elem = array.get(i);
			if (elem > EMPTY) {
				System.err.println(String.format("%s elem at pos %s.", elem, i));
				return false;
			}
		}
		return true;
	}

	private static boolean checkIndex(final long[] idx) {
		for (int i = 1; i < idx.length; i++) {
			if (idx[i - 1] >= idx[i]) {
				return false;
			}
		}
	    return true;
    } 
	
	private static boolean checkIndex(final long[] idx, final RandomAccessFile raf, final long length) throws IOException {
		for (long i = 0L; i < idx.length; i++) {
			final long pos = Math.min(i * NumEntriesPerPage, length);
			raf.seek(pos * LongSize);
			final long value = raf.readLong();
			final long index = idx[(int) i];
			if (value != index) {
				return false;
			}
		}
		return true;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/gettingstarted/views.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/gettingstarted/views.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

	<title>Managing Views</title>
</head>
<!-- a comment -->

<body>
<h1>Managing Views</h1>

<p> 
Your Toolbox window contains a collection of subwindows called <dfn>views</dfn>.&nbsp;
A view is identified by a tab in the upper left-hand corner.&nbsp;  The tab for
the welcome view that you saw when you started the Toobox for the first time
looks like this: 
<pre>
     <IMG SRC=view-tab.gif Align=bottom> 
</pre>
You can delete a view by clicking on the <samp>X</samp>.&nbsp;  This just removes
the view; it does not affect whatever the view is viewing.&nbsp;  For example,
deleting a view that shows a  file does not delete the file.

 <p>
Views are grouped in folders.&nbsp;
Here is a typical state of the Toolbox.
</p>
<pre>
     <IMG SRC=folders.gif Align=bottom> 
</pre>
<p>
It has two folders.&nbsp;  One contains two module-editor views for the module files 
<samp>ClientModule.tla</samp> and <samp>FileModule.tla</samp>.&nbsp;  These
views allow you to edit those files.&nbsp;
 The <samp>*</samp> preceding the name
<samp>FileModule.tla</samp> indicates that the file has unsaved
modifications.&nbsp;  The other folder contains a Help view. 
</p>

 <p>
The buttons <IMG SRC=folder-minimize.gif Align=bottom> at the top right-hand side
of the folder allow you to minimize 
the folder or maximize it, hiding all other
folders.&nbsp;  Clicking on the <IMG SRC=unmaximize.gif Align=bottom> button that 
replaces the maximize button undoes the maximization.&nbsp;  The 
 </p>
<pre>  
      <IMG SRC=minimized-folder.gif >
</pre>
<p>
 at the right edge of the Toolbox window is a minimized folder that can 
be restored by left-clicking on it.  Clicking on the bottom icon (the image of a computer screen 
in this example) and on the top icon (the overlapping rectangles) do different
things.  Try them.  Pay attention to the upper right-hand corner of the folder
that gets raised.


</p>
<p>
You can move a view by left-clicking on its tab, holding down the mouse button, and
dragging the view to where you want it (even outside the Toolbox window).&nbsp; What this does depends on exactly
where you drag it, on the current configuration of the Toolbox window, and
perhaps on what you had for breakfast.&nbsp;  

You can also
create multiple views on the same module by selecting the module editor
and choosing <em>New Editor</em> on the <em>Window</em> menu.&nbsp;

This is all implemented by Eclipse
code, so it's guaranteed to be bug free.&nbsp;  (A program can have a bug only
if there is a specification of what it's supposed to do.)&nbsp;  

It  works pretty well and you will quickly learn how to arrange your Toolbox views
the way you want them.&nbsp;  
If you get it into a weird state, just close
and reopen the spec.  
 
</p>
<hr>
<!--  comment out -- >
<dl>
<dt><font color=#0000c0>Topics</font></dt>
<dd> <A href="subtopic.html" target="_blank">A Subtopic</A></dd>
</dl>
< !-- -->
 <!-- comment out-->
<a href = "gettingstarted.html">&uarr; Getting Started</a>
 <!-- -->
</hr>

</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/ApplicationWorkbenchWindowAdvisor.java<|end_filename|>
package org.lamport.tla.toolbox;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IPluginContribution;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.internal.ide.EditorAreaDropAdapter;

/**
 * Configuration of the main window
 */
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
{

    public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
    {
        super(configurer);
    }

    public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer)
    {
        return new ApplicationActionBarAdvisor(configurer);
    }

    public void preWindowOpen()
    {
        IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
        configurer.setInitialSize(new Point(800, 600));
        configurer.setShowFastViewBars(true);
        configurer.setShowStatusLine(true);
        configurer.setShowProgressIndicator(true);
        configurer.setShowCoolBar(false);
        
        // A DropTargetAdapter is need for editor DND support
        final DropTargetListener dtl = new EditorAreaDropAdapter(
                configurer.getWindow());
        configurer.configureEditorAreaDropListener(dtl);
    }

	/* (non-Javadoc)
	 * @see org.eclipse.ui.application.WorkbenchWindowAdvisor#postWindowOpen()
	 */
	public void postWindowOpen() {
		final PreferenceManager preferenceManager = PlatformUI.getWorkbench().getPreferenceManager();
		final IPreferenceNode[] rootSubNodes = preferenceManager.getRootSubNodes();

		// @see Bug #191 in general/bugzilla/index.html
		final List<String> filters = new ArrayList<String>();
		filters.add("org.eclipse.compare");
		// The following three preferences are shown because the Toolbox uses
		// the local history feature provided by o.e.team.ui
		filters.add("org.eclipse.team.ui");
		filters.add("org.eclipse.ui.trace");
		filters.add("org.eclipse.jsch.ui");

		// Filter out Pdf4Eclipse preference page.
		filters.add("de.vonloesch.pdf4Eclipse");
		
		// Filter out GraphViz
		filters.add("com.abstratt.graphviz.ui");
		
		// Clean the preferences
		final List<IPreferenceNode> elements = preferenceManager.getElements(PreferenceManager.POST_ORDER);
		for (Iterator<IPreferenceNode> iterator = elements.iterator(); iterator.hasNext();) {
			final IPreferenceNode elem = iterator.next();
			if (elem instanceof IPluginContribution) {
				final IPluginContribution aPluginContribution = (IPluginContribution) elem;
				if (filters.contains(aPluginContribution.getPluginId())) {
					final IPreferenceNode node = (IPreferenceNode) elem;

					// remove from root node
					preferenceManager.remove(node);

					// remove from all subnodes
					for (int i = 0; i < rootSubNodes.length; i++) {
						final IPreferenceNode subNode = rootSubNodes[i];
						subNode.remove(node);
					}
				}
			}
		}
		super.postWindowOpen();
		
		// At this point in time we can be certain that the UI is fully
		// instantiated (views, editors, menus...). Thus, register
		// listeners that connect the UI to the workspace resources.
		ToolboxLifecycleParticipantManger.postWorkbenchWindowOpen();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/queue/StateQueueTest.java<|end_filename|>
package tlc2.tool.queue;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.Before;
import org.junit.Test;

import tlc2.tool.TLCState;

public class StateQueueTest {

	protected IStateQueue sQueue;

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	@Before
	public void setUp() throws Exception {
		sQueue = new MemStateQueue("");
	}

	// add and remove a single state
	@Test
	public void testEnqueue() {
		final TLCState expected = new DummyTLCState();
		sQueue.enqueue(expected);
		TLCState actual = sQueue.sDequeue();
		assertEquals("", expected, actual);
	}

	// dequeue from empty 
	@Test
	public void testsDequeueEmpty() {
		TLCState state = sQueue.sDequeue();
		assertNull(state);
	}
	
	// dequeue from empty 
	@Test
	public void testDequeueEmpty() {
		TLCState state = sQueue.dequeue();
		assertNull(state);
	}
	
	// dequeue from not empty 
	@Test
	public void testsDequeueNotEmpty() {
		DummyTLCState expected = new DummyTLCState();
		sQueue.sEnqueue(expected);
		assertTrue(sQueue.size() == 1);
		TLCState actual = sQueue.sDequeue();
		assertTrue(sQueue.size() == 0);
		assertEquals(expected, actual);
	}
	
	// dequeue from not empty 
	@Test
	public void testDequeueNotEmpty() {
		DummyTLCState expected = new DummyTLCState();
		sQueue.enqueue(expected);
		assertTrue(sQueue.size() == 1);
		TLCState actual = sQueue.dequeue();
		assertTrue(sQueue.size() == 0);
		assertEquals(expected, actual);
	}

	// add 10 states and check size
	@Test
	public void testEnqueueAddNotSame() {
		final int j = 10;
		for (int i = 0; i < j; i++) {
			sQueue.sEnqueue(new DummyTLCState());
		}
		assertTrue(sQueue.size() == j);
	}
	
	// add same states 10 times and check size
	@Test
	public void testEnqueueAddSame() {
		final DummyTLCState state = new DummyTLCState();
		final int j = 10;
		for (int i = 0; i < j; i++) {
			sQueue.sEnqueue(state);
		}
		assertTrue(sQueue.size() == j);
	}

	// uncommon input with empty queue sDequeue
	@Test
	public void testsDequeueAbuseEmpty() {
		expectRuntimeException(sQueue, 0);
		expectRuntimeException(sQueue, -1);
		expectRuntimeException(sQueue, Integer.MIN_VALUE);
		assertNull(sQueue.sDequeue(Integer.MAX_VALUE));
	}
	
	// uncommon input with non-empty queue
	// unfortunately sDequeue behaves differently depending what's its internal state
	@Test
	public void testsDequeueAbuseNonEmpty() {
		sQueue.sEnqueue(new DummyTLCState()); // make sure isAvail = true

		expectRuntimeException(sQueue, 0);
		expectRuntimeException(sQueue, -1);
		expectRuntimeException(sQueue, Integer.MIN_VALUE);

		assertTrue(sQueue.sDequeue(Integer.MAX_VALUE).length == 1);
	}
	
	private void expectRuntimeException(IStateQueue aQueue, int size)  {
		try {
			aQueue.sDequeue(size);
		} catch(RuntimeException|AssertionError e) {
			return;
		}
		fail("expected to throw RuntimeException with <= input");
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/GotoMatchingParenHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.CaretListener;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * 
 */

/**
 * This is the handler for the Goto Matching Paren command, which by default is bound
 * to Ctl+Shift+P.   THe command considers the following to be matching parens:
 * 
 *    ( )   [ ]   { }   << >>   (* *)  
 * 
 * If the cursor is immediately to the right of a paren, then it moves the cursor to the
 * right of the matching paren, except in case of error.  (It also does that if
 * the cursor is between the two charecters of a two-character paren.) 
 * If there is an error, then the cursor is not moved, an error message 
 * is put in the Toolbox's status bar (at the bottom of the window), and if 
 * the error is unmatched pair of parens, the parens are highlighted with
 * an Annotation marker.  The error message and highlighting disappear when the cursor
 * is moved (or more precisely, when a CaretListener is called).
 * 
 * The text is divided into three regions:
 * 
 *  - Line comments (which follow a "\*" on a line)
 *  
 *  - Strings (outside line comments), which are delimited by " " .  A beginning quote
 *    with no matching end quote is considered to be a string that extends to the end
 *    of the line.  
 *  
 *  - The rest of the text.
 *  
 * Matching considers only parens that appear in the same region as the selected paren.
 *  
 * There is one problematic case: when the cursor is between the '(' and the '*' in
 * "(*".  In that case, the cursor is considered not to be at a paren.
 * 
 * Note that text outside the module is treated the same as if it were in the module.
 * I don't know anything better to do for matching parens before or after the module.
 * While it might be better to consider text before or after the module to be
 * in separate regions than module text, it doesn't seem to be worth the trouble.
 * The user will see easily enough if a paren outside the module matches one inside 
 * the module.  
 * 
 * @author lamport
 *
 */
public class GotoMatchingParenHandler extends AbstractHandler implements
        IHandler {
    
    //
    public static String PAREN_ERROR_MARKER_TYPE = "org.lamport.tla.toolbox.editor.basic.showParenError";
    
    /**
     * This field holds the document of the module in which the action is
     * taking place.
     */
    private IDocument document;
    
    private int currLoc;
      // the current location of the parenthesis matching algorithm.
    private int regionType;
    // the type of the region being searched.
  
    // The following fields contain information about the regions of the
    // current line.
    private int currLineNum ;  
      // the number of the line (Java numbering)
    private int beginCurrRegion;
    private int endCurrRegion;
      // These are the beginning and end of the search
      // region containing currLoc--that is the offset
      // of the first character in the region and the
      // offset of the character immediately after the region.
      // If there are no strings on the line and we are searching
      // the main region, then these fields equal beginLineLoc
      // and endlineLoc.
    private int currRegionNumber;
      // - If regionType = STRING_REGION, then this is the
      // number of the string on the line (Java numbering).
      // That is, leftQuoteLocs[currRegionNumber] and
      // rightQuoteLocs[currRegionNumber] delimit the
      // current region.  
      //
      // - If regionType = MAIN_REGION, then
      // the current region lies between string number 
      // currRegionNumber-1 and string number currRegionNumber.
      // (If there are no strings, then currRegionNumber = 0,
      // and if the current region lies to the right of the last 
      // string on the line, then currRegionNumber equals the
      // number of strings.
      //
      // - If regionType = COMMENT_REGION, then this
      //   field is not meaningful.
    
    private int beginLineLoc ;
      // the offset of the beginning of the current line
    private int endLineLoc ;
      // the offset of the end of the current line, which
      // is the same as that of the beginning of the next
      // line, except at the end of the document.
    private int lineCommentLoc;
      // if there is an end-of-line comment, this is
      // the offset of the beginning of the "\*";
      // otherwise, it equals endLineLoc
    private int[] leftQuoteLocs = new int[1000];
      // An array whose i-th element is the location of
      // (immediately to the left of)  the " that begins the i-th string
      // on the line.  Only the first numberOfStrings elements
      // contain data.
    private int[] rightQuoteLocs = new int[1000];;
      // An array whose i-th element is the location of
      // (the left-side of) the " that ends the i-th string
      // on the line.  If that string runs to the end of the
      // line, then it equals endLineLoc.  Only the first 
      // numberOfStrings elements contain data.
    private int numberOfStrings;
      // the number of strings on the line. 
    
    // The definitions of the parentheses, the left parens are
    // in PARENS[0] .. PARENS[PCOUNT-1], and the right parens
    // are in PARENS[PCOUNT] ... PARENTS[2* PCOUNT -1]
    // Left paren PARENS[i] matches PARENS[i + PCOUNT], and parens
    // with indices i and j are matching iff (i - j) % PCOUNT equals 0.
    private static String[] PARENS  = 
              {"(*", "<<", "(", "[", "{", "*)", ">>", ")", "]", "}"} ;
    private static int PCOUNT = 5;
    private static int COMMENT_BEGIN_IDX = 0;
    private static int LEFT_ROUND_PAREN_IDX = 2;
      // The index of "(" in PARENS
    private static int BEGIN_MULTILINE_COMMENT_IDX = 0;
      // The index of "(*" in PARENS.
    
    // The three types of regions
    private static int MAIN_REGION = 0;
    private static int COMMENT_REGION = 1;
    private static int STRING_REGION = 2;
    
    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    
    /**
     * The method called when the user executes the Goto Matching Paren command.
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {
        TLAEditor tlaEditor = EditorUtil.getTLAEditorWithFocus();
        document = tlaEditor.publicGetSourceViewer().getDocument();
        
        try {
            ITextSelection selection = (ITextSelection) tlaEditor
                    .getSelectionProvider().getSelection();
            Region selectedRegion = new Region(selection.getOffset(),
                    selection.getLength());
            
            int selectedParenIdx = getSelectedParen(selectedRegion);
            
            int lineNumber = selection.getStartLine();
              // Note: if the selection covers multiple lines, then 
              // selectParenIdx should have thrown an exception.
            if (lineNumber < 0) {
                throw new ParenErrorException("Toolbox bug: bad selected line computed", null, null);
            }
            
            setLineRegions(lineNumber);
            setRegionInfo();
            
            if (selectedParenIdx < PCOUNT) {
                findMatchingRightParen(selectedParenIdx);
            } 
            else {
                findMatchingLeftParen(selectedParenIdx);
            }
            tlaEditor.selectAndReveal(currLoc, 0);            
        } catch (ParenErrorException e) {
            /*
             * Report the error.
             */
            IResource resource = ResourceHelper
                    .getResourceByModuleName(tlaEditor.getModuleName());
            ErrorMessageEraser listener = new ErrorMessageEraser(tlaEditor,
                    resource);
            tlaEditor.getViewer().getTextWidget().addCaretListener(listener);
            tlaEditor.getEditorSite().getActionBars().getStatusLineManager().setErrorMessage(e.message);
            
            Region[] regions = e.regions;
            if (regions[0] != null) {
                try {
                    // The following code was largely copied from the The
                    // ShowUsesHandler class.
                    Spec spec = ToolboxHandle.getCurrentSpec();
                    spec.setMarkersToShow(null);
                    IMarker[] markersToShow = new IMarker[2];
                    for (int i = 0; i < 2; i++) {
                        IMarker marker = resource
                                .createMarker(PAREN_ERROR_MARKER_TYPE);
                        Map<String, Integer> markerAttributes = new HashMap<String, Integer>(
                                2);
                        markerAttributes.put(IMarker.CHAR_START, new Integer(
                                regions[i].getOffset()));
                        markerAttributes.put(
                                IMarker.CHAR_END,
                                new Integer(regions[i].getOffset()
                                        + regions[i].getLength()));
                        marker.setAttributes(markerAttributes);

                        markersToShow[i] = marker;
                    }
                    spec.setMarkersToShow(markersToShow);
                } catch (CoreException exc) {
                    System.out
                            .println("GotoMatchingParenHandler.execute threw CoreException");
                }
            }
        }
        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (EditorUtil.getTLAEditorWithFocus() == null) {
			return false;
		}
		return super.isEnabled();
	}
	
    /****************  The Subroutines *****************/
    
    /**
     * Assumes that currLoc is just past a left paren with index
     * parenIdx in PARENS.  It sets currLoc to the location just past
     * the matching right paren, or throws an exception if there is 
     * a matching error.
     * 
     * @param parenIdx
     */
    private void findMatchingRightParen(int parenIdx) throws ParenErrorException {
        int savedCurrLoc = currLoc;
        while (true) {
            currLoc++;
            int pidx = -1;
            while (currLoc <= endCurrRegion  && ((pidx = getParenToLeftOf(currLoc)) == -1)) {
               currLoc++;
            }
            if (pidx == -1) {
                getNextRegion();
                currLoc = beginCurrRegion;
            }
            else {
                /*
                 * Need to check if we're just past the '(' in "(*".  Because of the
                 * unlikely event that the '(' is the last character in the file,
                 * it's easier to check that by calling getParenToLeftOf.
                 * 
                 */
                if (pidx == LEFT_ROUND_PAREN_IDX && 
                      getParenToLeftOf(currLoc+1) == BEGIN_MULTILINE_COMMENT_IDX) {
                    currLoc++;
                    pidx = BEGIN_MULTILINE_COMMENT_IDX;
                }
                if (pidx < PCOUNT) {
                    // This is a left paren
                    findMatchingRightParen(pidx);
                }
                else {
                    // This is a right paren
                    if ((pidx - parenIdx) % PCOUNT == 0 ) {
                        return;
                    }
                    else {
                        // Mismatched paren
                        throw new ParenErrorException(PARENS[parenIdx] + " matched by " + PARENS[pidx] , 
                           new Region(currLoc - PARENS[pidx].length(), PARENS[pidx].length()),
                           new Region(savedCurrLoc - PARENS[parenIdx].length(), PARENS[parenIdx].length()));
                    }
                }
            }
        }
    }
    
    /**
     * Assumes that currLoc is just past a right paren with index
     * parenIdx in PARENS.  It sets currLoc to the location just past
     * the matching left paren, or throws an exception if there is 
     * a matching error.
     * 
     * @param parenIdx
     */
    private void findMatchingLeftParen(int parenIdx) throws ParenErrorException {
        int savedCurrLoc = currLoc;
        
        /*
         * justWentToPrevRegion is true iff the search just moved to the end
         * of a new region.
         * 
         * When control is at the beginning of the while loop and justWentToPrevRegion
         * is false, there is a paren to the left of currLoc that must be skipped over 
         * when searching for the mathing left paren.  The paren with index 
         * lastParenSearched in PARENS is the right paren that either is the paren 
         * to be skipped over or else the right paren that matches the paren to be 
         * skipped over. 
         */
        int lastParenSearched = parenIdx;
        boolean justWentToPrevRegion = false;
        while (true) {
            if (! justWentToPrevRegion) {
                currLoc = currLoc - PARENS[lastParenSearched].length();
            }
            int pidx = -1;
            while (currLoc > beginCurrRegion  && ((pidx = getParenToLeftOf(currLoc)) == -1)) {
               currLoc--;
            }
            if (pidx == -1) {
                getPrevRegion();
                currLoc = endCurrRegion;
                justWentToPrevRegion = true;
            }
            else {
                if (pidx >= PCOUNT) {
                    // This is a right paren
                    findMatchingLeftParen(pidx);
                    lastParenSearched = pidx;
                    justWentToPrevRegion = false;
                }
                else {
                    // This is a left paren
                    if ((pidx - parenIdx) % PCOUNT == 0 ) {
                        return;
                    }
                    else {
                        // Mismatched paren
                        throw new ParenErrorException(PARENS[pidx] + " matches " +  PARENS[parenIdx], 
                           new Region(currLoc - PARENS[pidx].length(), PARENS[pidx].length()),
                           new Region(savedCurrLoc - PARENS[parenIdx].length(), PARENS[parenIdx].length()));
                    }
                }
            }
        }
    }
    
    /**
     * If location is the location in the document just to the right of a paren,
     * returns the index of the paren in PARENS.  Otherwise, it returns -1.
     * It should be called with location > 0; otherwise it always returns -1.
     * 
     * @param location
     * @return
     */
    private int getParenToLeftOf(int location) {
        for (int i = 0; i < PARENS.length; i++) {
            try {
                if (document.get(location - PARENS[i].length(), PARENS[i].length()).equals(PARENS[i])) {
                    return i;
                }
            } catch (BadLocationException e) {
                // this exception should occur only if location is close enough to
                // the beginning of the document so PARENS[i] couldn't fit to
                // the left of it, in which case we just want to do nothing here.
            }
        }
        return -1;
    }
    
    /**
     * Sets the region information for line number lineNumber--that is, it sets
     * 
     *    currLineNum, beginLineLoc, endLineLoc, lineCommentLoc, 
     *    leftQuoteLocs, rightQuoteLocs, and numberOfStrings.
     *    
     * Throws "Unmatched paren" exception if document does not have line lineNumber.
     * 
     * @param lineNumber
     * @throws ParenErrorException
     */
    private void setLineRegions(int lineNumber) throws ParenErrorException {
        currLineNum = lineNumber;
        try {
            beginLineLoc = document.getLineOffset(lineNumber);
            endLineLoc = beginLineLoc + document.getLineLength(lineNumber);
            lineCommentLoc = endLineLoc;
            numberOfStrings = 0;
            boolean inString = false;
            for (int loc = beginLineLoc; loc < endLineLoc; loc++) {
                char ch = document.getChar(loc);
                if (inString) {
                    if (ch == '"') {
                        inString = false;
                        rightQuoteLocs[numberOfStrings - 1] = loc;
                    } 
                    else if (ch == '\\') {
                        loc++;
                    }
                } else {
                    if ( ch == '"') {
                        leftQuoteLocs[numberOfStrings] = loc;
                        numberOfStrings++;
                        inString = true;
                    } else {
                        if (ch == '\\' && loc + 1 < endLineLoc && document.getChar(loc+1) == '*') {
                            lineCommentLoc = loc ;
                            break ;
                        }
                    }
                }
            }
            if (inString) {
                rightQuoteLocs[numberOfStrings - 1] = endLineLoc;
            }
        } catch (BadLocationException e) {
            throw new ParenErrorException("Unmatched paren", null, null);
//            throw new ParenErrorException(
//                    "Toolbox bug: BadLocationException in setLineRegions at line "
//                            + lineNumber, null);
        }
    }
    
    /**
     * Sets regionType, beginCurrRegion, and endCurrRegion.  It assumes that
     * setLineRegions has been called, and uses that and currLoc to determine
     * the region type and current region.
     */
    private void setRegionInfo() {
        currRegionNumber = 0;
        beginCurrRegion = beginLineLoc;
        endCurrRegion = endLineLoc;
        regionType = MAIN_REGION;
        boolean notDone = true ;
        while (notDone && currRegionNumber < numberOfStrings) {
            if (currLoc <= leftQuoteLocs[currRegionNumber]) {
                notDone = false;
                endCurrRegion = leftQuoteLocs[currRegionNumber];
            }
            else if (currLoc <= rightQuoteLocs[currRegionNumber]) {
                notDone = false;
                regionType = STRING_REGION;
                beginCurrRegion = leftQuoteLocs[currRegionNumber] + 1;
                endCurrRegion = rightQuoteLocs[currRegionNumber];
            } 
            else {
                beginCurrRegion = rightQuoteLocs[currRegionNumber] + 1;
                currRegionNumber++;
            }
        }
        if (notDone || numberOfStrings == 0) {
            if (lineCommentLoc < currLoc) {
                regionType = COMMENT_REGION;
                beginCurrRegion = lineCommentLoc + 2; 
                  // Note: 2 must be changed in the unlikely event that we
                  // either have a 1-character end-of-line comment token
                  // or we have one with more than 2 tokens that contains a
                  // paren.
            } 
            else {
                endCurrRegion = lineCommentLoc;
            }
        }
    }
    
    /**
     * Sets beginCurrRegion, endCurrRegion, and (perhaps) currRegionNumber
     * to indicate the next region of type regionType.  If that region is
     * on a later line, it will also call setLineLineRegions.  If there
     * is no next region of this type (because it runs off the end of the
     * file looking for one), it throws an "Unmatched paren" error.
     *    
     * @throws ParenErrorException
     */
    private void getNextRegion() throws ParenErrorException {
        if (regionType == MAIN_REGION) {
            if (currRegionNumber < numberOfStrings) {
                beginCurrRegion = rightQuoteLocs[currRegionNumber] + 1;
                currRegionNumber++;
                if (currRegionNumber == numberOfStrings) {
                    endCurrRegion = lineCommentLoc;
                } else {
                    endCurrRegion = leftQuoteLocs[currRegionNumber];
                }
            } else {
                setLineRegions(currLineNum + 1);
                currRegionNumber = 0;
                beginCurrRegion = beginLineLoc;
                if (numberOfStrings == 0) {
                    endCurrRegion = lineCommentLoc;
                } 
                else {
                    endCurrRegion = leftQuoteLocs[0];
                }
            }
        }
        else if (regionType == STRING_REGION) {
            if (currRegionNumber < numberOfStrings - 1) {
                currRegionNumber++;
            } else {
                setLineRegions(currLineNum + 1);
                while (numberOfStrings == 0) {
                    setLineRegions(currLineNum + 1);
                }
                currRegionNumber = 0;
            }
            beginCurrRegion = leftQuoteLocs[currRegionNumber] + 1;
            endCurrRegion = rightQuoteLocs[currRegionNumber];
        }
        else {
         // regionType == COMMENT_REGION
            setLineRegions(currLineNum + 1);
            while (lineCommentLoc == endLineLoc) {
                setLineRegions(currLineNum + 1);
            }
            beginCurrRegion = lineCommentLoc + 2;
            endCurrRegion = endLineLoc;
        }
    }
    
    /**
     * Sets beginCurrRegion, endCurrRegion, and (perhaps) currRegionNumber
     * to indicate the previous region of type regionType.  If that region is
     * on a later line, it will also call setLineLineRegions.  If there
     * is no previous region of this type (because it runs off the end of the
     * file looking for one), it throws an "Unmatched paren" error.
     *    
     * @throws ParenErrorException
     */
    private void getPrevRegion() throws ParenErrorException {
        if (regionType == MAIN_REGION) {
            if (currRegionNumber  > 0) {
                currRegionNumber--;
                endCurrRegion = leftQuoteLocs[currRegionNumber];
                
                if (currRegionNumber == 0) {
                    beginCurrRegion = beginLineLoc;
                } else {
                    beginCurrRegion = rightQuoteLocs[currRegionNumber-1] + 1;
                }
            } else {
                setLineRegions(currLineNum - 1);
                currRegionNumber = numberOfStrings;
                endCurrRegion = lineCommentLoc;
                if (numberOfStrings == 0) {
                    beginCurrRegion = beginLineLoc;
                } 
                else {
                    beginCurrRegion = rightQuoteLocs[numberOfStrings-1] + 1;
                }
            }
        }
        else if (regionType == STRING_REGION) {
            if (currRegionNumber > 0) {
                currRegionNumber--;
            } else {
                setLineRegions(currLineNum - 1);
                while (numberOfStrings == 0) {
                    setLineRegions(currLineNum - 1);
                }
                currRegionNumber = numberOfStrings - 1;
            }
            beginCurrRegion = leftQuoteLocs[currRegionNumber] + 1;
            endCurrRegion = rightQuoteLocs[currRegionNumber];
        }
        else {
         // regionType == COMMENT_REGION
            setLineRegions(currLineNum - 1);
            while (lineCommentLoc == endLineLoc) {
                setLineRegions(currLineNum - 1);
            }
            beginCurrRegion = lineCommentLoc + 2;
            endCurrRegion = endLineLoc;
        }
    }
    
    /**
     * Sets currLoc, and returns the index of the selected paren in PARENS.  
     * If the region has zero length, then it selects the paren to its left and 
     * sets currLoc to the selection--or the 2-char paren it's in the
     * middle of.  Otherwise, the region has to select a paren, 
     * and currLoc is set to the position to the right of that paren.
     * 
     * @param selectedRegion
     */
    private int getSelectedParen(Region selectedRegion)
            throws ParenErrorException {
        currLoc = selectedRegion.getOffset();
        int selectedParenIdx;
        if (selectedRegion.getLength() == 0) {
          selectedParenIdx = getParenToLeftOf(currLoc);
          if (selectedParenIdx == -1) {
              int tryNext = getParenToLeftOf(currLoc + 1);
              if (tryNext == -1 || PARENS[tryNext].length() == 1) {
                throw new ParenErrorException("Paren not selected", null, null);
              }
              currLoc++;
              return tryNext;
          }       
        } else {
            String selection = null; // initialization to keep compiler happy.
            try {
                selection = document.get(selectedRegion.getOffset(),
                        selectedRegion.getLength());
            } catch (BadLocationException e) {
                // This should not happen
                System.out.println(
                   "BadLocationException in GotoMatchingParenHandler.getSelectedParen");
            }
            selectedParenIdx = 0;
            boolean notDone = true ;
            while (notDone && (selectedParenIdx < PARENS.length)) {
                if (selection.equals(PARENS[selectedParenIdx])) {
                    notDone = false;
                } 
                else {
                    selectedParenIdx++;
                }
            }
            if (notDone) {
                throw new ParenErrorException("Selection is not a paren", null, null);
            }
            currLoc = currLoc + selectedRegion.getLength();
        }
        
        // Now test if we're between "(" and "*".
        if (    selectedParenIdx == LEFT_ROUND_PAREN_IDX
             && getParenToLeftOf(currLoc + 1) == COMMENT_BEGIN_IDX) {
//            throw new ParenErrorException("Selection between  (  and  *", null);
            currLoc++;
            return BEGIN_MULTILINE_COMMENT_IDX;
        }
        return selectedParenIdx ;
    }
    
    /**
     * The exception thrown when a mismatched or unmatched paren or other problem
     * is found.
     */
    private static class ParenErrorException extends Exception  {
        /*
         * The message to be displayed in the status bar
         */
        String message;
        /*
         * The region containing the string to be highlighted, or null if none.
         */
        Region[] regions = new Region[2];
        
        private ParenErrorException(String message, Region region1, Region region2){
             this.message = message;
             this.regions[0] = region1;
             this.regions[1] = region2;
        }
    }
    
    /**
     * An ErrorMessageEraser is a CaretListener that removes an error message and
     * Paren Error annotation.
     */
    private static class ErrorMessageEraser implements CaretListener{
        TLAEditor editor;
        IResource resource ;
        
       private ErrorMessageEraser(TLAEditor e, IResource res) {
            editor = e;
            resource = res;
        }

       public void caretMoved(CaretEvent event) {
           // TODO Auto-generated method stub
           editor.getEditorSite().getActionBars().getStatusLineManager().setErrorMessage(
                   null);
           editor.getViewer().getTextWidget().removeCaretListener(this);
           try {
            resource.deleteMarkers(PAREN_ERROR_MARKER_TYPE, false, 99);
        } catch (CoreException e) {
            // TODO Auto-generated catch block
            System.out.println("caretMoved threw exception");
        }

       } 
    }
    
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/preference/TLCPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.preference;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Preferences for TLC
 * @author <NAME>
 */
public class TLCPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{

    /**
     * Constructor
     */
    public TLCPreferencePage()
    {
        super(GRID);
        // Copy preference value to non-ui plugin.
        TLCUIActivator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent event) {
				final IPreferenceStore store = TLCActivator.getDefault().getPreferenceStore();
				if (TLCActivator.I_TLC_SNAPSHOT_KEEP_COUNT.equals(event.getProperty())) {
					store.setValue(TLCActivator.I_TLC_SNAPSHOT_KEEP_COUNT, (int)event.getNewValue());
				}
			}
		});
		setPreferenceStore(TLCUIActivator.getDefault().getPreferenceStore());
        setDescription("TLC Model Checker preferences");
    }

    protected Control createContents(Composite parent)
    {
        Control pageControl = super.createContents(parent);
        UIHelper.setHelp(pageControl, IHelpConstants.TLC_PREFERENCE_PAGE);
        return pageControl;
    }

    /**
     * Create field editors
     */
    protected void createFieldEditors()
    {
        addField(new BooleanFieldEditor(ITLCPreferenceConstants.I_TLC_POPUP_ERRORS, "&Always pop up TLC errors view",
                getFieldEditorParent()));

        addField(new BooleanFieldEditor(ITLCPreferenceConstants.I_TLC_REVALIDATE_ON_MODIFY,
                "&Re-validate model on save", getFieldEditorParent()));

        IntegerFieldEditor integerFieldEditor = new IntegerFieldEditor(TLCActivator.I_TLC_SNAPSHOT_KEEP_COUNT,
                                                                       "Number of model &snapshots to keep",
                                                                       getFieldEditorParent());
        integerFieldEditor.setValidRange(0, Integer.MAX_VALUE);
        addField(integerFieldEditor);
        
        // addField(new BooleanFieldEditor(ITLCPreferenceConstants.I_TLC_DELETE_PREVIOUS_FILES,
        // "&Automatically delete unused data from previous model run", getFieldEditorParent()));
        addField(new IntegerFieldEditor(ITLCPreferenceConstants.I_TLC_MAXIMUM_HEAP_SIZE_DEFAULT,
                "Maximum JVM Heap Size default in % of physical system memory", getFieldEditorParent()));
		
        integerFieldEditor = new IntegerFieldEditor(ITLCPreferenceConstants.I_TLC_TRACE_MAX_SHOW_ERRORS,
				"Default number of states shown in error traces", getFieldEditorParent());
		integerFieldEditor.setValidRange(1, Integer.MAX_VALUE);
		addField(integerFieldEditor);
    }

    public void init(IWorkbench workbench)
    {

    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TLAWhitespaceDetector.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import org.eclipse.jface.text.rules.IWhitespaceDetector;

/**
 * Detects whitespaces in TLA+ code
 * @author <NAME>
 * @version $Id$
 */
public class TLAWhitespaceDetector implements IWhitespaceDetector
{

    /* (non-Javadoc)
     * Method declared on IWhitespaceDetector
     */
    public boolean isWhitespace(char character)
    {
        return Character.isWhitespace(character);
    }
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/source/ITLAPMOutputSource.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.source;

import org.eclipse.core.runtime.IPath;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.TLAPMMessage;

/**
 * This is a source of data from the output of the
 * TLAPM for a single module given by {@link ITLAPMOutputSource#getFullModulePath()}.
 * Listeners can be added by calling {@link ITLAPMOutputSource#addListener(ITLAPMOutputSourceListener)}.
 * However, this method should not be called directly by listeners. Listeners
 * should register themselves using the singleton instance of the {@link TLAPMOutputSourceRegistry}
 * using the method {@link TLAPMOutputSourceRegistry#addListener(ITLAPMOutputSourceListener)}.
 * 
 * This interface is not used.
 * 
 * @author <NAME>
 *
 */
public interface ITLAPMOutputSource
{

    public void addListener(ITLAPMOutputSourceListener listener);

    public void removeListener(ITLAPMOutputSourceListener listener);

    /**
     * The full file system path to the module for which this source contains
     * output.
     * 
     * @return
     */
    public IPath getFullModulePath();

    /**
     * Returns the array of {@link ITLAPMOutputSourceListener}'s currently
     * listening to this source.
     * 
     * @return
     */
    public ITLAPMOutputSourceListener[] getListeners();

    /**
     * Called to notify this source of a new instance
     * of {@link ITLAPMData}.
     * 
     * @param data
     */
    public void newData(TLAPMMessage data);

    /**
     * Notifies the source that no more data is to be sent.
     */
    public void onDone();

}


<|start_filename|>tlatools/org.lamport.tlatools/javacc/TLAplusParser.java<|end_filename|>
/* Generated By:34&JavaCC: Do not edit this line. TLAplusParser.java */
package tla2sany.parser;

import tla2sany.st.ParseTree;
import tla2sany.st.TreeNode;
import tlc2.output.EC;

import tla2sany.utilities.Vector;
import tla2sany.utilities.Stack;
import util.Assert;
import util.TLAConstants;
import util.UniqueString;
import util.ToolIO;

public class TLAplusParser implements tla2sany.st.SyntaxTreeConstants, ParseTree, TLAplusParserConstants {

  public String[] dependencies() {
    /***********************************************************************
    * This method is used in modanalyzer/{SyntaxTreePrinter,ParserUnit}.   *
    ***********************************************************************/
    String[]deps = new String[ dependencyList.size() ];
    for (int lvi =0; lvi < deps.length; lvi++)
      deps[lvi] = ((UniqueString)dependencyList.elementAt(lvi)).toString();
    return deps;
  }
  public TreeNode rootNode() { return ParseTree; }
  public String moduleName() { return mn.toString(); }
//  public tla2sany.st.ParseErrors getErrors() { return PErrors; } Unused, apparently
// The front end can simply read the public PErrors.

  public SyntaxTreeNode ParseTree;
    /***********************************************************************
    * The root node.                                                       *
    ***********************************************************************/

  public Vector dependencyList = new Vector( 20 );

  private UniqueString mn = null;
     /**********************************************************************
     * The module name.                                                    *
     **********************************************************************/

  private boolean numberFlag = false;
  private boolean decimalFlag = false;

  private Operator FcnOp = Operators.getOperator( UniqueString.uniqueStringOf("[" ));
  private SyntaxTreeNode FairnessHook;

  private UniqueString At = UniqueString.uniqueStringOf("@");

  ParseErrors PErrors = new ParseErrors();

  private tla2sany.parser.OperatorStack OperatorStack = new tla2sany.parser.OperatorStack( PErrors );

  private BracketStack BStack;
    /***********************************************************************
    * This is a stack of the kinds and offsets of the tokens that start a  *
    * bulleted list within which the parser is currently grabbing tokens.  *
    ***********************************************************************/

  public boolean parse() {
    /***********************************************************************
    * This is a wrapper for actual parsing procedure CompilationUnit().    *
    * If an exception occurs, or if an error was pushed onto PErrors,      *
    * then an error message is printed and it returns false.  Otherwise,   *
    * it returns true.  Note that if we want to be able to parse an        *
    * expression, we need to implement a similar wrapper for               *
    * Expression().                                                        *
    ***********************************************************************/

    /***********************************************************************
    * The following code sets BStack to a new BracketStack object and      *
    * initializes its classes field as described in BracketStack.java.     *
    ***********************************************************************/
    BStack = new BracketStack();
    BStack.newClass();
//    BStack.registerInCurrentClass( BAND );
    BStack.registerInCurrentClass( AND );
    BStack.newClass();
//    BStack.registerInCurrentClass( BOR );
    BStack.registerInCurrentClass( OR );
    BStack.newClass();
    BStack.registerInCurrentClass( PROOF );
    BStack.newClass();
    BStack.registerInCurrentClass( LBR );
    BStack.newClass();
    BStack.registerInCurrentClass( ASSUME );

    try { ParseTree = CompilationUnit(); }
    catch( ParseException e ) {
         PErrors.push( new ParseError( msgStackToString(e) ) ); }
    catch( TokenMgrError tme ) {
      // lexical error.
      String msg = tme.getMessage();
      int bl = jj_input_stream.getBeginLine() + 1;
      int el = jj_input_stream.getEndLine() + 1;
      // lexical error.
      if ( (msg.indexOf("EOF") != -1) && (bl != el) )  {
        PErrors.push(new ParseError(
                  "Lexical {error: EOF reached, " +
                  "possibly open comment starting around line " +
                  (bl-1) )) ;
      } else  PErrors.push( new ParseError( msg  )) ;
//      PErrors.push( new ParseError( tme.getMessage() )) ;
    } /*** end catch(TokenMgrError) ****/
    if ( PErrors.empty() ) Assert.check( heirsIndex == 0, EC.SANY_PARSER_CHECK_1
//   "Assertion error in TLA+ Parser sanity check" 
       );
      /*********************************************************************
      * This is a sanity check.  The assertion should never be false.      *
      *********************************************************************/
    else {
      /*********************************************************************
      * An error has been pushed onto PErrors.  It might have been done    *
      * when an exception was caught, or by detecting an error during the  *
      * parsing without throwing an exception.  This happens in            *
      * ExceptComponent() if it finds "!.@", and in FairnessExpr().        *
      *********************************************************************/
      tla2sany.st.ParseError  list[] = PErrors.errors();
      for (int i = 0; i < list.length; i++ ) {
        ToolIO.out.println( list[i].reportedError() );
//        ToolIO.out.println( "+ " + list[i].defaultError() );
      }
    }
//   ParseTree.setNumberFlags( numberFlag, decimalFlag );
    return PErrors.empty();
  }

/*
  this is required to store temporarily information required by
  the semantic lookahead, as it doesn't have access to the variables
  of the production
*/
  private SyntaxTreeNode local;

  void registerTN( SyntaxTreeNode some) { local = some ; }

  boolean testTN() {
    /***********************************************************************
    * THIS METHOD IS APPARENTLY NOT USED.                                  *
    ***********************************************************************/
    return local.isKind(N_IdPrefix)
        && BStack.aboveReference( local.first().first().location[0] ) ;
  }

  private SyntaxTreeNode anchor = null;
    /***********************************************************************
    * This is set to a non-null value only in Expression().  If a          *
    * ClosedExpressionOrOp node is found when parsing an expression,       *
    * anchor is set to that node.  It is set to null in the following      *
    * places:                                                              *
    *                                                                      *
    *  - When beginning to parse a Substitution()                          *
    *                                                                      *
    *  - When OpSuite() or Substitution() finds that anchor equals an      *
    *    Op Symbol, as described below.                                    *
    *                                                                      *
    * The Substitution() and OpSuite() procedures look for an              *
    * Expression or Op Symbol by calling Expression() and, if that throws  *
    * an exception, catching the expression and checking if anchor is the  *
    * desired Op Symbol.                                                   *
    ***********************************************************************/

// Lookahead mechanisms for definitions
  /*************************************************************************
  * The following code is lifted directly from the getToken method         *
  * created by JavaCC in the file TLAplusParser.java.                      *
  *                                                                        *
  * J-Ch doesn't remember why he defined this method instead of just       *
  * using the GetToken method.  He thinks that it was to make sure         *
  * it would always return a token rather than null.                       *
  *************************************************************************/
  final private Token getNextPreviewToken(Token t) {
    if (t.next == null) t.next = token_source.getNextToken();
       /********************************************************************
       * token_source is declared in configuration/Configuration.java to   *
       * be a ConfigurationTokenManager.                                   *
       ********************************************************************/
    return t.next;
  }

// borrowed from code generated by JavaCC.
  final private Token initPreviewToken() {
    return lookingAhead ? jj_scanpos : token;
      /*********************************************************************
      * `lookingAhead', `token', and `jj_scanpos' are declared in          *
      * TLAplusParser (created by javacc from this file).  The javacc      *
      * documentation says that token is the value returned by             *
      * getToken(0).  God only knows what lookingAhead and jj_scanpos      *
      * are.                                                               *
      *********************************************************************/
  }

  private final void belchDEF() {
    /***********************************************************************
    * The purpose of this method seems to be to introduce a dummy          *
    * <DEFBREAK> token into the token stream, which is used in parsing     *
    * the OperatorOrFunctionDefinition non-terminal.                       *
    ***********************************************************************/
    Token previousT = initPreviewToken();
    Token currentT = getNextPreviewToken( previousT );
    previousT.next = null;  // <-- to break recursion 
    Token nextT = getNextPreviewToken( currentT );
    currentT.next = previousT;
    while (   nextT.kind != EOF
           && nextT.kind != THEOREM
           && nextT.kind != PROPOSITION
            /***************************************************************
            * This test for PROPOSITION added by LL on 5 Sep 2010 to get   *
            * the parser to handle a named PROPOSITION, LEMMA, or          *
            * COROLLARY.                                                   *
            ***************************************************************/
//           && nextT.kind != ASSUME
           /****************************************************************
           * This test for ASSUME removed on 26 June 2007.                 *
           * It made belchDEF get hung up on nested ASSUME/PROVEs.         *
           * However, this permitted extra DEFBREAK tokens to be inserted. *
           * Those extra tokens were eliminated by the change on the same  *
           * date described below.                                         *
           ****************************************************************/
           && nextT.kind != ASSUMPTION
           && nextT.kind != END_MODULE) {
      /*********************************************************************
      * As long as we have not yet reached the end of the stream or a      *
      * THEOREM, ASSUME, or END_MODULE token, move forward through the     *
      * token stream looking for a "==" token.  Maintain a chain of the    *
      * tokens passed over, with t.next equal to the previous token, and   *
      * t.next = null for the first token.                                 *
      *                                                                    *
      * At this point, the last three tokens obtained are previoustT,      *
      * currentT, and nextT, where currentT.next = previousT and           *
      * nextT.next points to the first unexamined token.                   *
      *********************************************************************/
      if ( currentT.kind == DEF ) {
        /*******************************************************************
        * currentT is a "==" token.                                        *
        *******************************************************************/
        Token t = previousT;
        if        ( t.kind == RBR || t.kind == RSB ) {
          /*****************************************************************
          * t = previousT is a ")" or "]" token.                           *
          *****************************************************************/
          // the following code assumes that parentheses are evenly balanced.
          // something could be added to reinforce the test.
          // they do not have to be on the same line either, btw.
          int depth = 1;
          while (t.next != null) {
            t = t.next;
            if ( (t.kind == LBR || t.kind == LSB) && depth == 1 ) break;
            if ( (t.kind == LBR || t.kind == LSB) && depth >  1 ) depth--;
            if ( (t.kind == RBR || t.kind == RSB) ) depth++;
           }
          if (t.next == null ) break;
          else if (t.next.kind == IDENTIFIER)
            t = t.next;
          // we are positioned at first symbol before "[" or "(" : must be an identifier
        } else
          /*****************************************************************
          * t = previousT is not a ")" or "]" token.                       *
          *****************************************************************/
           if ( t.kind == IDENTIFIER ) {
             /**************************************************************
             * t is an IDENTIFIER token.                                   *
             *                                                             *
             * If t.next [the previous token in the input stream] is a     *
             * non-prefix operator and is not preceded in the stream by    *
             * "<-" [so it belongs to a preceding substitution], then set  *
             * t to t.next if it is a prefix operator and to t.next.next   *
             * if it is an infix operator.                                 *
             *                                                             *
             * Note: If belchDef is called with the input stream at        *
             * something like "++ a ==", then evaluating t.next.next       *
             * dereferences null.  This should happen only if the user     *
             * has left off the first parameter of the definitiion and     *
             * the resulting exception seems to be caught, but it          *
             * produces a misleading error message.  This type of rare     *
             * error is hardly worth worrying about, but it would be easy  *
             * enough to add a test and might be worth doing if it's easy  *
             * to produce the right error message.                         *
             **************************************************************/
             Token identifier = t;
             if ( isOp( t.next )  && ! isPostfixOp( t.next ) ) {
               t = t.next;
               if ( t.next.kind == SUBSTITUTE )
                  t = identifier; // skip back
                else if ( isInfixOp( t ) ) t = t.next;
                // else assume prefix
              }
           } else {
             /**************************************************************
             * t is not an IDENTIFIER token.                               *
             *                                                             *
             * If it is an operator token, set t to t.next.  (It will be   *
             * a postfix operator unless the user made an error.)          *
             **************************************************************/
               if (  isOp(t) ) { // assume postfix op, the parser will catch the error
                  t = t.next;
                   }
              }
        /*******************************************************************
        * Insert a DEFBREAK token into the input stream right before       *
        * token t, and exit the while loop.                                *
        *                                                                  *
        * Changed by LL on 26 June 2007 so it doesn't add the DEFBREAK     *
        * token if there's already one there.  (This could happen because  *
        * of the change to pass over ASSUMEs described above.)             *
        *******************************************************************/
        if (   (t.next == null)
            || (t.next.kind != DEFBREAK)) {
          Token i = new Token();
          i.kind = DEFBREAK;
          i.image = "Beginning of definition";
          i.beginLine = t.beginLine;
          i.beginColumn = t.beginColumn;
          i.endLine = t.endLine;
          i.endColumn = t.endColumn;
          i.next = t.next;
          t.next = i;
         } ;
        break;  /* EXIT while */
      } else {
        /*******************************************************************
        * currentT is not a "==" token.                                    *
        *******************************************************************/
        previousT = currentT;
        currentT = nextT;
        nextT = getNextPreviewToken( currentT );
        currentT.next = previousT;
        }
    }  /* END while */
    // reverse pointers.
    /***********************************************************************
    * Go back through the examined tokens, making t.next point to the      *
    * next one for each token t.                                           *
    ***********************************************************************/
    while (previousT != null ) {
      currentT.next = nextT;
      nextT = currentT;
      currentT = previousT;
      previousT = currentT.next;
    }
    // relink firstT
    currentT.next = nextT;
  }

//
  void skipOver( int l ) {
    while ( true ) {
      Token t = getToken(1);
      int k = t.kind;
      if ( (k == EOF) || (t.beginColumn < l ) ) return;
      t = getNextToken();
    }
  }

/***************************************************************************
* Note: the non-terminal ClosedStart was commented out, apparently to be   *
* replaced by this boolean-valued method.                                  *
***************************************************************************/
boolean
ClosedStart( Token t ) {
  return   t.kind == IDENTIFIER
        || (t.kind >= op_57 && t.kind <= op_119)
           /****************************************************************
           * These are all prefix, infix, and postfix operators.           *
           ****************************************************************/
        || t.kind == NUMBER_LITERAL
        || t.kind == LBR
        || t.kind == LSB
        || t.kind == LAB
        || t.kind == LBC
        || t.kind == LWB
        || t.kind == STRING_LITERAL
        || t.kind == WF
        || t.kind == SF;
}

boolean
isOp( Token t ) {
  return t.kind >= op_57 && t.kind <= op_119;
}

boolean isInfixOp( Token t ) {
  return t.kind >= op_1 && t.kind <= op_119;
}

boolean isPostfixOp( Token t ) {
  return t.kind >= op_57 && t.kind <= op_70;
}

boolean isPrefixOp( Token t ) {
  return t.kind >= op_26 && t.kind <= op_116;
}

// global variable follows !!! Make sure it is set everywhere as required
Operator lastOp;
  /*************************************************************************
  * This seems to equal the last Prefix, Infix, PostFix, or NonExpPrefix   *
  * op that was parsed.                                                    *
  *************************************************************************/

  boolean isGenOp(SyntaxTreeNode tn) { /* has to be of the form prefix, opsym */
    int kind = tn.getKind();
    if ( kind == N_GenPrefixOp
      || kind == N_GenNonExpPrefixOp
      || kind == N_GenInfixOp
      || kind == N_GenPostfixOp
      || kind == N_FcnAppl )
       return true;
    else
      return false;
  }

//  boolean IsNotExpression () {
//    /***********************************************************************
//    * This method is called only in NumberedAssumeProve.                   *
//    ***********************************************************************/
//    Token t = initPreviewToken();
//          t = getNextPreviewToken(t);
//      /*********************************************************************
//      * Previous statement added on 1 Mar 2007 by J-Ch and LL to fix bug.  *
//      *********************************************************************/
//    int k = t.kind;
//    if ( k == US || k == LOCAL || k == VARIABLE || k == PARAMETER || k == INSTANCE || k == CONSTANT || k == STATE || k == ACTION || k == TEMPORAL ) return true;
//    else {
//      t = getNextPreviewToken(t); k = t.kind;
//      if ( k == US || k == DEF || k  == LSB )
//        return true;
//      else if (k == LBR) {
//        int depth = 1;
//        Token nt = getNextPreviewToken(t);
//        while (true) {
//          t = nt; nt = getNextPreviewToken(t); k = t.kind;
//          if ( k == RBR ) {
//             if ( depth == 1 )
//               if ( nt.kind == DEF ) return true;
//               else return false;
//             else
//                depth--;
//          } else
//          if ( k == LBR ) { depth++;
//          } else
//          if ( k == EOF ) return false;
//        }
//      }
//    }
//    return false;
//  }
//
  boolean isFieldNameToken( Token t ) {
    /***********************************************************************
    * Modified by LL on 10 Oct 2007 because of new keywords added and      *
    * obsolete ones removed.                                               *
    ***********************************************************************/
    if ( (t.kind >= ACTION && t.kind <= EXCEPT)
       ||(t.kind == EXTENDS)
       ||(t.kind >= IF && t.kind <= SF)
       ||(t.kind == STATE)
       ||(t.kind >= THEN && t.kind <= WITH)
       ||(t.kind == US)
       ||(t.kind >= op_112 && t.kind <= op_116)
       )
       return true;
     else
       return false;
  }

  boolean isLabel(SyntaxTreeNode node) {
    /***********************************************************************
    * Checks that node is a label, meaning that it is either an            *
    * identifier token or else an OpApplication node each of whose         *
    * arguments is an OpArgs node whose child is a GeneralId node with an  *
    * empty IdPrefix.                                                      *
    ***********************************************************************/
    if (node == null) {return false;} ;
    if (node.isKind(N_GeneralId)) {
        return (node.heirs()[0].heirs().length == 0) ;
       } ;
    if (! node.isKind(N_OpApplication)) {return false;} ;
    SyntaxTreeNode opArgs = (SyntaxTreeNode) node.heirs()[1] ;
if (opArgs.kind != N_OpArgs) { ToolIO.out.println("Bug: not N_OpArgs node"); };
        /*******************************************************************
        * Sanity check--can be removed after debugging.                    *
        *******************************************************************/
    for (int i = 1; i < opArgs.heirs().length; i = i+2) {
      /*********************************************************************
      * THe OpArg node for Op(arg_1, ... , arg_N) has the 2N+1 heirs       *
      *                                                                    *
      *     "("   arg_1   ","  ...  ","   arg_N   ")"                      *
      *********************************************************************/
      SyntaxTreeNode genId = (SyntaxTreeNode) opArgs.heirs()[i] ;
      if (genId.kind != N_GeneralId) {return false;} ;
      if (genId.heirs()[0].heirs().length != 0){return false;}
     } // for
    return true;
   }

  boolean labelDoesNotChangeParse(SyntaxTreeNode labeledExpr,
                                  Operator labelOp) {
    /***********************************************************************
    * Checks if preceding the expression labeledExpr with a label has not  *
    * changed the parsing of the enclosing expression.  It has changed     *
    * the parsing iff                                                      *
    *   /\ labeledExpr is an infix or postfix expression with operator     *
    *      labelOp                                                         *
    *   /\ the top of OperatorStack is an infix or prefix operator stackOp *
    *   /\ it is not the case that stackOp \prec labelOp.                  *
    ***********************************************************************/
    if ( ! (   labeledExpr.isKind(N_InfixExpr)
            || labeledExpr.isKind(N_PostfixExpr) ) ) {return true;} ;

    OSelement topNode = OperatorStack.topOfStack();
    if (topNode == null) {return true;} ;
    Operator stackOp = topNode.getOperator() ;
    return (stackOp == null) || Operator.prec(stackOp, labelOp) ;
  }

  void checkIndentation(SyntaxTreeNode nd, SyntaxTreeNode junct)
     throws ParseException {
    /***********************************************************************
    * Goes through the descendants of node nd, stopping at an N_DisjList   *
    * or N_ConjList node.  For each node it finds, if checks whether it    *
    * is properly indented with respect to the current N_DisjItem or       *
    * N_ConjItem junct.  If not, it reports an error by throwing an        *
    * exception.                                                           *
    ***********************************************************************/
    TreeNode[] children = nd.heirs() ;
    for (int i = 0; i < children.length; i++) {
      SyntaxTreeNode child = (SyntaxTreeNode) children[i] ;
      if (! (   child.isKind(N_ConjList)
             || child.isKind(N_DisjList))) {
         if (!BStack.aboveReference(child.location[1])) {
           throw new ParseException(
              "Item at " + child.getLocation().toString() +
              " is not properly indented inside conjunction or " +
              " disjunction list item at " + junct.getLocation().toString()) ;
          } ;
         checkIndentation(child, junct) ;
       } ;
     } ;
    }

// predicate used in lookahead to discriminate between the Case Separator and
// the box operator. Returns true if it is most likely not the separator.
// This is a weak mechanism.
  boolean boxDisc() {
    Token t = getToken(1);
    if ( t.kind == CASESEP )
      return OperatorStack.preInEmptyTop();
    else
      return true;
  }

  boolean caseSep() {
    Token t = getToken(1);
    return ( t.kind == CASESEP );
  }

  boolean matchFcnConst () {
    /***********************************************************************
    * Seems to return true iff the next current token sequence begins      *
    * with "<< ...  >> \in" or "Identifier [, Identifier] \in".  It is     *
    * used after a "{" to see if this is a subset expression such as "{x   *
    * \in S : exp}" and after a "[" to see if it is a function expression  *
    * such as "[x \in S |-> exp]".  This leads to the bug that it starts   *
    * incorrectly interpreting the expressions "{x \in S}" and             *
    * "{<<1, 2>> \in {}}" as a subset expression and reports an error.     *
    ***********************************************************************/
    Token t = initPreviewToken();
    t = getNextPreviewToken( t );
   if (t.kind == LAB) {
      int count = 1;
      while (count != 0 ) {
        t = getNextPreviewToken( t );
        if (t.kind == LAB) count++;
        if (t.kind == RAB) count--;
        if (t.kind == EOF) return false;
      }
      t = getNextPreviewToken( t );
      return (t.kind == IN );
    } else
    if (t.kind == IDENTIFIER) {
      t = getNextPreviewToken( t );
      while ( t.kind == COMMA ) {
        t = getNextPreviewToken( t );
        if (t.kind != IDENTIFIER) return false;
        t = getNextPreviewToken( t );
      }
      return (t.kind == IN );
    } else
      return false;
  }

//  int numberFromStep( String step ) {
//    int top = step.indexOf('>');
//    return Integer.parseInt( step.substring( 1, top ) );
//  }
//
  Object msgStack[] = new Object[ 512 ];
  int msgStackMaxSize = 512;
  int msgStackCurrentSize = 0;

  private final void pushMsg( String s, Token t ) {
    if ( msgStackCurrentSize == msgStackMaxSize) {
      Object neo[] = new Object[ 2 * msgStackMaxSize ];
      System.arraycopy(msgStack, 0, neo, 0, msgStackMaxSize);
      msgStack = neo;
      msgStackMaxSize *= 2;
    }
    msgStack [ msgStackCurrentSize   ] = s;
    msgStack [ msgStackCurrentSize+1 ] = t;
    msgStackCurrentSize +=2;
  }

  private final void popMsg() {
    msgStackCurrentSize -=2;
  }

  private String expecting = "nothing";
    /***********************************************************************
    * It appears that the value of expecting is what is printed out in     *
    * error messages as what the parser was expecting when it encountered  *
    * an error.                                                            *
    ***********************************************************************/

  private final String msgStackToString(ParseException e) {
    StringBuffer msg;
    String name = " *unknown* (error occurred before module header)";
    if (mn != null) name = mn.toString();

    msg = new StringBuffer("***Parse Error***\n");
    if ( expecting != emptyString ) {
      msg.append("Was expecting \"");
      msg.append( expecting );
      msg.append("\"\n");
    }

    msg.append(e.getShortMessage());
//    msg.append(" while parsing ");
//    msg.append(name);
//
//    msg.append(".\nResidual stack trace follows:\n");

    msg.append("\n\nResidual stack trace follows:\n");
    int last = msgStackCurrentSize - 10;
    if (last < 0 ) last = 0;
    for ( int lvi = msgStackCurrentSize; lvi > last; lvi -=2 ) {
      msg.append( (String) msgStack[lvi -2 ] );
      msg.append(" starting at line ");
      Token t =  (Token) msgStack[lvi - 1 ];
      msg.append( t.beginLine );
      msg.append(", column ");
      msg.append( t.beginColumn );
      msg.append(".\n");
    }
    return msg.toString();
  }

//

  /*************************************************************************
  * heirsTable is an array of physical length heirsSize that implements a  *
  * dynamic array of length heirsIndex, where heirsIndex <= heirsSize.     *
  * Elements are added to heirsTable by the addHeir method, which          *
  * increments heirsSize if needed.  Elements are removed from the array   *
  * by the getLastHeirs() and popHeir() methods.                           *
  *                                                                        *
  * It appears that the heirsTable is used as a stack of sequences of      *
  * syntax tree nodes, each being the sequence of heirs (children) of a    *
  * node that is currently being parsed.  The top of the stack is the      *
  * sequence at the end of the heirsTable array.  Each sequence is begun   *
  * by a null entry.  The bpa() method is called when about to push such   *
  * a sequence onto the stack; it adds the null element that marks the     *
  * beginning of the sequence.  Similarly, the epa() method is called      *
  * after popping a sequence off the top of the stack; it removes the      *
  * null element.                                                          *
  *************************************************************************/
  private SyntaxTreeNode heirsTable[] = new SyntaxTreeNode[ 512 ];
  private int heirsSize = 512;
  private int heirsIndex = 0;

  private final void addHeir( SyntaxTreeNode sn ) {
    /***********************************************************************
    * Appends the syntax tree sn to the end of the dynamic array           *
    * implemented by heirsTable.                                           *
    ***********************************************************************/
    if ( heirsIndex == heirsSize ) {
      SyntaxTreeNode nh[] = new SyntaxTreeNode[ heirsSize + 512 ];
      System.arraycopy( heirsTable, 0, nh, 0, heirsSize );
      heirsSize += 512;
      heirsTable = nh;
    }
    heirsTable[ heirsIndex ] = sn; heirsIndex++;
  }

  private final SyntaxTreeNode[] getLastHeirs() {
    /***********************************************************************
    * This method will throw an array-out-of-bounds exception if called    *
    * when heirsIndex = 0 (so the dynamic array implemented by heirsTable  *
    * is empty) or if that dynamic array contains no null entry.           *
    *                                                                      *
    * If the last element of the dynamic heirsTable array is null, then    *
    * it returns null.  Otherwise, it returns an array equal to the        *
    * sequence of non-null elements at the end of the dynamic heirsTable   *
    * array and removes them from that array.                              *
    ***********************************************************************/
    int lvi = heirsIndex - 1;
    while (heirsTable[ lvi ] != null ) lvi--;
    /***********************************************************************
    * Assert: /\ lvi < heirsIndex                                          *
    *         /\ heirsTable[lvi] = null                                    *
    *         /\ \A i \in lvi+1 .. heirsIndex-1 : heirsTable[i] # null     *
    ***********************************************************************/
    int as = heirsIndex - lvi - 1;
    if (as == 0)
      return null;
    else {
      SyntaxTreeNode ts[] = new SyntaxTreeNode[ as ];
      System.arraycopy( heirsTable, lvi + 1, ts, 0, as);
      heirsIndex = lvi + 1;
      /*********************************************************************
      * Assert /\ as > 0                                                   *
      *        /\ \A i \in 0..as-1 : ts[i] = heirsTable[lvi + i + 1]       *
      *        /\ heirsIndex = lvi + 1                                     *
      *********************************************************************/
      return ts;
    }
  }

  private final boolean popHeir() {
   /************************************************************************
   * Throws an array-out-of-bounds exception if heirsIndex = 0 (meaning    *
   * that the dynamic array implemented by heirsTable is empty).           *
   *                                                                       *
   * It removes the last element from the heirsTable array and returns     *
   * true iff the new last element is null.                                *
   ************************************************************************/
    return heirsTable[ --heirsIndex ] == null;
  }

  private String emptyString = "";

  private final void bpa( String s) { // Beginning of Production Actions 
    addHeir( null );
if (System.getProperty("TLA-StackTrace", "off").equals("on")) ToolIO.out.println("Beginning " + s);
    pushMsg( s, getToken(1) );
    expecting = emptyString;
  }

  private final void epa() {
    popMsg();
if (System.getProperty("TLA-StackTrace", "off").equals("on")) ToolIO.out.println("Ending " + msgStack [ msgStackCurrentSize   ]);
    Assert.check( popHeir(), EC.SANY_PARSER_CHECK_2);
 // "Assertion error in epa()" 
    expecting = emptyString;
  }
//

  Stack internals = new Stack();

  private final void addDependency( UniqueString s ) {
    int lvi = internals.search( s );
    if ( lvi < 0 )
      dependencyList.addElement( s );
  }

  private final UniqueString reduceString( String s ) {
    int l = s.length();
    StringBuffer copy = new StringBuffer( l );
    int i = 0;
    int j = 0;
    while ( i!= l ) {
      if (s.charAt(i) == '\\' ) {
        i++; char c = s.charAt(i);
             if (c == '\\') copy.append( '\\');
        else if (c == 'n')  copy.append( '\n');
        else if (c == 'r')  copy.append( '\r');
        else if (c == 'f')  copy.append( '\f');
        else if (c == 't')  copy.append( '\t');
        else if (c == '"')  copy.append( '"');
      } else
         copy.append( s.charAt(i));
      i++; j++;
    }
    copy.setLength(j);
    return UniqueString.uniqueStringOf(copy.toString());
  }

/***************************************************************************
* Fields and methods for parsing proofs.                                   *
***************************************************************************/
private int proofDepth = -1 ;
  /*************************************************************************
  * The nesting level of the proof we're currently processing, counting    *
  * from 0 a la Java.                                                      *
  *************************************************************************/

private final int MaxProofDepth = 100 ;
private int[] proofLevelStack = new int[MaxProofDepth] ;
  /*************************************************************************
  * The level number of a proof with steps numbered <n>x is n.  The value  *
  * of proofLevelStack[proofDepth] is the level number of the current      *
  * proof.  If we have started processing a proof haven't yet determined   *
  * its level, then proofLevelStack[proofDepth] equals -1.                 *
  *************************************************************************/

private int levelOfProofStepLexeme(Token tok){
  /*************************************************************************
  * The level of a ProofStepLexeme or ProofStepDotLexeme.  It returns -1   *
  * for "*" and -2 for "*".                                                *
  *************************************************************************/
  String im = tok.image ;
  if (im.substring(1,2).equals("*")) {return -1;} ;
  if (im.substring(1,2).equals("+")) {return -2;} ;
  return new Integer(im.substring(1, im.indexOf('>'))).intValue() ;
    /***********************************************************************
    * The ".intValue()" added by SZ because Java 1.4 doesn't support       *
    * auto-boxing.                                                         *
    ***********************************************************************/
 }

/***************************************************************************
* The following method returns the canonical form of the step number       *
* contained in token t.  This means that a "+" or "*" is replaced by the   *
* appropriate level number, and leading zeros are removed from a regular   *
* level number.                                                            *
***************************************************************************/
private UniqueString correctedStepNum(Token t) {
  String str = t.image ;
  if (   str.substring(1,2).equals("*")
      || str.substring(1,2).equals("+") ) {
    int level = getProofLevel() ;
    if ((level < 0) && (proofDepth > 0)) {
      /*********************************************************************
      * We've started a proof without yet determining the level number.    *
      * Since this method is being called when encountering a step number  *
      * token, this means we've encountered a step number inside a BY. So  *
      * the actual level number to use here is the "previous" level        *
      * number.                                                            *
      *********************************************************************/
      level = proofLevelStack[proofDepth-1] ;
     }
    str = "<" + level + str.substring(2) ;
   }
  else {str = "<" + levelOfProofStepLexeme(t) + str.substring(str.indexOf('>'));
   } ;
  return UniqueString.uniqueStringOf(str) ;
  } ;

private void pushProofLevel() throws ParseException {
  /*************************************************************************
  * Called to begin the processing of a new proof level.  It increments    *
  * proofDepth and sets the proofLevelStack entry to -1.                   *
  *************************************************************************/
  proofDepth++ ;
  if (proofDepth >= MaxProofDepth) {
    throw new ParseException("Proofs nested more than " +
                             MaxProofDepth + "deep.") ;
   } ;
  proofLevelStack[proofDepth] = -1 ;
 }

private void popProofLevel() throws ParseException {
  if (proofDepth < 0) {
    throw new ParseException("Parser bug: an extra QED step found." ) ;
   } ;
  proofDepth-- ;
 }

private void setProofLevel(int val) throws ParseException {
  if (proofDepth < 0) {
    throw new ParseException("Parser bug: proof step found outside proof." ) ;
   } ;
  proofLevelStack[proofDepth] = val;
 }

private int getProofLevel() {
  if (proofDepth < 0) { return proofDepth; } ;
  return proofLevelStack[proofDepth]; }

private boolean beginsProof(Token tok) {
  /*************************************************************************
  * True iff the token tok begins a new proof--that is, iff it is either   *
  * "BY", "PROOF", a step number that has a higher level than the current  *
  * level, begins "<+>", or begins "<*>" and we are not inside a proof.    *
  *************************************************************************/
  String im = tok.image ;
  if (im.length() < 2) {return false;}
    /***********************************************************************
    * This can happen if the user makes a weird error.                     *
    ***********************************************************************/
  if (im.substring(1,2).equals("*")) {return (proofDepth < 0);} ;

  if (im.substring(1,2).equals("+")) {return true ;} ;
  switch (tok.kind) {
    case ProofStepLexeme :
    case BareLevelLexeme :
    case UnnumberedStepLexeme :
    case ProofStepDotLexeme :
      if (proofDepth < 0) {return true ;} ;
      int tokLevel = levelOfProofStepLexeme(tok) ;
      return    (proofLevelStack[proofDepth] >= 0)
             && (tokLevel > proofLevelStack[proofDepth]) ;
    case BY :
    case PROOF :
    case OBVIOUS :
    case OMITTED :
      return true ;
   }; // switch
  return false ;
 }

private boolean correctLevel(Token tok) {
  /*************************************************************************
  * True iff tok is a correct proof step token for the current level of    *
  * proof, where precedeByPROOF is true iff the proof is preceded by a     *
  * "PROOF" token (needed in case this is the first step of the proof).    *
  * If this is the first step being processed for current proof, then it   *
  * sets the current proof level.                                          *
  *************************************************************************/
  int tokLevel = levelOfProofStepLexeme(tok) ;

  /*************************************************************************
  * Set lastDepth to the level of the containing proof, or -1 if this is   *
  * the top-level proof.                                                   *
  *************************************************************************/
  int lastLevel = -1 ;
  if (proofDepth > 0) {lastLevel = proofLevelStack[proofDepth-1] ;}
  switch (tokLevel) {
    case -1 :
      /*********************************************************************
      * tok is <*>...  This is always legal because it can begin a proof   *
      * iff it was preceded by a "PROOF".                                  *
      *********************************************************************/
      if (proofLevelStack[proofDepth] < 0) {
        proofLevelStack[proofDepth] = lastLevel + 1 ;
       } ;
      return true ;

    case -2 :
      /*********************************************************************
      * tok is <+>...  This is legal iff it begins a proof.                *
      *********************************************************************/
      if (proofLevelStack[proofDepth] < 0) {
        proofLevelStack[proofDepth] = lastLevel + 1 ;
        return true ;
       }
      else return false ;

    default :
      if (proofLevelStack[proofDepth] < 0) {
        proofLevelStack[proofDepth] = tokLevel;
        return   (tokLevel > lastLevel) ;
       }
      else return (proofLevelStack[proofDepth] == tokLevel) ;
   }
 }

/* beginning of the grammar productions */
  final public Token PrefixOpToken() throws ParseException {
  Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_26:
      t = jj_consume_token(op_26);
      break;
    case op_29:
      t = jj_consume_token(op_29);
      break;
    case op_58:
      t = jj_consume_token(op_58);
      break;
    case CASESEP:
      t = jj_consume_token(CASESEP);
      break;
    case op_61:
      t = jj_consume_token(op_61);
      break;
    case op_112:
      t = jj_consume_token(op_112);
      break;
    case op_113:
      t = jj_consume_token(op_113);
      break;
    case op_114:
      t = jj_consume_token(op_114);
      break;
    case op_115:
      t = jj_consume_token(op_115);
      break;
    case op_116:
      t = jj_consume_token(op_116);
      break;
    default:
      jj_la1[0] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return t;}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* NEPrefixOpToken and PrefixOpToken differ because the first includes      *
* "-." while the second contains does not.  Neither includes "-".          *
***************************************************************************/
  final public Token NEPrefixOpToken() throws ParseException {
  Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_26:
      t = jj_consume_token(op_26);
      break;
    case op_29:
      t = jj_consume_token(op_29);
      break;
    case op_58:
      t = jj_consume_token(op_58);
      break;
    case CASESEP:
      t = jj_consume_token(CASESEP);
      break;
    case op_61:
      t = jj_consume_token(op_61);
      break;
    case op_76:
      t = jj_consume_token(op_76);
      break;
    case op_112:
      t = jj_consume_token(op_112);
      break;
    case op_113:
      t = jj_consume_token(op_113);
      break;
    case op_114:
      t = jj_consume_token(op_114);
      break;
    case op_115:
      t = jj_consume_token(op_115);
      break;
    case op_116:
      t = jj_consume_token(op_116);
      break;
    default:
      jj_la1[1] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return t;}
    throw new Error("Missing return statement in function");
  }

  final public Token InfixOpToken() throws ParseException {
  Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_1:
      t = jj_consume_token(op_1);
      break;
    case AND:
      t = jj_consume_token(AND);
      break;
    case op_3:
      t = jj_consume_token(op_3);
      break;
    case op_4:
      t = jj_consume_token(op_4);
      break;
    case OR:
      t = jj_consume_token(OR);
      break;
    case op_6:
      t = jj_consume_token(op_6);
      break;
    case op_7:
      t = jj_consume_token(op_7);
      break;
    case op_8:
      t = jj_consume_token(op_8);
      break;
    case op_9:
      t = jj_consume_token(op_9);
      break;
    case op_10:
      t = jj_consume_token(op_10);
      break;
    case op_11:
      t = jj_consume_token(op_11);
      break;
    case op_12:
      t = jj_consume_token(op_12);
      break;
    case op_13:
      t = jj_consume_token(op_13);
      break;
    case op_14:
      t = jj_consume_token(op_14);
      break;
    case op_15:
      t = jj_consume_token(op_15);
      break;
    case op_16:
      t = jj_consume_token(op_16);
      break;
    case op_17:
      t = jj_consume_token(op_17);
      break;
    case op_18:
      t = jj_consume_token(op_18);
      break;
    case op_19:
      t = jj_consume_token(op_19);
      break;
    case IN:
      t = jj_consume_token(IN);
      break;
    case op_21:
      t = jj_consume_token(op_21);
      break;
    case op_22:
      t = jj_consume_token(op_22);
      break;
    case op_23:
      t = jj_consume_token(op_23);
      break;
    case op_24:
      t = jj_consume_token(op_24);
      break;
    case op_25:
      t = jj_consume_token(op_25);
      break;
    case op_27:
      t = jj_consume_token(op_27);
      break;
    case op_30:
      t = jj_consume_token(op_30);
      break;
    case op_31:
      t = jj_consume_token(op_31);
      break;
    case op_32:
      t = jj_consume_token(op_32);
      break;
    case op_33:
      t = jj_consume_token(op_33);
      break;
    case op_34:
      t = jj_consume_token(op_34);
      break;
    case op_35:
      t = jj_consume_token(op_35);
      break;
    case op_36:
      t = jj_consume_token(op_36);
      break;
    case op_37:
      t = jj_consume_token(op_37);
      break;
    case op_38:
      t = jj_consume_token(op_38);
      break;
    case op_39:
      t = jj_consume_token(op_39);
      break;
    case op_40:
      t = jj_consume_token(op_40);
      break;
    case op_41:
      t = jj_consume_token(op_41);
      break;
    case op_42:
      t = jj_consume_token(op_42);
      break;
    case op_43:
      t = jj_consume_token(op_43);
      break;
    case op_44:
      t = jj_consume_token(op_44);
      break;
    case op_45:
      t = jj_consume_token(op_45);
      break;
    case op_46:
      t = jj_consume_token(op_46);
      break;
    case op_47:
      t = jj_consume_token(op_47);
      break;
    case op_48:
      t = jj_consume_token(op_48);
      break;
    case op_49:
      t = jj_consume_token(op_49);
      break;
    case op_50:
      t = jj_consume_token(op_50);
      break;
    case op_51:
      t = jj_consume_token(op_51);
      break;
    case op_52:
      t = jj_consume_token(op_52);
      break;
    case op_53:
      t = jj_consume_token(op_53);
      break;
    case op_54:
      t = jj_consume_token(op_54);
      break;
    case op_55:
      t = jj_consume_token(op_55);
      break;
    case op_56:
      t = jj_consume_token(op_56);
      break;
    case op_59:
      t = jj_consume_token(op_59);
      break;
    case op_62:
      t = jj_consume_token(op_62);
      break;
    case op_63:
      t = jj_consume_token(op_63);
      break;
    case op_64:
      t = jj_consume_token(op_64);
      break;
    case EQUALS:
      t = jj_consume_token(EQUALS);
      break;
    case op_66:
      t = jj_consume_token(op_66);
      break;
    case op_67:
      t = jj_consume_token(op_67);
      break;
    case op_71:
      t = jj_consume_token(op_71);
      break;
    case op_72:
      t = jj_consume_token(op_72);
      break;
    case op_73:
      t = jj_consume_token(op_73);
      break;
    case op_74:
      t = jj_consume_token(op_74);
      break;
    case op_75:
      t = jj_consume_token(op_75);
      break;
    case op_77:
      t = jj_consume_token(op_77);
      break;
    case op_78:
      t = jj_consume_token(op_78);
      break;
    case op_79:
      t = jj_consume_token(op_79);
      break;
    case op_80:
      t = jj_consume_token(op_80);
      break;
    case op_81:
      t = jj_consume_token(op_81);
      break;
    case op_82:
      t = jj_consume_token(op_82);
      break;
    case op_83:
      t = jj_consume_token(op_83);
      break;
    case op_84:
      t = jj_consume_token(op_84);
      break;
    case op_85:
      t = jj_consume_token(op_85);
      break;
    case op_86:
      t = jj_consume_token(op_86);
      break;
    case op_87:
      t = jj_consume_token(op_87);
      break;
    case op_88:
      t = jj_consume_token(op_88);
      break;
    case op_89:
      t = jj_consume_token(op_89);
      break;
    case op_90:
      t = jj_consume_token(op_90);
      break;
    case op_91:
      t = jj_consume_token(op_91);
      break;
    case op_92:
      t = jj_consume_token(op_92);
      break;
    case op_93:
      t = jj_consume_token(op_93);
      break;
    case op_94:
      t = jj_consume_token(op_94);
      break;
    case op_95:
      t = jj_consume_token(op_95);
      break;
    case op_96:
      t = jj_consume_token(op_96);
      break;
    case op_97:
      t = jj_consume_token(op_97);
      break;
    case op_98:
      t = jj_consume_token(op_98);
      break;
    case op_100:
      t = jj_consume_token(op_100);
      break;
    case op_101:
      t = jj_consume_token(op_101);
      break;
    case op_102:
      t = jj_consume_token(op_102);
      break;
    case op_103:
      t = jj_consume_token(op_103);
      break;
    case op_104:
      t = jj_consume_token(op_104);
      break;
    case op_105:
      t = jj_consume_token(op_105);
      break;
    case op_106:
      t = jj_consume_token(op_106);
      break;
    case op_107:
      t = jj_consume_token(op_107);
      break;
    case op_108:
      t = jj_consume_token(op_108);
      break;
    case op_109:
      t = jj_consume_token(op_109);
      break;
    case op_110:
      t = jj_consume_token(op_110);
      break;
    case op_111:
      t = jj_consume_token(op_111);
      break;
    case op_117:
      t = jj_consume_token(op_117);
      break;
    case op_118:
      t = jj_consume_token(op_118);
      break;
    case op_119:
      t = jj_consume_token(op_119);
      break;
    default:
      jj_la1[2] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return t;}
    throw new Error("Missing return statement in function");
  }

  final public Token PostfixOpToken() throws ParseException {
Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_57:
      t = jj_consume_token(op_57);
      break;
    case op_68:
      t = jj_consume_token(op_68);
      break;
    case op_69:
      t = jj_consume_token(op_69);
      break;
    case op_70:
      t = jj_consume_token(op_70);
      break;
    default:
      jj_la1[3] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return t;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode CompilationUnit() throws ParseException {
  SyntaxTreeNode tempASTN;
  belchDEF();
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case BEGIN_PRAGMA:
      Prelude();
      break;
    default:
      jj_la1[4] = jj_gen;
      ;
    }
    tempASTN = Module();
                        token_source.SwitchTo(0);
    {if (true) return tempASTN;}
    throw new Error("Missing return statement in function");
  }

/* SwitchTo is used to reset the state of the tokenizer */
  final public void Prelude() throws ParseException {
    jj_consume_token(BEGIN_PRAGMA);
    label_1:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case NUMBER:
      case IDENTIFIER:
        ;
        break;
      default:
        jj_la1[5] = jj_gen;
        break label_1;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case NUMBER:
        jj_consume_token(NUMBER);
        break;
      case IDENTIFIER:
        jj_consume_token(IDENTIFIER);
        break;
      default:
        jj_la1[6] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
  }

  final public SyntaxTreeNode Module() throws ParseException {
  Token t;
  SyntaxTreeNode lSTN[] = new SyntaxTreeNode[ 4 ];
  bpa( "Module definition" );
  internals.push( null );
  Object pop = null;
  expecting = "---- MODULE";
    lSTN[0] = BeginModule();
  expecting = "EXTENDS clause or module body";
    lSTN[1] = Extends();
  expecting = "Module body";
    lSTN[2] = Body();
  expecting = "==== or more Module body";
    lSTN[3] = EndModule();
  do { pop = internals.pop(); } while (pop != null );
  internals.push( lSTN[0].zero[1].image );
  epa(); {if (true) return new SyntaxTreeNode( mn, N_Module, lSTN );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode BeginModule() throws ParseException {
  SyntaxTreeNode lSTN[] = new SyntaxTreeNode[3];
  Token t;
  bpa( "Begin module" );
  expecting = "---- MODULE (beginning of module)";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case _BM0:
      t = jj_consume_token(_BM0);
      break;
    case _BM1:
      t = jj_consume_token(_BM1);
      break;
    case _BM2:
      t = jj_consume_token(_BM2);
      break;
    default:
      jj_la1[7] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
      lSTN[0] =  new SyntaxTreeNode(mn, t);
  expecting = "Identifier";
  t = getToken(1);
  if (isFieldNameToken( t )) t.kind = IDENTIFIER;
    lSTN[1] = Identifier();
    if ( mn == null ) mn = lSTN[1].image;
    expecting = "----";
    t = jj_consume_token(SEPARATOR);
                      lSTN[2] =  new SyntaxTreeNode(mn, t );
    epa(); {if (true) return new SyntaxTreeNode( mn, N_BeginModule, lSTN );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode EndModule() throws ParseException {
  SyntaxTreeNode lSTN[] = new SyntaxTreeNode[1];
  Token t;
    t = jj_consume_token(END_MODULE);
    lSTN[0] = new SyntaxTreeNode(mn, t);
    {if (true) return new SyntaxTreeNode(mn, N_EndModule, lSTN );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Extends() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa( "Extends" );
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EXTENDS:
      t = jj_consume_token(EXTENDS);
                        addHeir( new SyntaxTreeNode(mn, t));
  expecting = "Identifier";
  t = getToken(1);
  if (isFieldNameToken( t )) t.kind = IDENTIFIER;
      tn = Identifier();
                      addDependency( tn.image ); addHeir( tn );
  expecting = "comma or module body";
      label_2:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[8] = jj_gen;
          break label_2;
        }
        t = jj_consume_token(COMMA);
                       addHeir( new SyntaxTreeNode(mn, t) );
  expecting = "Identifier";
  t = getToken(1);
  if (isFieldNameToken( t )) t.kind = IDENTIFIER;
        tn = Identifier();
                        addDependency( tn.image ); addHeir( tn );
      }
      break;
    default:
      jj_la1[9] = jj_gen;
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_Extends, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Body() throws ParseException {
  SyntaxTreeNode tn, sn[];
  Token t;
  bpa("Module body");
  expecting = "LOCAL, INSTANCE, PROOF, ASSUMPTION, THEOREM, " +
              "RECURSIVE, declaration, or definition";
    label_3:
    while (true) {
      if (jj_2_1(1)) {
        ;
      } else {
        break label_3;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case SEPARATOR:
        t = jj_consume_token(SEPARATOR);
                        tn = new SyntaxTreeNode(mn, t);
        break;
      case VARIABLE:
        tn = VariableDeclaration();
        break;
      case CONSTANT:
        tn = ParamDeclaration();
        break;
      default:
        jj_la1[10] = jj_gen;
        if (jj_2_2(2)) {
          tn = OperatorOrFunctionDefinition();
        } else {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case RECURSIVE:
            tn = Recursive();
            break;
          default:
            jj_la1[11] = jj_gen;
            if (jj_2_3(2)) {
              tn = Instance();
            } else if (jj_2_4(2)) {
              tn = Assumption();
            } else if (jj_2_5(2)) {
              tn = Theorem();
            } else {
              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
              case _BM1:
              case _BM2:
              case _BM0:
                tn = Module();
                                      belchDEF();
                break;
              default:
                jj_la1[12] = jj_gen;
                if ((getToken(1).kind == USE && getToken(2).kind != ONLY)
                                    || (getToken(1).kind == HIDE)) {
                  tn = UseOrHideOrBy();
                } else {
                  jj_consume_token(-1);
                  throw new ParseException();
                }
              }
            }
          }
        }
      }
                                addHeir(tn);
    }
    sn = getLastHeirs(); epa();
    {if (true) return new SyntaxTreeNode(mn, N_Body, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode VariableDeclaration() throws ParseException {
  SyntaxTreeNode tn, sn[];
  Token t;
  SyntaxTreeNode lSTN[] = new SyntaxTreeNode[1];
  bpa( "variable declaration" );
    t = jj_consume_token(VARIABLE);
                       lSTN[0] = new SyntaxTreeNode( mn, t);
  expecting = "Identifier";
    tn = Identifier();
                      addHeir( tn );
  expecting = "comma or module body";
    label_4:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[13] = jj_gen;
        break label_4;
      }
      t = jj_consume_token(COMMA);
                       addHeir( new SyntaxTreeNode( mn, t) ) ;
  expecting = "Identifier";
      tn = Identifier();
                        addHeir( tn );
    }
    sn = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_VariableDeclaration, lSTN, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ParamDeclaration() throws ParseException {
  SyntaxTreeNode tn, sn[];
  Token t;
  bpa("Parameter declaration");
  expecting = TLAConstants.KeyWords.CONSTANT;
    tn = ParamSubDecl();
                         addHeir(tn);
 expecting = "Identifier, operator or _";
    tn = ConstantDeclarationItems();
                                    addHeir(tn);
 expecting = ",";
    label_5:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[14] = jj_gen;
        break label_5;
      }
      t = jj_consume_token(COMMA);
                       addHeir( new SyntaxTreeNode(mn, t) ) ;
 expecting = "Identifier, operator or _";
      tn = ConstantDeclarationItems();
                                      addHeir(tn);
    }
    sn = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_ParamDeclaration, sn );}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Used to allow "STATE FUNCTION", "TEMPORAL", etc.                         *
***************************************************************************/
  final public SyntaxTreeNode ParamSubDecl() throws ParseException {
  SyntaxTreeNode tn, sn[];
  Token t, u;
  bpa("Parameter declaration item");
    t = jj_consume_token(CONSTANT);
     sn = new SyntaxTreeNode[1]; sn[0] = new SyntaxTreeNode(mn, t);
     tn = new SyntaxTreeNode(mn, N_ConsDecl, sn );
    epa();
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Recursive ::= <CONSTANT> ConstantDeclarationItems                        *
*                 ( <COMMA> ConstantDeclarationItems )*                    *
*                                                                          *
* Produces an N_Recursive node.                                            *
***************************************************************************/
  final public SyntaxTreeNode Recursive() throws ParseException {
  SyntaxTreeNode tn, sn[];
  Token t;
  bpa("Recursive");
  expecting = "RECURSIVE";
    t = jj_consume_token(RECURSIVE);
                    addHeir(new SyntaxTreeNode(mn, t));
                    expecting = "Identifier, operator or _";
    tn = ConstantDeclarationItems();
                                    addHeir(tn);
                                    expecting = ",";
    label_6:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[15] = jj_gen;
        break label_6;
      }
      t = jj_consume_token(COMMA);
                       addHeir( new SyntaxTreeNode(mn, t) ) ;
                       expecting = "Identifier, operator or _";
      tn = ConstantDeclarationItems();
                                      addHeir(tn);
                                      expecting = "`,' or `)'";
    }
    sn = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_Recursive, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ConstantDeclarationItems() throws ParseException {
  SyntaxTreeNode tn, sn[];
  int kind;
  Token t;
  bpa( "Constant declaration items");
  expecting = "Identifier, _ or prefix op";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      tn = Identifier();
                      addHeir( tn ); kind = N_IdentDecl;
expecting  = "(, comma, or Module Body";
      if (jj_2_6(2)) {
        /*******************************************************************
                * The following comment apparently made sense at the time.  I      *
                * wonder what it should have said.                                 *
                *                                                                  *
                * This lookahead was added by J-Ch & LL on 1 Mar 2007 to fix the   *
                * error when it tried to parse                                     *
                *                                                                  *
                *    CONSTANT ASSUME A                                             *
                *             (B+C)                                                *
                *    PROVE ...                                                     *
                *******************************************************************/
              t = jj_consume_token(LBR);
                  addHeir( new SyntaxTreeNode( mn, t) ) ;
expecting = "_";
        t = jj_consume_token(US);
                  addHeir( new SyntaxTreeNode( mn, t) ) ;
expecting = "comma or )";
        label_7:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[16] = jj_gen;
            break label_7;
          }
          t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode( mn, t) ) ;
expecting = "_";
          t = jj_consume_token(US);
                      addHeir( new SyntaxTreeNode( mn, t) ) ;
expecting = "comma or )";
        }
        t = jj_consume_token(RBR);
                  addHeir( new SyntaxTreeNode( mn, t) ) ;
      } else {
        ;
      }
      break;
    case op_76:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
      // LOOKAHEAD( <OpSymbol>, { isPrefixDeclOp( getToken(1) )  } )
          tn = NonExpPrefixOp();
expecting = "_";
      kind = N_PrefixDecl; addHeir( tn );
      t = jj_consume_token(US);
               addHeir( new SyntaxTreeNode( mn, t) ) ;
      break;
    case US:
      t = jj_consume_token(US);
expecting = "prefix or postfix operator";
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_1:
      case AND:
      case op_3:
      case op_4:
      case OR:
      case op_6:
      case op_7:
      case op_8:
      case op_9:
      case op_10:
      case op_11:
      case op_12:
      case op_13:
      case op_14:
      case op_15:
      case op_16:
      case op_17:
      case op_18:
      case op_19:
      case IN:
      case op_21:
      case op_22:
      case op_23:
      case op_24:
      case op_25:
      case op_27:
      case op_30:
      case op_31:
      case op_32:
      case op_33:
      case op_34:
      case op_35:
      case op_36:
      case op_37:
      case op_38:
      case op_39:
      case op_40:
      case op_41:
      case op_42:
      case op_43:
      case op_44:
      case op_45:
      case op_46:
      case op_47:
      case op_48:
      case op_49:
      case op_50:
      case op_51:
      case op_52:
      case op_53:
      case op_54:
      case op_55:
      case op_56:
      case op_59:
      case op_62:
      case op_63:
      case op_64:
      case EQUALS:
      case op_66:
      case op_67:
      case op_71:
      case op_72:
      case op_73:
      case op_74:
      case op_75:
      case op_77:
      case op_78:
      case op_79:
      case op_80:
      case op_81:
      case op_82:
      case op_83:
      case op_84:
      case op_85:
      case op_86:
      case op_87:
      case op_88:
      case op_89:
      case op_90:
      case op_91:
      case op_92:
      case op_93:
      case op_94:
      case op_95:
      case op_96:
      case op_97:
      case op_98:
      case op_100:
      case op_101:
      case op_102:
      case op_103:
      case op_104:
      case op_105:
      case op_106:
      case op_107:
      case op_108:
      case op_109:
      case op_110:
      case op_111:
      case op_117:
      case op_118:
      case op_119:
        tn = InfixOp();
expecting = "_";
        kind = N_InfixDecl;
        addHeir( new SyntaxTreeNode( mn, t) );
        addHeir(tn);
        t = jj_consume_token(US);
                   addHeir( new SyntaxTreeNode( mn, t) ) ;
        break;
      case op_57:
      case op_68:
      case op_69:
      case op_70:
        tn = PostfixOp();
        kind = N_PostfixDecl;
        addHeir( new SyntaxTreeNode( mn, t) );
        addHeir(tn);
        break;
      default:
        jj_la1[17] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    default:
      jj_la1[18] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    sn = getLastHeirs();
    epa();
    {if (true) return new SyntaxTreeNode( mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* The following production OperatorOrFunctionDefinition() produces an      *
* N_OperatorDefinition, N_FunctionDefinition, or N_ModuleDefinition        *
* node.  These nodes have syntax "[LOCAL] ...".  The resulting node n      *
* has n.zero equal to null if the "LOCAL" is missing and equal to an       *
* array of length 1 containing the LOCAL token if it is present.  The      *
* rest of the children/heirs of the node are in the array n.one.           *
***************************************************************************/
  final public SyntaxTreeNode OperatorOrFunctionDefinition() throws ParseException {
  SyntaxTreeNode tn;
  SyntaxTreeNode zn = null;
  bpa("Definition");
  int kind = 0;
  String n;
  Token t;
  expecting = "LOCAL, Identifier or Operator Symbol";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LOCAL:
      t = jj_consume_token(LOCAL);
                  zn = new SyntaxTreeNode( mn, t);
      break;
    default:
      jj_la1[19] = jj_gen;
      ;
    }
    t = jj_consume_token(DEFBREAK);
  expecting = "LOCAL, Identifier or Operator Symbol";
    if (jj_2_8(2147483647)) {
      /* recognize function */
              tn = Identifier();
                            addHeir( tn );  kind = N_FunctionDefinition;
expecting = "[";
      t = jj_consume_token(LSB);
          addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier";
      tn = QuantBound();
                            addHeir( tn );
expecting = "COMMA or ]";
      label_8:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[20] = jj_gen;
          break label_8;
        }
        t = jj_consume_token(COMMA);
                        addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier";
        tn = QuantBound();
                              addHeir( tn );
      }
      t = jj_consume_token(RSB);
expecting = "==";
          addHeir( new SyntaxTreeNode(mn, t) );
      t = jj_consume_token(DEF);
                     belchDEF(); addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression";
      tn = Expression();
                            addHeir( tn );
    } else if (jj_2_9(2147483647)) {
      tn = PostfixLHS();
                             addHeir( tn );
expecting = "==";
      t = jj_consume_token(DEF);
                     belchDEF(); kind = N_OperatorDefinition;
          addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression";
      tn = Expression();
                            addHeir( tn );
    } else if (jj_2_10(2147483647)) {
      tn = InfixLHS();
                           addHeir( tn );
expecting = "==";
      t = jj_consume_token(DEF);
                     belchDEF();  kind = N_OperatorDefinition;
          addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression";
      tn = Expression();
                            addHeir( tn );
    } else if (jj_2_11(2147483647)) {
      /* recognize operator OR module instance */
              tn = IdentLHS();
                          addHeir( tn );
expecting = "==";
      t = jj_consume_token(DEF);
                     belchDEF(); addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression or Instance";
      if (jj_2_7(1)) {
        tn = Expression();
                              kind = N_OperatorDefinition;
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case INSTANCE:
          tn = Instantiation();
                                   kind = N_ModuleDefinition;
          break;
        default:
          jj_la1[21] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
            addHeir( tn );
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_76:
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
        tn = PrefixLHS();
                         addHeir( tn );
expecting = "==";
        t = jj_consume_token(DEF);
                   belchDEF();
        kind = N_OperatorDefinition;
        addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression";
        tn = Expression();
                          addHeir( tn );
        break;
      default:
        jj_la1[22] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn,kind, zn, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IdentifierTuple() throws ParseException {
  SyntaxTreeNode tn;
  SyntaxTreeNode hn[];
  Token t;
  bpa("Identifier tuple");
    t = jj_consume_token(LAB);
               addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier or >>";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      tn = Identifier();
                        addHeir( tn );
expecting = "COMMA or >>";
      label_9:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[23] = jj_gen;
          break label_9;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
expecting = "COMMA or >>";
        tn = Identifier();
                          addHeir( tn );
expecting = "COMMA or >>";
      }
      break;
    default:
      jj_la1[24] = jj_gen;
      ;
    }
    t = jj_consume_token(RAB);
               addHeir( new SyntaxTreeNode(mn, t) );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_IdentifierTuple, sn  );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IdentLHS() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Identifier LHS");
    tn = Identifier();
                      addHeir( tn );
expecting = "( or ==";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LBR:
      t = jj_consume_token(LBR);
                  addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier Declaration, prefix op, _ or )";
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case IDENTIFIER:
        tn = IdentDecl();
        break;
      case US:
      case op_76:
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
        tn = SomeFixDecl();
        break;
      default:
        jj_la1[25] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
                                                   addHeir( tn );
expecting = "COMMA or )";
      label_10:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[26] = jj_gen;
          break label_10;
        }
        t = jj_consume_token(COMMA);
                       addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier Declaration, prefix op or _";
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case IDENTIFIER:
          tn = IdentDecl();
          break;
        case US:
        case op_76:
        case op_26:
        case op_29:
        case op_58:
        case CASESEP:
        case op_61:
        case op_112:
        case op_113:
        case op_114:
        case op_115:
        case op_116:
          tn = SomeFixDecl();
          break;
        default:
          jj_la1[27] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
                                                     addHeir( tn );
expecting = "COMMA or )";
      }
      t = jj_consume_token(RBR);
                  addHeir( new SyntaxTreeNode(mn, t) );
      break;
    default:
      jj_la1[28] = jj_gen;
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_IdentLHS, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode PrefixLHS() throws ParseException {
  SyntaxTreeNode sn[] = new SyntaxTreeNode[2];
  SyntaxTreeNode tn;
  Token t;
  bpa("Prefix LHS");
    t = NEPrefixOpToken();
                            sn[0] = new SyntaxTreeNode(mn, t);
expecting = "Identifier";
    tn = Identifier();
                      sn[1] = tn;
    epa(); {if (true) return new SyntaxTreeNode( mn, N_PrefixLHS, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode InfixLHS() throws ParseException {
  SyntaxTreeNode sn[] = new SyntaxTreeNode[3];
  SyntaxTreeNode tn;
  Token t;
  bpa("Infix LHS");
    tn = Identifier();
                      sn[0] = tn;
    t = InfixOpToken();
                         sn[1] = new SyntaxTreeNode(mn, t);
    tn = Identifier();
                      sn[2] = tn;
    epa(); {if (true) return new SyntaxTreeNode( mn, N_InfixLHS, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode PostfixLHS() throws ParseException {
  SyntaxTreeNode sn[] = new SyntaxTreeNode[2];
  SyntaxTreeNode tn;
  Token t;
  bpa("Postfix LHS");
    tn = Identifier();
                      sn[0] = tn;
    t = PostfixOpToken();
                           sn[1] = new SyntaxTreeNode(mn, t);
    epa(); {if (true) return new SyntaxTreeNode( mn, N_PostfixLHS, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IdentDecl() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Identifier Declation");
    tn = Identifier();
                      addHeir( tn );
expecting = "( or ...";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LBR:
      t = jj_consume_token(LBR);
                 addHeir( new SyntaxTreeNode(mn, t) );
expecting = "_";
      t = jj_consume_token(US);
                addHeir( new SyntaxTreeNode(mn, t) );
expecting = "COMMA or )";
      label_11:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[29] = jj_gen;
          break label_11;
        }
        t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
expecting = "_";
        t = jj_consume_token(US);
                  addHeir( new SyntaxTreeNode(mn, t) );
expecting = "COMMA or )";
      }
      t = jj_consume_token(RBR);
                 addHeir( new SyntaxTreeNode(mn, t) );
      break;
    default:
      jj_la1[30] = jj_gen;
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_IdentDecl, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode SomeFixDecl() throws ParseException {
  SyntaxTreeNode localASTN = null;
  SyntaxTreeNode tn;
  SyntaxTreeNode sn[] = null;
  int kind;
  Token t;
  UniqueString n;
  bpa("Op. Symbol Declaration");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_76:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
      // LOOKAHEAD( <OpSymbol>, { isPrefixDeclOp( getToken(1) )  } )
            tn = NonExpPrefixOp();
        kind = N_PrefixDecl; n = lastOp.getIdentifier();
        sn = new SyntaxTreeNode[2]; sn[0] = tn;
expecting = "_";
      t = jj_consume_token(US);
                  sn[1] = new SyntaxTreeNode(mn, t);
      break;
    case US:
      t = jj_consume_token(US);
expecting = "infix or postfix operator";
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_1:
      case AND:
      case op_3:
      case op_4:
      case OR:
      case op_6:
      case op_7:
      case op_8:
      case op_9:
      case op_10:
      case op_11:
      case op_12:
      case op_13:
      case op_14:
      case op_15:
      case op_16:
      case op_17:
      case op_18:
      case op_19:
      case IN:
      case op_21:
      case op_22:
      case op_23:
      case op_24:
      case op_25:
      case op_27:
      case op_30:
      case op_31:
      case op_32:
      case op_33:
      case op_34:
      case op_35:
      case op_36:
      case op_37:
      case op_38:
      case op_39:
      case op_40:
      case op_41:
      case op_42:
      case op_43:
      case op_44:
      case op_45:
      case op_46:
      case op_47:
      case op_48:
      case op_49:
      case op_50:
      case op_51:
      case op_52:
      case op_53:
      case op_54:
      case op_55:
      case op_56:
      case op_59:
      case op_62:
      case op_63:
      case op_64:
      case EQUALS:
      case op_66:
      case op_67:
      case op_71:
      case op_72:
      case op_73:
      case op_74:
      case op_75:
      case op_77:
      case op_78:
      case op_79:
      case op_80:
      case op_81:
      case op_82:
      case op_83:
      case op_84:
      case op_85:
      case op_86:
      case op_87:
      case op_88:
      case op_89:
      case op_90:
      case op_91:
      case op_92:
      case op_93:
      case op_94:
      case op_95:
      case op_96:
      case op_97:
      case op_98:
      case op_100:
      case op_101:
      case op_102:
      case op_103:
      case op_104:
      case op_105:
      case op_106:
      case op_107:
      case op_108:
      case op_109:
      case op_110:
      case op_111:
      case op_117:
      case op_118:
      case op_119:
        tn = InfixOp();
          kind = N_InfixDecl; n = lastOp.getIdentifier();
          sn = new SyntaxTreeNode[3]; sn[1] = tn;
          sn[0] =  new SyntaxTreeNode(mn, t);
expecting = "_";
        t = jj_consume_token(US);
                       sn[2] = new SyntaxTreeNode(mn, t);
        break;
      case op_57:
      case op_68:
      case op_69:
      case op_70:
        tn = PostfixOp();
          kind = N_PostfixDecl; n = lastOp.getIdentifier();
          sn = new SyntaxTreeNode[2]; sn[1] = tn;
          sn[0] =  new SyntaxTreeNode(mn, t);
        break;
      default:
        jj_la1[31] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    default:
      jj_la1[32] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    epa(); {if (true) return new SyntaxTreeNode(mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Instance() throws ParseException {
  SyntaxTreeNode tn;
  SyntaxTreeNode zn = null;
  Token t;
  bpa("Instance");
expecting = "LOCAL or instance";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LOCAL:
      t = jj_consume_token(LOCAL);
    zn =  new SyntaxTreeNode(mn, t);
      break;
    default:
      jj_la1[33] = jj_gen;
      ;
    }
    tn = Instantiation();
                         addHeir( tn );
expecting = "COMMA or Module Body";
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_Instance, zn, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Instantiation() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("NonLocalInstance");
    t = jj_consume_token(INSTANCE);
                    addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Module identifier";
  t = getToken(1);
  if (isFieldNameToken( t )) t.kind = IDENTIFIER;
    tn = Identifier();
                      addDependency( tn.image ); addHeir( tn );
expecting = "WITH or another definition.";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case WITH:
      t = jj_consume_token(WITH);
                  addHeir( new SyntaxTreeNode(mn, t) );
expecting = emptyString;
      tn = Substitution();
                          addHeir( tn );
expecting = emptyString;
      label_12:
      while (true) {
        if (jj_2_12(3)) {
          ;
        } else {
          break label_12;
        }
        t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
expecting = emptyString;
        tn = Substitution();
                            addHeir( tn );
expecting = emptyString;
      }
      break;
    default:
      jj_la1[34] = jj_gen;
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_NonLocalInstance, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Substitution() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  SyntaxTreeNode tn = null;
  Token t;
  anchor = null;
    /***********************************************************************
    * See the comments for the declaration of anchor to see what this is   *
    * being used for.                                                      *
    ***********************************************************************/
  String n;
  bpa("Substitution");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      tn = Identifier();
                        zn[0] = tn;
      break;
    case op_76:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
      tn = NonExpPrefixOp();
                            zn[0] = tn;
      break;
    case op_1:
    case AND:
    case op_3:
    case op_4:
    case OR:
    case op_6:
    case op_7:
    case op_8:
    case op_9:
    case op_10:
    case op_11:
    case op_12:
    case op_13:
    case op_14:
    case op_15:
    case op_16:
    case op_17:
    case op_18:
    case op_19:
    case IN:
    case op_21:
    case op_22:
    case op_23:
    case op_24:
    case op_25:
    case op_27:
    case op_30:
    case op_31:
    case op_32:
    case op_33:
    case op_34:
    case op_35:
    case op_36:
    case op_37:
    case op_38:
    case op_39:
    case op_40:
    case op_41:
    case op_42:
    case op_43:
    case op_44:
    case op_45:
    case op_46:
    case op_47:
    case op_48:
    case op_49:
    case op_50:
    case op_51:
    case op_52:
    case op_53:
    case op_54:
    case op_55:
    case op_56:
    case op_59:
    case op_62:
    case op_63:
    case op_64:
    case EQUALS:
    case op_66:
    case op_67:
    case op_71:
    case op_72:
    case op_73:
    case op_74:
    case op_75:
    case op_77:
    case op_78:
    case op_79:
    case op_80:
    case op_81:
    case op_82:
    case op_83:
    case op_84:
    case op_85:
    case op_86:
    case op_87:
    case op_88:
    case op_89:
    case op_90:
    case op_91:
    case op_92:
    case op_93:
    case op_94:
    case op_95:
    case op_96:
    case op_97:
    case op_98:
    case op_100:
    case op_101:
    case op_102:
    case op_103:
    case op_104:
    case op_105:
    case op_106:
    case op_107:
    case op_108:
    case op_109:
    case op_110:
    case op_111:
    case op_117:
    case op_118:
    case op_119:
      tn = InfixOp();
                     zn[0] = tn;
      break;
    case op_57:
    case op_68:
    case op_69:
    case op_70:
      tn = PostfixOp();
                       zn[0] = tn;
      break;
    default:
      jj_la1[35] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  expecting = "<-";
    t = jj_consume_token(SUBSTITUTE);
                     n = tn.getImage();
     zn[1] = new SyntaxTreeNode(mn, t);
expecting = "Expression or Op. Symbol";
    tn = OpOrExpr();
    epa(); zn[2] = tn; {if (true) return new SyntaxTreeNode(mn, N_Substitution, zn );}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Substitution ::=                                                         *
*     ( Identifier | NonExpPrefixOp | InfixOp | PostfixOp)                 *
*     <SUBSTITUTE> ( <op_76> | Lambda | Expression )                       *
*                                                                          *
* Note: <op_76> is "-.", the prefix - operator.                            *
*       <SUBSTITUTE> is "<-"                                               *
*                                                                          *
* Modified 27 March 2007 by LL to allow Lambda substitutions.              *
***************************************************************************/
  final public SyntaxTreeNode OldSubstitution() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  SyntaxTreeNode tn = null;
  Token t;
  anchor = null;
    /***********************************************************************
    * See the comments for the declaration of anchor to see what this is   *
    * being used for.                                                      *
    ***********************************************************************/
  String n;
  bpa("Substitution");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      tn = Identifier();
                        zn[0] = tn;
      break;
    case op_76:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
      tn = NonExpPrefixOp();
                            zn[0] = tn;
      break;
    case op_1:
    case AND:
    case op_3:
    case op_4:
    case OR:
    case op_6:
    case op_7:
    case op_8:
    case op_9:
    case op_10:
    case op_11:
    case op_12:
    case op_13:
    case op_14:
    case op_15:
    case op_16:
    case op_17:
    case op_18:
    case op_19:
    case IN:
    case op_21:
    case op_22:
    case op_23:
    case op_24:
    case op_25:
    case op_27:
    case op_30:
    case op_31:
    case op_32:
    case op_33:
    case op_34:
    case op_35:
    case op_36:
    case op_37:
    case op_38:
    case op_39:
    case op_40:
    case op_41:
    case op_42:
    case op_43:
    case op_44:
    case op_45:
    case op_46:
    case op_47:
    case op_48:
    case op_49:
    case op_50:
    case op_51:
    case op_52:
    case op_53:
    case op_54:
    case op_55:
    case op_56:
    case op_59:
    case op_62:
    case op_63:
    case op_64:
    case EQUALS:
    case op_66:
    case op_67:
    case op_71:
    case op_72:
    case op_73:
    case op_74:
    case op_75:
    case op_77:
    case op_78:
    case op_79:
    case op_80:
    case op_81:
    case op_82:
    case op_83:
    case op_84:
    case op_85:
    case op_86:
    case op_87:
    case op_88:
    case op_89:
    case op_90:
    case op_91:
    case op_92:
    case op_93:
    case op_94:
    case op_95:
    case op_96:
    case op_97:
    case op_98:
    case op_100:
    case op_101:
    case op_102:
    case op_103:
    case op_104:
    case op_105:
    case op_106:
    case op_107:
    case op_108:
    case op_109:
    case op_110:
    case op_111:
    case op_117:
    case op_118:
    case op_119:
      tn = InfixOp();
                     zn[0] = tn;
      break;
    case op_57:
    case op_68:
    case op_69:
    case op_70:
      tn = PostfixOp();
                       zn[0] = tn;
      break;
    default:
      jj_la1[36] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  expecting = "<-";
    t = jj_consume_token(SUBSTITUTE);
                     n = tn.getImage();
     zn[1] = new SyntaxTreeNode(mn, t);
expecting = "Expression or Op. Symbol";
    try {
      if (jj_2_13(2147483647)) {
        t = jj_consume_token(op_76);
      SyntaxTreeNode zzn[] = new SyntaxTreeNode[2];
      zzn[0] = new SyntaxTreeNode( mn, N_IdPrefix, new SyntaxTreeNode[0] );
      zzn[1] =  new SyntaxTreeNode( mn, N_NonExpPrefixOp, t );
      tn = new SyntaxTreeNode( mn, N_GenNonExpPrefixOp, zzn );
      } else if (jj_2_14(1)) {
        tn = Expression();
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case LAMBDA:
          tn = Lambda();
          break;
        default:
          jj_la1[37] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    } catch (ParseException e) {
// first things first - restore evaluation stack
    if ( OperatorStack.isWellReduced() )
      OperatorStack.popStack();
    else
      {if (true) throw e;}
// check the nature of the node returned. It can only be a GenOp. */
// should be reviewed - N_GenNonExpPrefixOp may be unnecessary because -. has been checked.
    if ( ( anchor != null )
       &&( anchor.isKind( N_GenPrefixOp ) || anchor.isKind( N_GenInfixOp ) || anchor.isKind( N_GenPostfixOp ) || anchor.isKind( N_GenNonExpPrefixOp ) ) ) {
       tn = anchor; anchor = null;
    } else
       {if (true) throw e;}
    }
    epa(); zn[2] = tn; {if (true) return new SyntaxTreeNode(mn, N_Substitution, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode PrefixOp() throws ParseException {
  Token t;
    t = PrefixOpToken();
    lastOp = Operators.getOperator( UniqueString.uniqueStringOf(t.image) ); // YYY to revise
    {if (true) return new SyntaxTreeNode(mn, N_PrefixOp, t) ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode NonExpPrefixOp() throws ParseException {
  Token t;
    t = NEPrefixOpToken();
    lastOp = Operators.getOperator( UniqueString.uniqueStringOf(t.image) ); // YYY to revise
    {if (true) return new SyntaxTreeNode(mn, N_NonExpPrefixOp, t) ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode InfixOp() throws ParseException {
  Token t;
bpa("Infix Op") ;
    t = InfixOpToken();
    lastOp = Operators.getOperator( UniqueString.uniqueStringOf(t.image) ); // YYY to revise
epa();
    {if (true) return new SyntaxTreeNode( mn, N_InfixOp, t) ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode PostfixOp() throws ParseException {
  Token t;
    t = PostfixOpToken();
    lastOp = Operators.getOperator( UniqueString.uniqueStringOf(t.image) ); // YYY to revise
    {if (true) return new SyntaxTreeNode(mn, N_PostfixOp, t) ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Identifier() throws ParseException {
  Token t;
    t = jj_consume_token(IDENTIFIER);
                     {if (true) return new SyntaxTreeNode(mn, t);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Assumption ::= ( <ASSUME> | <ASSUMPTION> )                               *
*                  ( Identifier <DEF> )? Expression                        *
***************************************************************************/
  final public SyntaxTreeNode Assumption() throws ParseException {
  SyntaxTreeNode tn;
  SyntaxTreeNode zn = null;
  Token t;
  bpa("Assumption");
// expecting = "LOCAL or ASSUM...";
expecting = "ASSUM...";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case ASSUMPTION:
      t = jj_consume_token(ASSUMPTION);
      break;
    case ASSUME:
      t = jj_consume_token(ASSUME);
      break;
    default:
      jj_la1[38] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                        addHeir( new SyntaxTreeNode(mn, t) );
    if (jj_2_15(2)) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case DEFBREAK:
        t = jj_consume_token(DEFBREAK);
        break;
      default:
        jj_la1[39] = jj_gen;
        ;
      }
      /* A DEFBREAK might get added here by belchDEF */
          tn = Identifier();
                        addHeir( tn );
expecting = "==";
      t = jj_consume_token(DEF);
                       // belchDEF(); extra belchDEF removed 15 Mar 2007 by LL because it caused
                       // an extra <DEFBREAK> to be inserted, producing an error.
                       addHeir( new SyntaxTreeNode(mn, t) );
    } else {
      ;
    }
     belchDEF();
expecting = "Expression";
    tn = Expression();
    addHeir(tn);
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_Assumption, zn, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode AssumeProve() throws ParseException {
  /*************************************************************************
  * AssumeProve ::= (<IDENTIFIER> <COLONCOLON>)?                           *
  *                 (<ASSUME> | <BOXASSUME>)                               *
  *                   (AssumeProve | NewDecl | Expression)                 *
  *                 (<COMMA> (AssumeProve  | NewDecl | Expression))+       *
  *                 (<PROVE> | <BOXPROVE>) Expression                      *
  *                                                                        *
  * For ASSUME A1, A2 PROVE B, it constructs an AssumeProve node tn with   *
  * tn.zero equal to the array containing the 6 elements                   *
  *                                                                        *
  *     "ASSUME"  A1  ","  A2  "PROVE"  B                                  *
  *                                                                        *
  * If there is a label "foo::", it returns an N_Label node.               *
  *                                                                        *
  * Changed 18 May 2008 by LL to allow a label.                            *
  *                                                                        *
  * Comment by LL on 25 May 2010: I don't understand this "label"          *
  * business.  Testing shows that an ASSUME/PROVE can't have a label.  I   *
  * have no idea what the code that apparently is looking for a label is   *
  * supposed to do, but it never seems to do anything.                     *
  *                                                                        *
  * The []ASSUME / []PROVE added by LL on 9 Feb 2011.  This grammar        *
  * allows []ASSUME and []PROVE to be used interchangably with ASSUME and  *
  * PROVE. The semantic processing should report an error if []ASSUME is   *
  * used with PROVE and vice-versa.                                        *
  *************************************************************************/
  SyntaxTreeNode tn;
  Token t;
  SyntaxTreeNode sn[] ;
  bpa("Assume-Prove");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      tn = Identifier();
      /*********************************************************************
      * The semantic analyzer expects the label name to be a GeneralId     *
      * node whose first child is an empty N_IdPrefix node and whose       *
      * second child is the label's Identifier node.                       *
      *********************************************************************/
      addHeir(new SyntaxTreeNode(
                    mn,
                    N_GeneralId,
                    new SyntaxTreeNode[] {
                       new SyntaxTreeNode(
                             mn,
                             N_IdPrefix,
                             new SyntaxTreeNode[0]),
                       tn}
                      ) ) ;
      t = jj_consume_token(COLONCOLON);
                        addHeir( new SyntaxTreeNode(mn, t) );
      tn = AssumeProve();
                        addHeir(tn);
      sn = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode( mn, N_Label, sn);}
      break;
    default:
      jj_la1[40] = jj_gen;
      ;
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case ASSUME:
      t = jj_consume_token(ASSUME);
      break;
    case BOXASSUME:
      t = jj_consume_token(BOXASSUME);
      break;
    default:
      jj_la1[41] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                      addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression, Declaration, or AssumeProve";
    if ((getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME)
                       || ((getToken(2).kind == COLONCOLON) &&
                           (getToken(3).kind == ASSUME || getToken(3).kind == BOXASSUME)  )) {
      /*****************************************************
                            * Check for COLONCOLON added by LL 17 Feb 2009.      *
                            *****************************************************/
           tn = AssumeProve();
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ACTION:
      case CONSTANT:
      case NEW:
      case STATE:
      case TEMPORAL:
      case VARIABLE:
        tn = NewSymb();
        break;
      default:
        jj_la1[42] = jj_gen;
        if (jj_2_16(1)) {
          tn = Expression();

        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    }
      addHeir(tn);
expecting = "PROVE or `,'";
    label_13:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[43] = jj_gen;
        break label_13;
      }
      t = jj_consume_token(COMMA);
                  addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression, Declaration, or AssumeProve";
      if ((getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME)
                         || ((getToken(2).kind == COLONCOLON) &&
                             (getToken(3).kind == ASSUME || getToken(3).kind == BOXASSUME)  )) {
        /*****************************************************
                              * Check for COLONCOLON added by LL 17 Feb 2009.      *
                              *****************************************************/
               tn = AssumeProve();
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case ACTION:
        case CONSTANT:
        case NEW:
        case STATE:
        case TEMPORAL:
        case VARIABLE:
          tn = NewSymb();
          break;
        default:
          jj_la1[44] = jj_gen;
          if (jj_2_17(1)) {
            tn = Expression();
          } else {
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
      }
      addHeir(tn);
expecting = "PROVE or `,'";
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case PROVE:
      t = jj_consume_token(PROVE);
      break;
    case BOXPROVE:
      t = jj_consume_token(BOXPROVE);
      break;
    default:
      jj_la1[45] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                   addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Expression";
    tn = Expression();
                      addHeir( tn );
    sn = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_AssumeProve, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode NewSymb() throws ParseException {
  /*************************************************************************
  * NewSymb ::=   (<NEW> | <CONSTANT> | <NEW> <CONSTANT>)                  *
  *               (Identifier <IN> Expression | IdentDecl | SomeFixDecl)   *
  *              | [<NEW>] <VARIABLE> Identifier                           *
  *              | [<NEW>] (<STATE> | <ACTION> | <TEMPORAL>)               *
  *                (IdentDecl | SomeFixDecl)                               *
  *************************************************************************/
  SyntaxTreeNode tn ;
  Token t ;
  boolean hasArgs ;
    /***********************************************************************
    * We want to allow "NEW Id \in S" but disallow "NEW Id(_) \in S".      *
    * For simplicity, the we do this by letting javacc accept either, but  *
    * set hasArgs to true in the latter case and report the error when we  *
    * detect the "\in".                                                    *
    ***********************************************************************/
  bpa( "NEW symbol declaration");
  expecting = "NEW, CONSTANT, VARIABLE, STATE, ACTION, or TEMPORAL";
    if (jj_2_20(2)) {
      if (jj_2_18(2)) {
        t = jj_consume_token(NEW);
                           addHeir( new SyntaxTreeNode(mn, t) );
        t = jj_consume_token(CONSTANT);
                           addHeir( new SyntaxTreeNode(mn, t) );
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case NEW:
          t = jj_consume_token(NEW);
                           addHeir( new SyntaxTreeNode(mn, t) );
          break;
        case CONSTANT:
          t = jj_consume_token(CONSTANT);
                           addHeir( new SyntaxTreeNode(mn, t) );
          break;
        default:
          jj_la1[46] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
      expecting = "Constant declaration";
      if (jj_2_19(2)) {
        tn = IdentDecl();
                            hasArgs = tn.heirs().length > 1;
                            addHeir (tn) ;
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case IN:
          t = jj_consume_token(IN);
                      if (hasArgs) {
                        {if (true) throw new ParseException(
                          "declared symbol with arguments before \\in at "
                           + tn.getLocation().toString());}
                        } ;
                      addHeir(new SyntaxTreeNode(mn, t) );
                      expecting = "Expression";
          tn = Expression();
                               addHeir (tn) ;
          break;
        default:
          jj_la1[47] = jj_gen;
          ;
        }
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case US:
        case op_76:
        case op_26:
        case op_29:
        case op_58:
        case CASESEP:
        case op_61:
        case op_112:
        case op_113:
        case op_114:
        case op_115:
        case op_116:
          tn = SomeFixDecl();
                              addHeir (tn) ;
          break;
        default:
          jj_la1[48] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    } else if (jj_2_21(2)) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case NEW:
        t = jj_consume_token(NEW);
                   addHeir(new SyntaxTreeNode(mn, t) );
        break;
      default:
        jj_la1[49] = jj_gen;
        ;
      }
      t = jj_consume_token(VARIABLE);
                      addHeir(new SyntaxTreeNode(mn, t) );
                      expecting = "Identifier";
      tn = Identifier();
                         /**************************************************
                         * The semantic processor expects an N_IdentDecl   *
                         * node, and doesn't cope with a bare Identifier   *
                         * node.                                           *
                         **************************************************/
                         SyntaxTreeNode[] sn = new SyntaxTreeNode[1] ;
                         sn[0] = tn ;
                         addHeir(new SyntaxTreeNode( mn, N_IdentDecl, sn));
    } else if (jj_2_22(2)) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case NEW:
        t = jj_consume_token(NEW);
                     addHeir(new SyntaxTreeNode(mn, t));
        break;
      default:
        jj_la1[50] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case STATE:
        t = jj_consume_token(STATE);
        break;
      case ACTION:
        t = jj_consume_token(ACTION);
        break;
      case TEMPORAL:
        t = jj_consume_token(TEMPORAL);
        break;
      default:
        jj_la1[51] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
       addHeir( new SyntaxTreeNode(mn, t));
       expecting = "Declaration" ;
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case IDENTIFIER:
        tn = IdentDecl();
                           addHeir(tn);
        break;
      case US:
      case op_76:
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
        tn = SomeFixDecl();
                             addHeir(tn);
        break;
      default:
        jj_la1[52] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_NewSymb, sn);}
    throw new Error("Missing return statement in function");
  }

// NumberedAssumeProve() commented out 5 Mar 2007 by LL
// number . sequence 
// SyntaxTreeNode
// NumberedAssumeProve () : {
//   SyntaxTreeNode tn;
//   Token t;
//   boolean b = false;
//   bpa("Numbered Assume-Prove");
// }{
//   [ LOOKAHEAD(2)
//     t = <NUMBER_LITERAL>  { addHeir( new SyntaxTreeNode(mn, t) );
// expecting = "."; }
//     t = <DOT> {
//       BStack.newReference(t.endColumn, ASSUME); b = true;
//       addHeir( new SyntaxTreeNode(mn, t) );
// expecting = "Assume-Prove, Assume-Decl or expression"; } ]
//   ( tn = AssumeProve()
//   | LOOKAHEAD( { IsNotExpression() } ) tn = AssumeDecl()
//   | tn = Expression() ) /* XXX parser confusion here !!! */
//   { if (b) BStack.popReference();
//     addHeir(tn);
//     SyntaxTreeNode sn[] = getLastHeirs();
//     epa(); return new SyntaxTreeNode( mn, N_NumberedAssumeProve, sn); }
// }

// AssumeDecl() commented out 27 March 2007; it seems to be left over
//   from the old proof grammar.
// SyntaxTreeNode
// AssumeDecl () : {
//   SyntaxTreeNode zn[] = null;
//   SyntaxTreeNode tn;
//   Token t;
//   bpa("Assume Decl.");
// }{
//   ( tn = VariableDeclaration() { zn = new SyntaxTreeNode[1]; zn[0] = tn; }
//   | ( tn = ParamDeclaration() {
//         zn = new SyntaxTreeNode[2]; zn[0] = tn;
// expecting = "optional \\in or ..."; }
//       zn[1] = MaybeBound() )
//   | LOOKAHEAD (2) tn = OperatorOrFunctionDefinition() { zn = new SyntaxTreeNode[1]; zn[0] = tn; }
//   | tn = Instance() { zn = new SyntaxTreeNode[1]; zn[0] = tn; } )
//   { epa();
//     return new SyntaxTreeNode( mn, N_AssumeDecl, zn );  }
// }
  final public SyntaxTreeNode MaybeBound() throws ParseException {
  SyntaxTreeNode zn[] = null;
  SyntaxTreeNode tn;
  Token t;
  bpa("Domain binding");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IN:
      t = jj_consume_token(IN);
      zn    = new SyntaxTreeNode[2];
      zn[0] =  new SyntaxTreeNode(mn, t);
      zn[0].setKind(T_IN);
expecting = "Expression";
      zn[1] = Expression();
      break;
    default:
      jj_la1[53] = jj_gen;
      ;
    }
    epa(); {if (true) return new SyntaxTreeNode( mn, N_MaybeBound, zn);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Theorem ::= ( <THEOREM> | <PROPOSITION> )                                *
*                ( Identifier <DEF> )? ( AssumeProve | Expression )        *
*                                                                          *
* Produces a Theorem node tn with tn.zero containing 2 or 4 nodes,         *
* depending on whether or not the "Identifier <DEF>" is present.           *
***************************************************************************/
  final public SyntaxTreeNode Theorem() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Theorem");
expecting= "THEOREM, PROPOSITION";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case THEOREM:
      t = jj_consume_token(THEOREM);
      break;
    case PROPOSITION:
      t = jj_consume_token(PROPOSITION);
      break;
    default:
      jj_la1[54] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                          addHeir( new SyntaxTreeNode(mn, t) );
expecting = "Identifier, Assume-Prove or Expression";
    if (jj_2_23(2)) {
      tn = Identifier();
                        addHeir( tn );
expecting = "==";
      t = jj_consume_token(DEF);
                       // belchDEF(); extra belchDEF removed 15 Mar 2007 by LL because it caused
                       // an extra <DEFBREAK> to be inserted, producing an error.
                       addHeir( new SyntaxTreeNode(mn, t) );
    } else {
      ;
    }
    belchDEF();
    if (jj_2_24(3)) {
      if (getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME) {

      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }
      tn = AssumeProve();
    } else if (jj_2_25(1)) {
      tn = Expression();
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
    addHeir(tn);
    if (beginsProof(getToken(1))) {
      tn = Proof();
       addHeir(tn) ;
    } else {
      ;
    }
   SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_Theorem, sn);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* The Grammar of Proofs                                                    *
*  XXXXXXX THIS IS OBSOLETE                                                *
* Proof ::= InnerProof                                                     *
*   // Proof checks that we're not inside a proof at the end.              *
*                                                                          *
* InnerProof ::=                                                           *
*      TerminalProof                                                       *
*    | (<PROOF>)?                                                          *
*      ( Step )* // Terminated by lookahead for "QED"                      *
*      QEDStep                                                             *
*                                                                          *
*   // Note: (InnerProof)? uses lookahead for beginsProof(...)             *
*                                                                          *
* TerminalProof ::=    <BY> ...                                            *
*                    | (<PROOF>)? OBVIOUS                                  *
* QEDStep ::= (<ProofStepLexeme> | <ProofStepDotLexeme> )?                 *
*             <QED> (InnerProof)?                                          *
*                                                                          *
* Step ::=   N_DefStep                                                     *
*          | N_UseOrHide                                                   *
*          | N_NonLocalInstance                                            *
*          | N_NumerableStep                                               *
*          | N_QEDStep                                                     *
*                                                                          *
* NumerableStep ==    ExprStep                                             *
*                   | NumberedStep                                         *
*                   | UnnumberedStep                                       *
*                                                                          *
* DefStep ::= (<DEFINE>)? OperatorOrFunctionDefinition                     *
*                                                                          *
* NumberedStep ::= (<ProofStepLexeme> | <ProofStepDotLexeme> )             *
*                  UnnumberedStep                                          *
*                                                                          *
* ExprStep ::= (   <PROVE>                                                 *
*                | <SUFFICES>                                              *
*                | (<ProofStepLexeme> | <ProofStepDotLexeme> )             *
*                  (<SUFFICES>)?                                           *
*              )                                                           *
*              Expression                                                  *
*                                                                          *
* UnnumberedStep ::=                                                       *
*     Have                                                                 *
*   | Take                                                                 *
*   | Witness                                                              *
*   | (  Pick                                                              *
*      | (<SUFFICES>)? (AssumeProve | <CASE> Expression)                   *
*     )                                                                    *
*     (InnerProof)?                                                        *
***************************************************************************/
  final public SyntaxTreeNode Proof() throws ParseException {
/***************************************************************************
* Returns an N_Proof or N_TerminalProof node.  The heirs of an N_Proof     *
* node consist of an option PROOF token followed by a seequence of         *
* N_ProofStep nodes.  The heirs of an N_ProofStep node are a StartStep()   *
* token, a statement body, and an optional proof.  A statement body is     *
* one of the following node kinds:                                         *
*                                                                          *
*   Have no proof:                                                         *
*     N_DefStep   N_UseOrHide   N_NonLocalInstance   N_HaveStep,           *
*     N_TakeStep  N_WitnessStep                                            *
*                                                                          *
*   Have a proof                                                           *
*     N_QEDStep  N_PickStep   N_CaseStep   N_AssertStep                    *
***************************************************************************/
  SyntaxTreeNode tn;
  Token t = null ;
  Token t0 = null;
  pushProofLevel() ;
  bpa("Proof");
    if ((getToken(1).kind == BY) || (getToken(2).kind == BY)) {
      tn = UseOrHideOrBy();
    } else if (jj_2_27(2)) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case PROOF:
        t0 = jj_consume_token(PROOF);
        break;
      default:
        jj_la1[55] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case OBVIOUS:
        t = jj_consume_token(OBVIOUS);
        break;
      case OMITTED:
        t = jj_consume_token(OMITTED);
        break;
      default:
        jj_la1[56] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
     SyntaxTreeNode sn[] ;
     if (t0 != null) {
       sn = new SyntaxTreeNode[2];
       sn[0] = new SyntaxTreeNode(mn, t0);
       sn[1] = new SyntaxTreeNode(mn, t);
      }
     else {
       sn = new SyntaxTreeNode[1];
       sn[0] = new SyntaxTreeNode(mn, t);
      };
     tn = new SyntaxTreeNode(mn, N_TerminalProof, sn );
    } else if (jj_2_28(1)) {
      if (jj_2_26(2)) {
        t = jj_consume_token(PROOF);
                  addHeir(new SyntaxTreeNode(mn, t));
      } else {
        ;
      }
      label_14:
      while (true) {
        if (getToken(2).kind != QED) {
          ;
        } else {
          break label_14;
        }
        tn = Step();
                   addHeir(tn);
                   expecting = "a proof step";
      }
      tn = QEDStep();
     addHeir(tn);
     SyntaxTreeNode sn[] = getLastHeirs();
     tn = new SyntaxTreeNode(mn, N_Proof, sn );
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
   epa();
   popProofLevel() ;
   {if (true) return tn ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode UseOrHideOrBy() throws ParseException {
/***************************************************************************
* Returns an N_TerminalProof (for a BY) or N_UseOrHide node.  Having       *
* one nonterminal that returns both is the only easy way I know to         *
* avoid having to duplicate the code for handling BY and for handling      *
* USE/HIDE.  Lookahead should prevent it from being called to parse        *
* the wrong kind of object.                                                *
*                                                                          *
* Note: This production accepts a By, USE, or HIDE with no items.  This    *
* should be reported by an error in the semantic analysis phase.           *
***************************************************************************/
  SyntaxTreeNode tn;
  Token t;
  int kind = N_UseOrHide;
  bpa("UseOrHideOrBy");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case BY:
    case PROOF:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case PROOF:
        t = jj_consume_token(PROOF);
                    addHeir(new SyntaxTreeNode(mn, t));
        break;
      default:
        jj_la1[57] = jj_gen;
        ;
      }
      t = jj_consume_token(BY);
                 kind = N_TerminalProof;
        addHeir(new SyntaxTreeNode(mn, t));
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ONLY:
        t = jj_consume_token(ONLY);
                   addHeir(new SyntaxTreeNode(mn, t));
        break;
      default:
        jj_la1[58] = jj_gen;
        ;
      }
      break;
    case USE:
      t = jj_consume_token(USE);
       addHeir(new SyntaxTreeNode(mn, t));
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ONLY:
        t = jj_consume_token(ONLY);
                   addHeir(new SyntaxTreeNode(mn, t));
        break;
      default:
        jj_la1[59] = jj_gen;
        ;
      }
      break;
    case HIDE:
      t = jj_consume_token(HIDE);
       addHeir(new SyntaxTreeNode(mn, t));
      break;
    default:
      jj_la1[60] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     expecting = "an expression, `MODULE' or `DEF'";
    if (jj_2_31(1)) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case MODULE:
        t = jj_consume_token(MODULE);
                             addHeir( new SyntaxTreeNode(mn, t) );
                             expecting = "identifier";
        tn = Identifier();
                             addHeir(tn);
        break;
      default:
        jj_la1[61] = jj_gen;
        if (jj_2_29(1)) {
          tn = Expression();
                            addHeir(tn);
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
      label_15:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[62] = jj_gen;
          break label_15;
        }
        t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
                     expecting = "MODULE or expression";
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case MODULE:
          t = jj_consume_token(MODULE);
                               addHeir( new SyntaxTreeNode(mn, t) );
                               expecting = "identifier";
          tn = Identifier();
                               addHeir(tn);
          break;
        default:
          jj_la1[63] = jj_gen;
          if (jj_2_30(1)) {
            tn = Expression();
                              addHeir(tn);
          } else {
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
         if (kind == N_TerminalProof) { expecting = "comma, DEF, or [.]"; }
         else {expecting = "comma, DEF, or proof step";};
      }
    } else {
      ;
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DF:
      t = jj_consume_token(DF);
                addHeir( new SyntaxTreeNode(mn, t) );
                expecting = "MODULE or expression";
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case MODULE:
        t = jj_consume_token(MODULE);
                             addHeir( new SyntaxTreeNode(mn, t) );
                               expecting = "identifier";
        tn = Identifier();
                             addHeir(tn);
        break;
      default:
        jj_la1[64] = jj_gen;
        if (jj_2_32(1)) {
          tn = Expression();
                            addHeir(tn);
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
      label_16:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[65] = jj_gen;
          break label_16;
        }
        t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
                     expecting = "MODULE or expression";
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case MODULE:
          t = jj_consume_token(MODULE);
                               addHeir( new SyntaxTreeNode(mn, t) );
                               expecting = "identifier";
          tn = Identifier();
                               addHeir(tn);
          break;
        default:
          jj_la1[66] = jj_gen;
          if (jj_2_33(1)) {
            tn = Expression();
                              addHeir(tn);
          } else {
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
          if (kind == N_TerminalProof) { expecting = "comma or [.]"; }
         else {expecting = "comma or proof step" ; };
      }
      break;
    default:
      jj_la1[67] = jj_gen;
      ;
    }
    if (kind == N_TerminalProof) {expecting = "[.]";};
    SyntaxTreeNode sn[] = getLastHeirs();
    epa();
    {if (true) return new SyntaxTreeNode(mn, kind, sn );}
    throw new Error("Missing return statement in function");
  }

  final public Token StepStartToken() throws ParseException {
 Token t ;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case ProofStepLexeme:
      t = jj_consume_token(ProofStepLexeme);
      break;
    case ProofImplicitStepLexeme:
      t = jj_consume_token(ProofImplicitStepLexeme);
      break;
    case ProofStepDotLexeme:
      t = jj_consume_token(ProofStepDotLexeme);
      break;
    case BareLevelLexeme:
      t = jj_consume_token(BareLevelLexeme);
      break;
    case UnnumberedStepLexeme:
      t = jj_consume_token(UnnumberedStepLexeme);
      break;
    default:
      jj_la1[68] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return t ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode QEDStep() throws ParseException {
/***************************************************************************
* Returns an N_ProofStep node whose body is an N_QEDStep node.             *
***************************************************************************/
 Token t ;
 SyntaxTreeNode tn;
 SyntaxTreeNode[] sn;
 int level = -1 ;
 bpa("QED step") ;
 expecting = "Step number" ;
    t = StepStartToken();
      tn = new SyntaxTreeNode(mn, t) ;
      if (!correctLevel(t)) {
         {if (true) throw new ParseException(tn.getLocation().toString() +
             ": QED step's number has bad level." );}
       };
      if (   (t.kind == ProofImplicitStepLexeme)
          || (t.kind == ProofStepLexeme)
          || (t.kind == ProofStepDotLexeme)) {
        tn.originalImage = tn.image ;
        tn.image = correctedStepNum(t) ;
// ToolIO.out.println("correcting " + tn.originalImage) ;
       } ;
// ToolIO.out.println("xyz: t.image = " + t.image + ", correctedImage = " 
// + tn.image + ", t.kind = " + t.kind ) ;

      addHeir(tn) ;
      expecting = "QED" ;
    t = jj_consume_token(QED);
        sn = new SyntaxTreeNode[1] ;
        sn[0] = new SyntaxTreeNode(mn, t) ;
        addHeir(new SyntaxTreeNode(mn, N_QEDStep, sn));
    if (beginsProof(getToken(1))) {
      tn = Proof();
       addHeir(tn) ;
    } else {
      ;
    }
     sn = getLastHeirs();
     epa();
     {if (true) return new SyntaxTreeNode(mn, N_ProofStep, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Step() throws ParseException {
/***************************************************************************
* Returns an N_ProofStep node with the following heirs:                    *
*                                                                          *
*  - A StepStart() token.                                                  *
*                                                                          *
*  - An N_DefStep (for an operator or function def or named                *
*    instantiation, N_UseOrHide, N_NonLocalInstance, N_HaveStep,           *
*    N_TakeStep, N_WitnessStep, N_PickStep, N_CaseStep, or                 *
*    N_AssertStep node.  (An N_AssertStep node has an optional             *
*    "SUFFICES" followed by an expression or N_AssumeProve node.)          *
*                                                                          *
*  - An optional N_Proof or N_TerminalProof node.                          *
*                                                                          *
* Note: The grammar accepts a USE or HIDE with no items.  This should      *
* be reported as an error in the semantic analysis phase.                  *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 boolean mayHaveProof = false ;
 bpa("Step") ;
 expecting = "Step number" ;
    t = StepStartToken();
      tn = new SyntaxTreeNode(mn, t);
      if (!correctLevel(t)) {
         {if (true) throw new ParseException(tn.getLocation().toString() +
             ": step's number has bad level." );}
        };
      if (   (t.kind == ProofImplicitStepLexeme)
          || (t.kind == ProofStepLexeme)
          || (t.kind == ProofStepDotLexeme)) {
        tn.originalImage = tn.image ;
        tn.image = correctedStepNum(t) ;
       } ;
// ToolIO.out.println("xyz2: t.image = " + t.image + ", correctedImage = " 
// + tn.image + ", t.kind = " + t.kind ) ;
      addHeir(tn) ;
      expecting = "proof step";
    if ((getToken(1).kind == USE) || (getToken(1).kind == HIDE)) {
      tn = UseOrHideOrBy();
                            addHeir(tn) ;
    } else if (getToken(1).kind == INSTANCE) {
      tn = Instantiation();
                            addHeir(tn) ;
    } else if ((getToken(1).kind == DEFBREAK)
                       || (getToken(1).kind == DEFINE)) {
      tn = DefStep();
                           addHeir(tn) ;
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case HAVE:
        tn = HaveStep();
                           addHeir(tn) ;
        break;
      case TAKE:
        tn = TakeStep();
                           addHeir(tn) ;
        break;
      case WITNESS:
        tn = WitnessStep();
                           addHeir(tn) ;
        break;
      case PICK:
        tn = PickStep();
                           addHeir(tn) ;  mayHaveProof = true;
        break;
      case CASE:
        tn = CaseStep();
                           addHeir(tn) ;  mayHaveProof = true;
        break;
      default:
        jj_la1[69] = jj_gen;
        if (jj_2_34(1)) {
          tn = AssertStep();
                           addHeir(tn) ; mayHaveProof = true;
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    }
    if (beginsProof(getToken(1))) {
      if (! mayHaveProof) {
         {if (true) throw new ParseException(tn.getLocation().toString() +
             ": proof of step that does not take a proof." );}
        } ;
      tn = Proof();
                    addHeir(tn) ;
    } else {
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
     epa();
     {if (true) return new SyntaxTreeNode(mn, N_ProofStep, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode DefStep() throws ParseException {
/***************************************************************************
* Returns an N_DefStep node whose heirs begin with an optional <DEFINE>    *
* followed by a non-empty sequence of nodes returned by                    *
* OperatorOrFunctionDefinition().                                          *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("DefStep") ;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DEFINE:
      t = jj_consume_token(DEFINE);
                    addHeir(new SyntaxTreeNode(mn, t));
      break;
    default:
      jj_la1[70] = jj_gen;
      ;
    }
    label_17:
    while (true) {
      tn = OperatorOrFunctionDefinition();
                                           addHeir(tn) ;
      if (jj_2_35(2)) {
        ;
      } else {
        break label_17;
      }
    }
     SyntaxTreeNode sn[] = getLastHeirs();
     epa();
     {if (true) return new SyntaxTreeNode(mn, N_DefStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode HaveStep() throws ParseException {
/***************************************************************************
* Returns an N_HaveStep node whose heirs are a <HAVE> token and an         *
* expression node.                                                         *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("HaveStep") ;
    t = jj_consume_token(HAVE);
                 addHeir(new SyntaxTreeNode(mn, t));
                  expecting = "expression";
    tn = Expression();
      addHeir(tn) ;
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_HaveStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode TakeStep() throws ParseException {
/***************************************************************************
* Returns an N_TakeStep node whose first heir is a <TAKE> token and whose  *
* remaining heirs are a sequence of QuantBound() nodes or a sequence of    *
* identifiers.                                                             *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("TakeStep") ;
    t = jj_consume_token(TAKE);
                addHeir(new SyntaxTreeNode(mn, t)) ;
                   expecting = "identifier";
    if (jj_2_36(2147483647)) {
      tn = QuantBound();
                         addHeir(tn) ;
                         expecting = "comma or step";
      label_18:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[71] = jj_gen;
          break label_18;
        }
        t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
                     expecting = "identifier or tuple of identifiers";
        tn = QuantBound();
                           addHeir(tn) ;
                           expecting = "comma or proof step";
      }
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case IDENTIFIER:
        tn = Identifier();
                         addHeir(tn) ;
                         expecting = "comma or proof step";
        label_19:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[72] = jj_gen;
            break label_19;
          }
          t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
                     expecting = "identifier";
          tn = Identifier();
                           addHeir(tn) ;
                           expecting = "comma or proof step";
        }
        break;
      default:
        jj_la1[73] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_TakeStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode WitnessStep() throws ParseException {
/***************************************************************************
* Returns an N_WitnessStep node whose heirs are a <WITNESS> token and a    *
* sequence of expression nodes.  It's up to later processing to decide if  *
* those expressions have the form <<expr, ...  , expr>> \in expr,          *
* expr \in expr, or just expr.                                             *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("WitnessStep") ;
    t = jj_consume_token(WITNESS);
                    addHeir(new SyntaxTreeNode(mn, t));
                   expecting = "expression";
    tn = Expression();
                        addHeir(tn) ;
    label_20:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[74] = jj_gen;
        break label_20;
      }
      t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
                        expecting = "expression";
      tn = Expression();
                            addHeir(tn) ;
                            expecting = "comma or colon";
    }
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_WitnessStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode PickStep() throws ParseException {
/***************************************************************************
* Returns an N_PickStep node whose heirs are a <PICK> token and an         *
* expression node.                                                         *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("PickStep") ;
    t = jj_consume_token(PICK);
                 addHeir(new SyntaxTreeNode(mn, t)) ;
                 expecting = "identifier";
    if (jj_2_37(2147483647)) {
      /* CommaList Identifier */
            tn = Identifier();
                          addHeir(tn) ;
                          expecting = "comma, or colon";
      label_21:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[75] = jj_gen;
          break label_21;
        }
        t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
                      expecting = "identifier";
        tn = Identifier();
                            addHeir(tn) ;
                            expecting = "comma or colon";
      }
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LAB:
      case IDENTIFIER:
        tn = QuantBound();
                          addHeir(tn) ;
                          expecting = "comma or colon";
        label_22:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[76] = jj_gen;
            break label_22;
          }
          t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
                      expecting = "identifier or tuple of identifiers";
          tn = QuantBound();
                            addHeir(tn) ;
                            expecting = "comma or colon";
        }
        break;
      default:
        jj_la1[77] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    t = jj_consume_token(COLON);
                  addHeir( new SyntaxTreeNode(mn, t) );
                  expecting = "expression";
    tn = Expression();
                        addHeir(tn) ;
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_PickStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode CaseStep() throws ParseException {
/***************************************************************************
* Returns an N_CaseStep node whose heirs are a <CASE> token and an         *
* expression node.                                                         *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("CaseStep") ;
    t = jj_consume_token(CASE);
                addHeir(new SyntaxTreeNode(mn, t));
                  expecting = "expression";
    tn = Expression();
      addHeir(tn) ;
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_CaseStep, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode AssertStep() throws ParseException {
/***************************************************************************
* Returns an N_AssertStep node whose heirs are an optional <SUFFICES>      *
* token and an expression or N_AssumeProve node.                           *
***************************************************************************/
 Token t = null;
 SyntaxTreeNode tn = null;
 bpa("AssertStep") ;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case SUFFICES:
      t = jj_consume_token(SUFFICES);
                     addHeir(new SyntaxTreeNode(mn, t));
                    expecting = "expression or ASSUME/PROVE";
      break;
    default:
      jj_la1[78] = jj_gen;
      ;
    }
    if (jj_2_38(1)) {
      tn = Expression();
    } else if (getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME) {
      tn = AssumeProve();
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
      addHeir(tn) ;
      SyntaxTreeNode sn[] = getLastHeirs();
      epa();
      {if (true) return new SyntaxTreeNode(mn, N_AssertStep, sn );}
    throw new Error("Missing return statement in function");
  }

// SyntaxTreeNode
// NumerableStep() : {
// /***************************************************************************
// * Returns an N_NumerableStep node, which has the syntax                    *
// *                                                                          *
// *  ( <ProofStep[Dot]Lexeme> (N_NonExprBody node)                           *
// *   | N_NonExprBody node )                                                 *
// *  ( N_Proof node | N_TerminalProof node)?                                 *
// ***************************************************************************/
//  Token t = null;
//  SyntaxTreeNode tn = null;
//  boolean mayHaveProof = true ;
//  bpa("NumerableStep") ;
//  }{( LOOKAHEAD(2)
//      (t = <ProofStepLexeme> | t = <ProofStepDotLexeme>)
//      { tn = new SyntaxTreeNode(mn, t) ;
//        addHeir(tn); 
//        if ((proofDepth > 0) && (proofLevelStack[proofDepth-1] == -1)){
//          throw new ParseException(tn.getLocation() + 
//                     ": numbered step inside unnumbered proof.");
//         } ;
//        if (!correctLevel(t)) {
//          throw new ParseException(tn.getLocation() + 
//                     ": step number has incorrect level.");
//         } ;
//       }
//      ( (t = <CASE> {addHeir(new SyntaxTreeNode(mn, t)); })?          // XXXX
// //     ^^^^^^^^^^^
// // javacc generates the following warning here:
// //   Choice conflict in [...] construct at line 2700, column 8.
// //   Expansion nested within construct and expansion following construct
// //   have common prefixes, one of which is: "CASE"
// //   Consider using a lookahead of 2 or more for nested expansion.
// //
// // This conflict is between "<1>2.  CASE expr" and 
// // "<1>2.  CASE p -> ...".  This is an inherent ambiguity that arises
// // from the use of "CASE" as a keyword here.  Javacc resolves
// // conflicts by choosing the first successful match.  Here, this
// // means that "<1>2.  CASE p -> ..." is parsed as
// //
// //      <ProofStepDotLexeme> <CASE> Expression()
// //
// // causing an error when it tries to parse "-> ..." as an expression.
// 
// 
// 
//        tn = Expression() {addHeir(tn);                               // XXXX
//                           mayHaveProof = true ;}   // XXXX
//       |                                                              // XXXX
//         tn = NonExprBody() {addHeir(tn);
//                             mayHaveProof = nonExprBodyMayHaveProof;}
//       )                                                              // XXXX
//    | t = <CASE> {addHeir(new SyntaxTreeNode(mn, t)); }             // XXXX
//      tn = Expression() {addHeir(tn);                               // XXXX
//                         mayHaveProof = nonExprBodyMayHaveProof;} // XXXX
// 
//    | tn = NonExprBody() 
//        { addHeir(tn); 
//          mayHaveProof = nonExprBodyMayHaveProof;
//          if (getProofLevel() == -2)
//            { setProofLevel(-1) ;
//           }
//          else {
//           if (getProofLevel() != -1) {
//          throw new ParseException(tn.getLocation() + 
//                     ": Unnumbered step in numbered proof.");
//             }
//           }
//       }
//   )
//   ( LOOKAHEAD( {mayHaveProof && beginsProof(getToken(1))} )
//      tn = Proof() 
//      { addHeir(tn) ; }
//   )?
//   { SyntaxTreeNode sn[] = getLastHeirs();
//     epa(); 
//     return new SyntaxTreeNode(mn, N_NumerableStep, sn);
//   }
// }

// /***************************************************************************
// * Hack: In addition to returning a node, NonExprBody() needs to return a   *
// * boolean saying whether or not the statement it is returning can have a   *
// * proof.  It does this by setting the field nonExprBodyMayHaveProof.       *
// ***************************************************************************/
// SyntaxTreeNode
// NonExprBody() : {
//  SyntaxTreeNode tn = null;
//  Token t = null;
//  nonExprBodyMayHaveProof = false ;
//  bpa("NonExprBody") ;
// }{ (  LOOKAHEAD(2)
//       (t = <SUFFICES>    { addHeir(new SyntaxTreeNode(mn, t)); }) ? 
//       tn = AssumeProve() { addHeir(tn) ; 
//                            nonExprBodyMayHaveProof = true;}
//     | LOOKAHEAD(2)
//       ( t = <PROVE> | t = <SUFFICES>)   // | t = <PROOFCASE>
//       { addHeir(new SyntaxTreeNode(mn, t));  
//         expecting = "expression";}
//       tn = Expression() { addHeir(tn) ; 
//                           nonExprBodyMayHaveProof = true;}
//     | t = <HAVE> { addHeir(new SyntaxTreeNode(mn, t)) ;   
//                    expecting = "expression";}
//       tn = Expression() { addHeir(tn) ; }
//     | t = <TAKE> { addHeir(new SyntaxTreeNode(mn, t)) ;    
//                    expecting = "identifier";}
//       ( LOOKAHEAD (  <IDENTIFIER> (<COMMA> <IDENTIFIER>)* <IN>
//                    | <LAB>) 
//         tn = QuantBound() { addHeir(tn) ;  
//                             expecting = "comma or step";}
//         ( t = <COMMA> { addHeir( new SyntaxTreeNode(mn, t) ); 
//                         expecting = "identifier or tuple of identifiers";}
//           tn = QuantBound() { addHeir(tn) ;  
//                               expecting = "comma or proof step";}
//         )*
//       |  
//         tn = Identifier() { addHeir(tn) ; 
//                              expecting = "comma or proof step";}
//          ( t = <COMMA> { addHeir( new SyntaxTreeNode(mn, t) ); 
//                           expecting = "identifier";}
//            tn = Identifier() { addHeir(tn) ;  
//                                expecting = "comma or proof step";}
//          )*
//       )
// 
//     | t = <WITNESS> { addHeir(new SyntaxTreeNode(mn, t)) ;     
//                       expecting = "expression";}
//       tn = Expression() { addHeir(tn) ; }
//       /*********************************************************************
//       * Note: The semantic phase must determine if this is expr \in expr,  *
//       * or <<expr, ...  , expr>> \in expr, or just expr.                   *
//       *********************************************************************/
//       ( t = <COMMA> { addHeir( new SyntaxTreeNode(mn, t) ); 
//                         expecting = "expression";}
//         tn = Expression() { addHeir(tn) ;  
//                             expecting = "comma or colon";}
//       )*
//       
//     | t = <PICK> { addHeir(new SyntaxTreeNode(mn, t)) ;  
//                    expecting = "identifier";}
//       ( LOOKAHEAD ( <IDENTIFIER> ( <COMMA> <IDENTIFIER> )* <COLON> ) 
//                           /* CommaList Identifier */
//         tn = Identifier() { addHeir(tn) ; 
//                              expecting = "comma, or colon";}
//          ( t = <COMMA> { addHeir( new SyntaxTreeNode(mn, t) ); 
//                           expecting = "identifier";}
//            tn = Identifier() { addHeir(tn) ;  
//                                expecting = "comma or colon";}
//          )*
//       |  
//         tn = QuantBound() { addHeir(tn) ;  
//                             expecting = "comma or colon";}
//         ( t = <COMMA> { addHeir( new SyntaxTreeNode(mn, t) ); 
//                         expecting = "identifier or tuple of identifiers";}
//           tn = QuantBound() { addHeir(tn) ;  
//                               expecting = "comma or colon";}
//         )*
//        )
//        t = <COLON> { addHeir( new SyntaxTreeNode(mn, t) );  
//                      expecting = "expression";}
//        tn = Expression() { addHeir(tn) ; }
//        { nonExprBodyMayHaveProof = true;}
//    )
//   { SyntaxTreeNode sn[] = getLastHeirs();
//     epa(); 
//     return new SyntaxTreeNode(mn, N_NonExprBody, sn);
//   }
// }



/***************************************************************************
* The GeneralId() production is not used and can be deleted.  The parser   *
* uses Java code to construct N_GeneralId nodes inside Extension(),        *
* NoOpExtension(), and BraceCases()                                        *
***************************************************************************/
  final public SyntaxTreeNode GeneralId() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[2];
  Token t;
  bpa("General ID");
    zn[0] = IdPrefix();
    zn[1] = Identifier();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_GeneralId, zn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IdPrefix() throws ParseException {
  SyntaxTreeNode tn;
  bpa("ID Prefix");
    label_23:
    while (true) {
      if (jj_2_39(2147483647)) {
        ;
      } else {
        break label_23;
      }
      tn = IdPrefixElement();
                            addHeir( tn );
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_Proof, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IdPrefixElement() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("ID Prefix Element");
    tn = Identifier();
                      addHeir( tn );
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LBR:
      tn = OpArgs();
                   addHeir( tn );
      break;
    default:
      jj_la1[79] = jj_gen;
      ;
    }
    t = jj_consume_token(BANG);
               addHeir( new SyntaxTreeNode(mn, t) );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return  new SyntaxTreeNode(mn, N_IdPrefixElement, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ParenthesesExpression() throws ParseException {
  SyntaxTreeNode tn;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LBR:
      tn = ParenExpr();
      break;
    case LBC:
      tn = BraceCases();
      break;
    case LSB:
      tn = SBracketCases();
      break;
    case LWB:
      tn = SetExcept();
      break;
    case LAB:
      tn = TupleOrAction();
      break;
    case SF:
    case WF:
      tn = FairnessExpr();
      break;
    default:
      jj_la1[80] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ClosedExpressionOrOp() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case NUMBER_LITERAL:
    case STRING_LITERAL:
    case op_57:
    case op_68:
    case op_69:
    case op_70:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
    case op_1:
    case AND:
    case op_3:
    case op_4:
    case OR:
    case op_6:
    case op_7:
    case op_8:
    case op_9:
    case op_10:
    case op_11:
    case op_12:
    case op_13:
    case op_14:
    case op_15:
    case op_16:
    case op_17:
    case op_18:
    case op_19:
    case IN:
    case op_21:
    case op_22:
    case op_23:
    case op_24:
    case op_25:
    case op_27:
    case op_30:
    case op_31:
    case op_32:
    case op_33:
    case op_34:
    case op_35:
    case op_36:
    case op_37:
    case op_38:
    case op_39:
    case op_40:
    case op_41:
    case op_42:
    case op_43:
    case op_44:
    case op_45:
    case op_46:
    case op_47:
    case op_48:
    case op_49:
    case op_50:
    case op_51:
    case op_52:
    case op_53:
    case op_54:
    case op_55:
    case op_56:
    case op_59:
    case op_62:
    case op_63:
    case op_64:
    case EQUALS:
    case op_66:
    case op_67:
    case op_71:
    case op_72:
    case op_73:
    case op_74:
    case op_75:
    case op_77:
    case op_78:
    case op_79:
    case op_80:
    case op_81:
    case op_82:
    case op_83:
    case op_84:
    case op_85:
    case op_86:
    case op_87:
    case op_88:
    case op_89:
    case op_90:
    case op_91:
    case op_92:
    case op_93:
    case op_94:
    case op_95:
    case op_96:
    case op_97:
    case op_98:
    case op_100:
    case op_101:
    case op_102:
    case op_103:
    case op_104:
    case op_105:
    case op_106:
    case op_107:
    case op_108:
    case op_109:
    case op_110:
    case op_111:
    case op_117:
    case op_118:
    case op_119:
    case IDENTIFIER:
      tn = ElementaryExpression();
      break;
    case SF:
    case WF:
    case LBR:
    case LSB:
    case LWB:
    case LBC:
    case LAB:
      tn = ParenthesesExpression();
      break;
    default:
      jj_la1[81] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* The following does not seem to be used anywhere.                         *
***************************************************************************/
  final public SyntaxTreeNode ClosedExpressionOnly() throws ParseException {
  SyntaxTreeNode tn;
    tn = ClosedExpressionOrOp();
    if ( isGenOp( tn ) ) {if (true) throw new ParseException( "Encountered unexpected Operator" );}
    else {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode OpenExpression() throws ParseException {
  SyntaxTreeNode tn;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EXISTS:
    case FORALL:
      tn = SomeQuant();
      break;
    case T_EXISTS:
    case T_FORALL:
      tn = SomeTQuant();
      break;
    case IF:
      tn = IfThenElse();
      break;
    case CASE:
      tn = Case();
      break;
    case LET:
      tn = LetIn();
      break;
    case CHOOSE:
      tn = UnboundOrBoundChoose();
      break;
    default:
      jj_la1[82] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

/*
  L.GeneralId, L.OpApplication, L.String, L.Number, L.GenOp...
*/
  final public SyntaxTreeNode ElementaryExpression() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Elementary expression");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_57:
    case op_68:
    case op_69:
    case op_70:
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
    case op_1:
    case AND:
    case op_3:
    case op_4:
    case OR:
    case op_6:
    case op_7:
    case op_8:
    case op_9:
    case op_10:
    case op_11:
    case op_12:
    case op_13:
    case op_14:
    case op_15:
    case op_16:
    case op_17:
    case op_18:
    case op_19:
    case IN:
    case op_21:
    case op_22:
    case op_23:
    case op_24:
    case op_25:
    case op_27:
    case op_30:
    case op_31:
    case op_32:
    case op_33:
    case op_34:
    case op_35:
    case op_36:
    case op_37:
    case op_38:
    case op_39:
    case op_40:
    case op_41:
    case op_42:
    case op_43:
    case op_44:
    case op_45:
    case op_46:
    case op_47:
    case op_48:
    case op_49:
    case op_50:
    case op_51:
    case op_52:
    case op_53:
    case op_54:
    case op_55:
    case op_56:
    case op_59:
    case op_62:
    case op_63:
    case op_64:
    case EQUALS:
    case op_66:
    case op_67:
    case op_71:
    case op_72:
    case op_73:
    case op_74:
    case op_75:
    case op_77:
    case op_78:
    case op_79:
    case op_80:
    case op_81:
    case op_82:
    case op_83:
    case op_84:
    case op_85:
    case op_86:
    case op_87:
    case op_88:
    case op_89:
    case op_90:
    case op_91:
    case op_92:
    case op_93:
    case op_94:
    case op_95:
    case op_96:
    case op_97:
    case op_98:
    case op_100:
    case op_101:
    case op_102:
    case op_103:
    case op_104:
    case op_105:
    case op_106:
    case op_107:
    case op_108:
    case op_109:
    case op_110:
    case op_111:
    case op_117:
    case op_118:
    case op_119:
    case IDENTIFIER:
      tn = Extension();
      break;
    case STRING_LITERAL:
      tn = String();
                    epa();
      break;
    case NUMBER_LITERAL:
      tn = Number();
                    epa();
      break;
    default:
      jj_la1[83] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode String() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("String");
    t = jj_consume_token(STRING_LITERAL);
    tn = new SyntaxTreeNode( mn, N_String, t);
    tn.image = reduceString( tn.image.toString() );
    epa();
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Number() throws ParseException {
  SyntaxTreeNode tn, sn[] = null;
  Token t1, t2;
  int kind = N_Number;
    t1 = jj_consume_token(NUMBER_LITERAL);
    if (jj_2_40(2)) {
      t2 = jj_consume_token(DOT);
     kind = N_Real;
     decimalFlag = true;
     sn = new SyntaxTreeNode[3];
     sn[0] = new SyntaxTreeNode(mn, t1);
     sn[1] = new SyntaxTreeNode(mn, t2);
      t1 = jj_consume_token(NUMBER_LITERAL);
     sn[2] = new SyntaxTreeNode(mn,t1);
    } else {
      ;
    }
    if (sn == null) {
      numberFlag = true;
      sn = new SyntaxTreeNode[1];
      sn[0] =  new SyntaxTreeNode(mn, t1);
      kind = N_Number;
    }
    {if (true) return new SyntaxTreeNode(mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Extension() throws ParseException {
  SyntaxTreeNode last = null, tid, top = null;
  Token t = null;
  SyntaxTreeNode heirs[];
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case op_26:
    case op_29:
    case op_58:
    case CASESEP:
    case op_61:
    case op_112:
    case op_113:
    case op_114:
    case op_115:
    case op_116:
      //  LOOKAHEAD( { isPrefixOp( getToken(1) )  } )
            top = PrefixOp();
        heirs = new SyntaxTreeNode[2];
        heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
        heirs[1] = top;
        last = new SyntaxTreeNode( mn, N_GenPrefixOp, heirs );
        epa();
      break;
    case op_1:
    case AND:
    case op_3:
    case op_4:
    case OR:
    case op_6:
    case op_7:
    case op_8:
    case op_9:
    case op_10:
    case op_11:
    case op_12:
    case op_13:
    case op_14:
    case op_15:
    case op_16:
    case op_17:
    case op_18:
    case op_19:
    case IN:
    case op_21:
    case op_22:
    case op_23:
    case op_24:
    case op_25:
    case op_27:
    case op_30:
    case op_31:
    case op_32:
    case op_33:
    case op_34:
    case op_35:
    case op_36:
    case op_37:
    case op_38:
    case op_39:
    case op_40:
    case op_41:
    case op_42:
    case op_43:
    case op_44:
    case op_45:
    case op_46:
    case op_47:
    case op_48:
    case op_49:
    case op_50:
    case op_51:
    case op_52:
    case op_53:
    case op_54:
    case op_55:
    case op_56:
    case op_59:
    case op_62:
    case op_63:
    case op_64:
    case EQUALS:
    case op_66:
    case op_67:
    case op_71:
    case op_72:
    case op_73:
    case op_74:
    case op_75:
    case op_77:
    case op_78:
    case op_79:
    case op_80:
    case op_81:
    case op_82:
    case op_83:
    case op_84:
    case op_85:
    case op_86:
    case op_87:
    case op_88:
    case op_89:
    case op_90:
    case op_91:
    case op_92:
    case op_93:
    case op_94:
    case op_95:
    case op_96:
    case op_97:
    case op_98:
    case op_100:
    case op_101:
    case op_102:
    case op_103:
    case op_104:
    case op_105:
    case op_106:
    case op_107:
    case op_108:
    case op_109:
    case op_110:
    case op_111:
    case op_117:
    case op_118:
    case op_119:
      // LOOKAHEAD( { isInfixOp( getToken(1) )  } )
            top = InfixOp();
        heirs = new SyntaxTreeNode[2];
        heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
        heirs[1] = top;
        last =  new SyntaxTreeNode( mn, N_GenInfixOp, heirs );
        epa();
      break;
    case op_57:
    case op_68:
    case op_69:
    case op_70:
      // LOOKAHEAD( { isPostfixOp( getToken(1) )  } )
            top = PostfixOp();
        heirs = new SyntaxTreeNode[2];
        heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
        heirs[1] = top;
        last =  new SyntaxTreeNode( mn, N_GenPostfixOp, heirs );
        epa();
      break;
    case IDENTIFIER:
      tid = Identifier();
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LBR:
        top = OpArgs();
        break;
      default:
        jj_la1[84] = jj_gen;
        ;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case BANG:
        t = jj_consume_token(BANG);
        if ( top == null ) {
          heirs = new SyntaxTreeNode[2];
          heirs[1] = new SyntaxTreeNode( mn, t );
        } else {
          heirs = new SyntaxTreeNode[3];
          heirs[1] = top;
          heirs[2] = new SyntaxTreeNode(mn, t );
        }
        heirs[0] = tid;
        SyntaxTreeNode current = new SyntaxTreeNode( mn, N_IdPrefixElement, heirs );
        addHeir( current );
        last = Extension();
        break;
      default:
        jj_la1[85] = jj_gen;
        ;
      }
      if ( last == null ) {
         if ( top == null ) {
           heirs = new SyntaxTreeNode[2];
           heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
           heirs[1] = tid;
           last = new SyntaxTreeNode( mn, N_GeneralId, heirs );
         } else {
/* XXX Wrong.
           addHeir( tid );
           tid = new SyntaxTreeNode( mn, N_GeneralId, getLastHeirs() );
*/
           heirs = new SyntaxTreeNode[2];
           heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
           heirs[1] = tid;
           tid = new SyntaxTreeNode( mn, N_GeneralId, heirs );

           heirs = new SyntaxTreeNode[2];
           heirs[0] = tid;
           heirs[1] = top;
           last = new SyntaxTreeNode( mn, N_OpApplication, heirs );
         }
         epa();
      }
      break;
    default:
      jj_la1[86] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return last;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode OpArgs() throws ParseException {
                      // OpSuite contributes to Heir list.
  SyntaxTreeNode tn;
  Token t;
  bpa("Optional Arguments");
    t = jj_consume_token(LBR);
               addHeir( new SyntaxTreeNode(mn, t) );
    OpSuite();
    label_24:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[87] = jj_gen;
        break label_24;
      }
      t = jj_consume_token(COMMA);
                  addHeir( new SyntaxTreeNode(mn, t) );
      OpSuite();
    }
    t = jj_consume_token(RBR);
               addHeir( new SyntaxTreeNode(mn, t) );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_OpArgs, sn);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* OpOrExpr ::=    (NonExpPrefixOp | InfixOp | PostfixOp)                   *
*                   followed by                                            *
*                     "," | ")" | <DEFBREAK> | "LOCAL" | "INSTANCE" |      *
*                     "THEOREM" | "ASSUME" | "ASSUMPTION" |                *
*                     "CONSTANT" | "VARIABLE" | "RECURSIVE" |              *
*                    <END_MODULE> | <SEPARATOR> | <BEGIN_MODULE>           *
*               | Lambda                                                   *
*               | Expression                                               *
*                                                                          *
* This production is called where either an operator or an expression is   *
* expected--which is either as the argument of an operator or in a         *
* substitution.  For an expression or an operator argument that's a        *
* LAMBDA expression, there's no problem.  However, something like Foo!Bar  *
* could be either an expression or an operator.  In TLA+2, something like  *
* Foo!+!Bar could only be an operator, while something like                *
* Foo!+(a,b)!Bar could only be an expression.  However, in order to        *
* minimize the changes from the TLA+1 parser, we represent both Foo!+!Bar  *
* and Foo!+(a,b)!Bar as a GeneralId node and leave it to the semantic      *
* processing to sort things out.  Thus, Foo!+(a,b)!Bar produces the        *
* folowing tree of SyntaxTreeNode objects:                                 *
*                                                                          *
*    N_GeneralId                                                           *
*    _.N_IdPrefix                                                          *
*    _._.N_IdPrefixElement                                                 *
*    _._._.IDENTIFIER "Foo"                                                *
*    _._._.BANG "!"                                                        *
*    _._.N_IdPrefixElement                                                 *
*    _._._.N_InfixOp  +                                                    *
*    _._._.N_OpArgs                                                        *
*    _._._._.LBR "("                                                       *
*    _._._._.whatever a produces                                           *
*    _._._._.COMMA ","                                                     *
*    _._._._.whatever b produces                                           *
*    _._._._.RBR ")"                                                       *
*    _._._.BANG "!"                                                        *
*    _.IDENTIFIER "Bar"                                                    *
*                                                                          *
* Something like Foo!+(a,b)!Bar(x) producs an N_OpApplication node         *
* whose first child is the N_GeneralId node above and whose second         *
* child is an N_OpArgs node.                                               *
*                                                                          *
* TLA+2 adds labels and structural operators like "<<" to this kind of     *
* operator or expression.  A label in such an expression looks just like   *
* an ordinary identifier.  A structural operator is represented by a       *
* token with the new kind "N_StructOp".  Such a node is created by         *
*                                                                          *
*   new SynaxTreeNode(moduleName, N_StructOp, node)                        *
*                                                                          *
* where node is created by either                                          *
*                                                                          *
*   new SyntaxTreeNode(moduleName, tok)                                    *
*                                                                          *
* where tok is "<<", ">>", "@", or ":", or by                              *
*                                                                          *
*    new SynaxTreeNode(moduleName, N_Number, ...)                          *
*                                                                          *
* for a <NUMBER_LITERAL> token.                                            *
*                                                                          *
* Let OpArgs = (arg_1, ...  , arg_k).  In general, there are three         *
* interesting classes of expressions of the form e_1!e_2!...!e_n.          *
*                                                                          *
* Case 1: e_n = tok OpArgs,                                                *
*           where tok is an Identifier or an In/Pre/PostfixOp.             *
*   In this case an OpApplication node is produced with two children:      *
*   - An N_GeneralId node with children                                    *
*      - An N_IdPrefixNode with n-1 children consisting N_IdPRefixElement  *
*        nodes for e_1!, ... , e_n-1!.                                     *
*      - A node of kind IDENTIFIER, N_PrefixOp, etc. for tok               *
*   - An N_OpArgs nodes obtained from OpArgs                               *
*                                                                          *
* Case 2: e_n = tok                                                        *
*           where tok is an Identifier or an In/Pre/PostfixOp.             *
*   In this case, it produces just the N_GeneralId node of Case 1          *
*                                                                          *
* Case 3: e_n = OpArgs                                                     *
*   In this case, a GeneralId node is produced with two children:          *
*    - The N_IdPrefixNode node produced in cases 1 and 2                   *
*    - An N_OpArgs node for OpArgs.                                        *
***************************************************************************/
  final public SyntaxTreeNode OpOrExpr() throws ParseException {
  /*************************************************************************
  * Used for parsing an operator argument or the right-hand side of a      *
  * substitution, which could be either an operator (like +) or an         *
  * expression (like a+b).                                                 *
  *************************************************************************/
SyntaxTreeNode tn;
int kind ;
    if (jj_2_41(2) && (BStack.aboveReference( getToken(1).beginColumn))) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_76:
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
        tn = NonExpPrefixOp();
                             kind = N_GenNonExpPrefixOp;
        break;
      case op_1:
      case AND:
      case op_3:
      case op_4:
      case OR:
      case op_6:
      case op_7:
      case op_8:
      case op_9:
      case op_10:
      case op_11:
      case op_12:
      case op_13:
      case op_14:
      case op_15:
      case op_16:
      case op_17:
      case op_18:
      case op_19:
      case IN:
      case op_21:
      case op_22:
      case op_23:
      case op_24:
      case op_25:
      case op_27:
      case op_30:
      case op_31:
      case op_32:
      case op_33:
      case op_34:
      case op_35:
      case op_36:
      case op_37:
      case op_38:
      case op_39:
      case op_40:
      case op_41:
      case op_42:
      case op_43:
      case op_44:
      case op_45:
      case op_46:
      case op_47:
      case op_48:
      case op_49:
      case op_50:
      case op_51:
      case op_52:
      case op_53:
      case op_54:
      case op_55:
      case op_56:
      case op_59:
      case op_62:
      case op_63:
      case op_64:
      case EQUALS:
      case op_66:
      case op_67:
      case op_71:
      case op_72:
      case op_73:
      case op_74:
      case op_75:
      case op_77:
      case op_78:
      case op_79:
      case op_80:
      case op_81:
      case op_82:
      case op_83:
      case op_84:
      case op_85:
      case op_86:
      case op_87:
      case op_88:
      case op_89:
      case op_90:
      case op_91:
      case op_92:
      case op_93:
      case op_94:
      case op_95:
      case op_96:
      case op_97:
      case op_98:
      case op_100:
      case op_101:
      case op_102:
      case op_103:
      case op_104:
      case op_105:
      case op_106:
      case op_107:
      case op_108:
      case op_109:
      case op_110:
      case op_111:
      case op_117:
      case op_118:
      case op_119:
        tn = InfixOp();
         kind = N_GenInfixOp;
         if (   (tn.image == UniqueString.uniqueStringOf("\\X"))
             || (tn.image == UniqueString.uniqueStringOf("\\times"))){
            {if (true) throw new ParseException(
                        tn.getLocation().toString() +
                        ": \\X may not be used as an infix operator.");}
           };
        break;
      case op_57:
      case op_68:
      case op_69:
      case op_70:
        tn = PostfixOp();
                             kind = N_GenPostfixOp;
        break;
      default:
        jj_la1[88] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    SyntaxTreeNode heirs[] = new SyntaxTreeNode[2];
    heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, ( SyntaxTreeNode []) null );
    heirs[1] = tn;
    tn = new SyntaxTreeNode(mn, kind, heirs);
    } else if (jj_2_42(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
      /***********************************************************************
          * Need the BStack.aboveReference check to make sure that the LAMBDA    *
          * is properly indented with respect to any enclosing dis/conjunction   *
          * list.  However, without the <LAMBDA>, the lookahead would succeed    *
          * and the next production would be executed even if it shouldn't       *
          * match.                                                               *
          ***********************************************************************/
        tn = Lambda();
    } else if (jj_2_43(1)) {
      tn = Expression();
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
 {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  final public void OpSuite() throws ParseException {
SyntaxTreeNode tn;
    tn = OpOrExpr();
                    addHeir(tn);
  }

  // OpSuite


// void /* nodes are linked internally here : no value returned */
// oldOpSuite() : {
//   SyntaxTreeNode tn = null;
//   anchor = null;
//     /***********************************************************************
//     * See the comments for the declaration of anchor to see what this is   *
//     * being used for.                                                      *
//     ***********************************************************************/
//   Token t;
// } {
//   ( /***********************************************************************
//     * This handles the operator argument "-." (token op_76)                *
//     ***********************************************************************/
// // XXXXX -- this won't work with the new expression syntax.
//     t = <op_76> {
//     tn = new SyntaxTreeNode(mn, N_NonExpPrefixOp, t); 
//     SyntaxTreeNode heirs[] = new SyntaxTreeNode[2];
//     heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, ( SyntaxTreeNode []) null );
//     heirs[1] = tn;
//     tn = new SyntaxTreeNode( mn, N_GenNonExpPrefixOp, heirs ); }
//   | LOOKAHEAD( (<AND> | <OR>) (<COMMA>|<RBR>) )
//       tn = InfixOp() {
//         heirs = new SyntaxTreeNode[2];
//         heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, (SyntaxTreeNode []) null );
//         heirs[1] = tn;
//         tn =  new SyntaxTreeNode( mn, N_GenInfixOp, heirs );
//      }
//   | tn = Lambda() 
//   | try {
//       tn = Expression()
//     } catch ( ParseException e ) {
// // ToolIO.out.println("Caught exception (bis)");
// // first things first - restore evaluation stack
//     if ( OperatorStack.isWellReduced() )
//       OperatorStack.popStack();
//     else
//       throw e;
//     /* it wasn't an expression, what was it ? */
//     /* check the nature of the node returned. It can only be a prefixed op. */
//     if ( ( anchor != null )
//        &&(    anchor.isKind( N_GenPrefixOp ) 
//            || anchor.isKind( N_GenInfixOp ) 
//            || anchor.isKind( N_GenPostfixOp ) ) ) {tn = anchor; anchor = null;
//       } else {
// // ToolIO.out.println("anchor is " + anchor.toString());
//        throw e;
//       } // end else
//     } // end catch.
// )
//     /* it wasn't an expression, what was it ?  L.GenNonExpPrefixOp | L.GenInfixOp | L.GenPostfixOp */
//     /* check the nature of the node returned . Below Expression, it has to be a prefixed op. */
//   { addHeir( tn ); }
// }
  final public SyntaxTreeNode ParenExpr() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  SyntaxTreeNode tn;
  Token t;
    t = jj_consume_token(LBR);
               zn[0] = new SyntaxTreeNode(mn, t);
    zn[1] = Expression();
    t = jj_consume_token(RBR);
               zn[2] = new SyntaxTreeNode(mn, t);
    {if (true) return new SyntaxTreeNode(mn, N_ParenExpr, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode SomeQuant() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Quantified form");
  int kind;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EXISTS:
      t = jj_consume_token(EXISTS);
      break;
    case FORALL:
      t = jj_consume_token(FORALL);
      break;
    default:
      jj_la1[89] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                    addHeir( new SyntaxTreeNode(mn, t));
    if (jj_2_44(2147483647)) {
      tn = Identifier();
      kind = N_UnboundQuant;
      addHeir( tn );
      label_25:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[90] = jj_gen;
          break label_25;
        }
        t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
        tn = Identifier();
        addHeir( tn );
      }
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LAB:
      case IDENTIFIER:
        tn = QuantBound();
      kind = N_BoundQuant;
      addHeir( tn );
        label_26:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[91] = jj_gen;
            break label_26;
          }
          t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
          tn = QuantBound();
                          addHeir( tn );
        }
        break;
      default:
        jj_la1[92] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    t = jj_consume_token(COLON);
                 addHeir( new SyntaxTreeNode(mn, t) );
    tn = Expression();
                      addHeir( tn );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode SomeTQuant() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Bound Quantified Expression");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case T_EXISTS:
      t = jj_consume_token(T_EXISTS);
      break;
    case T_FORALL:
      t = jj_consume_token(T_FORALL);
      break;
    default:
      jj_la1[93] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                                        addHeir( new SyntaxTreeNode(mn, t) );
    tn = Identifier();
    addHeir( tn );
    label_27:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[94] = jj_gen;
        break label_27;
      }
      t = jj_consume_token(COMMA);
                  addHeir( new SyntaxTreeNode(mn, t) );
      tn = Identifier();
      addHeir( tn );
    }
    t = jj_consume_token(COLON);
                 addHeir( new SyntaxTreeNode(mn, t) );
    tn = Expression();
                      addHeir( tn );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_UnboundQuant, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode QuantBound() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Quant Bound");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LAB:
      tn = IdentifierTuple();
      addHeir( tn );
      break;
    case IDENTIFIER:
      tn = Identifier();
      addHeir( tn );
      label_28:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[95] = jj_gen;
          break label_28;
        }
        t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
        tn = Identifier();
          addHeir( tn );
          expecting = ", or \\in";
      }
      break;
    default:
      jj_la1[96] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    t = jj_consume_token(IN);
    tn =  new SyntaxTreeNode(mn, t);
    tn.setKind(T_IN);
    addHeir(tn);
    tn = Expression();
                      addHeir( tn );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_QuantBound, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode BraceCases() throws ParseException {
  int kind = N_SetEnumerate; // set by default.
  SyntaxTreeNode tn, tn_0, tn_1, tn_2, htn = null;
  Token t;
  boolean te = false;
    /***********************************************************************
    * The value of te is set in a couple of places, but it is never        *
    * read.  J-Ch hopes it's obsolete.                                     *
    ***********************************************************************/
  bpa("Some { } form");
    t = jj_consume_token(LBC);
               addHeir( new SyntaxTreeNode(mn, t) );
    if (jj_2_48(1)) {
      if (matchFcnConst()) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case LAB:
          tn = IdentifierTuple();
          break;
        case IDENTIFIER:
          tn = Identifier();
          break;
        default:
          jj_la1[97] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      tn_0 = tn;
      expecting = "\\in";
        // At this stage, we need to break since it maybe a MaybeBound or
        // a SubsetOf
        // So we'll hold to the pieces in the meantime.
            t = jj_consume_token(IN);
      tn_1 =  new SyntaxTreeNode(mn, t);
      tn_1.setKind(T_IN);
        /*******************************************************************
        * Changed from tn.setKind(T_IN) by LL on 19 Mar 2007.              *
        *                                                                  *
        * Appears to fix bug that caused semantic error on something like  *
        * {<<m, n>> \in Nat \X Nat : m > 0}.                               *
        *******************************************************************/

//      addHeir(tn);

        tn_2 = Expression();
//      addHeir( tn );
// need to create a node for a N_InfixExpr. Some reassembly required, but if course it may be for naught.
// This is in case it isn't a N_SubsetOf
      expecting = "':', ',' or '}'";
      SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
      SyntaxTreeNode wn[]= new SyntaxTreeNode[2];
      wn[0] = new SyntaxTreeNode(mn, N_IdPrefix, new SyntaxTreeNode[0]);
      wn[1] = tn_0;
      zn[0] = new SyntaxTreeNode(mn, N_GeneralId, wn);
      wn = new SyntaxTreeNode[2];
      wn[0] = new SyntaxTreeNode(mn, N_IdPrefix, new SyntaxTreeNode[0]);
      wn[1] = tn_1;
      zn[1] = new SyntaxTreeNode(mn, N_GenInfixOp, wn);
      zn[2] = tn_2;
      htn = new SyntaxTreeNode( mn, N_InfixExpr, zn);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
        case COLON:
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COLON:
            t = jj_consume_token(COLON);
      htn = null; // it was for naught, ignore it later.
      addHeir(tn_0); // ID
      addHeir(tn_1); // \\in
      addHeir(tn_2); // expression
      addHeir( new SyntaxTreeNode(mn, t) );
      kind = N_SubsetOf;
            tn = Expression();
                          addHeir( tn );
            break;
          case COMMA:
            label_29:
            while (true) {
              t = jj_consume_token(COMMA);
        if (htn != null) {
          addHeir( htn); htn = null;
        }
        addHeir( new SyntaxTreeNode(mn, t) );
              tn = Expression();
                            addHeir( tn );
              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
              case COMMA:
                ;
                break;
              default:
                jj_la1[98] = jj_gen;
                break label_29;
              }
            }
            break;
          default:
            jj_la1[99] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          break;
        default:
          jj_la1[100] = jj_gen;
          ;
        }
      } else if (jj_2_45(2147483647)) {
        tn = Expression();
      kind = N_SetEnumerate;
      addHeir( tn );
        label_30:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[101] = jj_gen;
            break label_30;
          }
          t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
          tn = Expression();
                            addHeir( tn );
        }
      } else if (jj_2_46(2147483647)) {
      te = true; kind = N_SetOfAll;
        tn = Expression();
      addHeir( tn );
        t = jj_consume_token(COLON);
                   addHeir( new SyntaxTreeNode(mn, t) );
        tn = QuantBound();
                        addHeir( tn );
        label_31:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[102] = jj_gen;
            break label_31;
          }
          t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
          tn = QuantBound();
                          addHeir( tn );
        }
      } else if (jj_2_47(1)) {
        tn = Expression();
                        addHeir( tn );
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
        case COLON:
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COLON:
            t = jj_consume_token(COLON);
        te = true; kind = N_SetOfAll;
// IF tn is infix expression, with operator IN, we have a pbm for throw new ParseException( "Form {a \in b : c \in d } is forbidden" );

        /*******************************************************************
        * The following code causes an incorrect error on the legal        *
        * expression {1 \in x : x \in T}.  It seems to me that this        *
        * test should simply be eliminated.  It seems to be based on the   *
        * mistaken belief that {x \in S : x \in T} is illegal, when it's   *
        * actually an expression of type N_SubsetOf.                       *
        *******************************************************************/
        SyntaxTreeNode Hone[] = (SyntaxTreeNode[])tn.heirs();
        if (Hone.length>1) { // better make sure it's long enough.
          Hone = (SyntaxTreeNode[])Hone[1].heirs(); // second heir of second heir
          if ( tn.isKind( N_InfixExpr ) && Hone[1].getImage().equals("\\in") ) {
            {if (true) throw new ParseException( "Form {a \\in b : c \\in d }, at line " + t.beginLine + ", is not allowed" );}
          }
        }
        addHeir( new SyntaxTreeNode(mn, t) );
            tn = QuantBound();
                          addHeir( tn );
            label_32:
            while (true) {
              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
              case COMMA:
                ;
                break;
              default:
                jj_la1[103] = jj_gen;
                break label_32;
              }
              t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
              tn = QuantBound();
                          addHeir( tn );
            }
            break;
          case COMMA:
            label_33:
            while (true) {
              t = jj_consume_token(COMMA);
                      kind = N_SetEnumerate;
        addHeir( new SyntaxTreeNode(mn, t) );
              tn = Expression();
                            addHeir( tn );
              switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
              case COMMA:
                ;
                break;
              default:
                jj_la1[104] = jj_gen;
                break label_33;
              }
            }
            break;
          default:
            jj_la1[105] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          break;
        default:
          jj_la1[106] = jj_gen;
          ;
        }
      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }
    } else {
      ;
    }
    t = jj_consume_token(RBC);
    if (htn!=null) addHeir(htn);
    addHeir( new SyntaxTreeNode(mn, t) );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode SBracketCases() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  int kind = 0;
  bpa("Some [] Form");
    t = jj_consume_token(LSB);
               addHeir( new SyntaxTreeNode(mn, t) );
    if (matchFcnConst()) {
      // FcnConst - because we use OpSymbol rather than IN, we need to use semantic detection.
          tn = QuantBound();
      kind = N_FcnConst;
      addHeir( tn );
      label_34:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[107] = jj_gen;
          break label_34;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = QuantBound();
                          addHeir( tn );
      }
      t = jj_consume_token(MAPTO);
                  addHeir( new SyntaxTreeNode(mn, t) );
      tn = Expression();
                        addHeir( tn );
      t = jj_consume_token(RSB);
                addHeir( new SyntaxTreeNode(mn, t) );
    } else if (jj_2_49(2147483647)) {
      /* RcdConstructor */
          tn = FieldVal();
      kind = N_RcdConstructor;
      addHeir( tn );
      label_35:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[108] = jj_gen;
          break label_35;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = FieldVal();
                        addHeir( tn );
      }
      t = jj_consume_token(RSB);
                addHeir( new SyntaxTreeNode(mn, t) );
    } else if ((getToken(2).kind == MAPTO) && isFieldNameToken( getToken(1))) {
      getToken(1).kind = IDENTIFIER;
      tn = FieldVal();
      kind = N_RcdConstructor;
      addHeir( tn );
      label_36:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[109] = jj_gen;
          break label_36;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = FieldVal();
                        addHeir( tn );
      }
      t = jj_consume_token(RSB);
                addHeir( new SyntaxTreeNode(mn, t) );
    } else if (jj_2_50(2147483647)) {
      /* SetOfRcds */
          tn = FieldSet();
      kind = N_SetOfRcds;
      addHeir( tn );
      label_37:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[110] = jj_gen;
          break label_37;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = FieldSet();
                        addHeir( tn );
      }
      t = jj_consume_token(RSB);
                addHeir( new SyntaxTreeNode(mn, t) );
    } else if (jj_2_51(1)) {
      tn = Expression();
                        addHeir( tn );
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
      case RSB:
        label_38:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[111] = jj_gen;
            break label_38;
          }
          t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
          tn = Expression();
                            addHeir( tn );
        }
        t = jj_consume_token(RSB);
                  addHeir( new SyntaxTreeNode(mn, t) );
      kind = N_FcnAppl;
      lastOp = FcnOp;
        break;
      case ARROW:
        t = jj_consume_token(ARROW);
                                          // SetOfFcns
        kind = N_SetOfFcns;
        addHeir( new SyntaxTreeNode(mn, t) );
        tn = Expression();
                          addHeir( tn );
        t = jj_consume_token(RSB);
                  addHeir( new SyntaxTreeNode(mn, t) );
        break;
      case EXCEPT:
        t = jj_consume_token(EXCEPT);
                                           // Except
        kind = N_Except;
        addHeir( new SyntaxTreeNode(mn, t) );
        tn = ExceptSpec();
                          addHeir( tn );
        label_39:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[112] = jj_gen;
            break label_39;
          }
          t = jj_consume_token(COMMA);
                      addHeir( new SyntaxTreeNode(mn, t) );
          tn = ExceptSpec();
                            addHeir( tn );
        }
        t = jj_consume_token(RSB);
                  addHeir( new SyntaxTreeNode(mn, t) );
        break;
      case ARSB:
        t = jj_consume_token(ARSB);
        kind = N_ActionExpr;
        addHeir( new SyntaxTreeNode(mn, t) );
        tn = ReducedExpression();
                                 addHeir( tn );
        break;
      default:
        jj_la1[113] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    Assert.check(kind !=0, EC.SANY_PARSER_CHECK_3);
// "Assertion error in SBracketCases()"
    epa(); {if (true) return new SyntaxTreeNode(mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode FieldVal() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  Token t;
  bpa("Field Value");
    zn[0] = Identifier();
    t = jj_consume_token(MAPTO);
                zn[1] = new SyntaxTreeNode(mn, t);
    zn[2] = Expression();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_FieldVal, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode FieldSet() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  SyntaxTreeNode tn;
  Token t;
  bpa("Field Set");
    zn[0] = Identifier();
    t = jj_consume_token(COLON);
                zn[1] = new SyntaxTreeNode(mn, t);
    zn[2] = Expression();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_FieldSet, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ExceptSpec() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Except Spec");
    t = jj_consume_token(BANG);
               addHeir( new SyntaxTreeNode(mn, t) );
    label_40:
    while (true) {
      tn = ExceptComponent();
    addHeir( tn );
    expecting = "= or ,";
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case DOT:
      case LSB:
        ;
        break;
      default:
        jj_la1[114] = jj_gen;
        break label_40;
      }
    }
    t = jj_consume_token(EQUALS);
    tn =  new SyntaxTreeNode(mn, t);
    tn.setKind(T_EQUAL);
    addHeir(tn);
    tn = Expression();
                      addHeir( tn );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_ExceptSpec, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ExceptComponent() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Except Component");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DOT:
      t = jj_consume_token(DOT);
                addHeir( new SyntaxTreeNode(mn, t) );
                /***********************************************************
                * Following added by LL on 10 Oct 2007 to make something   *
                * like "!.THEN" work right.                                *
                ***********************************************************/
                Token next = getToken(1);
                if (isFieldNameToken( next )) next.kind = IDENTIFIER;
      tn = Identifier();
      if (tn.getUS().equals(At) ) {
        PErrors.push( new ParseError("@ used in !.@") );
      }
      addHeir( tn );
      break;
    case LSB:
      t = jj_consume_token(LSB);
                addHeir( new SyntaxTreeNode(mn, t) );
      tn = Expression();
                        addHeir( tn );
      label_41:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[115] = jj_gen;
          break label_41;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = Expression();
                          addHeir( tn );
      }
      t = jj_consume_token(RSB);
                addHeir( new SyntaxTreeNode(mn, t) );
      break;
    default:
      jj_la1[116] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    SyntaxTreeNode sn[] = getLastHeirs(); epa();
    {if (true) return new SyntaxTreeNode( mn, N_ExceptComponent, sn );}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* The SetExcept non-terminal was eliminated from the grammar, but not      *
* from the parser.                                                         *
***************************************************************************/
  final public SyntaxTreeNode SetExcept() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Set Except");
    t = jj_consume_token(LWB);
              addHeir( new SyntaxTreeNode(mn, t) );
    tn = Expression();
                      addHeir( tn );
    t = jj_consume_token(EXCEPT);
                 addHeir( new SyntaxTreeNode(mn, t) );
    tn = SExceptSpec();
                       addHeir( tn );
    label_42:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[117] = jj_gen;
        break label_42;
      }
      t = jj_consume_token(COMMA);
                  addHeir( new SyntaxTreeNode(mn, t) );
      tn = SExceptSpec();
                         addHeir( tn );
    }
    t = jj_consume_token(RWB);
              addHeir( new SyntaxTreeNode(mn, t) );
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_SetExcept, sn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode SExceptSpec() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[4];
  SyntaxTreeNode tn;
  Token t;
  bpa("Set Expect Spec");
    t = jj_consume_token(BANG);
               zn[0] = new SyntaxTreeNode(mn, t);
    zn[1] = ExceptComponent();
    expecting = "= or \\in";
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EQUALS:
      t = jj_consume_token(EQUALS);
      zn[2] =  new SyntaxTreeNode(mn, t); zn[2].setKind( T_EQUAL );
      break;
    case IN:
      t = jj_consume_token(IN);
      zn[2] =  new SyntaxTreeNode(mn, t); zn[2].setKind( T_IN );
      break;
    default:
      jj_la1[118] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    zn[3] = Expression();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_SExceptSpec, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode TupleOrAction() throws ParseException {
  int kind = 0;
  SyntaxTreeNode tn;
  Token t;
  bpa("Some << -- >> or >>_ Form");
    t = jj_consume_token(LAB);
              addHeir( new SyntaxTreeNode(mn, t) );
    if (jj_2_52(1)) {
      tn = Expression();
                        addHeir( tn );
      label_43:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[119] = jj_gen;
          break label_43;
        }
        t = jj_consume_token(COMMA);
                    addHeir( new SyntaxTreeNode(mn, t) );
        tn = Expression();
                            addHeir( tn );
      }
    } else {
      ;
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case RAB:
      t = jj_consume_token(RAB);
      kind = N_Tuple; addHeir( new SyntaxTreeNode(mn, t) );
      break;
    case ARAB:
      t = jj_consume_token(ARAB);
      kind = N_ActionExpr; addHeir( new SyntaxTreeNode(mn, t) );
      tn = ReducedExpression();
                               addHeir( tn );
      break;
    default:
      jj_la1[120] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, kind, sn );}
    throw new Error("Missing return statement in function");
  }

//  new SyntaxTreeNode( N_IdPrefix )  ???
  final public SyntaxTreeNode NoOpExtension() throws ParseException {
  SyntaxTreeNode tid, top, last;
  last = null; top = null;
  Token t = null;
    tid = Identifier();
    if (jj_2_53(2)) {
      top = OpArgs();
    } else {
      ;
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case BANG:
      t = jj_consume_token(BANG);
        SyntaxTreeNode heirs[];
        if ( top == null ) {
          heirs = new SyntaxTreeNode[2];
          heirs[1] = new SyntaxTreeNode( mn, t );
        } else {
          heirs = new SyntaxTreeNode[3];
          heirs[1] = top;
          heirs[2] = new SyntaxTreeNode(mn, t );
        }
        heirs[0] = tid;
        SyntaxTreeNode current = new SyntaxTreeNode( mn, N_IdPrefixElement, heirs );
        addHeir( current );
      last = NoOpExtension();
      break;
    default:
      jj_la1[121] = jj_gen;
      ;
    }
      if ( last == null ) { // means no bang, bottom of recursion
         if ( top != null )
           FairnessHook = top;
         else
           FairnessHook = null;
         SyntaxTreeNode zn[] = new SyntaxTreeNode[2];
         zn[0] = new SyntaxTreeNode( mn, N_IdPrefix, getLastHeirs() );
         zn[1] = tid;
         last = new SyntaxTreeNode( mn, N_GeneralId, zn );
      }
    {if (true) return last;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode ReducedExpression() throws ParseException {
  /*************************************************************************
  * This is an expression that can follow "[...]_" or "<<...>>_".          *
  *************************************************************************/
  SyntaxTreeNode expr;
  bpa("restricted form of expression");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      expr = NoOpExtension();
      break;
    case LBR:
      expr = ParenExpr();
      break;
    case LBC:
      expr = BraceCases();
      break;
    case LSB:
      expr = SBracketCases();
      break;
    case LWB:
      expr = SetExcept();
      break;
    case LAB:
      expr = TupleOrAction();
      break;
    default:
      jj_la1[122] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     epa(); {if (true) return expr;}
    throw new Error("Missing return statement in function");
  }

// The following cases - for the first expression - must be recognized :
// "GeneralId", "OpApplication", "RecordComponent", "FcnAppl", "ParenExpr", "SetEnumerate", "SubsetOf", "SetOfAll", "FcnConst", "SetOfFcns", "RcdConstructor", "SetOfRcds", "Except", "Tuple", "ActionExpr"
// The cases break down in two categories: two set of () or a single one.
// in general, it's going to be some () [] or {} expression, or an Identifier foollowed by . () or [].
// Note that FcnAppl may be more intricate.
  final public SyntaxTreeNode FairnessExpr() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[5];
  SyntaxTreeNode tn, expr;
  Token t;
  FairnessHook = null;
  bpa("Fairness Expression");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case WF:
      t = jj_consume_token(WF);
      break;
    case SF:
      t = jj_consume_token(SF);
      break;
    default:
      jj_la1[123] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                          zn[0] = new SyntaxTreeNode(mn, t);
    expr = ReducedExpression();
    if (jj_2_54(2)) {
      t = jj_consume_token(LBR);
// ^^^  
// Warning 3 -- Eliminated by LOOKAHEAD
    zn[1] = expr; expr = null;
    zn[2] = new SyntaxTreeNode(mn, t);
      zn[3] = Expression();
      t = jj_consume_token(RBR);
                zn[4] = new SyntaxTreeNode(mn, t);
    } else {
      ;
    }
    epa();
    if ( expr != null ) {  // no extra (), FairnessHook can't be null ** Add check.
      if (FairnessHook == null) {
        {if (true) throw new ParseException("Ill-structured fairness expression at line " + zn[0].location[0] + ", column " + zn[0].location[1]);}
      }

      SyntaxTreeNode parameters[] = (SyntaxTreeNode[]) FairnessHook.heirs();
      if ( parameters != null && parameters.length == 3) { // was FairnessHook
        zn[1] = expr;
        zn[2] = parameters[0];
        zn[3] = parameters[1];
        zn[4] = parameters[2];
      } else {
        PErrors.push( new ParseError("Error in fairness expression at " + zn[0].location[0] + ": " + zn[0].location[1] + "\n", "-- --") );
        {if (true) return expr;}
      }
// left for level checking.
//      if ( expr.isKind( N_ActionExpr ) ) {
//        PErrors.push( new ParseError("Error in fairness expression at " + zn[0].location[0] + ": " + zn[0].location[1] + ": use of an action form\n", "-- --") );
//        return expr;
//      }
    } else { // reattach FairnessHook ! unless it is tuple
// "GeneralId", "RecordComponent", "FcnAppl",
      if ( zn[1].isKind( N_GeneralId ) &&  FairnessHook != null ) {
        SyntaxTreeNode ozn[] = new SyntaxTreeNode[2];
        ozn[0] = zn[1];
        ozn[1] = FairnessHook;
        zn[1] = new SyntaxTreeNode( mn, N_OpApplication, ozn );
      } else if ( ! (zn[1].isKind( N_Tuple )|| zn[1].isKind( N_ParenExpr ) || zn[1].isKind( N_SetEnumerate )|| zn[1].isKind( N_SubsetOf )|| zn[1].isKind( N_SetOfAll )|| zn[1].isKind( N_SetOfFcns )|| zn[1].isKind( N_RcdConstructor )|| zn[1].isKind( N_SetOfRcds )|| zn[1].isKind( N_Except )|| zn[1].isKind( N_FcnConst )|| zn[1].isKind( N_ActionExpr )) ){
// "ParenExpr", "SetEnumerate", "SubsetOf", "SetOfAll", "FcnConst",
// "SetOfFcns", "RcdConstructor", "SetOfRcds", "Except",
// "Tuple", "ActionExpr"
        PErrors.push( new ParseError("Error in fairness expression at " + zn[0].location[0] + ": " + zn[0].location[1] + ": could not link arguments\n", "-- --") );
        {if (true) return zn[1];}
      }
    }
    {if (true) return new SyntaxTreeNode( mn, N_FairnessExpr, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode IfThenElse() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[6];
  Token t;
  bpa("IF THEN ELSE");
    t = jj_consume_token(IF);
               zn[0] = new SyntaxTreeNode(mn, t);
    zn[1] = Expression();
    t = jj_consume_token(THEN);
               zn[2] =  new SyntaxTreeNode(mn, t);
    zn[3] = Expression();
    t = jj_consume_token(ELSE);
               zn[4] =  new SyntaxTreeNode(mn, t);
    zn[5] = Expression();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_IfThenElse, zn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Case() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("CASE Expression");
    t = jj_consume_token(CASE);
               addHeir( new SyntaxTreeNode(mn, t) );
    tn = CaseArm();
                   addHeir( tn );
    label_44:
    while (true) {
      if (caseSep() && (getToken(2).kind != OTHER)) {
        ;
      } else {
        break label_44;
      }
      t = jj_consume_token(CASESEP);
                    addHeir( new SyntaxTreeNode(mn, t) );
      tn = CaseArm();
                     addHeir( tn );
    }
    if (caseSep()) {
      t = jj_consume_token(CASESEP);
                    addHeir( new SyntaxTreeNode(mn, t) );
      tn = OtherArm();
                      addHeir( tn );
    } else {
      ;
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_Case, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode CaseArm() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  Token t;
  bpa("Case Arm");
    zn[0] = Expression();
    t = jj_consume_token(ARROW);
                zn[1] = new SyntaxTreeNode(mn, t);
    zn[2] = Expression();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_CaseArm, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode OtherArm() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[3];
  Token t;
  bpa("Case Other Arm");
    t = jj_consume_token(OTHER);
                zn[0] = new SyntaxTreeNode(mn, t);
    t = jj_consume_token(ARROW);
                zn[1] = new SyntaxTreeNode(mn, t);
    zn[2] = Expression();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_OtherArm, zn );}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* LetIn ::= <LET> LetDefinitions() <LETIN> Expression()                    *
*                                                                          *
* It produces a SyntaxTreeNode tn with the four heirs                      *
*    "LET", LetDefinitions, "IN", Expression                               *
* in tn.zero.                                                              *
***************************************************************************/
  final public SyntaxTreeNode LetIn() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[4];
  SyntaxTreeNode tn;
  Token t;
  bpa("Case Other Arm");
    t = jj_consume_token(LET);
              zn[0] = new SyntaxTreeNode(mn, t);
    zn[1] = LetDefinitions();
    t = jj_consume_token(LETIN);
                zn[2] = new SyntaxTreeNode(mn, t);
    zn[3] = Expression();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_LetIn, zn );}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode LetDefinitions() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Let Definitions");
    label_45:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LOCAL:
      case DEFBREAK:
        tn = OperatorOrFunctionDefinition();
                                            addHeir( tn );
        break;
      case RECURSIVE:
        tn = Recursive();
                         addHeir( tn );
        break;
      default:
        jj_la1[124] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LOCAL:
      case RECURSIVE:
      case DEFBREAK:
        ;
        break;
      default:
        jj_la1[125] = jj_gen;
        break label_45;
      }
    }
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode(mn, N_LetDefinitions, sn);}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode Junctions() throws ParseException {
  BStack.newReference(getToken(1).endColumn, getToken(1).kind);
    /***********************************************************************
    * Pushes onto BStack an element of the appropriate kind with offest    *
    * equal to the column of the last character in the /\ or \/ token.     *
    ***********************************************************************/

  bpa("AND-OR Junction");
  int kind;
    if (jj_2_55(2147483647)) {
                                      kind = N_DisjList;
      DisjList();
    } else if (jj_2_56(2147483647)) {
                                       kind = N_ConjList;
      ConjList();
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
    BStack.popReference();
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, kind, sn);}
    throw new Error("Missing return statement in function");
  }

  final public void DisjList() throws ParseException {
  SyntaxTreeNode tn;
    tn = JuncItem(N_DisjItem);
    addHeir(tn);
    label_46:
    while (true) {
      if (BStack.onReference( getToken(1).endColumn, getToken(1).kind )) {
        ;
      } else {
        break label_46;
      }
      tn = JuncItem(N_DisjItem);
                                 addHeir(tn);
    }
  }

  final public void ConjList() throws ParseException {
  SyntaxTreeNode tn;
    tn = JuncItem(N_ConjItem);
    addHeir( tn );
    label_47:
    while (true) {
      if (BStack.onReference( getToken(1).endColumn, getToken(1).kind )) {
        ;
      } else {
        break label_47;
      }
      tn = JuncItem(N_ConjItem);
                                 addHeir( tn );
    }
  }

  final public SyntaxTreeNode JuncItem(int itemKind) throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[2];
  SyntaxTreeNode tn;
  Token t;
  bpa("Junction Item");
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case OR:
      /* t = <BOR> | */ t = jj_consume_token(OR);
      break;
    case AND:
      t = jj_consume_token(AND);
      break;
    default:
      jj_la1[126] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    zn[0] = new SyntaxTreeNode(mn, t);
    zn[1] = Expression();
    epa();
    /***********************************************************************
    * Check for indentation errors.                                        *
    ***********************************************************************/
    tn = new SyntaxTreeNode( mn, itemKind, zn );
    TreeNode[] children = tn.heirs() ;
    for (int i = 1; i < children.length; i++) {
      checkIndentation((SyntaxTreeNode) children[i], tn) ;
     };
    {if (true) return tn ;}
    throw new Error("Missing return statement in function");
  }

  final public SyntaxTreeNode UnboundOrBoundChoose() throws ParseException {
  SyntaxTreeNode zn[] = new SyntaxTreeNode[5];
  SyntaxTreeNode tn;
  Token t;
  bpa("(Un)Bounded Choose");
    t = jj_consume_token(CHOOSE);
                 zn[0] = new SyntaxTreeNode(mn, t);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case IDENTIFIER:
      zn[1] = Identifier();
      break;
    case LAB:
      zn[1] = IdentifierTuple();
      break;
    default:
      jj_la1[127] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    zn[2] = MaybeBound();
    t = jj_consume_token(COLON);
                zn[3] = new SyntaxTreeNode(mn, t);
    zn[4] = Expression();
    SyntaxTreeNode sn[] = getLastHeirs();
    epa(); {if (true) return new SyntaxTreeNode( mn, N_UnboundOrBoundChoose, zn);}
    throw new Error("Missing return statement in function");
  }

/***************************************************************************
* Lambda expression added by LL on 27 March 2007                           *
*                                                                          *
* L.Lambda ::=                                                             *
*   <LAMBDA>                                                               *
*   (IdentDecl | SomeFixDecl) (<COMMA> (IdentDecl | SomeFixDecl))*         *
*   <COLON> Expression                                                     *
***************************************************************************/
  final public SyntaxTreeNode Lambda() throws ParseException {
  SyntaxTreeNode tn;
  Token t;
  bpa("Lambda");
    t = jj_consume_token(LAMBDA);
                   addHeir(new SyntaxTreeNode(mn, t));
                   expecting = "Identifier";
    tn = Identifier();
                         addHeir( tn );
                                                 expecting = "`,' or `:'";
    label_48:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case COMMA:
        ;
        break;
      default:
        jj_la1[128] = jj_gen;
        break label_48;
      }
      t = jj_consume_token(COMMA);
                     addHeir( new SyntaxTreeNode(mn, t) );
                     expecting = "Identifier";
      tn = Identifier();
                               addHeir( tn );
                               expecting = "`,' or `:'";
    }
    t = jj_consume_token(COLON);
                  addHeir( new SyntaxTreeNode(mn, t) );
                  expecting = "Expression";
    tn = Expression();
                       addHeir(tn);
                       SyntaxTreeNode sn[] = getLastHeirs();
                       epa();
                       {if (true) return new SyntaxTreeNode( mn, N_Lambda, sn);}
    throw new Error("Missing return statement in function");
  }

// boxDisc (riminate) uses preInEmptyTop
// note that junction is processed separately.
  final public SyntaxTreeNode Expression() throws ParseException {
  SyntaxTreeNode tn, tn0, tn1, tn2;
  int kind ;
  Token t;
  bpa("Expression");
  OperatorStack.newStack();
    label_49:
    while (true) {
      if (jj_2_57(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
        ;
      } else {
        break label_49;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
        tn = PrefixOp();
                      kind = N_GenPrefixOp;
        break;
      case op_1:
      case AND:
      case op_3:
      case op_4:
      case OR:
      case op_6:
      case op_7:
      case op_8:
      case op_9:
      case op_10:
      case op_11:
      case op_12:
      case op_13:
      case op_14:
      case op_15:
      case op_16:
      case op_17:
      case op_18:
      case op_19:
      case IN:
      case op_21:
      case op_22:
      case op_23:
      case op_24:
      case op_25:
      case op_27:
      case op_30:
      case op_31:
      case op_32:
      case op_33:
      case op_34:
      case op_35:
      case op_36:
      case op_37:
      case op_38:
      case op_39:
      case op_40:
      case op_41:
      case op_42:
      case op_43:
      case op_44:
      case op_45:
      case op_46:
      case op_47:
      case op_48:
      case op_49:
      case op_50:
      case op_51:
      case op_52:
      case op_53:
      case op_54:
      case op_55:
      case op_56:
      case op_59:
      case op_62:
      case op_63:
      case op_64:
      case EQUALS:
      case op_66:
      case op_67:
      case op_71:
      case op_72:
      case op_73:
      case op_74:
      case op_75:
      case op_77:
      case op_78:
      case op_79:
      case op_80:
      case op_81:
      case op_82:
      case op_83:
      case op_84:
      case op_85:
      case op_86:
      case op_87:
      case op_88:
      case op_89:
      case op_90:
      case op_91:
      case op_92:
      case op_93:
      case op_94:
      case op_95:
      case op_96:
      case op_97:
      case op_98:
      case op_100:
      case op_101:
      case op_102:
      case op_103:
      case op_104:
      case op_105:
      case op_106:
      case op_107:
      case op_108:
      case op_109:
      case op_110:
      case op_111:
      case op_117:
      case op_118:
      case op_119:
        tn = InfixOp();
                      kind = N_GenInfixOp;
        break;
      default:
        jj_la1[129] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
     SyntaxTreeNode[] heirs = new SyntaxTreeNode[2];
     heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, (SyntaxTreeNode []) null);
     heirs[1] = tn ;
     OperatorStack.pushOnStack(new SyntaxTreeNode(mn, kind, heirs), lastOp);
     if (OperatorStack.size() != 1) {OperatorStack.reduceStack();} ;
          /*****************************************************************
          * This is probably a no-op since we can't reduce the stack at    *
          * this point.                                                    *
          *****************************************************************/

    }
    if (jj_2_58(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
      tn = OpenExpression();
                          OperatorStack.pushOnStack( tn, null );
    } else if (BStack.aboveReference( getToken(1).beginColumn)) {
      ExtendableExpr();
    } else {
      jj_consume_token(-1);
      throw new ParseException();
    }
  epa();
  tn = OperatorStack.finalReduce();
   if (tn==null) {
     {if (true) throw new ParseException(" Couldn't reduce expression stack.");}
    } ;
   OperatorStack.popStack();
   {if (true) return tn ;}
    throw new Error("Missing return statement in function");
  }

  // Expression
  final public void ExtendableExpr() throws ParseException {
  SyntaxTreeNode tn, tn0, tn1, tn2;
  SyntaxTreeNode[] heirs;
  int kind ;
  Token t;
  bpa("ExtendableExpr") ;
    if (jj_2_59(2147483647) && (OperatorStack.preInEmptyTop()
               // && BStack.aboveReference( getToken(1).beginColumn) 
    )) {
      tn = Junctions();
                      OperatorStack.pushOnStack( tn, null );
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case SF:
      case WF:
      case LBR:
      case LSB:
      case LWB:
      case LBC:
      case LAB:
        /************************************************************************
           * ParenthesesExpression                                                 *
           ************************************************************************/
           tn = ParenthesesExpression();
                                  OperatorStack.pushOnStack( tn, null );
        break;
      default:
        jj_la1[130] = jj_gen;
        if (jj_2_60(1)) {
          /************************************************************************
             * PrimitiveExpression                                                 *
             ************************************************************************/
             tn = PrimitiveExp();
                         OperatorStack.pushOnStack( tn, null );
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    }
    label_50:
    while (true) {
      if (jj_2_61(1)) {
        ;
      } else {
        break label_50;
      }
      if (jj_2_62(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
        tn = PostfixOp();
       heirs = new SyntaxTreeNode[2];
       heirs[0] =
         new SyntaxTreeNode( mn, N_IdPrefix, (SyntaxTreeNode []) null);
       heirs[1] = tn ;
       OperatorStack.pushOnStack(new SyntaxTreeNode(mn, N_GenPostfixOp, heirs),
                                 lastOp);
       if (OperatorStack.size() != 1) {OperatorStack.reduceStack();} ;
      } else if (jj_2_63(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
        t = jj_consume_token(DOT);
       Token next = getToken(1);
       if (isFieldNameToken( next )) next.kind = IDENTIFIER;
        if (BStack.aboveReference( getToken(1).beginColumn)) {

        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
        tn = Identifier();
         OperatorStack.reduceRecord(  new SyntaxTreeNode(mn, t) , tn );
      } else if (jj_2_64(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
    expecting = "function argument";
        tn = SBracketCases();
      if ( isGenOp( tn ) ) {
        /*******************************************************************
        * In the normal case, tn will be an N_FcnAppl node and             *
        * isGenOp(tn) will be true.  In an error case, isGenOp(tn) should  *
        * be false, and whatever is returned will presumably not be an     *
        * operator and pushing it on the stack will produce an error       *
        * because the stack will have two expressions with no intervening  *
        * infix operator.                                                  *
        *******************************************************************/
        OperatorStack.pushOnStack( tn, lastOp );
        if (OperatorStack.size() != 1) {OperatorStack.reduceStack();} ;
       }
      else {OperatorStack.pushOnStack( tn, null );};
      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    if (jj_2_69(1)) {
      if (jj_2_67(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
        tn = InfixOp();
     heirs = new SyntaxTreeNode[2];
     heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, (SyntaxTreeNode []) null);
     heirs[1] = tn ;
     OperatorStack.pushOnStack(new SyntaxTreeNode(mn, N_GenInfixOp, heirs),
                               lastOp);
     if (OperatorStack.size() != 1) {OperatorStack.reduceStack();} ;
        label_51:
        while (true) {
          if (jj_2_65(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
            ;
          } else {
            break label_51;
          }
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case op_26:
          case op_29:
          case op_58:
          case CASESEP:
          case op_61:
          case op_112:
          case op_113:
          case op_114:
          case op_115:
          case op_116:
            tn = PrefixOp();
                        kind = N_GenPrefixOp;
            break;
          case op_1:
          case AND:
          case op_3:
          case op_4:
          case OR:
          case op_6:
          case op_7:
          case op_8:
          case op_9:
          case op_10:
          case op_11:
          case op_12:
          case op_13:
          case op_14:
          case op_15:
          case op_16:
          case op_17:
          case op_18:
          case op_19:
          case IN:
          case op_21:
          case op_22:
          case op_23:
          case op_24:
          case op_25:
          case op_27:
          case op_30:
          case op_31:
          case op_32:
          case op_33:
          case op_34:
          case op_35:
          case op_36:
          case op_37:
          case op_38:
          case op_39:
          case op_40:
          case op_41:
          case op_42:
          case op_43:
          case op_44:
          case op_45:
          case op_46:
          case op_47:
          case op_48:
          case op_49:
          case op_50:
          case op_51:
          case op_52:
          case op_53:
          case op_54:
          case op_55:
          case op_56:
          case op_59:
          case op_62:
          case op_63:
          case op_64:
          case EQUALS:
          case op_66:
          case op_67:
          case op_71:
          case op_72:
          case op_73:
          case op_74:
          case op_75:
          case op_77:
          case op_78:
          case op_79:
          case op_80:
          case op_81:
          case op_82:
          case op_83:
          case op_84:
          case op_85:
          case op_86:
          case op_87:
          case op_88:
          case op_89:
          case op_90:
          case op_91:
          case op_92:
          case op_93:
          case op_94:
          case op_95:
          case op_96:
          case op_97:
          case op_98:
          case op_100:
          case op_101:
          case op_102:
          case op_103:
          case op_104:
          case op_105:
          case op_106:
          case op_107:
          case op_108:
          case op_109:
          case op_110:
          case op_111:
          case op_117:
          case op_118:
          case op_119:
            tn = InfixOp();
                        kind = N_GenInfixOp;
            break;
          default:
            jj_la1[131] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
      heirs = new SyntaxTreeNode[2];
      heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix, (SyntaxTreeNode []) null);
      heirs[1] = tn ;
      OperatorStack.pushOnStack(new SyntaxTreeNode(mn, kind, heirs), lastOp);
      if (OperatorStack.size() != 1) {OperatorStack.reduceStack();} ;
          /*****************************************************************
          * This is probably a no-op since we can't reduce the stack at    *
          * this point.                                                    *
          *****************************************************************/

        }
        if (jj_2_66(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
          tn = OpenExpression();
                            OperatorStack.pushOnStack( tn, null );
        } else if (BStack.aboveReference( getToken(1).beginColumn)) {
          ExtendableExpr();
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      } else if (jj_2_68(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
        t = jj_consume_token(COLONCOLON);
     tn1 = new SyntaxTreeNode(mn, t) ;
     tn0 = OperatorStack.topOfStack().getNode();
     if (! isLabel(tn0)) {
       {if (true) throw new ParseException("`::' at " + tn1.getLocation().toString()
                                 + " does not follow a label.") ;}
      } ;
     OperatorStack.popCurrentTop() ;
        // t = <COLONCOLON>
          tn2 = Expression();
      if (! labelDoesNotChangeParse(tn2, lastOp)) {
        /*****************************************************************
        * Note: if tn1 is a prefix, infix, or postfix expression, then   *
        * I believe (perhaps naively) that lastOp will be its operator.  *
        *****************************************************************/
        {if (true) throw new ParseException(
          "Removing label at " + tn0.getLocation().toString() +
          " would change expression parsing.") ;}
       } ;
      SyntaxTreeNode labelHeirs[] = {tn0, tn1, tn2} ;
      tn = new SyntaxTreeNode(N_Label, labelHeirs) ;
      OperatorStack.pushOnStack( tn, null );
      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }
    } else {
      ;
    }
   epa() ;
  }

  // ExtendableExpr
  final public SyntaxTreeNode PrimitiveExp() throws ParseException {
  SyntaxTreeNode tn, tn0, tn1, tn2;
  SyntaxTreeNode tnOpArgs = null ;
  SyntaxTreeNode tnBangs[] = null ;
  SyntaxTreeNode[] heirs ;
  Token t;
  bpa("Primitive expression") ;
    if (jj_2_72(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
      tn = String();
    } else if (jj_2_73(2147483647) && (BStack.aboveReference( getToken(1).beginColumn))) {
      tn = Number();
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case op_57:
      case op_68:
      case op_69:
      case op_70:
      case op_76:
      case op_26:
      case op_29:
      case op_58:
      case CASESEP:
      case op_61:
      case op_112:
      case op_113:
      case op_114:
      case op_115:
      case op_116:
      case op_1:
      case AND:
      case op_3:
      case op_4:
      case OR:
      case op_6:
      case op_7:
      case op_8:
      case op_9:
      case op_10:
      case op_11:
      case op_12:
      case op_13:
      case op_14:
      case op_15:
      case op_16:
      case op_17:
      case op_18:
      case op_19:
      case IN:
      case op_21:
      case op_22:
      case op_23:
      case op_24:
      case op_25:
      case op_27:
      case op_30:
      case op_31:
      case op_32:
      case op_33:
      case op_34:
      case op_35:
      case op_36:
      case op_37:
      case op_38:
      case op_39:
      case op_40:
      case op_41:
      case op_42:
      case op_43:
      case op_44:
      case op_45:
      case op_46:
      case op_47:
      case op_48:
      case op_49:
      case op_50:
      case op_51:
      case op_52:
      case op_53:
      case op_54:
      case op_55:
      case op_56:
      case op_59:
      case op_62:
      case op_63:
      case op_64:
      case EQUALS:
      case op_66:
      case op_67:
      case op_71:
      case op_72:
      case op_73:
      case op_74:
      case op_75:
      case op_77:
      case op_78:
      case op_79:
      case op_80:
      case op_81:
      case op_82:
      case op_83:
      case op_84:
      case op_85:
      case op_86:
      case op_87:
      case op_88:
      case op_89:
      case op_90:
      case op_91:
      case op_92:
      case op_93:
      case op_94:
      case op_95:
      case op_96:
      case op_97:
      case op_98:
      case op_100:
      case op_101:
      case op_102:
      case op_103:
      case op_104:
      case op_105:
      case op_106:
      case op_107:
      case op_108:
      case op_109:
      case op_110:
      case op_111:
      case op_117:
      case op_118:
      case op_119:
      case IDENTIFIER:
      case ProofStepLexeme:
      case ProofImplicitStepLexeme:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case IDENTIFIER:
          tn0 = Identifier();
          break;
        case ProofStepLexeme:
        case ProofImplicitStepLexeme:
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case ProofStepLexeme:
            t = jj_consume_token(ProofStepLexeme);
            break;
          case ProofImplicitStepLexeme:
            t = jj_consume_token(ProofImplicitStepLexeme);
            break;
          default:
            jj_la1[132] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
                  tn0 = new SyntaxTreeNode(mn, t);
                  if ((getProofLevel() < 0) && (proofDepth <= 0)) {
                    {if (true) throw new
                      ParseException(tn0.getLocation().toString() +
                           ": Step number used outside proof.");}
                    } ;
                  if (t.image.substring(1,2).equals("+")) {
                    {if (true) throw new ParseException(tn0.getLocation().toString() +
                           ": <+> step number used in an expression.");}
                    } ;
                  if (t.kind == ProofImplicitStepLexeme) {
                    tn0.originalImage = tn0.image ;
                    tn0.image = correctedStepNum(t) ;
                   } ;

// ToolIO.out.println("xyz-expr: t.image = " + t.image + 
// ", correctedImage = " + tn0.image) ;

          break;
        case op_1:
        case AND:
        case op_3:
        case op_4:
        case OR:
        case op_6:
        case op_7:
        case op_8:
        case op_9:
        case op_10:
        case op_11:
        case op_12:
        case op_13:
        case op_14:
        case op_15:
        case op_16:
        case op_17:
        case op_18:
        case op_19:
        case IN:
        case op_21:
        case op_22:
        case op_23:
        case op_24:
        case op_25:
        case op_27:
        case op_30:
        case op_31:
        case op_32:
        case op_33:
        case op_34:
        case op_35:
        case op_36:
        case op_37:
        case op_38:
        case op_39:
        case op_40:
        case op_41:
        case op_42:
        case op_43:
        case op_44:
        case op_45:
        case op_46:
        case op_47:
        case op_48:
        case op_49:
        case op_50:
        case op_51:
        case op_52:
        case op_53:
        case op_54:
        case op_55:
        case op_56:
        case op_59:
        case op_62:
        case op_63:
        case op_64:
        case EQUALS:
        case op_66:
        case op_67:
        case op_71:
        case op_72:
        case op_73:
        case op_74:
        case op_75:
        case op_77:
        case op_78:
        case op_79:
        case op_80:
        case op_81:
        case op_82:
        case op_83:
        case op_84:
        case op_85:
        case op_86:
        case op_87:
        case op_88:
        case op_89:
        case op_90:
        case op_91:
        case op_92:
        case op_93:
        case op_94:
        case op_95:
        case op_96:
        case op_97:
        case op_98:
        case op_100:
        case op_101:
        case op_102:
        case op_103:
        case op_104:
        case op_105:
        case op_106:
        case op_107:
        case op_108:
        case op_109:
        case op_110:
        case op_111:
        case op_117:
        case op_118:
        case op_119:
          tn0 = InfixOp();
          break;
        case op_57:
        case op_68:
        case op_69:
        case op_70:
          tn0 = PostfixOp();
          break;
        default:
          jj_la1[133] = jj_gen;
          if (jj_2_70(2147483647)) {
            tn0 = NonExpPrefixOp();
          } else {
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
        if (jj_2_71(2)) {
          tnOpArgs = OpArgs();
        } else {
          ;
        }
        label_52:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case BANG:
            ;
            break;
          default:
            jj_la1[134] = jj_gen;
            break label_52;
          }
          tn1 = BangExt();
                          addHeir(tn1) ;
        }
        tnBangs = getLastHeirs() ;
        if (tnBangs == null) {
          heirs = new SyntaxTreeNode[2];
          heirs[0] = new SyntaxTreeNode( mn, N_IdPrefix,
                                         new SyntaxTreeNode[0]);
          heirs[1] = tn0;
          tn1 = new SyntaxTreeNode(mn, N_GeneralId, heirs) ;
          if (tnOpArgs == null) {tn = tn1;}
          else { heirs    = new SyntaxTreeNode[2];
                 heirs[0] = tn1 ;
                 heirs[1] = tnOpArgs ;
                 tn = new SyntaxTreeNode(mn, N_OpApplication, heirs) ;
           }
         } // if (tnBangs == null)
        else {
         /******************************************************************
         * There is a BangExt.  The parse tree constructed so far needs    *
         * to be rearranged to be what is expected of the parser           *
         * (because the parser was designed for TLA+1).  For example, if   *
         * we're parsing                                                   *
         *                                                                 *
         *   foo(1)!b!c(2,3), so far we have                               *
         *   tn0 = foo                                                     *
         *   tnOpArgs = OpArgs[1]                                          *
         *   tnBangs = IdPrefixElement[! b]                                *
         *             IdPrefixElement[! c OpArgs[2, 3]]                   *
         *                                                                 *
         * and we must turn that into                                      *
         *                                                                 *
         *   OpAppl[ GeneralId[ IdPrefix[IdPrefixElement[foo OpArgs[1] !]  *
         *                               IdPrefixElement[b !]]             *
         *                      c]                                         *
         *           OpArgs[2, 3]]                                         *
         *                                                                 *
         * Note that the result is an OpAppl node iff the last             *
         * IdPrefixElement contains an OpArg heir, otherwise it is a       *
         * GeneralId node.                                                 *
         ******************************************************************/

         /******************************************************************
         * We set heirs to the array of IdPrefixElement nodes that are     *
         * the heirs of the IdPrefix node that is the first heir of the    *
         * GeneralId node.                                                 *
         ******************************************************************/
         heirs = new SyntaxTreeNode[tnBangs.length] ;

         /******************************************************************
         * Set eltHeirs to the heirs of heirs[0].                          *
         ******************************************************************/
         SyntaxTreeNode[] eltHeirs;
         if (tnOpArgs == null) {
            eltHeirs = new SyntaxTreeNode[2] ;
            eltHeirs[0] = tn0 ;
            eltHeirs[1] = (SyntaxTreeNode) tnBangs[0].heirs()[0] ;
          }
         else {
            eltHeirs = new SyntaxTreeNode[3] ;
            eltHeirs[0] = tn0 ;
            eltHeirs[1] = tnOpArgs;
            eltHeirs[2] = (SyntaxTreeNode) tnBangs[0].heirs()[0] ;
          } ;
         heirs[0] =
           new SyntaxTreeNode(mn, N_IdPrefixElement, eltHeirs);
         for (int i = 0; i < tnBangs.length - 1; i++) {
           eltHeirs =
              new SyntaxTreeNode[tnBangs[i].heirs().length] ;
           for (int j = 0 ; j < eltHeirs.length-1; j++) {
             eltHeirs[j] = (SyntaxTreeNode) tnBangs[i].heirs()[j+1];
             } ;
           eltHeirs[eltHeirs.length-1] = (SyntaxTreeNode)
                                            tnBangs[i+1].heirs()[0];
           heirs[i+1] = new SyntaxTreeNode(mn, N_IdPrefixElement, eltHeirs);
          } // for
         TreeNode[] lastBang = tnBangs[tnBangs.length-1].heirs() ;
         SyntaxTreeNode[] genIdHeirs = new SyntaxTreeNode[2] ;
         genIdHeirs[0] = new SyntaxTreeNode(mn, N_IdPrefix, heirs) ;
         genIdHeirs[1] = (SyntaxTreeNode) lastBang[1];
         SyntaxTreeNode genId =
             new SyntaxTreeNode(mn, N_GeneralId, genIdHeirs) ;
         if (lastBang.length == 2) {tn = genId;}
         else { heirs = new SyntaxTreeNode[2] ;
                heirs[0] = genId ;
                heirs[1] = (SyntaxTreeNode) lastBang[2] ;
                tn = new SyntaxTreeNode(mn, N_OpApplication, heirs) ;
          } // else       
      } // else

        break;
      default:
        jj_la1[135] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    epa() ;
    {if (true) return tn;}
    throw new Error("Missing return statement in function");
  }

  // PrimitiveExp
  final public SyntaxTreeNode BangExt() throws ParseException {
  /*************************************************************************
  * Returns an N_IdPrefixElement node with 2 or 3 heirs consisting of:     *
  *  - A "!" (<BANG>) token.                                               *
  *  - An Identifier(), PrefixOp(), InfixOp(), or PostfixOp() node.        *
  *  - An optional OpArgs() node.                                          *
  * Note that this is not the kind of N_IdPrefixElement that the parser    *
  * ultimately produces, which ends with a "!" rather than beginning with  *
  * one.                                                                   *
  *************************************************************************/
  SyntaxTreeNode tn ;
  Token t;
  bpa("Bang Extension") ;
    t = jj_consume_token(BANG);
                addHeir(new SyntaxTreeNode(mn, t)) ;
    if (jj_2_76(1)) {
      if (jj_2_74(2147483647) && (!getToken(1).image.equals("@"))) {
        tn = Identifier();
      } else {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case op_76:
        case op_26:
        case op_29:
        case op_58:
        case CASESEP:
        case op_61:
        case op_112:
        case op_113:
        case op_114:
        case op_115:
        case op_116:
          tn = NonExpPrefixOp();
          break;
        case op_1:
        case AND:
        case op_3:
        case op_4:
        case OR:
        case op_6:
        case op_7:
        case op_8:
        case op_9:
        case op_10:
        case op_11:
        case op_12:
        case op_13:
        case op_14:
        case op_15:
        case op_16:
        case op_17:
        case op_18:
        case op_19:
        case IN:
        case op_21:
        case op_22:
        case op_23:
        case op_24:
        case op_25:
        case op_27:
        case op_30:
        case op_31:
        case op_32:
        case op_33:
        case op_34:
        case op_35:
        case op_36:
        case op_37:
        case op_38:
        case op_39:
        case op_40:
        case op_41:
        case op_42:
        case op_43:
        case op_44:
        case op_45:
        case op_46:
        case op_47:
        case op_48:
        case op_49:
        case op_50:
        case op_51:
        case op_52:
        case op_53:
        case op_54:
        case op_55:
        case op_56:
        case op_59:
        case op_62:
        case op_63:
        case op_64:
        case EQUALS:
        case op_66:
        case op_67:
        case op_71:
        case op_72:
        case op_73:
        case op_74:
        case op_75:
        case op_77:
        case op_78:
        case op_79:
        case op_80:
        case op_81:
        case op_82:
        case op_83:
        case op_84:
        case op_85:
        case op_86:
        case op_87:
        case op_88:
        case op_89:
        case op_90:
        case op_91:
        case op_92:
        case op_93:
        case op_94:
        case op_95:
        case op_96:
        case op_97:
        case op_98:
        case op_100:
        case op_101:
        case op_102:
        case op_103:
        case op_104:
        case op_105:
        case op_106:
        case op_107:
        case op_108:
        case op_109:
        case op_110:
        case op_111:
        case op_117:
        case op_118:
        case op_119:
          tn = InfixOp();
          break;
        case op_57:
        case op_68:
        case op_69:
        case op_70:
          tn = PostfixOp();
          break;
        default:
          jj_la1[136] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
      addHeir(tn);
      if (jj_2_75(2)) {
        tn = OpArgs();
                      addHeir(tn) ;
      } else {
        ;
      }
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case LBR:
        tn = OpArgs();
                      addHeir(tn) ;
        break;
      default:
        jj_la1[137] = jj_gen;
        if (jj_2_77(1)) {
          tn = StructOp();
                      addHeir(tn) ;
        } else {
          jj_consume_token(-1);
          throw new ParseException();
        }
      }
    }
    tn = new SyntaxTreeNode(mn, N_IdPrefixElement, getLastHeirs());
    epa();
    {if (true) return tn ;}
    throw new Error("Missing return statement in function");
  }

  // BangExt
  final public SyntaxTreeNode StructOp() throws ParseException {
  SyntaxTreeNode tn = null ;
  Token t = null;
  bpa("StructOp");
  expecting = "`<<' , `>>' , `:' , `@' , or number" ;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LAB:
      t = jj_consume_token(LAB);
      break;
    case RAB:
      t = jj_consume_token(RAB);
      break;
    case COLON:
      t = jj_consume_token(COLON);
      break;
    case NUMBER_LITERAL:
      tn = Number();
      break;
    default:
      jj_la1[138] = jj_gen;
      if (getToken(1).image.equals("@")) {
        t = jj_consume_token(IDENTIFIER);
      } else {
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
   epa() ;
   if (tn == null){{if (true) return new SyntaxTreeNode(mn, N_StructOp, t) ;} }
     else { if (tn.getKind() == N_Real) {
              {if (true) throw new ParseException(
                         "Illegal structural term at " +
                          tn.getLocation().toString());}
             };
           SyntaxTreeNode[] heirs = new SyntaxTreeNode[1] ;
           heirs[0] = tn;
           {if (true) return new SyntaxTreeNode(mn, N_StructOp, heirs) ;} } ;
    throw new Error("Missing return statement in function");
  }

// SyntaxTreeNode
// oldExpression() : {
//   /*************************************************************************
//   * The basic production is                                                *
//   *                                                                        *
//   *    Expression ::= (  OpenExpression                                    *
//   *                     | (Junctions                                       *
//   *                         | ClosedExpressionOrOp                         *
//   *                         | <DOT> Identifier                             *
//   *                         | <COLONCOLON> Expression                      *
//   *                        )+                                              *
//   *                        ( OpenExpression )?                             *
//   *                   )                                                    *
//   *************************************************************************/
//   SyntaxTreeNode tn, tn0, tn1, tn2;
//   Token t;
//   OperatorStack.newStack();
// } { 
// ( 
//  LOOKAHEAD(OpenStart(), {BStack.aboveReference( getToken(1).beginColumn) } )
//    tn = OpenExpression() { OperatorStack.pushOnStack( tn, null ); }
// |   (  LOOKAHEAD( /* <BAND> | <BOR> | */ <AND> | <OR>, 
// // ^^^ 
// // Warning 4 -- Eliminated in SANY2
//          { OperatorStack.preInEmptyTop() && 
//            BStack.aboveReference( getToken(1).beginColumn) } )
//        tn = Junctions() { OperatorStack.pushOnStack( tn, null ); }
//      | LOOKAHEAD( {    ClosedStart(getToken(1)) 
//                    && boxDisc()  
//                         /***************************************************
//                        * \equiv                                            *
//                        *   (token is "[]" => it's the temporal operator)   *
//                         ***************************************************/
//                    && BStack.aboveReference( 
//                                 getToken(1).beginColumn) })
//        tn = ClosedExpressionOrOp() {
//           anchor = tn; // XXX is this correct ? Why had it disappered ? 
//                        // This is the only place where anchor is set it seems.
//           /*****************************************************************
//           * If tn is an operator, push it on the stack and, if it's not    *
//           * the only thing on the stack, then reduce the stack.            *
//           * Otherwise, just push it on the stack.                          *
//           *****************************************************************/
//           if ( isGenOp( tn ) ) {
//             OperatorStack.pushOnStack( tn, lastOp );
//             if (OperatorStack.size() != 1)
//               OperatorStack.reduceStack();
// // else
// // ToolIO.out.println("size of 1");
//           } else OperatorStack.pushOnStack( tn, null );
//         }
//      | 
//        t = <DOT> { 
//         Token next = getToken(1);
//         if (isFieldNameToken( next )) next.kind = IDENTIFIER;
//        }
//        tn = Identifier()
//        { OperatorStack.reduceRecord(  new SyntaxTreeNode(mn, t) , tn ); }
//      |
//        t = <COLONCOLON> {
//         tn1 = new SyntaxTreeNode(mn, t) ;
//         tn0 = OperatorStack.topOfStack().getNode();
//         if (! isLabel(tn0)) {
//           throw new ParseException("`::' at " + tn1.getLocation().toString()
//                                     + " does not follow a label.") ;
//          } ;
//         OperatorStack.popCurrentTop() ;
//        } // t = <COLONCOLON>
//        tn2 = Expression() {
// // String str = "null" ;
// // if (lastOp != null) { str = lastOp.toString(); } ;
// // ToolIO.out.println("lastOp after parsing labeled expression is: " + str);
//         if (! labelDoesNotChangeParse(tn2, lastOp)) {
//           /*****************************************************************
//           * Note: if tn1 is a prefix, infix, or postfix expression, then   *
//           * I believe (perhaps naively) that lastOp will be its operator.  *
//           *****************************************************************/
//           throw new ParseException(
//              "Removing label at " + tn0.getLocation().toString() +
//              " would change expression parsing.") ;
//           } ;
//         SyntaxTreeNode labelHeirs[] = {tn0, tn1, tn2} ;
//         tn = new SyntaxTreeNode(N_Label, labelHeirs) ;
//         OperatorStack.pushOnStack( tn, null );
//       }
//   )+
//   [ LOOKAHEAD( OpenStart(), {BStack.aboveReference( getToken(1).beginColumn) } )
//     tn = OpenExpression() { OperatorStack.pushOnStack( tn, null ); } ]
// )
//  { tn = OperatorStack.finalReduce();
//    if (tn==null) throw new ParseException( " Couldn't reduce expression stack.");
//    OperatorStack.popStack();
//    return tn; }
// } // Expression()

/* Obsolete
void
ClosedStart() : {
}{
  <IDENTIFIER> | <STRING_LITERAL> | <NUMBER_LITERAL> | <LBR> | <LSB> | <LAB> | <LBC> | <LWB> | <OpSymbol> | <OR> | <AND> | <WF> | <SF>
}
*/
  final public void OpenStart() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case CASE:
      jj_consume_token(CASE);
      break;
    case CHOOSE:
      jj_consume_token(CHOOSE);
      break;
    case EXISTS:
      jj_consume_token(EXISTS);
      break;
    case FORALL:
      jj_consume_token(FORALL);
      break;
    case IF:
      jj_consume_token(IF);
      break;
    case LET:
      jj_consume_token(LET);
      break;
    case T_EXISTS:
      jj_consume_token(T_EXISTS);
      break;
    case T_FORALL:
      jj_consume_token(T_FORALL);
      break;
    default:
      jj_la1[139] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final private boolean jj_2_1(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_1(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(0, xla); }
  }

  final private boolean jj_2_2(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_2(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(1, xla); }
  }

  final private boolean jj_2_3(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_3(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(2, xla); }
  }

  final private boolean jj_2_4(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_4(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(3, xla); }
  }

  final private boolean jj_2_5(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_5(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(4, xla); }
  }

  final private boolean jj_2_6(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_6(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(5, xla); }
  }

  final private boolean jj_2_7(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_7(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(6, xla); }
  }

  final private boolean jj_2_8(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_8(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(7, xla); }
  }

  final private boolean jj_2_9(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_9(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(8, xla); }
  }

  final private boolean jj_2_10(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_10(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(9, xla); }
  }

  final private boolean jj_2_11(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_11(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(10, xla); }
  }

  final private boolean jj_2_12(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_12(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(11, xla); }
  }

  final private boolean jj_2_13(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_13(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(12, xla); }
  }

  final private boolean jj_2_14(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_14(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(13, xla); }
  }

  final private boolean jj_2_15(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_15(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(14, xla); }
  }

  final private boolean jj_2_16(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_16(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(15, xla); }
  }

  final private boolean jj_2_17(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_17(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(16, xla); }
  }

  final private boolean jj_2_18(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_18(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(17, xla); }
  }

  final private boolean jj_2_19(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_19(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(18, xla); }
  }

  final private boolean jj_2_20(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_20(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(19, xla); }
  }

  final private boolean jj_2_21(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_21(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(20, xla); }
  }

  final private boolean jj_2_22(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_22(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(21, xla); }
  }

  final private boolean jj_2_23(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_23(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(22, xla); }
  }

  final private boolean jj_2_24(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_24(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(23, xla); }
  }

  final private boolean jj_2_25(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_25(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(24, xla); }
  }

  final private boolean jj_2_26(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_26(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(25, xla); }
  }

  final private boolean jj_2_27(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_27(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(26, xla); }
  }

  final private boolean jj_2_28(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_28(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(27, xla); }
  }

  final private boolean jj_2_29(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_29(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(28, xla); }
  }

  final private boolean jj_2_30(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_30(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(29, xla); }
  }

  final private boolean jj_2_31(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_31(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(30, xla); }
  }

  final private boolean jj_2_32(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_32(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(31, xla); }
  }

  final private boolean jj_2_33(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_33(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(32, xla); }
  }

  final private boolean jj_2_34(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_34(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(33, xla); }
  }

  final private boolean jj_2_35(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_35(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(34, xla); }
  }

  final private boolean jj_2_36(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_36(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(35, xla); }
  }

  final private boolean jj_2_37(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_37(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(36, xla); }
  }

  final private boolean jj_2_38(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_38(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(37, xla); }
  }

  final private boolean jj_2_39(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_39(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(38, xla); }
  }

  final private boolean jj_2_40(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_40(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(39, xla); }
  }

  final private boolean jj_2_41(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_41(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(40, xla); }
  }

  final private boolean jj_2_42(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_42(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(41, xla); }
  }

  final private boolean jj_2_43(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_43(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(42, xla); }
  }

  final private boolean jj_2_44(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_44(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(43, xla); }
  }

  final private boolean jj_2_45(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_45(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(44, xla); }
  }

  final private boolean jj_2_46(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_46(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(45, xla); }
  }

  final private boolean jj_2_47(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_47(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(46, xla); }
  }

  final private boolean jj_2_48(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_48(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(47, xla); }
  }

  final private boolean jj_2_49(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_49(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(48, xla); }
  }

  final private boolean jj_2_50(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_50(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(49, xla); }
  }

  final private boolean jj_2_51(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_51(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(50, xla); }
  }

  final private boolean jj_2_52(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_52(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(51, xla); }
  }

  final private boolean jj_2_53(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_53(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(52, xla); }
  }

  final private boolean jj_2_54(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_54(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(53, xla); }
  }

  final private boolean jj_2_55(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_55(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(54, xla); }
  }

  final private boolean jj_2_56(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_56(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(55, xla); }
  }

  final private boolean jj_2_57(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_57(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(56, xla); }
  }

  final private boolean jj_2_58(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_58(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(57, xla); }
  }

  final private boolean jj_2_59(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_59(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(58, xla); }
  }

  final private boolean jj_2_60(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_60(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(59, xla); }
  }

  final private boolean jj_2_61(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_61(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(60, xla); }
  }

  final private boolean jj_2_62(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_62(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(61, xla); }
  }

  final private boolean jj_2_63(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_63(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(62, xla); }
  }

  final private boolean jj_2_64(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_64(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(63, xla); }
  }

  final private boolean jj_2_65(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_65(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(64, xla); }
  }

  final private boolean jj_2_66(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_66(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(65, xla); }
  }

  final private boolean jj_2_67(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_67(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(66, xla); }
  }

  final private boolean jj_2_68(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_68(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(67, xla); }
  }

  final private boolean jj_2_69(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_69(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(68, xla); }
  }

  final private boolean jj_2_70(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_70(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(69, xla); }
  }

  final private boolean jj_2_71(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_71(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(70, xla); }
  }

  final private boolean jj_2_72(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_72(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(71, xla); }
  }

  final private boolean jj_2_73(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_73(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(72, xla); }
  }

  final private boolean jj_2_74(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_74(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(73, xla); }
  }

  final private boolean jj_2_75(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_75(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(74, xla); }
  }

  final private boolean jj_2_76(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_76(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(75, xla); }
  }

  final private boolean jj_2_77(int xla) {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_77(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(76, xla); }
  }

  final private boolean jj_3R_92() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_147()) {
    jj_scanpos = xsp;
    if (jj_3R_148()) return true;
    }
    if (jj_scan_token(IN)) return true;
    if (jj_3R_63()) return true;
    xsp = jj_scanpos;
    if (jj_3R_291()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3_48() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = matchFcnConst();
    lookingAhead = false;
    if (!jj_semLA || jj_3R_92()) {
    jj_scanpos = xsp;
    if (jj_3R_93()) {
    jj_scanpos = xsp;
    if (jj_3R_94()) {
    jj_scanpos = xsp;
    if (jj_3_47()) return true;
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_104() {
    if (jj_3R_65()) return true;
    return false;
  }

  final private boolean jj_3R_218() {
    if (jj_scan_token(LBC)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_48()) jj_scanpos = xsp;
    if (jj_scan_token(RBC)) return true;
    return false;
  }

  final private boolean jj_3R_105() {
    if (jj_3R_104()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_259()) { jj_scanpos = xsp; break; }
    }
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_260()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_261()) return true;
    }
    return false;
  }

  final private boolean jj_3_69() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_105()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_106()) return true;
    }
    return false;
  }

  final private boolean jj_3R_155() {
    if (jj_3R_145()) return true;
    return false;
  }

  final private boolean jj_3_64() {
    if (jj_scan_token(LSB)) return true;
    return false;
  }

  final private boolean jj_3R_182() {
    if (jj_3R_150()) return true;
    return false;
  }

  final private boolean jj_3R_65() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(129)) {
    jj_scanpos = xsp;
    if (jj_scan_token(130)) {
    jj_scanpos = xsp;
    if (jj_scan_token(131)) {
    jj_scanpos = xsp;
    if (jj_scan_token(132)) {
    jj_scanpos = xsp;
    if (jj_scan_token(133)) {
    jj_scanpos = xsp;
    if (jj_scan_token(134)) {
    jj_scanpos = xsp;
    if (jj_scan_token(135)) {
    jj_scanpos = xsp;
    if (jj_scan_token(136)) {
    jj_scanpos = xsp;
    if (jj_scan_token(137)) {
    jj_scanpos = xsp;
    if (jj_scan_token(138)) {
    jj_scanpos = xsp;
    if (jj_scan_token(139)) {
    jj_scanpos = xsp;
    if (jj_scan_token(140)) {
    jj_scanpos = xsp;
    if (jj_scan_token(141)) {
    jj_scanpos = xsp;
    if (jj_scan_token(142)) {
    jj_scanpos = xsp;
    if (jj_scan_token(143)) {
    jj_scanpos = xsp;
    if (jj_scan_token(144)) {
    jj_scanpos = xsp;
    if (jj_scan_token(145)) {
    jj_scanpos = xsp;
    if (jj_scan_token(146)) {
    jj_scanpos = xsp;
    if (jj_scan_token(147)) {
    jj_scanpos = xsp;
    if (jj_scan_token(148)) {
    jj_scanpos = xsp;
    if (jj_scan_token(149)) {
    jj_scanpos = xsp;
    if (jj_scan_token(150)) {
    jj_scanpos = xsp;
    if (jj_scan_token(151)) {
    jj_scanpos = xsp;
    if (jj_scan_token(152)) {
    jj_scanpos = xsp;
    if (jj_scan_token(153)) {
    jj_scanpos = xsp;
    if (jj_scan_token(154)) {
    jj_scanpos = xsp;
    if (jj_scan_token(155)) {
    jj_scanpos = xsp;
    if (jj_scan_token(156)) {
    jj_scanpos = xsp;
    if (jj_scan_token(157)) {
    jj_scanpos = xsp;
    if (jj_scan_token(158)) {
    jj_scanpos = xsp;
    if (jj_scan_token(159)) {
    jj_scanpos = xsp;
    if (jj_scan_token(160)) {
    jj_scanpos = xsp;
    if (jj_scan_token(161)) {
    jj_scanpos = xsp;
    if (jj_scan_token(162)) {
    jj_scanpos = xsp;
    if (jj_scan_token(163)) {
    jj_scanpos = xsp;
    if (jj_scan_token(164)) {
    jj_scanpos = xsp;
    if (jj_scan_token(165)) {
    jj_scanpos = xsp;
    if (jj_scan_token(166)) {
    jj_scanpos = xsp;
    if (jj_scan_token(167)) {
    jj_scanpos = xsp;
    if (jj_scan_token(168)) {
    jj_scanpos = xsp;
    if (jj_scan_token(169)) {
    jj_scanpos = xsp;
    if (jj_scan_token(170)) {
    jj_scanpos = xsp;
    if (jj_scan_token(171)) {
    jj_scanpos = xsp;
    if (jj_scan_token(172)) {
    jj_scanpos = xsp;
    if (jj_scan_token(173)) {
    jj_scanpos = xsp;
    if (jj_scan_token(174)) {
    jj_scanpos = xsp;
    if (jj_scan_token(175)) {
    jj_scanpos = xsp;
    if (jj_scan_token(176)) {
    jj_scanpos = xsp;
    if (jj_scan_token(177)) {
    jj_scanpos = xsp;
    if (jj_scan_token(178)) {
    jj_scanpos = xsp;
    if (jj_scan_token(179)) {
    jj_scanpos = xsp;
    if (jj_scan_token(180)) {
    jj_scanpos = xsp;
    if (jj_scan_token(181)) {
    jj_scanpos = xsp;
    if (jj_scan_token(182)) {
    jj_scanpos = xsp;
    if (jj_scan_token(183)) {
    jj_scanpos = xsp;
    if (jj_scan_token(184)) {
    jj_scanpos = xsp;
    if (jj_scan_token(185)) {
    jj_scanpos = xsp;
    if (jj_scan_token(186)) {
    jj_scanpos = xsp;
    if (jj_scan_token(187)) {
    jj_scanpos = xsp;
    if (jj_scan_token(188)) {
    jj_scanpos = xsp;
    if (jj_scan_token(189)) {
    jj_scanpos = xsp;
    if (jj_scan_token(190)) {
    jj_scanpos = xsp;
    if (jj_scan_token(191)) {
    jj_scanpos = xsp;
    if (jj_scan_token(192)) {
    jj_scanpos = xsp;
    if (jj_scan_token(193)) {
    jj_scanpos = xsp;
    if (jj_scan_token(194)) {
    jj_scanpos = xsp;
    if (jj_scan_token(195)) {
    jj_scanpos = xsp;
    if (jj_scan_token(196)) {
    jj_scanpos = xsp;
    if (jj_scan_token(197)) {
    jj_scanpos = xsp;
    if (jj_scan_token(198)) {
    jj_scanpos = xsp;
    if (jj_scan_token(199)) {
    jj_scanpos = xsp;
    if (jj_scan_token(200)) {
    jj_scanpos = xsp;
    if (jj_scan_token(201)) {
    jj_scanpos = xsp;
    if (jj_scan_token(202)) {
    jj_scanpos = xsp;
    if (jj_scan_token(203)) {
    jj_scanpos = xsp;
    if (jj_scan_token(204)) {
    jj_scanpos = xsp;
    if (jj_scan_token(205)) {
    jj_scanpos = xsp;
    if (jj_scan_token(206)) {
    jj_scanpos = xsp;
    if (jj_scan_token(207)) {
    jj_scanpos = xsp;
    if (jj_scan_token(208)) {
    jj_scanpos = xsp;
    if (jj_scan_token(209)) {
    jj_scanpos = xsp;
    if (jj_scan_token(210)) {
    jj_scanpos = xsp;
    if (jj_scan_token(211)) {
    jj_scanpos = xsp;
    if (jj_scan_token(212)) {
    jj_scanpos = xsp;
    if (jj_scan_token(213)) {
    jj_scanpos = xsp;
    if (jj_scan_token(214)) {
    jj_scanpos = xsp;
    if (jj_scan_token(215)) {
    jj_scanpos = xsp;
    if (jj_scan_token(216)) {
    jj_scanpos = xsp;
    if (jj_scan_token(217)) {
    jj_scanpos = xsp;
    if (jj_scan_token(218)) {
    jj_scanpos = xsp;
    if (jj_scan_token(219)) {
    jj_scanpos = xsp;
    if (jj_scan_token(220)) {
    jj_scanpos = xsp;
    if (jj_scan_token(221)) {
    jj_scanpos = xsp;
    if (jj_scan_token(222)) {
    jj_scanpos = xsp;
    if (jj_scan_token(223)) {
    jj_scanpos = xsp;
    if (jj_scan_token(224)) {
    jj_scanpos = xsp;
    if (jj_scan_token(225)) {
    jj_scanpos = xsp;
    if (jj_scan_token(226)) {
    jj_scanpos = xsp;
    if (jj_scan_token(227)) {
    jj_scanpos = xsp;
    if (jj_scan_token(228)) {
    jj_scanpos = xsp;
    if (jj_scan_token(229)) {
    jj_scanpos = xsp;
    if (jj_scan_token(230)) return true;
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_280() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3_63() {
    if (jj_scan_token(DOT)) return true;
    return false;
  }

  final private boolean jj_3R_143() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_scan_token(IDENTIFIER)) return true;
    return false;
  }

  final private boolean jj_3R_101() {
    if (jj_3R_154()) return true;
    return false;
  }

  final private boolean jj_3R_258() {
    return false;
  }

  final private boolean jj_3R_234() {
    if (jj_3R_67()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_280()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_233() {
    if (jj_3R_146()) return true;
    return false;
  }

  final private boolean jj_3_62() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_230() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_233()) {
    jj_scanpos = xsp;
    if (jj_3R_234()) return true;
    }
    if (jj_scan_token(IN)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_100() {
    if (jj_scan_token(DOT)) return true;
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_258()) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3_13() {
    if (jj_scan_token(op_76)) return true;
    return false;
  }

  final private boolean jj_3R_145() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(119)) {
    jj_scanpos = xsp;
    if (jj_scan_token(120)) {
    jj_scanpos = xsp;
    if (jj_scan_token(121)) {
    jj_scanpos = xsp;
    if (jj_scan_token(122)) {
    jj_scanpos = xsp;
    if (jj_scan_token(123)) {
    jj_scanpos = xsp;
    if (jj_scan_token(118)) {
    jj_scanpos = xsp;
    if (jj_scan_token(124)) {
    jj_scanpos = xsp;
    if (jj_scan_token(125)) {
    jj_scanpos = xsp;
    if (jj_scan_token(126)) {
    jj_scanpos = xsp;
    if (jj_scan_token(127)) {
    jj_scanpos = xsp;
    if (jj_scan_token(128)) return true;
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_83() {
    if (jj_scan_token(IDENTIFIER)) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_143()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(IN)) return true;
    return false;
  }

  final private boolean jj_3_36() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_83()) {
    jj_scanpos = xsp;
    if (jj_scan_token(103)) return true;
    }
    return false;
  }

  final private boolean jj_3_14() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_99() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3_61() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_99()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_100()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_101()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3_60() {
    if (jj_3R_98()) return true;
    return false;
  }

  final private boolean jj_3R_254() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_89() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_scan_token(IDENTIFIER)) return true;
    return false;
  }

  final private boolean jj_3R_190() {
    if (jj_3R_202()) return true;
    return false;
  }

  final private boolean jj_3_59() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(130)) {
    jj_scanpos = xsp;
    if (jj_scan_token(133)) return true;
    }
    return false;
  }

  final private boolean jj_3R_196() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(59)) {
    jj_scanpos = xsp;
    if (jj_scan_token(60)) return true;
    }
    if (jj_3R_67()) return true;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_254()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_189() {
    if (jj_3R_201()) return true;
    return false;
  }

  final private boolean jj_3R_150() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(119)) {
    jj_scanpos = xsp;
    if (jj_scan_token(120)) {
    jj_scanpos = xsp;
    if (jj_scan_token(121)) {
    jj_scanpos = xsp;
    if (jj_scan_token(122)) {
    jj_scanpos = xsp;
    if (jj_scan_token(123)) {
    jj_scanpos = xsp;
    if (jj_scan_token(124)) {
    jj_scanpos = xsp;
    if (jj_scan_token(125)) {
    jj_scanpos = xsp;
    if (jj_scan_token(126)) {
    jj_scanpos = xsp;
    if (jj_scan_token(127)) {
    jj_scanpos = xsp;
    if (jj_scan_token(128)) return true;
    }
    }
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_263() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_230()) return true;
    return false;
  }

  final private boolean jj_3_44() {
    if (jj_scan_token(IDENTIFIER)) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_89()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(COLON)) return true;
    return false;
  }

  final private boolean jj_3R_169() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = OperatorStack.preInEmptyTop();
    lookingAhead = false;
    if (!jj_semLA || jj_3R_189()) {
    jj_scanpos = xsp;
    if (jj_3R_190()) {
    jj_scanpos = xsp;
    if (jj_3_60()) return true;
    }
    }
    while (true) {
      xsp = jj_scanpos;
      if (jj_3_61()) { jj_scanpos = xsp; break; }
    }
    xsp = jj_scanpos;
    if (jj_3_69()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_262() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_224() {
    if (jj_3R_230()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_263()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_223() {
    if (jj_3R_67()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_262()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_195() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(46)) {
    jj_scanpos = xsp;
    if (jj_scan_token(48)) return true;
    }
    xsp = jj_scanpos;
    if (jj_3R_223()) {
    jj_scanpos = xsp;
    if (jj_3R_224()) return true;
    }
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_58() {
    if (jj_3R_97()) return true;
    return false;
  }

  final private boolean jj_3R_128() {
    if (jj_3R_169()) return true;
    return false;
  }

  final private boolean jj_3R_127() {
    if (jj_3R_168()) return true;
    return false;
  }

  final private boolean jj_3_35() {
    if (jj_3R_59()) return true;
    return false;
  }

  final private boolean jj_3R_217() {
    if (jj_scan_token(LBR)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3R_132() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_131() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_130() {
    if (jj_3R_155()) return true;
    return false;
  }

  final private boolean jj_3R_96() {
    if (jj_3R_150()) return true;
    return false;
  }

  final private boolean jj_3_57() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_96()) {
    jj_scanpos = xsp;
    if (jj_scan_token(194)) return true;
    }
    return false;
  }

  final private boolean jj_3R_129() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_167() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_66() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_129()) {
    jj_scanpos = xsp;
    if (jj_3R_130()) {
    jj_scanpos = xsp;
    if (jj_3R_131()) {
    jj_scanpos = xsp;
    if (jj_3R_132()) return true;
    }
    }
    }
    if (jj_scan_token(SUBSTITUTE)) return true;
    if (jj_3R_174()) return true;
    return false;
  }

  final private boolean jj_3R_166() {
    if (jj_3R_182()) return true;
    return false;
  }

  final private boolean jj_3R_126() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_166()) {
    jj_scanpos = xsp;
    if (jj_3R_167()) return true;
    }
    return false;
  }

  final private boolean jj_3R_63() {
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_126()) { jj_scanpos = xsp; break; }
    }
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_127()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_128()) return true;
    }
    return false;
  }

  final private boolean jj_3_34() {
    if (jj_3R_82()) return true;
    return false;
  }

  final private boolean jj_3R_229() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3_12() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_66()) return true;
    return false;
  }

  final private boolean jj_3R_206() {
    if (jj_scan_token(LAMBDA)) return true;
    if (jj_3R_67()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_229()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_318() {
    if (jj_scan_token(WITH)) return true;
    if (jj_3R_66()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3_12()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_88() {
    if (jj_3R_64()) return true;
    return false;
  }

  final private boolean jj_3R_125() {
    if (jj_scan_token(INSTANCE)) return true;
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_318()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_149() {
    if (jj_3R_174()) return true;
    return false;
  }

  final private boolean jj_3R_228() {
    if (jj_3R_146()) return true;
    return false;
  }

  final private boolean jj_3R_227() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_124() {
    if (jj_scan_token(LOCAL)) return true;
    return false;
  }

  final private boolean jj_3R_200() {
    if (jj_scan_token(CHOOSE)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_227()) {
    jj_scanpos = xsp;
    if (jj_3R_228()) return true;
    }
    if (jj_3R_257()) return true;
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_60() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_124()) jj_scanpos = xsp;
    if (jj_3R_125()) return true;
    return false;
  }

  final private boolean jj_3R_87() {
    if (jj_3R_65()) return true;
    return false;
  }

  final private boolean jj_3_42() {
    if (jj_scan_token(LAMBDA)) return true;
    return false;
  }

  final private boolean jj_3_43() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_139() {
    if (jj_3R_140()) return true;
    return false;
  }

  final private boolean jj_3R_324() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_194() {
    if (jj_3R_206()) return true;
    return false;
  }

  final private boolean jj_3R_205() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_323() {
    if (jj_3R_104()) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3R_86() {
    if (jj_3R_145()) return true;
    return false;
  }

  final private boolean jj_3_41() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_86()) {
    jj_scanpos = xsp;
    if (jj_3R_87()) {
    jj_scanpos = xsp;
    if (jj_3R_88()) return true;
    }
    }
    xsp = jj_scanpos;
    if (jj_scan_token(87)) {
    jj_scanpos = xsp;
    if (jj_scan_token(94)) {
    jj_scanpos = xsp;
    if (jj_scan_token(95)) {
    jj_scanpos = xsp;
    if (jj_scan_token(53)) {
    jj_scanpos = xsp;
    if (jj_scan_token(50)) {
    jj_scanpos = xsp;
    if (jj_scan_token(66)) {
    jj_scanpos = xsp;
    if (jj_scan_token(38)) {
    jj_scanpos = xsp;
    if (jj_scan_token(36)) {
    jj_scanpos = xsp;
    if (jj_scan_token(35)) {
    jj_scanpos = xsp;
    if (jj_scan_token(34)) {
    jj_scanpos = xsp;
    if (jj_scan_token(40)) {
    jj_scanpos = xsp;
    if (jj_scan_token(43)) {
    jj_scanpos = xsp;
    if (jj_scan_token(84)) {
    jj_scanpos = xsp;
    if (jj_scan_token(78)) return true;
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_222() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(133)) {
    jj_scanpos = xsp;
    if (jj_scan_token(130)) return true;
    }
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_204() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_203() {
    if (jj_3R_155()) return true;
    return false;
  }

  final private boolean jj_3R_171() {
    if (jj_scan_token(US)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_323()) {
    jj_scanpos = xsp;
    if (jj_3R_324()) return true;
    }
    return false;
  }

  final private boolean jj_3R_170() {
    if (jj_3R_155()) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3_56() {
    if (jj_scan_token(AND)) return true;
    return false;
  }

  final private boolean jj_3R_269() {
    if (jj_3R_222()) return true;
    return false;
  }

  final private boolean jj_3R_193() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_203()) {
    jj_scanpos = xsp;
    if (jj_3R_204()) {
    jj_scanpos = xsp;
    if (jj_3R_205()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_134() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_170()) {
    jj_scanpos = xsp;
    if (jj_3R_171()) return true;
    }
    return false;
  }

  final private boolean jj_3_55() {
    if (jj_scan_token(OR)) return true;
    return false;
  }

  final private boolean jj_3R_174() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_193()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_194()) {
    jj_scanpos = xsp;
    if (jj_3_43()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_216() {
    if (jj_3R_222()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_269()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_268() {
    if (jj_3R_222()) return true;
    return false;
  }

  final private boolean jj_3R_215() {
    if (jj_3R_222()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_268()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_322() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3R_208() {
    if (jj_3R_216()) return true;
    return false;
  }

  final private boolean jj_3R_133() {
    if (jj_scan_token(LBR)) return true;
    if (jj_scan_token(US)) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_322()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3R_207() {
    if (jj_3R_215()) return true;
    return false;
  }

  final private boolean jj_3R_201() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_207()) {
    jj_scanpos = xsp;
    if (jj_3R_208()) return true;
    }
    return false;
  }

  final private boolean jj_3R_68() {
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_133()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_80() {
    if (jj_3R_140()) return true;
    return false;
  }

  final private boolean jj_3R_162() {
    if (jj_3R_67()) return true;
    if (jj_3R_64()) return true;
    return false;
  }

  final private boolean jj_3R_236() {
    if (jj_3R_115()) return true;
    return false;
  }

  final private boolean jj_3R_235() {
    if (jj_3R_59()) return true;
    return false;
  }

  final private boolean jj_3R_231() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_235()) {
    jj_scanpos = xsp;
    if (jj_3R_236()) return true;
    }
    return false;
  }

  final private boolean jj_3R_226() {
    Token xsp;
    if (jj_3R_231()) return true;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_231()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_140() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(232)) {
    jj_scanpos = xsp;
    if (jj_scan_token(233)) {
    jj_scanpos = xsp;
    if (jj_scan_token(234)) {
    jj_scanpos = xsp;
    if (jj_scan_token(235)) {
    jj_scanpos = xsp;
    if (jj_scan_token(236)) return true;
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_163() {
    if (jj_3R_67()) return true;
    if (jj_3R_65()) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_321() {
    if (jj_3R_134()) return true;
    return false;
  }

  final private boolean jj_3R_199() {
    if (jj_scan_token(LET)) return true;
    if (jj_3R_226()) return true;
    if (jj_scan_token(LETIN)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_316() {
    if (jj_3R_134()) return true;
    return false;
  }

  final private boolean jj_3_33() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_165() {
    if (jj_3R_145()) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3_32() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_320() {
    if (jj_3R_68()) return true;
    return false;
  }

  final private boolean jj_3R_317() {
    if (jj_scan_token(COMMA)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_320()) {
    jj_scanpos = xsp;
    if (jj_3R_321()) return true;
    }
    return false;
  }

  final private boolean jj_3R_264() {
    if (jj_scan_token(OTHER)) return true;
    if (jj_scan_token(ARROW)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_315() {
    if (jj_3R_68()) return true;
    return false;
  }

  final private boolean jj_3_30() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_309() {
    if (jj_scan_token(LBR)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_315()) {
    jj_scanpos = xsp;
    if (jj_3R_316()) return true;
    }
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_317()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3R_225() {
    if (jj_3R_63()) return true;
    if (jj_scan_token(ARROW)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_164() {
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_309()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3_29() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_81() {
    if (jj_scan_token(MODULE)) return true;
    return false;
  }

  final private boolean jj_3R_191() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_149()) return true;
    return false;
  }

  final private boolean jj_3_31() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_81()) {
    jj_scanpos = xsp;
    if (jj_3_29()) return true;
    }
    return false;
  }

  final private boolean jj_3R_95() {
    if (jj_scan_token(LBR)) return true;
    if (jj_3R_149()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_191()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3R_256() {
    if (jj_scan_token(CASESEP)) return true;
    if (jj_3R_264()) return true;
    return false;
  }

  final private boolean jj_3R_161() {
    if (jj_scan_token(HIDE)) return true;
    return false;
  }

  final private boolean jj_3R_192() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_255() {
    if (jj_scan_token(CASESEP)) return true;
    if (jj_3R_225()) return true;
    return false;
  }

  final private boolean jj_3R_160() {
    if (jj_scan_token(USE)) return true;
    return false;
  }

  final private boolean jj_3R_173() {
    if (jj_3R_67()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_192()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_198() {
    if (jj_scan_token(CASE)) return true;
    if (jj_3R_225()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_255()) { jj_scanpos = xsp; break; }
    }
    xsp = jj_scanpos;
    if (jj_3R_256()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_181() {
    if (jj_scan_token(PROOF)) return true;
    return false;
  }

  final private boolean jj_3R_159() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_181()) jj_scanpos = xsp;
    if (jj_scan_token(BY)) return true;
    return false;
  }

  final private boolean jj_3R_146() {
    if (jj_scan_token(LAB)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_173()) jj_scanpos = xsp;
    if (jj_scan_token(RAB)) return true;
    return false;
  }

  final private boolean jj_3R_117() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_159()) {
    jj_scanpos = xsp;
    if (jj_3R_160()) {
    jj_scanpos = xsp;
    if (jj_3R_161()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_197() {
    if (jj_scan_token(IF)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(THEN)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(ELSE)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_11() {
    if (jj_scan_token(IDENTIFIER)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(93)) {
    jj_scanpos = xsp;
    if (jj_scan_token(92)) return true;
    }
    return false;
  }

  final private boolean jj_3R_299() {
    if (jj_3R_125()) return true;
    return false;
  }

  final private boolean jj_3_7() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_123() {
    if (jj_3R_165()) return true;
    if (jj_scan_token(DEF)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_10() {
    if (jj_scan_token(IDENTIFIER)) return true;
    if (jj_3R_65()) return true;
    return false;
  }

  final private boolean jj_3R_122() {
    if (jj_3R_164()) return true;
    if (jj_scan_token(DEF)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_7()) {
    jj_scanpos = xsp;
    if (jj_3R_299()) return true;
    }
    return false;
  }

  final private boolean jj_3_9() {
    if (jj_scan_token(IDENTIFIER)) return true;
    if (jj_3R_64()) return true;
    return false;
  }

  final private boolean jj_3R_79() {
    if (jj_3R_139()) return true;
    return false;
  }

  final private boolean jj_3_26() {
    if (jj_scan_token(PROOF)) return true;
    return false;
  }

  final private boolean jj_3R_121() {
    if (jj_3R_163()) return true;
    if (jj_scan_token(DEF)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_28() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_26()) jj_scanpos = xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_79()) { jj_scanpos = xsp; break; }
    }
    if (jj_3R_80()) return true;
    return false;
  }

  final private boolean jj_3R_120() {
    if (jj_3R_162()) return true;
    if (jj_scan_token(DEF)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_27() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(74)) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(70)) {
    jj_scanpos = xsp;
    if (jj_scan_token(71)) return true;
    }
    return false;
  }

  final private boolean jj_3R_298() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_230()) return true;
    return false;
  }

  final private boolean jj_3_8() {
    if (jj_scan_token(IDENTIFIER)) return true;
    if (jj_scan_token(LSB)) return true;
    return false;
  }

  final private boolean jj_3_54() {
    if (jj_scan_token(LBR)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3R_119() {
    if (jj_3R_67()) return true;
    if (jj_scan_token(LSB)) return true;
    if (jj_3R_230()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_298()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    if (jj_scan_token(DEF)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_118() {
    if (jj_scan_token(LOCAL)) return true;
    return false;
  }

  final private boolean jj_3R_221() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(85)) {
    jj_scanpos = xsp;
    if (jj_scan_token(58)) return true;
    }
    if (jj_3R_243()) return true;
    xsp = jj_scanpos;
    if (jj_3_54()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_59() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_118()) jj_scanpos = xsp;
    if (jj_scan_token(DEFBREAK)) return true;
    xsp = jj_scanpos;
    if (jj_3R_119()) {
    jj_scanpos = xsp;
    if (jj_3R_120()) {
    jj_scanpos = xsp;
    if (jj_3R_121()) {
    jj_scanpos = xsp;
    if (jj_3R_122()) {
    jj_scanpos = xsp;
    if (jj_3R_123()) return true;
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_97() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(41)) {
    jj_scanpos = xsp;
    if (jj_scan_token(42)) {
    jj_scanpos = xsp;
    if (jj_scan_token(46)) {
    jj_scanpos = xsp;
    if (jj_scan_token(48)) {
    jj_scanpos = xsp;
    if (jj_scan_token(49)) {
    jj_scanpos = xsp;
    if (jj_scan_token(51)) {
    jj_scanpos = xsp;
    if (jj_scan_token(59)) {
    jj_scanpos = xsp;
    if (jj_scan_token(60)) return true;
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_252() {
    if (jj_3R_220()) return true;
    return false;
  }

  final private boolean jj_3_40() {
    if (jj_scan_token(DOT)) return true;
    if (jj_scan_token(NUMBER_LITERAL)) return true;
    return false;
  }

  final private boolean jj_3R_251() {
    if (jj_3R_219()) return true;
    return false;
  }

  final private boolean jj_3R_250() {
    if (jj_3R_154()) return true;
    return false;
  }

  final private boolean jj_3R_249() {
    if (jj_3R_218()) return true;
    return false;
  }

  final private boolean jj_3R_185() {
    if (jj_3R_197()) return true;
    return false;
  }

  final private boolean jj_3R_175() {
    if (jj_scan_token(NUMBER_LITERAL)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_40()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_248() {
    if (jj_3R_217()) return true;
    return false;
  }

  final private boolean jj_3R_247() {
    if (jj_3R_253()) return true;
    return false;
  }

  final private boolean jj_3R_311() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_243() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_247()) {
    jj_scanpos = xsp;
    if (jj_3R_248()) {
    jj_scanpos = xsp;
    if (jj_3R_249()) {
    jj_scanpos = xsp;
    if (jj_3R_250()) {
    jj_scanpos = xsp;
    if (jj_3R_251()) {
    jj_scanpos = xsp;
    if (jj_3R_252()) return true;
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_310() {
    if (jj_3R_104()) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3R_188() {
    if (jj_3R_200()) return true;
    return false;
  }

  final private boolean jj_3R_107() {
    if (jj_scan_token(STRING_LITERAL)) return true;
    return false;
  }

  final private boolean jj_3R_302() {
    if (jj_scan_token(US)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_310()) {
    jj_scanpos = xsp;
    if (jj_3R_311()) return true;
    }
    return false;
  }

  final private boolean jj_3R_301() {
    if (jj_3R_155()) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3R_184() {
    if (jj_3R_196()) return true;
    return false;
  }

  final private boolean jj_3R_319() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_scan_token(US)) return true;
    return false;
  }

  final private boolean jj_3R_187() {
    if (jj_3R_199()) return true;
    return false;
  }

  final private boolean jj_3R_214() {
    if (jj_3R_221()) return true;
    return false;
  }

  final private boolean jj_3R_211() {
    if (jj_3R_154()) return true;
    return false;
  }

  final private boolean jj_3R_308() {
    if (jj_scan_token(BANG)) return true;
    if (jj_3R_253()) return true;
    return false;
  }

  final private boolean jj_3R_186() {
    if (jj_3R_198()) return true;
    return false;
  }

  final private boolean jj_3R_183() {
    if (jj_3R_195()) return true;
    return false;
  }

  final private boolean jj_3R_168() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_183()) {
    jj_scanpos = xsp;
    if (jj_3R_184()) {
    jj_scanpos = xsp;
    if (jj_3R_185()) {
    jj_scanpos = xsp;
    if (jj_3R_186()) {
    jj_scanpos = xsp;
    if (jj_3R_187()) {
    jj_scanpos = xsp;
    if (jj_3R_188()) return true;
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3_6() {
    if (jj_scan_token(LBR)) return true;
    if (jj_scan_token(US)) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_319()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RBR)) return true;
    return false;
  }

  final private boolean jj_3_53() {
    if (jj_3R_95()) return true;
    return false;
  }

  final private boolean jj_3R_253() {
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_53()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_3R_308()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_300() {
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_6()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_289() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_300()) {
    jj_scanpos = xsp;
    if (jj_3R_301()) {
    jj_scanpos = xsp;
    if (jj_3R_302()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_213() {
    if (jj_3R_220()) return true;
    return false;
  }

  final private boolean jj_3_25() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_210() {
    if (jj_3R_218()) return true;
    return false;
  }

  final private boolean jj_3R_77() {
    return false;
  }

  final private boolean jj_3_24() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME;
    lookingAhead = false;
    if (!jj_semLA || jj_3R_77()) return true;
    if (jj_3R_78()) return true;
    return false;
  }

  final private boolean jj_3R_242() {
    if (jj_scan_token(ARAB)) return true;
    if (jj_3R_243()) return true;
    return false;
  }

  final private boolean jj_3R_241() {
    if (jj_scan_token(RAB)) return true;
    return false;
  }

  final private boolean jj_3R_284() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_23() {
    if (jj_3R_67()) return true;
    if (jj_scan_token(DEF)) return true;
    return false;
  }

  final private boolean jj_3R_290() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_289()) return true;
    return false;
  }

  final private boolean jj_3_52() {
    if (jj_3R_63()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_284()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_62() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(66)) {
    jj_scanpos = xsp;
    if (jj_scan_token(57)) return true;
    }
    xsp = jj_scanpos;
    if (jj_3_23()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_3_24()) {
    jj_scanpos = xsp;
    if (jj_3_25()) return true;
    }
    return false;
  }

  final private boolean jj_3R_220() {
    if (jj_scan_token(LAB)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_52()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_3R_241()) {
    jj_scanpos = xsp;
    if (jj_3R_242()) return true;
    }
    return false;
  }

  final private boolean jj_3R_212() {
    if (jj_3R_219()) return true;
    return false;
  }

  final private boolean jj_3R_115() {
    if (jj_scan_token(RECURSIVE)) return true;
    if (jj_3R_289()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_290()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_209() {
    if (jj_3R_217()) return true;
    return false;
  }

  final private boolean jj_3R_202() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_209()) {
    jj_scanpos = xsp;
    if (jj_3R_210()) {
    jj_scanpos = xsp;
    if (jj_3R_211()) {
    jj_scanpos = xsp;
    if (jj_3R_212()) {
    jj_scanpos = xsp;
    if (jj_3R_213()) {
    jj_scanpos = xsp;
    if (jj_3R_214()) return true;
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_283() {
    if (jj_scan_token(IN)) return true;
    return false;
  }

  final private boolean jj_3R_156() {
    if (jj_3R_175()) return true;
    return false;
  }

  final private boolean jj_3R_282() {
    if (jj_scan_token(EQUALS)) return true;
    return false;
  }

  final private boolean jj_3R_144() {
    if (jj_3R_95()) return true;
    return false;
  }

  final private boolean jj_3_39() {
    if (jj_3R_85()) return true;
    return false;
  }

  final private boolean jj_3R_85() {
    if (jj_3R_67()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_144()) jj_scanpos = xsp;
    if (jj_scan_token(BANG)) return true;
    return false;
  }

  final private boolean jj_3R_270() {
    if (jj_scan_token(BANG)) return true;
    if (jj_3R_281()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_282()) {
    jj_scanpos = xsp;
    if (jj_3R_283()) return true;
    }
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_157() {
    if (jj_scan_token(CONSTANT)) return true;
    return false;
  }

  final private boolean jj_3R_265() {
    if (jj_scan_token(IN)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_257() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_265()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_271() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_270()) return true;
    return false;
  }

  final private boolean jj_3R_219() {
    if (jj_scan_token(LWB)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(EXCEPT)) return true;
    if (jj_3R_270()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_271()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RWB)) return true;
    return false;
  }

  final private boolean jj_3R_114() {
    if (jj_3R_157()) return true;
    return false;
  }

  final private boolean jj_3R_307() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_112() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(103)) {
    jj_scanpos = xsp;
    if (jj_scan_token(105)) {
    jj_scanpos = xsp;
    if (jj_scan_token(88)) {
    jj_scanpos = xsp;
    if (jj_3R_156()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = getToken(1).image.equals("@");
    lookingAhead = false;
    if (!jj_semLA || jj_scan_token(231)) return true;
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_296() {
    if (jj_scan_token(LSB)) return true;
    if (jj_3R_63()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_307()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3_77() {
    if (jj_3R_112()) return true;
    return false;
  }

  final private boolean jj_3R_285() {
    if (jj_3R_95()) return true;
    return false;
  }

  final private boolean jj_3_75() {
    if (jj_3R_95()) return true;
    return false;
  }

  final private boolean jj_3_74() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_113() {
    if (jj_scan_token(VARIABLE)) return true;
    return false;
  }

  final private boolean jj_3R_56() {
    if (jj_3R_115()) return true;
    return false;
  }

  final private boolean jj_3R_111() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_110() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_295() {
    if (jj_scan_token(DOT)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_109() {
    if (jj_3R_155()) return true;
    return false;
  }

  final private boolean jj_3R_281() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_295()) {
    jj_scanpos = xsp;
    if (jj_3R_296()) return true;
    }
    return false;
  }

  final private boolean jj_3R_108() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_58() {
    if (jj_3R_117()) return true;
    return false;
  }

  final private boolean jj_3R_57() {
    if (jj_3R_116()) return true;
    return false;
  }

  final private boolean jj_3_5() {
    if (jj_3R_62()) return true;
    return false;
  }

  final private boolean jj_3_76() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = !getToken(1).image.equals("@");
    lookingAhead = false;
    if (!jj_semLA || jj_3R_108()) {
    jj_scanpos = xsp;
    if (jj_3R_109()) {
    jj_scanpos = xsp;
    if (jj_3R_110()) {
    jj_scanpos = xsp;
    if (jj_3R_111()) return true;
    }
    }
    }
    xsp = jj_scanpos;
    if (jj_3_75()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3_4() {
    if (jj_3R_61()) return true;
    return false;
  }

  final private boolean jj_3_3() {
    if (jj_3R_60()) return true;
    return false;
  }

  final private boolean jj_3R_244() {
    if (jj_scan_token(BANG)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_76()) {
    jj_scanpos = xsp;
    if (jj_3R_285()) {
    jj_scanpos = xsp;
    if (jj_3_77()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_76() {
    if (jj_3R_134()) return true;
    return false;
  }

  final private boolean jj_3R_75() {
    if (jj_3R_68()) return true;
    return false;
  }

  final private boolean jj_3_2() {
    if (jj_3R_59()) return true;
    return false;
  }

  final private boolean jj_3R_55() {
    if (jj_3R_114()) return true;
    return false;
  }

  final private boolean jj_3R_54() {
    if (jj_3R_113()) return true;
    return false;
  }

  final private boolean jj_3R_53() {
    if (jj_scan_token(SEPARATOR)) return true;
    return false;
  }

  final private boolean jj_3R_74() {
    if (jj_scan_token(NEW)) return true;
    return false;
  }

  final private boolean jj_3_1() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_53()) {
    jj_scanpos = xsp;
    if (jj_3R_54()) {
    jj_scanpos = xsp;
    if (jj_3R_55()) {
    jj_scanpos = xsp;
    if (jj_3_2()) {
    jj_scanpos = xsp;
    if (jj_3R_56()) {
    jj_scanpos = xsp;
    if (jj_3_3()) {
    jj_scanpos = xsp;
    if (jj_3_4()) {
    jj_scanpos = xsp;
    if (jj_3_5()) {
    jj_scanpos = xsp;
    if (jj_3R_57()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = (getToken(1).kind == USE && getToken(2).kind != ONLY)
                    || (getToken(1).kind == HIDE);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_58()) return true;
    }
    }
    }
    }
    }
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_297() {
    if (jj_3R_281()) return true;
    return false;
  }

  final private boolean jj_3_22() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_74()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(79)) {
    jj_scanpos = xsp;
    if (jj_scan_token(37)) {
    jj_scanpos = xsp;
    if (jj_scan_token(80)) return true;
    }
    }
    xsp = jj_scanpos;
    if (jj_3R_75()) {
    jj_scanpos = xsp;
    if (jj_3R_76()) return true;
    }
    return false;
  }

  final private boolean jj_3R_287() {
    if (jj_scan_token(BANG)) return true;
    Token xsp;
    if (jj_3R_297()) return true;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_297()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(EQUALS)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_73() {
    if (jj_scan_token(NEW)) return true;
    return false;
  }

  final private boolean jj_3R_72() {
    if (jj_3R_134()) return true;
    return false;
  }

  final private boolean jj_3_21() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_73()) jj_scanpos = xsp;
    if (jj_scan_token(VARIABLE)) return true;
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_246() {
    if (jj_3R_67()) return true;
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_69() {
    if (jj_scan_token(IN)) return true;
    return false;
  }

  final private boolean jj_3_19() {
    if (jj_3R_68()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_69()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_245() {
    if (jj_3R_67()) return true;
    if (jj_scan_token(MAPTO)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_71() {
    if (jj_scan_token(CONSTANT)) return true;
    return false;
  }

  final private boolean jj_3R_70() {
    if (jj_scan_token(NEW)) return true;
    return false;
  }

  final private boolean jj_3_18() {
    if (jj_scan_token(NEW)) return true;
    if (jj_scan_token(CONSTANT)) return true;
    return false;
  }

  final private boolean jj_3_20() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_18()) {
    jj_scanpos = xsp;
    if (jj_3R_70()) {
    jj_scanpos = xsp;
    if (jj_3R_71()) return true;
    }
    }
    xsp = jj_scanpos;
    if (jj_3_19()) {
    jj_scanpos = xsp;
    if (jj_3R_72()) return true;
    }
    return false;
  }

  final private boolean jj_3R_279() {
    if (jj_scan_token(ARSB)) return true;
    if (jj_3R_243()) return true;
    return false;
  }

  final private boolean jj_3R_172() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3_20()) {
    jj_scanpos = xsp;
    if (jj_3_21()) {
    jj_scanpos = xsp;
    if (jj_3_22()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_288() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_287()) return true;
    return false;
  }

  final private boolean jj_3R_278() {
    if (jj_scan_token(EXCEPT)) return true;
    if (jj_3R_287()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_288()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3R_277() {
    if (jj_scan_token(ARROW)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3R_158() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(34)) {
    jj_scanpos = xsp;
    if (jj_scan_token(3)) {
    jj_scanpos = xsp;
    if (jj_scan_token(20)) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_286() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3_50() {
    if (jj_scan_token(IDENTIFIER)) return true;
    if (jj_scan_token(COLON)) return true;
    return false;
  }

  final private boolean jj_3R_276() {
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_286()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3_51() {
    if (jj_3R_63()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_276()) {
    jj_scanpos = xsp;
    if (jj_3R_277()) {
    jj_scanpos = xsp;
    if (jj_3R_278()) {
    jj_scanpos = xsp;
    if (jj_3R_279()) return true;
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_275() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_246()) return true;
    return false;
  }

  final private boolean jj_3_17() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_240() {
    if (jj_3R_246()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_275()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3R_274() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_245()) return true;
    return false;
  }

  final private boolean jj_3_49() {
    if (jj_scan_token(IDENTIFIER)) return true;
    if (jj_scan_token(MAPTO)) return true;
    return false;
  }

  final private boolean jj_3R_116() {
    if (jj_3R_158()) return true;
    return false;
  }

  final private boolean jj_3R_239() {
    if (jj_3R_245()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_274()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3R_273() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_245()) return true;
    return false;
  }

  final private boolean jj_3R_138() {
    if (jj_scan_token(COMMA)) return true;
    return false;
  }

  final private boolean jj_3_16() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_137() {
    if (jj_3R_172()) return true;
    return false;
  }

  final private boolean jj_3R_238() {
    if (jj_3R_245()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_273()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3R_272() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_230()) return true;
    return false;
  }

  final private boolean jj_3R_136() {
    if (jj_3R_78()) return true;
    return false;
  }

  final private boolean jj_3R_237() {
    if (jj_3R_230()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_272()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(MAPTO)) return true;
    if (jj_3R_63()) return true;
    if (jj_scan_token(RSB)) return true;
    return false;
  }

  final private boolean jj_3_70() {
    if (jj_scan_token(op_76)) return true;
    return false;
  }

  final private boolean jj_3R_232() {
    if (jj_3R_244()) return true;
    return false;
  }

  final private boolean jj_3R_154() {
    if (jj_scan_token(LSB)) return true;
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = matchFcnConst();
    lookingAhead = false;
    if (!jj_semLA || jj_3R_237()) {
    jj_scanpos = xsp;
    if (jj_3R_238()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = (getToken(2).kind == MAPTO) && isFieldNameToken( getToken(1));
    lookingAhead = false;
    if (!jj_semLA || jj_3R_239()) {
    jj_scanpos = xsp;
    if (jj_3R_240()) {
    jj_scanpos = xsp;
    if (jj_3_51()) return true;
    }
    }
    }
    }
    return false;
  }

  final private boolean jj_3_71() {
    if (jj_3R_95()) return true;
    return false;
  }

  final private boolean jj_3R_180() {
    if (jj_3R_155()) return true;
    return false;
  }

  final private boolean jj_3R_179() {
    if (jj_3R_102()) return true;
    return false;
  }

  final private boolean jj_3R_178() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_314() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_313() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_230()) return true;
    return false;
  }

  final private boolean jj_3R_306() {
    Token xsp;
    if (jj_3R_314()) return true;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_314()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_64() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(114)) {
    jj_scanpos = xsp;
    if (jj_scan_token(115)) {
    jj_scanpos = xsp;
    if (jj_scan_token(116)) {
    jj_scanpos = xsp;
    if (jj_scan_token(117)) return true;
    }
    }
    }
    return false;
  }

  final private boolean jj_3R_135() {
    if (jj_3R_67()) return true;
    if (jj_scan_token(COLONCOLON)) return true;
    if (jj_3R_78()) return true;
    return false;
  }

  final private boolean jj_3R_78() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_135()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(38)) {
    jj_scanpos = xsp;
    if (jj_scan_token(39)) return true;
    }
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = (getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME)
                   || ((getToken(2).kind == COLONCOLON) &&
                       (getToken(3).kind == ASSUME || getToken(3).kind == BOXASSUME)  );
    lookingAhead = false;
    if (!jj_semLA || jj_3R_136()) {
    jj_scanpos = xsp;
    if (jj_3R_137()) {
    jj_scanpos = xsp;
    if (jj_3_16()) return true;
    }
    }
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_138()) { jj_scanpos = xsp; break; }
    }
    xsp = jj_scanpos;
    if (jj_scan_token(75)) {
    jj_scanpos = xsp;
    if (jj_scan_token(76)) return true;
    }
    return false;
  }

  final private boolean jj_3_73() {
    if (jj_scan_token(NUMBER_LITERAL)) return true;
    return false;
  }

  final private boolean jj_3R_177() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(232)) {
    jj_scanpos = xsp;
    if (jj_scan_token(233)) return true;
    }
    return false;
  }

  final private boolean jj_3_72() {
    if (jj_3R_107()) return true;
    return false;
  }

  final private boolean jj_3R_176() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_153() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_176()) {
    jj_scanpos = xsp;
    if (jj_3R_177()) {
    jj_scanpos = xsp;
    if (jj_3R_178()) {
    jj_scanpos = xsp;
    if (jj_3R_179()) {
    jj_scanpos = xsp;
    if (jj_3R_180()) return true;
    }
    }
    }
    }
    xsp = jj_scanpos;
    if (jj_3_71()) jj_scanpos = xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_232()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_91() {
    if (jj_3R_146()) return true;
    return false;
  }

  final private boolean jj_3R_152() {
    if (jj_3R_175()) return true;
    return false;
  }

  final private boolean jj_3R_142() {
    if (jj_3R_78()) return true;
    return false;
  }

  final private boolean jj_3R_305() {
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_230()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_313()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_294() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_305()) {
    jj_scanpos = xsp;
    if (jj_3R_306()) return true;
    }
    return false;
  }

  final private boolean jj_3_46() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_91()) {
    jj_scanpos = xsp;
    if (jj_scan_token(231)) return true;
    }
    if (jj_scan_token(COLON)) return true;
    return false;
  }

  final private boolean jj_3R_151() {
    if (jj_3R_107()) return true;
    return false;
  }

  final private boolean jj_3_38() {
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_293() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_230()) return true;
    return false;
  }

  final private boolean jj_3_47() {
    if (jj_3R_63()) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_294()) jj_scanpos = xsp;
    return false;
  }

  final private boolean jj_3R_98() {
    Token xsp;
    xsp = jj_scanpos;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_151()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = BStack.aboveReference( getToken(1).beginColumn);
    lookingAhead = false;
    if (!jj_semLA || jj_3R_152()) {
    jj_scanpos = xsp;
    if (jj_3R_153()) return true;
    }
    }
    return false;
  }

  final private boolean jj_3R_90() {
    if (jj_3R_146()) return true;
    return false;
  }

  final private boolean jj_3R_141() {
    if (jj_scan_token(SUFFICES)) return true;
    return false;
  }

  final private boolean jj_3_45() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_90()) {
    jj_scanpos = xsp;
    if (jj_scan_token(231)) return true;
    }
    if (jj_scan_token(COMMA)) return true;
    return false;
  }

  final private boolean jj_3R_82() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_141()) jj_scanpos = xsp;
    xsp = jj_scanpos;
    if (jj_3_38()) {
    jj_scanpos = xsp;
    lookingAhead = true;
    jj_semLA = getToken(1).kind == ASSUME || getToken(1).kind == BOXASSUME;
    lookingAhead = false;
    if (!jj_semLA || jj_3R_142()) return true;
    }
    return false;
  }

  final private boolean jj_3R_94() {
    if (jj_3R_63()) return true;
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_230()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_293()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_292() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_93() {
    if (jj_3R_63()) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_292()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3R_312() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_304() {
    Token xsp;
    if (jj_3R_312()) return true;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_312()) { jj_scanpos = xsp; break; }
    }
    return false;
  }

  final private boolean jj_3_68() {
    if (jj_scan_token(COLONCOLON)) return true;
    return false;
  }

  final private boolean jj_3_15() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(95)) jj_scanpos = xsp;
    if (jj_3R_67()) return true;
    if (jj_scan_token(DEF)) return true;
    return false;
  }

  final private boolean jj_3R_303() {
    if (jj_scan_token(COLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_291() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_303()) {
    jj_scanpos = xsp;
    if (jj_3R_304()) return true;
    }
    return false;
  }

  final private boolean jj_3R_61() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(40)) {
    jj_scanpos = xsp;
    if (jj_scan_token(38)) return true;
    }
    xsp = jj_scanpos;
    if (jj_3_15()) jj_scanpos = xsp;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_84() {
    if (jj_scan_token(COMMA)) return true;
    if (jj_scan_token(IDENTIFIER)) return true;
    return false;
  }

  final private boolean jj_3_66() {
    if (jj_3R_97()) return true;
    return false;
  }

  final private boolean jj_3R_106() {
    if (jj_scan_token(COLONCOLON)) return true;
    if (jj_3R_63()) return true;
    return false;
  }

  final private boolean jj_3R_148() {
    if (jj_3R_67()) return true;
    return false;
  }

  final private boolean jj_3R_261() {
    if (jj_3R_169()) return true;
    return false;
  }

  final private boolean jj_3R_260() {
    if (jj_3R_168()) return true;
    return false;
  }

  final private boolean jj_3_37() {
    if (jj_scan_token(IDENTIFIER)) return true;
    Token xsp;
    while (true) {
      xsp = jj_scanpos;
      if (jj_3R_84()) { jj_scanpos = xsp; break; }
    }
    if (jj_scan_token(COLON)) return true;
    return false;
  }

  final private boolean jj_3R_67() {
    if (jj_scan_token(IDENTIFIER)) return true;
    return false;
  }

  final private boolean jj_3R_103() {
    if (jj_3R_150()) return true;
    return false;
  }

  final private boolean jj_3_65() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_103()) {
    jj_scanpos = xsp;
    if (jj_scan_token(194)) return true;
    }
    return false;
  }

  final private boolean jj_3R_267() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_266() {
    if (jj_3R_182()) return true;
    return false;
  }

  final private boolean jj_3R_102() {
    if (jj_3R_64()) return true;
    return false;
  }

  final private boolean jj_3_67() {
    if (jj_3R_104()) return true;
    return false;
  }

  final private boolean jj_3R_259() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_266()) {
    jj_scanpos = xsp;
    if (jj_3R_267()) return true;
    }
    return false;
  }

  final private boolean jj_3R_147() {
    if (jj_3R_146()) return true;
    return false;
  }

  public TLAplusParserTokenManager token_source;
  SimpleCharStream jj_input_stream;
  public Token token, jj_nt;
  private int jj_ntk;
  private Token jj_scanpos, jj_lastpos;
  private int jj_la;
  public boolean lookingAhead = false;
  private boolean jj_semLA;
  private int jj_gen;
  final private int[] jj_la1 = new int[140];
  static private int[] jj_la1_0;
  static private int[] jj_la1_1;
  static private int[] jj_la1_2;
  static private int[] jj_la1_3;
  static private int[] jj_la1_4;
  static private int[] jj_la1_5;
  static private int[] jj_la1_6;
  static private int[] jj_la1_7;
  static {
      jj_la1_0();
      jj_la1_1();
      jj_la1_2();
      jj_la1_3();
      jj_la1_4();
      jj_la1_5();
      jj_la1_6();
      jj_la1_7();
   }
   private static void jj_la1_0() {
      jj_la1_0 = new int[] {0x0,0x0,0x0,0x0,0x4,0x80000,0x80000,0x100008,0x0,0x0,0x0,0x0,0x100008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
   }
   private static void jj_la1_1() {
      jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x8000,0x808,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x0,0x0,0x0,0x140,0x0,0x0,0xc0,0x800820,0x0,0x800820,0x0,0x800800,0x0,0x0,0x800000,0x800000,0x20,0x0,0x0,0x2000000,0x0,0x0,0x0,0x80000000,0x80000000,0x40000000,0x400000,0x0,0x400000,0x400000,0x0,0x400000,0x0,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000000,0x4000000,0x180b4600,0x0,0x0,0x0,0x0,0x0,0x0,0x14000,0x0,0x0,0x0,0x18000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000000,0x200000,0x200000,0x0,0x0,0x0,0x0,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180b4600,};
   }
   private static void jj_la1_2() {
      jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,0x100000,0x4000,0x0,0x800000,0x800000,0x800000,0x800000,0x0,0x8000000,0x0,0x800000,0x0,0x0,0x800000,0x0,0x8000000,0x800000,0x8000000,0x20000000,0x800000,0x20000000,0x0,0x8000000,0x0,0x400000,0x0,0x0,0x100,0x0,0x80000000,0x0,0x0,0x118000,0x800000,0x118000,0x1800,0x0,0x0,0x8000000,0x0,0x0,0x18000,0x8000000,0x0,0x4,0x400,0xc0,0x400,0x0,0x0,0x418,0x0,0x800000,0x0,0x0,0x800000,0x0,0x2,0x0,0x60220,0x1,0x800000,0x800000,0x0,0x800000,0x800000,0x800000,0x0,0x80000,0x20000000,0x20200000,0x20200000,0x0,0x0,0x20000000,0x0,0x0,0x800000,0x0,0x0,0x800000,0x800000,0x0,0x0,0x800000,0x800000,0x0,0x0,0x800000,0x1800000,0x1800000,0x800000,0x800000,0x800000,0x800000,0x1800000,0x1800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x800000,0x4000000,0x800000,0x4000000,0x800000,0x0,0x800000,0x0,0x0,0x20000000,0x200000,0x80004000,0x80004000,0x0,0x0,0x800000,0x0,0x20200000,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x1000000,0x0,};
   }
   private static void jj_la1_3() {
      jj_la1_3 = new int[] {0xff800000,0xffc00000,0x0,0x3c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0000,0xffc00000,0x0,0x0,0x0,0xffc00000,0x0,0x0,0xffc00000,0x0,0xffc00000,0x0,0x0,0x0,0x3c0000,0xffc00000,0x0,0x0,0xfffc0000,0xfffc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffc00000,0x0,0x0,0x0,0xffc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0xa9,0xffbcc0a9,0x0,0xffbcc000,0x0,0x400,0xffbc0000,0x0,0xfffc0000,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x806,0x1,0x0,0x1,0x0,0x0,0x0,0x300,0x400,0xa9,0x0,0x0,0x0,0x0,0x80,0x0,0xff800000,0xa9,0xff800000,0x0,0x3c0000,0x400,0xfffc0000,0xfffc0000,0x0,0x4280,0x0,};
   }
   private static void jj_la1_4() {
      jj_la1_4 = new int[] {0x1,0x1,0xfffffffe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfffffffe,0x1,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x1,0x0,0x0,0x0,0xfffffffe,0x1,0x0,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100000,0x1,0x0,0x0,0x0,0x1,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x24,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0xfffffffe,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,};
   }
   private static void jj_la1_5() {
      jj_la1_5 = new int[] {0x0,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0x0,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0xffffffff,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,};
   }
   private static void jj_la1_6() {
      jj_la1_6 = new int[] {0x0,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0x0,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffffff,0x0,0xffffffff,0x0,0xffffffff,0x0,0xffffffff,0xffffffff,0x0,0x0,0x0,};
   }
   private static void jj_la1_7() {
      jj_la1_7 = new int[] {0x0,0x0,0x7f,0x0,0x0,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0x80,0x0,0x0,0x0,0x0,0x0,0x80,0x80,0x0,0x80,0x0,0x0,0x0,0x7f,0x0,0x0,0x0,0xff,0xff,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0xff,0x0,0xff,0x0,0x0,0xff,0x0,0x7f,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x80,0x0,0x7f,0x0,0x7f,0x300,0x3ff,0x0,0x3ff,0x7f,0x0,0x0,0x0,};
   }
  final private JJCalls[] jj_2_rtns = new JJCalls[77];
  private boolean jj_rescan = false;
  private int jj_gc = 0;

  public TLAplusParser(java.io.InputStream stream) {
     this(stream, null);
  }
  public TLAplusParser(java.io.InputStream stream, String encoding) {
    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source = new TLAplusParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  public void ReInit(java.io.InputStream stream) {
     ReInit(stream, null);
  }
  public void ReInit(java.io.InputStream stream, String encoding) {
    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  public TLAplusParser(java.io.Reader stream) {
    jj_input_stream = new SimpleCharStream(stream, 1, 1);
    token_source = new TLAplusParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  public void ReInit(java.io.Reader stream) {
    jj_input_stream.ReInit(stream, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  public TLAplusParser(TLAplusParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  public void ReInit(TLAplusParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 140; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  final private Token jj_consume_token(int kind) throws ParseException {
    Token oldToken;
    if ((oldToken = token).next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    if (token.kind == kind) {
      jj_gen++;
      if (++jj_gc > 100) {
        jj_gc = 0;
        for (int i = 0; i < jj_2_rtns.length; i++) {
          JJCalls c = jj_2_rtns[i];
          while (c != null) {
            if (c.gen < jj_gen) c.first = null;
            c = c.next;
          }
        }
      }
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  }

  static private final class LookaheadSuccess extends java.lang.Error { }
  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
  final private boolean jj_scan_token(int kind) {
    if (jj_scanpos == jj_lastpos) {
      jj_la--;
      if (jj_scanpos.next == null) {
        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
      } else {
        jj_lastpos = jj_scanpos = jj_scanpos.next;
      }
    } else {
      jj_scanpos = jj_scanpos.next;
    }
    if (jj_rescan) {
      int i = 0; Token tok = token;
      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
      if (tok != null) jj_add_error_token(kind, i);
    }
    if (jj_scanpos.kind != kind) return true;
    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
    return false;
  }

  final public Token getNextToken() {
    if (token.next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    jj_gen++;
    return token;
  }

  final public Token getToken(int index) {
    Token t = lookingAhead ? jj_scanpos : token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  }

  final private int jj_ntk() {
    if ((jj_nt=token.next) == null)
      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
    else
      return (jj_ntk = jj_nt.kind);
  }

  private java.util.Vector jj_expentries = new java.util.Vector();
  private int[] jj_expentry;
  private int jj_kind = -1;
  private int[] jj_lasttokens = new int[100];
  private int jj_endpos;

  private void jj_add_error_token(int kind, int pos) {
    if (pos >= 100) return;
    if (pos == jj_endpos + 1) {
      jj_lasttokens[jj_endpos++] = kind;
    } else if (jj_endpos != 0) {
      jj_expentry = new int[jj_endpos];
      for (int i = 0; i < jj_endpos; i++) {
        jj_expentry[i] = jj_lasttokens[i];
      }
      boolean exists = false;
      for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
        int[] oldentry = (int[])(e.nextElement());
        if (oldentry.length == jj_expentry.length) {
          exists = true;
          for (int i = 0; i < jj_expentry.length; i++) {
            if (oldentry[i] != jj_expentry[i]) {
              exists = false;
              break;
            }
          }
          if (exists) break;
        }
      }
      if (!exists) jj_expentries.addElement(jj_expentry);
      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
    }
  }

  public ParseException generateParseException() {
    jj_expentries.removeAllElements();
    boolean[] la1tokens = new boolean[237];
    for (int i = 0; i < 237; i++) {
      la1tokens[i] = false;
    }
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 140; i++) {
      if (jj_la1[i] == jj_gen) {
        for (int j = 0; j < 32; j++) {
          if ((jj_la1_0[i] & (1<<j)) != 0) {
            la1tokens[j] = true;
          }
          if ((jj_la1_1[i] & (1<<j)) != 0) {
            la1tokens[32+j] = true;
          }
          if ((jj_la1_2[i] & (1<<j)) != 0) {
            la1tokens[64+j] = true;
          }
          if ((jj_la1_3[i] & (1<<j)) != 0) {
            la1tokens[96+j] = true;
          }
          if ((jj_la1_4[i] & (1<<j)) != 0) {
            la1tokens[128+j] = true;
          }
          if ((jj_la1_5[i] & (1<<j)) != 0) {
            la1tokens[160+j] = true;
          }
          if ((jj_la1_6[i] & (1<<j)) != 0) {
            la1tokens[192+j] = true;
          }
          if ((jj_la1_7[i] & (1<<j)) != 0) {
            la1tokens[224+j] = true;
          }
        }
      }
    }
    for (int i = 0; i < 237; i++) {
      if (la1tokens[i]) {
        jj_expentry = new int[1];
        jj_expentry[0] = i;
        jj_expentries.addElement(jj_expentry);
      }
    }
    jj_endpos = 0;
    jj_rescan_token();
    jj_add_error_token(0, 0);
    int[][] exptokseq = new int[jj_expentries.size()][];
    for (int i = 0; i < jj_expentries.size(); i++) {
      exptokseq[i] = (int[])jj_expentries.elementAt(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  }

  final public void enable_tracing() {
  }

  final public void disable_tracing() {
  }

  final private void jj_rescan_token() {
    jj_rescan = true;
    for (int i = 0; i < 77; i++) {
    try {
      JJCalls p = jj_2_rtns[i];
      do {
        if (p.gen > jj_gen) {
          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
          switch (i) {
            case 0: jj_3_1(); break;
            case 1: jj_3_2(); break;
            case 2: jj_3_3(); break;
            case 3: jj_3_4(); break;
            case 4: jj_3_5(); break;
            case 5: jj_3_6(); break;
            case 6: jj_3_7(); break;
            case 7: jj_3_8(); break;
            case 8: jj_3_9(); break;
            case 9: jj_3_10(); break;
            case 10: jj_3_11(); break;
            case 11: jj_3_12(); break;
            case 12: jj_3_13(); break;
            case 13: jj_3_14(); break;
            case 14: jj_3_15(); break;
            case 15: jj_3_16(); break;
            case 16: jj_3_17(); break;
            case 17: jj_3_18(); break;
            case 18: jj_3_19(); break;
            case 19: jj_3_20(); break;
            case 20: jj_3_21(); break;
            case 21: jj_3_22(); break;
            case 22: jj_3_23(); break;
            case 23: jj_3_24(); break;
            case 24: jj_3_25(); break;
            case 25: jj_3_26(); break;
            case 26: jj_3_27(); break;
            case 27: jj_3_28(); break;
            case 28: jj_3_29(); break;
            case 29: jj_3_30(); break;
            case 30: jj_3_31(); break;
            case 31: jj_3_32(); break;
            case 32: jj_3_33(); break;
            case 33: jj_3_34(); break;
            case 34: jj_3_35(); break;
            case 35: jj_3_36(); break;
            case 36: jj_3_37(); break;
            case 37: jj_3_38(); break;
            case 38: jj_3_39(); break;
            case 39: jj_3_40(); break;
            case 40: jj_3_41(); break;
            case 41: jj_3_42(); break;
            case 42: jj_3_43(); break;
            case 43: jj_3_44(); break;
            case 44: jj_3_45(); break;
            case 45: jj_3_46(); break;
            case 46: jj_3_47(); break;
            case 47: jj_3_48(); break;
            case 48: jj_3_49(); break;
            case 49: jj_3_50(); break;
            case 50: jj_3_51(); break;
            case 51: jj_3_52(); break;
            case 52: jj_3_53(); break;
            case 53: jj_3_54(); break;
            case 54: jj_3_55(); break;
            case 55: jj_3_56(); break;
            case 56: jj_3_57(); break;
            case 57: jj_3_58(); break;
            case 58: jj_3_59(); break;
            case 59: jj_3_60(); break;
            case 60: jj_3_61(); break;
            case 61: jj_3_62(); break;
            case 62: jj_3_63(); break;
            case 63: jj_3_64(); break;
            case 64: jj_3_65(); break;
            case 65: jj_3_66(); break;
            case 66: jj_3_67(); break;
            case 67: jj_3_68(); break;
            case 68: jj_3_69(); break;
            case 69: jj_3_70(); break;
            case 70: jj_3_71(); break;
            case 71: jj_3_72(); break;
            case 72: jj_3_73(); break;
            case 73: jj_3_74(); break;
            case 74: jj_3_75(); break;
            case 75: jj_3_76(); break;
            case 76: jj_3_77(); break;
          }
        }
        p = p.next;
      } while (p != null);
      } catch(LookaheadSuccess ls) { }
    }
    jj_rescan = false;
  }

  final private void jj_save(int index, int xla) {
    JJCalls p = jj_2_rtns[index];
    while (p.gen > jj_gen) {
      if (p.next == null) { p = p.next = new JJCalls(); break; }
      p = p.next;
    }
    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
  }

  static final class JJCalls {
    int gen;
    Token first;
    int arg;
    JJCalls next;
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/OpenModelHandlerDelegate.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.util.UIHelper;

public class OpenModelHandlerDelegate extends AbstractHandler implements IHandler
{
    public final static String COMMAND_ID = "toolbox.command.cnf.open.delegate";

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        /*
         * Try to get the spec from active navigator if any
         */
        ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
        if (selection != null && selection instanceof IStructuredSelection
                && ((IStructuredSelection) selection).size() == 1)
        {
            Object selected = ((IStructuredSelection) selection).getFirstElement();
            if (selected instanceof Model)
            {
                Map<String, String> parameters = new HashMap<String, String>();

                // fill the model name for the handler
                parameters.put(OpenModelHandler.PARAM_MODEL_NAME, ((Model) selected).getName());
                // delegate the call to the open model handler
                UIHelper.runCommand(OpenModelHandler.COMMAND_ID, parameters);
            }
        }
        return null;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/pcal/ValidationProgressMonitorDialog.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic.pcal;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import org.eclipse.jface.dialogs.ForkedProgressMonitorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import pcal.ValidationCallBack;

public class ValidationProgressMonitorDialog extends ForkedProgressMonitorDialog implements IRunnableContext, ValidationCallBack {
	
	private Button continueButton;

	private Button thirdButton;

	public ValidationProgressMonitorDialog(final Shell parent) {
		super(parent);
	}
	
	@Override
	protected void configureShell(final Shell shell) {
		super.configureShell(shell);
		// Set the title (dialog frame).
		shell.setText("Translate PlusCal Algorithm.");
	}
	
	@Override
	protected void createButtonsForButtonBar(final Composite parent) {
		// Create a second button with which the user can chose to continue.
		thirdButton = createButton(parent, IDialogConstants.OK_ID, "&Overwrite Translation", true);
		thirdButton.setEnabled(false); // disabled by default unless doIt explicitly called.
		thirdButton.setVisible(false);
		
		// Create a second button with which the user can chose to continue.
		continueButton = createButton(parent, IDialogConstants.OK_ID, "&Overwrite Translation", true);
		continueButton.setEnabled(false); // disabled by default unless doIt explicitly called.
		
		// Let superclass create the cancel button to which we attach our listener.
		super.createButtonsForButtonBar(parent);
		cancel.setText("&Abort");
		
		getShell().setDefaultButton(continueButton);
	}
	
	@Override
	public boolean shouldCancel() {

		final Object lock = new Object();

		final Listener listener = new Listener() {
			public void handleEvent(final Event e) {
				// Nothing to do here except releasing the latch.
				synchronized (lock) {
					lock.notifyAll(); // Technically, notify would suffice.
				};
			}
		};

		// Set the label on the dialog and enable the cancel and
		// continue buttons.
		getShell().getDisplay().syncExec(() -> {
			getProgressMonitor().setTaskName("Overwrite modified TLA+ translation?");
			getProgressMonitor().subTask(
					"The TLA+ translation has been manually modified since its last translation (chksum(tla) mismatch).  Click the \"Overwrite Translation\" button to replace the TLA+ translation anyway or \"Cancel\" to abort re-translation and keep the modified TLA+ translation.");
			continueButton.setText("&Overwrite Translation");
			continueButton.setEnabled(true);
			continueButton.addListener(SWT.Selection, listener);
			cancel.setText("&Abort");
			cancel.setEnabled(true);
			cancel.addListener(SWT.Selection, listener);
		});
		
		// Block this thread until the user presses either the cancel or continue button.
		try {
			synchronized (lock) {
				lock.wait();
			};
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			return true;
		}
		
		// True if the user pressed cancel button, false if continue.
		return getProgressMonitor().isCanceled();
	}
	
	@Override
	public Generate shouldGenerate() {
		final BlockingQueue<Generate> q = new ArrayBlockingQueue<>(1);
		
		// Set the label on the dialog and enable the cancel and
		// continue buttons.
		getShell().getDisplay().syncExec(() -> {
			getProgressMonitor().setTaskName("Add Checksums to TLA+ translation?");
			getProgressMonitor().subTask(
					"The PlusCal translator can add checksums to the \\* BEGIN TRANSLATION line of this spec to warn you before model-checking a stale TLA+ translation. Do you want to add checksums, never add checksums, or decide later?");
			continueButton.setText("&Add Checksums");
			continueButton.setEnabled(true);
			continueButton.addListener(SWT.Selection,(e) -> q.offer(Generate.DO_IT));
			cancel.setText("&Later");
			cancel.setEnabled(true);
			cancel.addListener(SWT.Selection,(e) -> q.offer(Generate.NOT_NOW));
			thirdButton.setText("&Never Add");
			thirdButton.setEnabled(true);
			thirdButton.setVisible(true);
			thirdButton.addListener(SWT.Selection,(e) -> q.offer(Generate.IGNORE));
		});
		
		try {
			return q.take();
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			return Generate.NOT_NOW;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/generator/LongVecFingerPrintGenerator.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp.generator;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

import org.junit.Assert;

import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.MultiThreadedFPSetTest;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

public class LongVecFingerPrintGenerator extends FingerPrintGenerator {

	private static final int batch = 1024;
	
	public LongVecFingerPrintGenerator(MultiThreadedFPSetTest test, int id, int numThreads, FPSet fpSet, CountDownLatch latch, long seed, long insertions, final CyclicBarrier barrier) {
		super(test, id, numThreads, fpSet, latch, seed, insertions, barrier);
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		waitForAllThreadsStarted();
		
		TestLongVec predecessors = new TestLongVec(batch);
		boolean initialized = false;
		// Reduce number of FPSet#size invocation by counting puts/collisions.
		// FPSet#size can cause an FPSet to synchronize all its writers slowing
		// down execution.
		while (puts + collisions < perThreadInsertions || fpSet.size() < totalInsertions) {
			try {
				// Make sure set still contains predecessors
				if (initialized) {
					final BitVector bitVector = fpSet.containsBlock(predecessors);
					Assert.assertEquals(batch, batch - bitVector.trueCnt());
				}

				// Fill new fingerprints and sort them
				for (int i = 0; i < batch; i++) {
					predecessors.setElement(i, rnd.nextLong());
				}
				initialized = true;
				predecessors.sort();

				// Add sorted batch to fpset
				final BitVector bitVector = fpSet.putBlock(predecessors);
				puts += bitVector.trueCnt();
				collisions += (batch - bitVector.trueCnt());
			} catch (IOException e) {
				e.printStackTrace();
				Assert.fail("Unexpected");
			}
		}
		latch.countDown();
	}
	
	// This implementation adds two methods that should be used with caution as
	// they mess with the internal capacity checks of LongVec. We don't want to
	// make them API.
	private class TestLongVec extends LongVec {

		private static final long serialVersionUID = -720614225756936980L;

		public TestLongVec(int batch) {
			super(batch);
		}

		public final void sort() {
			Arrays.sort(elementData);
		}
		  
		public final void setElement(int index, long x) {
			this.elementData[index] = x;
			this.elementCount = ++elementCount % elementData.length + 1;
		}
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ParseUnit.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Tue 13 May 2008 at  5:13:46 PST by lamport

/***************************************************************************
* 2 Mar 07: J-Ch extended TLAPrint switch to print syntax tree either to   *
* file or to screen.                                                       *
***************************************************************************/

package tla2sany.modanalyzer;

// A ParseUnit is, roughly, a wrapper for a parser and the file it 
// originates from.

// The parser contains the root syntactic node

// At creation time, ParseUnit is given a NamedInputStream as parameter, 
// which supplies it with the input stream as well as other relevant 
// information.

// ParseUnit keeps track of whether or not a syntactic unit needs to be 
// reparsed.  This can be tested with isLoaded(), and done with parseFile().

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.nio.file.Path;

import tla2sany.semantic.AbortException;
import tla2sany.semantic.Errors;
import tla2sany.st.Location;
import tla2sany.st.ParseTree;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Vector;
import util.FileUtil;
import util.FilenameToStream.TLAFile;
import util.MonolithSpecExtractor;
import util.NamedInputStream;
import util.TLAConstants;
import util.TLAFlightRecorder;
import util.ToolIO;

/**
 * This class represents a parse unit, i.e. a file containing a
 *  single top-level TLA+ module and its inner modules.
 */
public class ParseUnit {

  private SpecObj            spec;                   
    // Back-reference to the SpecObj that this ParseUnit is part of
  private NamedInputStream   nis        = null;      
    // nis contains the file name, top-level module name, and 
    //   source File object for a module

  public NamedInputStream   getNis() {return this.nis; } ;
    /***********************************************************************
    * Added by LL on 12 May 2008 because the gui might want to get hold    *
    * of it here.                                                          *
    ***********************************************************************/
    
  private ParseTree          parseTree  = null;      
    // Parse tree for the contents of "nis"; ParseTree is an 
    // interface.  This is how one gets at the root of the 
    // parse tree for a ParseUnit
  private long               parseStamp = 0;         
    // time stamp of the source file last parsed.
  private ModulePointer      rootModule = null;      
    // The ModulePointer for the top level module of this ParseUnit 
  private String             rootModuleName;         
    // The String name of the ParseUnit, and also of its root module
  private ParseUnitRelatives parseUnitRelatives = new ParseUnitRelatives();
    // The ParseUnits this one is related to by EXTENTION and INSTANCE
  // Constructor
  public ParseUnit( SpecObj spec, NamedInputStream source ) {
    this.spec = spec;
    this.nis = source;
    rootModuleName = (source != null ? nis.getModuleName() : null);
  }

  // Simple toString that just prints the ParseUnit's name
  public final String toString() {
    return "[ ParseUnit: " + rootModuleName + " ]";
  }

  /** 
   *  Returns true the source file for the nis still exists (i.e. has
   *  not been deleted) and if the parseStamp of THIS ParseUnit is
   *  more recent than the modification time of the source file.
   */
  public final boolean isLoaded() {
    return (nis != null &&  
	    nis.sourceFile().exists() &&
	    parseStamp > nis.sourceFile().lastModified());
  }

  public boolean isLibraryModule() {
	  if (nis == null || !(nis.sourceFile() instanceof TLAFile)) {
		  return false;
	  }
	  return ((TLAFile) nis.sourceFile()).isLibraryModule();
  }

  // Get-methods
  public final String        getName()        { return rootModuleName; } 

  public final SpecObj       getSpec()        { return spec; }

  public final String        getFileName()    { return (nis != null ? nis.getFileName() : null); } 

  public final TreeNode      getParseTree()   { return (parseTree != null ? parseTree.rootNode() : null); }

  public final ModulePointer getRootModule()  { return rootModule; }

  final        Vector        getExtendees()   { return parseUnitRelatives.extendees; }

  final        Vector        getExtendedBy()  { return parseUnitRelatives.extendedBy; }

  final        Vector        getInstancees()  { return parseUnitRelatives.instancees; }
             
  final        Vector        getInstancedBy() { return parseUnitRelatives.instancedBy; }

  // Add-methods
  final        void          addExtendee(ParseUnit pu)    { parseUnitRelatives.extendees.addElement(pu); }

  final        void          addExtendedBy(ParseUnit pu)  { parseUnitRelatives.extendedBy.addElement(pu); }

  final        void          addInstancee(ParseUnit pu)   { parseUnitRelatives.instancees.addElement(pu); }

  final        void          addInstancedBy(ParseUnit pu) { parseUnitRelatives.instancedBy.addElement(pu); }

  final ModuleRelatives getRelatives(ModulePointer module) {
    return module.getRelatives();
  }

  final ParseUnitRelatives getRelatives() { return parseUnitRelatives; }

  final ModuleContext getContext(ModuleRelatives relatives) {
    return relatives.context;
  }

  final ModuleContext getContext(ModulePointer module) {
    return module.getRelatives().context;
  }

  final ModulePointer getParent(ModulePointer module) {
    return module.getRelatives().outerModule;
  }

  final Vector getPeers(ModulePointer module) {
    if ( module.getRelatives().outerModule != null ) {
      return module.getRelatives().outerModule.getRelatives().directInnerModules;
    }
    return null;
  }

  private final void writeParseTreeToFile(boolean file, Errors errors) throws AbortException {
      // Construct the name with a .jcg extension (Jean-<NAME>)
      PrintWriter pw;
      if (file) 
      {
          String sinkName = nis.getModuleName() + ".jcg";
          File compiled = this.spec.getResolver().resolve(sinkName, false);
          
          // SZ 23.02.2009: name resolver used          
          // File compiled =  new File( sinkName );

          // if that file already exists, we are about to overwrite it, so delete it first
          // SZ 23.02.2009: this could lead to problems under windows 
          if ( compiled.exists() )
          {
              compiled.delete();

          } 
          
          // SZ 23.02.2009: FileUtil method used
          //           try {
          // FileOutputStream output = new FileOutputStream( compiled );

          // Go ahead and write the tree out
          pw = new PrintWriter(FileUtil.newFOS(compiled)); 
          
          // This is different from parseTree.SyntaxTreeNode.printST()
          SyntaxTreePrinter.print( parseTree, pw );
          pw.flush(); 
          pw.close();

          // SZ 23.02.2009:
          // FileUtil method used
          // } catch ( IOException e ) {
          // errors.addAbort("Error: Failed to open output file " + sinkName +
          //        "\n" + e.getMessage());        }
      } else {
          pw = new PrintWriter(ToolIO.out);
          SyntaxTreePrinter.print( parseTree, pw );
          pw.flush();
      }
  }

  private final void verifyEquivalenceOfFileAndModuleNames(Errors errors) throws AbortException {
    // Retrieve the full file name
    String fName = getFileName();

    // Remove all of the pathname up to the final "/"
    fName = fName.substring(fName.lastIndexOf(System.getProperty("file.separator"))+1);

    // Remove any extension from file name
    fName = fName.substring(0,fName.lastIndexOf("."));

    // mName = name of top-level module declared in the file
    String mName = getParseTree().heirs()[0].heirs()[1].getImage();

    // Make sure the module named in the file matches the name of the file, at least
    // with a case-independent test.
    //
    // Change made by LL on 16 Jan 2014.  Added requirement that module name 
    // exactly matches file name.  Done because a mismatch provoked a bug in
    // the code calling TLAPS, and it was easier to add this requirement
    // than to fix that bug.  (See documentation of 
    // toolbox.util.AdapterFactory.locationToRegion.)  
    if (!mName.equals(fName)) {
    //  was:    if (!mName.equalsIgnoreCase(fName)) {
      errors.addAbort("File name '" + fName + "' does not match the name '" +
		      mName + "' of the top level module it contains.");
    }
  }

    /**
     * This method parses the source in THIS.nis, if it has not been
     * parsed already; It then proceeds to analyze the resulting parse
     * tree to see what other external modules must be found and parsed.
     * Finally, it writes result to a file if required by a command line
     * switch.
     * We receive `rootParseUnit` so we are able to find the file location for a 
     * module part of a monolith spec. 
     */
    public final void parseFile(Errors errors, boolean firstCall, String name, ParseUnit rootParseUnit) throws AbortException
    {
        // Has it already been parsed since last modified? If yes, then no need to parse again
        if (parseStamp > nis.sourceFile().lastModified())
            return;

        // Does the file exist? If not abort cleanly. Of course the file could be deleted
        // during the next few lines, and execution would also abort, but not so cleanly.
        // We ignore that possibility.
        if (!nis.sourceFile().exists())
        {
            errors.addAbort("Error: source file '" + nis.getName() + "' has apparently been deleted.");
        }

        // Print user feedback
		// MAK 01/2018: Always print the absolute path. Useful if e.g. users symlink
		// common TLA files and want to verify that symlinking worked.
        Path absoluteResolvedPath;
		try {
			absoluteResolvedPath = nis.getAbsoluteResolvedPath();
		} catch (IOException e1) {
			// Fall back to to relative path if resolving the path to an absolute one fails.
			// Chance of failure should be fairly low because existence is checked above.
			absoluteResolvedPath = nis.sourceFile().toPath();
		}
        /***********************************************************************
        * This is a bug.  The higher-level parsing methods have a PrintStream  *
        * argument to which such output gets written.  That argument should    *
        * have been passed down to this method.  (LL: 11 Mar 08)               *
        *                                                                      *
        * The following statement modified by LL on 13 Mar 08 to produce       *
        * more useful output for the GUI.                                      *
        ***********************************************************************/
        if (ToolIO.getMode() == ToolIO.SYSTEM)
        {            
            // If `resolver.getLibraryPath` returns `null` or the file is not an instance of TLAFile
            // (and as we didn't have errors in previous steps, the module
            // really exists somewhere), then we assume that this file is part of a monolith file.
            String originalFilePath = "";
            // If we are a instance of a TLAFile then try to get some library path.
            if (nis.sourceFile() instanceof TLAFile && ((TLAFile) (nis.sourceFile())).hasLibraryPath()) {
                final URI libraryPath = ((TLAFile) (nis.sourceFile())).getLibraryPath();
                if (!absoluteResolvedPath.toUri().getPath().equals(libraryPath.getPath())) {
                	originalFilePath = " (" + libraryPath + ")";                
                }
            } else if (rootParseUnit != null && rootParseUnit.getNis() != null) {
                // We try to get the monolith file path.
                File rootSourceFile = rootParseUnit.getNis().sourceFile();
                if (rootSourceFile != null) {
                    try {
                        MonolithSpecExtractor.module(rootSourceFile, name);
                        originalFilePath = " (" + rootSourceFile.getAbsolutePath() + ")";
                    } catch (IOException e) {
                        // This should never happen.
                        e.printStackTrace();
                    }
                }
            }
			      ToolIO.out.println(TLAFlightRecorder.message(String.format("%s %s%s", TLAConstants.LoggingAtoms.PARSING_FILE, absoluteResolvedPath, originalFilePath)));            
        } else {
            ToolIO.out.println(TLAFlightRecorder.message(String.format("Parsing module %s in file %s", nis.getModuleName(), absoluteResolvedPath)));
        }

        boolean parseSuccess; 
        try 
        {
            // create parser object
            parseTree = new tla2sany.parser.TLAplusParser(nis);

            // Here is the one true REAL call to the parseTree.parse() for a file;
            // The root node of the parse tree is left in parseTree.
            parseSuccess = parseTree.parse();

            // set the parse time stamp
            parseStamp = System.currentTimeMillis();
        } finally 
        {
            try
            {
                // SZ Aug 6, 2009: close the stream and release the OS resources
                // this is Ok, since the repeated call of the parse method will
                // return due to the fact, that the parse time stamp is newer 
                // then the file time stamp
                nis.close();
            } catch (IOException e)
            {
                // eventually it is a good place to inform the user that the resources are
                // not released 
            }
        }
        
        if (!parseSuccess)
        { // if parsing the contents of "nis" failed...
            // create the abort and throw the exception
            errors.addAbort(Location.moduleLocation(nis.getModuleName()), "Could not parse module "
                    + nis.getModuleName() + " from file " + nis.getName(), true);
        }

        // if the is the very first time parseFile() is called
        if (firstCall)
        {
            // We don't know the name of the specification until this moment!
            spec.setName(getParseTree().heirs()[0].heirs()[1].getImage());
        }

        rootModule = new ModulePointer(spec, this, getParseTree());

        // Determine which modules extend or include which others
        determineModuleRelationships(rootModule, /* parent */null);

        /*
        // Debugging
        ToolIO.err.println("ModuleRelationships for ParseUnit " + this.getName() + "\n" +  
                           spec.getModuleRelationships().toString() ); 
        */

        // Make sure file contains module of the same name
        verifyEquivalenceOfFileAndModuleNames(errors);

        // Use system property to decide whether to "print" the parse tree to a file
        if (System.getProperty("TLA-Print", "off").equals("file"))
        {
            writeParseTreeToFile(true, errors);
        } else if (System.getProperty("TLA-Print", "off").equals("on"))
        {
            writeParseTreeToFile(false, errors);
        }
    }

  private void handleExtensions(ModulePointer currentModule, ModulePointer otherModule) {
    /*
    // Debugging
    System.err.println("Entering HandleExtensions for (" + 
                       currentModule.getName() + ", " + 
                       ( otherModule.getName() != null ? otherModule.getName() : "null" ) + 
                       ")");
    System.err.println(currentModule.getContext().toString());
    */

    if (otherModule == null) {
      // System.err.println("Leaving handleExtensions because otherModule == null");
      return;
    }

    ModuleContext currentContext = getContext(currentModule);
    Vector        extendeeNames  = otherModule.getNamesOfModulesExtended();

    // For all modules extended by otherModule
    for (int i = 0; i < extendeeNames.size(); i++) {
      String        extendeeName = (String)extendeeNames.elementAt(i);
      ModulePointer extendeeResolvant = currentContext.resolve(extendeeName);

      // if extendeeName is resolved in currentContext, then
      // incorporate all of its inner modules into currentContext And
      // recursively add to currentContext all of the inner modules in
      // modules extended by resolvant
      if ( extendeeResolvant != null ) {
        Vector directInnerModules = extendeeResolvant.getDirectInnerModules();
        for (int j = 0; j < directInnerModules.size(); j++) {
          ModulePointer upperInnerMod = (ModulePointer)directInnerModules.elementAt(j);
          currentContext.bindIfNotBound(upperInnerMod.getName(), upperInnerMod);
          handleExtensions(currentModule,extendeeResolvant); // recursive call
	}
      }
    }

    /*
    // Debugging
    if ( currentModule.getName().equals("BB") ) {
      System.err.println("Leaving HandleExtensions for " + currentModule.getName() + "; context is:");
      System.err.println(currentModule.getContext().toString());
    }
    */
  }

  /**
   * Calculates the bindings (context) for module names known at the
   * location where currentModule is defined, and bound to modules
   * defined within this ParseUnit.  Does NOT include currentModule
   * itself, but DOES include peers defined earlier in the parent
   * module, and peers of the parent defined earlier than the parent,
   * and peers of the grandparent defined earlier than the
   * grandparent, etc.
   *
   * This method must be called before "peer" modules (other inner
   * modules at the same level) defined later are encountered, because
   * peer modules defined earlier are in the context of the current
   * module, but peer modules defined later are not.
   */
  private void calculateContextWithinParseUnit(ModulePointer currentModule) {
    // System.err.println("Context before adding parents: " + currentModule.getContext());
    ModuleContext currentContext = getContext(currentModule);

    // A module's context includes that of parent, grandparent,
    // etc. at point where it is defined
    if ( getParent(currentModule) != null) {
      currentContext.union(getParent(currentModule).getContext());
    }

    // A module's context also contains the names of direct inner
    // modules of ancestors defined before this one
    ModulePointer ancestorModule = currentModule;
    while ( getParent(ancestorModule) != null ) {
      // A module's context includes that of parent, grandparent,
      // etc. at point where it is defined
      currentContext.union(getParent(ancestorModule).getContext());

      Vector peers = getPeers(ancestorModule);
      // All peers defined so far are in the currentContext
      for (int i = 0; i < peers.size() - 1; i++) {
        ModulePointer nextPeer = (ModulePointer)peers.elementAt(i);
        currentContext.bindIfNotBound(nextPeer.getName(), nextPeer);
      }
      ancestorModule = getParent(ancestorModule);
    } // end while

    // A module's context also includes inner modules of modules
    // extended by currentModule's parent, etc.  directly or
    // indirectly, are in this module's context.
    handleExtensions(currentModule, currentModule );

    // System.err.println("Context after handling extentions: \n" + getContext(currentModule));
  }

  // Analyzes various sets of modules related to the module at
  // "currentNode" (which must be an "N_Module" node).  The second
  // argument is the ModulePointer for the immediate outer module for
  // currentNode (or null if none).
  //
  // For the module "currentModule" do the following:
  //   1) Create a ModuleRelatives object associated with it 
  //   2) Fill in the outerModule field for currentNode
  //   3) Calculate the module context as known within this ParseUnit
  //   4) Fill its directlyExtendedModules Vector with the String names
  //      of all of the modules it extends
  //   5) Fill its directlyInstantiatedModules Vector with the String
  //      names of all modules it instances
  //   6) Fill in its directInnerModules Vector with references to the
  //      module name TreeNodes of all direct inner modules it defines
  //   7) For all direct inner modules defined, call
  //      determineModuleRelationships recursively

  /*************************************************************************
  * First of all, I have no idea why the parser maintains separate lists   *
  * of directlyExtendedModules and directlyInstantiatedModules, since      *
  * they are just used to determine the names of imported modules that     *
  * have to be parsed and may cause dependency cycles.  I also don't       *
  * understand why this method walks the parse tree to find the            *
  * directlyInstantiatedModules.  The names of imported modules are        *
  * gathered in the parsing phase and are available in                     *
  * parseTree.dependencies().  (It would be easy to modify tla+.jj and     *
  * the ParseTree interface to list the instantiated modules separately.)  *
  *************************************************************************/
  void determineModuleRelationships(ModulePointer currentModule, ModulePointer parent) {
    /***
    System.err.println("< Entering determineModuleRelationships for currentModule " +
		       currentModule.getName() + ", with parent " +
		       (parent != null ? parent.getName() : "null"));  
     for (int i = 0; i < parseTree.dependencies().length; i++) {
     System.err.println(" Dependency: " + parseTree.dependencies()[i]) ;
       } ;

    ***/

    // Allocate ModuleRelatives object for the "current" module
    ModuleRelatives currentRelatives = new ModuleRelatives(this, currentModule);

    // Create Association between currentModule and its new ModuleRelatives object
    currentModule.putRelatives(currentRelatives);

    // indicate outerModule relationship
    currentRelatives.outerModule = parent;

    // Find the N_Extends node of the currentModule
    TreeNode extendNode = currentModule.getExtendsDecl();
    
    // Loop through the EXTENDS decl for the odd nodes, which are the
    // names of the modules being extended, and add an entry in the
    // directlyExtendsModules vector for each module mentioned
    for (int i = 1; i < extendNode.heirs().length; i += 2) {
      String extendedModuleName = extendNode.heirs()[i].getImage();
      currentRelatives.directlyExtendedModuleNames.addElement(extendedModuleName);
    }

    // Calculate the module context for current module, i.e. the names
    // and bindings of all modules within the current parseUnit that
    // are in the context of this module
    calculateContextWithinParseUnit(currentModule);

    // Find the body part of module tree
    TreeNode body = currentModule.getBody();

    // loop through the top level definitions in the body of the module
    // looking for embedded modules instantiations, and module definitions
    for (int i = 0; i < body.heirs().length; i++) {
      TreeNode def = body.heirs()[i];

      if (def.getImage().equals("N_Module")) {
	// We encounter an new (inner) module
        // Pick off name of inner module
        ModulePointer innerModule = new ModulePointer(spec, this,def);

        // Indicate that the inner module is inner to the current module
        currentRelatives.directInnerModules.addElement( innerModule );

        // Recursive call to determine module relationships for the inner module
        determineModuleRelationships(innerModule, currentModule); 
      }
/************************ code removed by LL on 6 Aug 2007

      else if (def.getImage().equals("N_Instance")) {
	// We encounter an INSTANCE decl
        TreeNode[] instanceHeirs = def.heirs();
        int nonLocalInstanceNodeIX = 0;

        // The modifier "LOCAL" may or may not appear in the syntax
        // tree; if so, offset by 1.
        if (instanceHeirs[0].getImage().equals("LOCAL")) {
          nonLocalInstanceNodeIX = 1;
	}

        // Find the name of the module being instantiated
        String instanceModuleName = instanceHeirs[nonLocalInstanceNodeIX].heirs()[1].getImage();

        // Append it to the Vector of instantiated modules
        currentRelatives.directlyInstantiatedModuleNames.addElement(instanceModuleName);
      }
      else if ( def.getImage().equals("N_ModuleDefinition") ) {
	// We encounter a module definition (i.e. D(x,y) == INSTANCE Modname WITH ...)
	// that counts as an instance also
        TreeNode[] instanceHeirs = def.heirs();
        int nonLocalInstanceNodeIX = 2;

        // The modifier "LOCAL" may or may not appear in the syntax
        // tree; if so, offset by 1.
        if (instanceHeirs[0].getImage().equals("LOCAL")) {
          nonLocalInstanceNodeIX = 3;
	}

        // Find the name of the module being instantiated
        String instanceModuleName = instanceHeirs[nonLocalInstanceNodeIX].heirs()[1].getImage();

        // Append it to the Vector of instantiated modules
        currentRelatives.directlyInstantiatedModuleNames.addElement(instanceModuleName);
      }
// BUG:  The following doesn't work
//
//   INSTANCE Test2 WITH B <- LET f == INSTANCE Test1 IN TRUE
//
// because getInstanceInLet is not being executed on the LET 
// expresssion inside the WITH, so Test1 isn't being
// found.

// XXXXXX we need to look for INSTANCEs inside proofs of theoremss.
      else {
	// We also need to look for INSTANCE in Let constructs
	this.getInstanceInLet(def, currentRelatives);
      }
************ end code eliminated by LL on 6 Aug 2007 ******/
      else { this.getInstances(def, currentRelatives); } ;
    } // end for

    /***
    System.err.println("  Leaving determineModuleRelationships for currentModule " +
		       currentModule.getName() +  ", with parent " +
		       (parent != null ? parent.getName() : "null") + "\n>");
    System.err.println("ModuleRelationships =" +  spec.getModuleRelationships());
    ***/
  }

  /*************************************************************************
  * If we want to allow plain INSTANCEs inside a LET, this method must be  *
  * modified accordingly.                                                  *
  * @deprecated not used (no local references)
  *************************************************************************/
  private void getInstanceInLet(TreeNode treeNode, ModuleRelatives currentRelatives) {
    TreeNode[] children = treeNode.heirs();  

    if (treeNode.getImage().equals("N_LetIn")) {
      TreeNode[] syntaxTreeNode = children[1].heirs();

      for (int i = 0; i < syntaxTreeNode.length; i++) {
	TreeNode def = syntaxTreeNode[i];
	if (def.getImage().equals("N_ModuleDefinition")) {
	  // We encounter a module definition (i.e. D(x,y) == INSTANCE Modname WITH ...)
	  // that counts as an instance also
	  TreeNode[] instanceHeirs = def.heirs();
	  int nonLocalInstanceNodeIX = 2;

	  // Find the name of the module being instantiated
	  String instanceModuleName = instanceHeirs[nonLocalInstanceNodeIX].heirs()[1].getImage();

	  // Append it to the Vector of instantiated modules
	  currentRelatives.directlyInstantiatedModuleNames.addElement(instanceModuleName);
	} // if (def.getImage().equals("N_ModuleDefinition"))
	else {
	  TreeNode[] defChildren = def.heirs();
	  for (int j = 0; j < defChildren.length; j++) {
	    this.getInstanceInLet(defChildren[j], currentRelatives);
	  }
	}
      }
    } // if (treeNode.getImage().equals("N_LetIn"))
    else {
      for (int i = 0; i < children.length; i++) {
	this.getInstanceInLet(children[i], currentRelatives);
      }
    }
  } // getInstanceInLet 


  private void getInstances(TreeNode treeNode, 
                            ModuleRelatives currentRelatives) {
    /***********************************************************************
    * This is a very simple-minded method that walks the syntactic parse   *
    * tree at node treeNode and hunts for N_NonLocalInstance nodes and,    *
    * for each one it finds, adds the module name to the                   *
    * directlyInstantiatedModuleNames vector of currentRelatives.  There   *
    * is much that could be done to avoid walking down dead-end branches.  *
    * However, most of the nodes in real specs are expression nodes, and   *
    * they have to be searched to find the INSTANCEs inside LET/INs.  So,  *
    * I don't think that optimizing the search would save much time.       *
    ***********************************************************************/
    TreeNode[] children = treeNode.heirs();  

    int i = 0 ;
    if (treeNode.getImage().equals("N_NonLocalInstance")) {
      /*********************************************************************
      * Note: We need to scan the children of a NonLocalInstance node      *
      * because a substitution in the WITH could contain a LET with an     *
      * INSTANCE.                                                          *
      *********************************************************************/
      currentRelatives.directlyInstantiatedModuleNames.addElement(
         children[1].getImage() );
         // System.err.println("Found Instance: " + children[1].getImage()) ;
      i = 2 ;
     }; 

    for (int j = i ; j < children.length ; j++) {
      getInstances(children[j], currentRelatives) ;
     } ;      
  } // getInstances

}



<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/job/TLCJobFactory.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.job;

import java.io.File;
import java.util.Properties;

import org.eclipse.core.runtime.jobs.Job;

import util.MailSender;

public interface TLCJobFactory {

	final String MAIN_CLASS = "mainClass";
	final String MAIL_ADDRESS = MailSender.MAIL_ADDRESS;
	final String SPEC_NAME = MailSender.SPEC_NAME;
	final String MODEL_NAME = MailSender.MODEL_NAME;
	
	Job getTLCJob(String aName, File aModelFolder, int numberOfWorkers, Properties props, String string);
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/preference/GeneralPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.preference;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * This class represents the general preference page that
 * is contributed to the Preferences dialog. By 
 * subclassing <samp>FieldEditorPreferencePage</samp>, we
 * can use the field support built into JFace that allows
 * us to create a page that is small and knows how to 
 * save, restore and apply itself.
 * <p>
 * This page is used to modify preferences only. They
 * are stored in the preference store that belongs to
 * the main plug-in class. That way, preferences can
 * be accessed directly via the preference store.
 * @author <NAME>
 * @version $Id$
 */
public class GeneralPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{
    /**
     * The default value for the minimum size (in kbytes) of storage occupied by
     * the spec that is displayed.
     */
    public static final int MIN_DISPLAYED_SIZE_DEFAULT = 50000;
	private LibraryPathComposite libraryPathComposite;
    
    public GeneralPreferencePage()
    {
        super(GRID);
        setPreferenceStore(PreferenceStoreHelper.getInstancePreferenceStore());
        setDescription("General toolbox preferences");
    }
    
    protected Control createContents(Composite parent)
    {
        Control pageControl = super.createContents(parent);
        
        libraryPathComposite = new LibraryPathComposite(this);
        
        UIHelper.setHelp(pageControl, IHelpConstants.GENERAL_PREFERENCE_PAGE);
        return pageControl;
    }
    
    /**
     * Creates the field editors. Field editors are abstractions of
     * the common GUI blocks needed to manipulate various types
     * of preferences. Each field editor knows how to save and
     * restore itself.
     */
    public void createFieldEditors()
    {
        /*
        addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, "&Directory preference:", getFieldEditorParent()));
        addField(new BooleanFieldEditor(PreferenceConstants.P_BOOLEAN, "&An example of a boolean preference",
                getFieldEditorParent()));

        addField(new RadioGroupFieldEditor(PreferenceConstants.P_CHOICE, "An example of a multiple-choice preference",
                1, new String[][] { { "&Choice 1", "choice1" }, { "C&hoice 2", "choice2" } }, getFieldEditorParent()));
        addField(new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent()));
        */
        addField(new BooleanFieldEditor(IPreferenceConstants.I_RESTORE_LAST_SPEC,
                "&Continue Previous Session on Restart", getFieldEditorParent()));
        
        IntegerFieldEditor minStorageSizeEditor = 
             new IntegerFieldEditor(IPreferenceConstants.I_MIN_DISPLAYED_SIZE, 
                "&Minimum spec storage displayed (in kilobytes)", getFieldEditorParent());
        addField(minStorageSizeEditor);
        minStorageSizeEditor.setValidRange(0, 2000000);
    }

    /**
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
    public void init(IWorkbench workbench)
    {
    }

	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.PreferencePage#performOk()
	 */
	public boolean performOk() {
		libraryPathComposite.applyChanges();
		return super.performOk();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.PreferencePage#performApply()
	 */
	protected void performApply() {
		libraryPathComposite.applyChanges();
		super.performApply();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()
	 */
	protected void performDefaults() {
		libraryPathComposite.performInit();
		super.performDefaults();
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/contribution/ModuleListContributionItem.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.contribution;

import java.util.HashMap;
import java.util.Vector;

import org.eclipse.core.resources.IResource;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.handler.AddModuleHandler;
import org.lamport.tla.toolbox.ui.handler.OpenModuleHandler;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tlc2.output.SpecWriterUtilities;

/**
 * Contribution item for opening the modules
 */
public class ModuleListContributionItem extends CompoundContributionItem
{
    private ImageDescriptor rootIcon = UIHelper.imageDescriptor("icons/full/obj16/ftr_mf_obj.gif");
    private ImageDescriptor icon = UIHelper.imageDescriptor("icons/full/obj16/file_obj.gif");
    private ImageDescriptor iconAddModule = UIHelper.imageDescriptor("icons/full/newmodule_wiz.gif");    

    
    /**
     * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems()
     */
    protected IContributionItem[] getContributionItems()
    {
        final Spec spec = Activator.getSpecManager().getSpecLoaded();
        final Vector<IContributionItem> moduleContributions = new Vector<IContributionItem>();
        HashMap<String, String> parameters = new HashMap<String, String>();
        
        // create the contribution item for add module
        CommandContributionItemParameter param = new CommandContributionItemParameter(UIHelper.getActiveWindow(),
                "toolbox.command.module.add", AddModuleHandler.COMMAND_ID, parameters, iconAddModule, null, null,
                "Add TLA+ Module...", null, "Adds new TLA+ Module to the specification",
                CommandContributionItem.STYLE_PUSH, null, true);

        // add contribution item to the list
        moduleContributions.add(new CommandContributionItem(param));
        moduleContributions.add(new Separator());

        if (spec != null)
        {
            final IResource[] modules = spec.getModuleResources();
            final IResource rootModule = spec.getRootFile();
            boolean isRoot;
            for (int i = 0; i < modules.length; i++)
            {
                // skip non-modules and non-existing files
                if (!ResourceHelper.isModule(modules[i]))
                {
                    continue;
                } 
                

                isRoot = rootModule.equals(modules[i]);

                parameters = new HashMap<String, String>();
                // fill the module name for the handler
                parameters.put(OpenModuleHandler.PARAM_MODULE, SpecWriterUtilities.getModuleNameChecked(
                        modules[i].getName(), false));

                // create the contribution item
                param = new CommandContributionItemParameter(UIHelper.getActiveWindow(), "toolbox.command.module.open."
                        + modules[i].getName(), OpenModuleHandler.COMMAND_ID, parameters, ((isRoot) ? rootIcon : icon),
                        null, null, modules[i].getName(), null, "Opens " + modules[i].getName(),
                        CommandContributionItem.STYLE_PUSH, null, true);

                // add contribution item to the list
                moduleContributions.add(new CommandContributionItem(param));
            }
        }
        return (IContributionItem[]) moduleContributions.toArray(new IContributionItem[moduleContributions.size()]);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/Combinatorics.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.util;

import java.math.BigInteger;

import tlc2.output.EC;
import util.Assert;

public class Combinatorics {

  public static final int MAXCHOOSENUM = 62;
	public static final int CHOOSETABLESIZE = (MAXCHOOSENUM - 3) * (MAXCHOOSENUM - 4) / 2 + MAXCHOOSENUM - 3;
	public static long[] CHOOSETABLE = new long[CHOOSETABLESIZE];
  private static long[] SUMCHOOSETABLE = new long[CHOOSETABLESIZE];

  public static long choose(int n, int m) {
		if (n < 0 || m < 0) {
    Assert.check(((m >= 0) && (n >= 0) && (n >= m)), EC.TLC_CHOOSE_ARGUMENTS_WRONG, "choose");
		}
		if (m == 0 || m == n) {
      return (long)1;
		} else if (m == 1 || m == n - 1) {
      return (long)n;
		} else if (n == 0 || m > n) {
			// Cannot choose from zero elements or more elements than present.
			return 0;
		} else {
      int j = choosePairToInt(n, m);
      if (j < CHOOSETABLESIZE) {
	return CHOOSETABLE[j];
      }
			return binomial(n, m); // calculate on demand
    }
  }

	public static long sumChoose(int n, int m) {
      Assert.check(((m>=0) && (n>=0) && (n>=m)), EC.TLC_CHOOSE_ARGUMENTS_WRONG, "sumChoose");
		if (m == 0) {
          return (long)1;
		} else if (m == n) {
          return ((long)1 << n);
		} else if (m == 1) {
          return (long)n;
		} else if (m == n - 1) {
          return ((long)2 << n) - n;
		} else {
          int j = choosePairToInt(n,m);
			if (j < CHOOSETABLESIZE) {
              return SUMCHOOSETABLE[j];
          }
          Assert.fail(EC.TLC_CHOOSE_UPPER_BOUND, String.valueOf(MAXCHOOSENUM));
          // make the compiler happy
          return Long.MIN_VALUE;
      }
  }
	     
	public static int choosePairToInt(int n, int m) {
    return ((n-3)*(n-4))/2 + m -2;
  }

  static {
    int i, n, m;
    long sum;
    
    n = 4;
    m = 2;
    sum = 5;
    for (i = 0; i < CHOOSETABLESIZE; i++) {
      CHOOSETABLE[i] = choose(n-1,m)+choose(n-1,m-1);
      sum += CHOOSETABLE[i];
      SUMCHOOSETABLE[i] = sum;
      if (n == m+2) {
	n++;
	m = 2;
	sum = 1+n;
			} else
	m++;
    }
  }

  public static BigInteger toNum(BigInteger[] B, BigInteger[] N, int len) {
    Assert.check((B.length >= len) && (len > 0), EC.SYSTEM_INDEX_ERROR);

    BigInteger num = N[len-1];
    for (int i = len-2; i >= 0; i--) {
      num = num.multiply(B[i]).add(N[i]);
    }
    return num;
  }
  
  public static BigInteger toNum(BigInteger[] B, BigInteger[] N) {
    return toNum(B, N, B.length);
  }

  public static BigInteger[] toSeq(BigInteger[] B, BigInteger n, int len) {
    Assert.check((B.length >= len) && (len != 0), EC.SYSTEM_INDEX_ERROR);

    BigInteger[] nlist = new BigInteger[len];
    BigInteger num = n;
    BigInteger base = B[0];
    nlist[0] = num.remainder(base);
    for (int i = 1; i < len; i++) {
      num = num.divide(base);
      base = B[i];
      nlist[i] = num.remainder(base);
    }
    return nlist;
  }
  
  public static BigInteger[] toSeq(BigInteger[] B, BigInteger n) {
    return toSeq(B, n, B.length);
  }

  public static BigInteger fact(int n) {
    BigInteger result = BigInt.BigOne;

    for (int i = n; i > 1; i--)
      result = result.multiply(BigInteger.valueOf(i));
    return result;
  }

  public static BigInteger bigChoose(int n, int m) {
		if (n < MAXCHOOSENUM && m < MAXCHOOSENUM) {
			return BigInteger.valueOf(choose(n, m));
		}

		BigInteger binomial = BigInteger.ONE;
		for (int i = 1, j = n; i <= m; i++, j--) {
			final BigInteger bj = BigInteger.valueOf(j);
			final BigInteger bi = BigInteger.valueOf(i);
			binomial = binomial.multiply(bj).divide(bi);
		}
		return binomial;
	}
	
	public static BigInteger slowBigChoose(int n, int m) {
    BigInteger num = fact(n);
    BigInteger denom = fact(n - m).multiply(fact(m));

    return num.divide(denom);
  }

  public static BigInteger bigSumChoose(int n, int m) {
    BigInteger result;

    if ((n/2) >= m) {
      result = BigInt.BigZero;
      for (int i = 0; i <= m; i++) 
	result = result.add(bigChoose(n, i));
		} else {
      result = BigInt.BigOne;
      result = result.shiftLeft(n);
      for (int i = m+1; i <= n; i++) 
	result = result.subtract(bigChoose(n, i));
    }
    return result;
  }

  public static String print (BigInteger[] A) {
    StringBuffer sb = new StringBuffer();
    for (int i=0; i<A.length; i++) {
      sb.append(A[i].toString());
      sb.append(", ");
    }
    return new String(sb);
  }

	// https://blog.plover.com/math/choose.html
	public static final long binomial(int n, int k) {
		if (k > n) {
			return 0;
		}
		if (k > n - k) {
			// Optimize to n choose n - k.
			k = n - k;
		}

		long binomial = 1L;
		for (int i = 1, m = n; i <= k; i++, m--) {
			binomial = binomial * m / i;
		}
		return binomial;
	}

	public static long[] pascalTableUpTo(final int maxN, final int maxK) {
		if (maxN > MAXCHOOSENUM) {
			final long[] ppt = new long[((maxN - MAXCHOOSENUM) * (maxK - 1))];
			int idx = 0;

			// Initialize first "row" of extension table from existing triangle.
			int i = MAXCHOOSENUM + 1;
			for (int j = 2; j <= maxK; j++) {
				ppt[idx++] = choose(i, j);
			}
			// Subsequent rows initialize from previous row.
			final int k = maxK - 1;
			for (int j = 1; j < (maxN - MAXCHOOSENUM); j++) {
				for (int l = 0; l < k; l++) {
					if (l == 0) {
						ppt[idx] = i++ + ppt[idx - k];
					} else {
						ppt[idx] = ppt[idx - k] + ppt[idx - k - 1];
					}
					idx++;
				}
			}
			return ppt;
		}
		return new long[0];
	}


// SZ Jul 14, 2009: Dead code. not used.
//  public static void main(String argv[]) {
//    int i,j;
//    BigInteger b;
//    // Date d1,d2;
//    // SZ Feb 24, 2009: not used
//    BigInteger [] A = new BigInteger[16];
//    BigInteger [] B = new BigInteger[16];
//    BigInteger [] C;
//    Random r = new Random();
//
//    
//    for (i=0; i<8; i++) {
//      B[2*i] = BigInteger.valueOf(1048576);
//      B[2*i+1] = BigInteger.valueOf(1024);
//    }
//
//    
//    for (j = 0; j < 200; j++) {
//      for (i = 0; i < 8; i++) {
//	A[2*i] = new BigInteger(20, r);
//	A[2*i+1] = new BigInteger(10, r);
//      }
//      ToolIO.out.println("A is "+print(A));
//      b = toNum(B, A);
//      C = toSeq(B, b);
//      ToolIO.out.println("C is "+print(C));
//      for (i = 0; i < 16; i++)
//	if (!C[i].equals(A[i]))
//	    ToolIO.out.println("***********Error***********");
//      ToolIO.out.println("b is " + b);
//    }      
//  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/SpecTraceExpressionWriter.java<|end_filename|>
package tlc2.output;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import tlc2.model.Assignment;
import tlc2.model.Formula;
import tlc2.model.MCState;
import tlc2.model.MCVariable;
import tlc2.model.TraceExpressionInformationHolder;
import tlc2.tool.impl.ModelConfig;
import util.TLAConstants;

/**
 * This is a reified class of spec writer which can produce specs capable of containing trace expressions; it is also
 * 	the parent class for a more specialized version used by the toolbox, {@code TraceExpressionModelWriter}.
 */
public class SpecTraceExpressionWriter extends AbstractSpecWriter {
	private static final String TRACE_EXPRESSION_VARIABLE = "TraceExp";
	private static final String TRI_INDENT = TLAConstants.INDENT + TLAConstants.INDENT + TLAConstants.INDENT;
	
	/**
	 * This will generate three identifiers equal to the initial and next state
	 * predicate for the trace, and the action constraint.
	 * 
	 * @param tlaBuffer the buffer into which the TLA code will be placed
	 * @param cfgBuffer if non-null, the buffer into which the CFG code will be placed
	 * @param trace
	 * @param expressionData data on trace explorer expressions, can be null
	 * @return String[], first element is the identifier for the initial state predicate,
	 * second element is the identifier for the next-state action, the third element is the identifier for
	 * the action contraint
	 * @see #addInitNextToBuffers(StringBuilder, StringBuilder, List, TraceExpressionInformationHolder[], String, String, String)
	 */
	public static String[] addInitNextToBuffers(final StringBuilder tlaBuffer, final StringBuilder cfgBuffer,
			final List<MCState> trace, final TraceExpressionInformationHolder[] expressionData) {
	    final String initId = SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.INIT_SCHEME);
	    final String nextId = SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.NEXT_SCHEME);
	    final String actionConstraintId = SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.ACTIONCONSTRAINT_SCHEME);
	
	    addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId);
	
	    return new String[] { initId, nextId, actionConstraintId };
	}
	
	/**
	 * This calls:
	 * 	{@code addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId, TLAConstants.Schemes.NEXT_SCHEME, false);}
	 * 
	 * @param tlaBuffer the buffer into which the TLA code will be placed
	 * @param cfgBuffer if non-null, the buffer into which the CFG code will be placed
	 * @param trace
	 * @param expressionData data on trace explorer expressions, can be null
	 * @param initId the identifier to be used for the initial state predicate, cannot be null
	 * @param nextId the identifier to be used for the next-state action, cannot be null
	 * @param actionConstraintId the indentified used for the action constraint
	 * @see #addInitNextToBuffers(StringBuilder, StringBuilder, List, TraceExpressionInformationHolder[], String, String, String, String)
	 */
	public static void addInitNextToBuffers(final StringBuilder tlaBuffer, final StringBuilder cfgBuffer,
			final List<MCState> trace, final TraceExpressionInformationHolder[] expressionData, final String initId,
			final String nextId, final String actionConstraintId) {
		addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId,
							 TLAConstants.Schemes.NEXT_SCHEME, false);
	}

	/**
	 * This calls:
	 * 	{@code addInitNextToBuffers(cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId, nextSubActionBasename, leaveStubsForTraceExpression);}
	 * and then concatenates the returned {@code StringBuilder} instances in order to tlaBuffer.
	 * 
	 * @param tlaBuffer the buffer into which the TLA code will be placed
	 * @param cfgBuffer if non-null, the buffer into which the CFG code will be placed
	 * @param trace
	 * @param expressionData data on trace explorer expressions, can be null
	 * @param initId the identifier to be used for the initial state predicate, cannot be null
	 * @param nextId the identifier to be used for the next-state action, cannot be null
	 * @param actionConstraintId the identifier used for the action constraint
	 * @param nextSubActionBasename the base string to be used as the prefix to unique names for next sub-actions
	 * @param leaveStubsForTraceExpression if true, then a variable will be defined {@link TRACE_EXPRESSION_VARIABLE},
	 * 						yet commented out, and similarly conjoined, but commented out in the SpecTE Init and Next
	 * 						declarations
	 */
	public static void addInitNextToBuffers(final StringBuilder tlaBuffer, final StringBuilder cfgBuffer,
			final List<MCState> trace, final TraceExpressionInformationHolder[] expressionData, final String initId,
			final String nextId, final String actionConstraintId, final String nextSubActionBasename,
			final boolean leaveStubsForTraceExpression) {
		final StringBuilder[] tlaBuffers = addInitNextToBuffers(cfgBuffer, trace, expressionData, initId, nextId,
				actionConstraintId, nextSubActionBasename, leaveStubsForTraceExpression);
		
		tlaBuffer.append(tlaBuffers[0].toString());
		tlaBuffer.append(tlaBuffers[1].toString());
	}

	/**
	 * This will set initId equal to the initial state predicate, nextId equal to the next state
	 * action for the trace, and actionConstraintId equal to the action constraint for the trace.
	 * If expressionData is not null, it should contain information about trace explorer expressions. This
	 * information is used to appropriately put the variables representing trace explorer expressions
	 * in the trace. In the following example, trace explorer expressions are used, but if expressionData
	 * is null, those variables will not appear in the init and next definitions, but everything else will be the same.
	 * 
	 * Note: In the following example, the expressions expr1,...,expr6, texpr1, texpr2 can take up multiple
	 * lines.
	 * 
	 * Consider the following trace:
	 * 
	 * <Initial predicate> <State num 1>
	 * var1=expr1
	 * var2=expr2
	 * 
	 * <Action...> <State num 2>
	 * var1=expr3
	 * var2=expr4
	 * 
	 * <Action...> <State num 3>
	 * var1=expr5
	 * var2=expr6
	 * 
	 * The user has defined two expressions in the trace explorer:
	 * 
	 * texpr1 (level 2 represented by var3)
	 * texpr2 (level 1 represented by var4)
	 * 
	 * This method defines the following identifiers:
	 * 
	 * init_4123123123 ==
	 * var1=(
	 * expr1
	 * )/\
	 * var2=(
	 * expr2
	 * )/\
	 * var3=(
	 * "--"
	 * )/\
	 * var4=(
	 * texpr2
	 * )
	 * 
	 * next_12312312312 ==
	 * (var1=(
	 * expr1
	 * )/\
	 * var2=(
	 * expr2
	 * )/\
	 * var1'=(
	 * expr3
	 * )/\
	 * var2'=(
	 * expr4
	 * )/\
	 * var3'=(
	 * texpr1
	 * )/\
	 * var4'=(
	 * texpr2
	 * )')
	 * \/
	 * (var1=(
	 * expr3
	 * )/\
	 * var2=(
	 * expr4
	 * )/\
	 * var1'=(
	 * expr5
	 * )/\
	 * var2'=(
	 * expr6
	 * )/\
	 * var3'=(
	 * texpr1
	 * )/\
	 * var4'=(
	 * texpr2
	 * )')
	 * 
	 * If the last state is back to state i, then this method treats
	 * the trace as if it has the state labeled "Back to state i" removed and
	 * replaced with a copy of state i.
	 * 
	 * If the last state is stuttering, then this method treats the trace as if it
	 * has the state labeled "Stuttering" removed and replaced with a copy
	 * of the state before the state labeled "Stuttering".
	 * 
	 * @param cfgBuffer if non-null, the buffer into which the CFG code will be placed
	 * @param trace
	 * @param expressionData data on trace explorer expressions, can be null
	 * @param initId the identifier to be used for the initial state predicate, cannot be null
	 * @param nextId the identifier to be used for the next-state action, cannot be null
	 * @param actionConstraintId the indentified used for the action constraint
	 * @param nextSubActionBasename the base string to be used as the prefix to unique names for next sub-actions
	 * @param leaveStubsForTraceExpression if true, then a variable will be defined {@link TRACE_EXPRESSION_VARIABLE},
	 * 						yet commented out, and similarly conjoined, but commented out in the SpecTE Init and Next
	 * 						declarations
	 * @return an array of length 2, the first element is a buffer containing all trace expression subaction
	 * 				declarations followed by the action constraint definition; the second element is a buffer
	 * 				containing a potential VARIABLE stub for the trace expression variable, followed by the
	 * 				definitions for Init and finally Next.
	 */
	public static StringBuilder[] addInitNextToBuffers(final StringBuilder cfgBuffer,
													   final List<MCState> trace,
													   final TraceExpressionInformationHolder[] expressionData,
													   final String initId, final String nextId,
													   final String actionConstraintId,
													   final String nextSubActionBasename,
													   final boolean leaveStubsForTraceExpression) {
		if (trace.size() > 0) {
	        final Iterator<MCState> it = trace.iterator();
	        MCState currentState = it.next();
	        final StringBuilder subActionsAndConstraint = new StringBuilder();
	        final StringBuilder initAndNext = new StringBuilder();
	
	        /*******************************************************
	         * Add the init definition.                            *
	         *******************************************************/
			if (cfgBuffer != null) {
				cfgBuffer.append(TLAConstants.CR);
				cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.INIT).append(TLAConstants.CR);
				cfgBuffer.append(initId).append(TLAConstants.CR);
			}
			
			if (leaveStubsForTraceExpression) {
				initAndNext.append(TLAConstants.COMMENT).append(TLAConstants.KeyWords.VARIABLE).append(' ');
				initAndNext.append(TRACE_EXPRESSION_VARIABLE).append(TLAConstants.CR).append(TLAConstants.CR);
			}
	
			initAndNext.append(TLAConstants.COMMENT).append("TRACE INIT definition ");
			initAndNext.append(TLAConstants.TraceExplore.TRACE_EXPLORE_INIT).append(TLAConstants.CR);
			initAndNext.append(initId).append(TLAConstants.DEFINES_CR);
	        final MCVariable[] vars = currentState.getVariables();
	
	        // variables from spec
			for (int i = 0; i < vars.length; i++) {
	            final MCVariable var = vars[i];
	            /*
	             *    /\ var = (
	             *            expr
	             *          )
	             */
	            initAndNext.append(TLAConstants.INDENTED_CONJUNCTIVE);
	            initAndNext.append(var.getName()).append(TLAConstants.EQ).append(TLAConstants.L_PAREN);
	            initAndNext.append(TLAConstants.CR);
	            
	            initAndNext.append(var.getValueAsStringReIndentedAs(TRI_INDENT)).append(TLAConstants.CR);
	            
	            initAndNext.append(TLAConstants.INDENT).append(TLAConstants.INDENT);
	            initAndNext.append(TLAConstants.R_PAREN).append(TLAConstants.CR);
	        }
	
	        // variables representing trace explorer expressions
			if (expressionData != null) {
				for (int i = 0; i < expressionData.length; i++) {
	                final TraceExpressionInformationHolder expressionInfo = expressionData[i];
	                initAndNext.append(TLAConstants.INDENTED_CONJUNCTIVE);
	                initAndNext.append(expressionInfo.getVariableName()).append(TLAConstants.EQ);
	                initAndNext.append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	
	                initAndNext.append(TRI_INDENT);
					if (expressionInfo.getLevel() == 2) {
	                    // add "--" if the expression is temporal level
						initAndNext.append(TLAConstants.TRACE_NA);
					} else {
	                    // add the actual expression if it is not temporal level
						initAndNext.append(expressionInfo.getIdentifier());
	                }
	
					initAndNext.append(TLAConstants.CR).append(TLAConstants.INDENT).append(TLAConstants.INDENT);
		            initAndNext.append(TLAConstants.R_PAREN).append(TLAConstants.CR);
	            }
	        }
			
			if (leaveStubsForTraceExpression) {
				initAndNext.append(TLAConstants.COMMENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
				initAndNext.append(TRACE_EXPRESSION_VARIABLE).append(TLAConstants.EQ);
				initAndNext.append(TLAConstants.KeyWords.TRUE).append(TLAConstants.CR);
			}
	
			initAndNext.append(CLOSING_SEP).append(TLAConstants.CR);
	
	        /**********************************************************
	         *  Now add the next state actions definition             *
	         **********************************************************/
			if (cfgBuffer != null) {
				cfgBuffer.append(TLAConstants.COMMENT).append(TLAConstants.KeyWords.NEXT).append(" definition");
				cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.NEXT).append(TLAConstants.CR);
				cfgBuffer.append(nextId).append(TLAConstants.CR);
			}
	
	        MCState nextState;
	        final boolean isSingleState;
			if (it.hasNext()) {
				nextState = it.next();
				isSingleState = false;
			} else {
	            nextState = currentState;
	            isSingleState = true;
	        }
	
	        /*
	         * MAK 09/25/2019: Previously, TE.tla was a next-state relation consisting of
	         * disjuncts of (unnamed) sub-actions:
	         * 
	         * Next_123 == (x=1 /\ x'=2) \/ (x=2 /\ x'=3) \/ ... \/ (x=42 /\ x'=42)
	         * 
	         * At runtime, TLC created an Action for each sub-action of the next-state
	         * relation (42 for the example above).
	         */
	        final StringBuilder nextDisjunctBuffer = new StringBuilder();
	        nextDisjunctBuffer.append(nextId).append(TLAConstants.DEFINES_CR);
	        final String firstIndent;
			if (leaveStubsForTraceExpression) {
				nextDisjunctBuffer.append(TLAConstants.TLA_AND).append(' ');
				firstIndent = " ";
			} else {
				firstIndent = TLAConstants.INDENT;
			}
	        
	        final StringBuilder actionConstraintBuffer = new StringBuilder();
	        actionConstraintBuffer.append(actionConstraintId).append(TLAConstants.DEFINES_CR);
	        actionConstraintBuffer.append(TLAConstants.BEGIN_TUPLE).append(TLAConstants.CR);
	
			if (cfgBuffer != null) {
				cfgBuffer.append(TLAConstants.COMMENT).append("Action Constraint definition").append(TLAConstants.CR);
				cfgBuffer.append(TLAConstants.COMMENT).append(TLAConstants.KeyWords.ACTION_CONSTRAINT).append(TLAConstants.CR);
				cfgBuffer.append(TLAConstants.COMMENT).append(actionConstraintId).append(TLAConstants.CR);
			}

	        int subActionIndex = 0;
			while (nextState != null) {
				final String nextDisjunct = String.format("%s_sa_%d", nextSubActionBasename, subActionIndex);
				nextDisjunctBuffer.append((subActionIndex == 0) ? firstIndent : TLAConstants.INDENT);
				nextDisjunctBuffer.append(TLAConstants.TLA_OR).append(' ').append(nextDisjunct).append(TLAConstants.CR);
		        actionConstraintBuffer.append(nextDisjunct);
		        	        	
		        subActionsAndConstraint.append(TLAConstants.COMMENT).append("TRACE Sub-Action definition ");
		        subActionsAndConstraint.append(subActionIndex++).append(TLAConstants.CR);
		        subActionsAndConstraint.append(nextDisjunct).append(TLAConstants.DEFINES_CR);
	            /*
	             * Handle Back to state and stuttering.
	             * 
	             * nextState is assigned to the state which the "Back to state"
	             * or "Stuttering" state represents. If nextState is "Back to state i",
	             * then it is assigned to state i. If nextState is "Stuttering", then
	             * it is assigned to the current state.
	             */
				if (nextState.isBackToState()) {
					nextState = trace.get(nextState.getStateNumber() - 1);
				} else if (nextState.isStuttering()) {
					nextState = currentState;
				}
	
	            /*
	             * Write the action:
	             * 
	             * (/\ var1=(
	             * expr1
	             * )
	             * /\ var2=(
	             * expr2
	             * )
	             * /\ var1'=(
	             * expr3
	             * )
	             * /\ var2'=(
	             * expr4
	             * ))
	             */
				subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	
	            final MCVariable[] currentStateVars = currentState.getVariables();
	            final MCVariable[] nextStateVars = nextState.getVariables();
	
	            /*
	             * Iterate through current state variables. This adds:
	             * 
	             * /\ var1=(
	             * expr1
	             * )
	             * /\ var2=(
	             * expr2
	             * )
	             * 
	             */
				for (int i = 0; i < currentStateVars.length; i++) {
					final MCVariable currentStateVar = currentStateVars[i];
					subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
					subActionsAndConstraint.append(currentStateVar.getName()).append(TLAConstants.EQ);
					subActionsAndConstraint.append(TLAConstants.L_PAREN).append(TLAConstants.CR);
					subActionsAndConstraint.append(currentStateVar.getValueAsStringReIndentedAs(TRI_INDENT + TLAConstants.INDENT));
					subActionsAndConstraint.append(TLAConstants.CR);
					subActionsAndConstraint.append(TRI_INDENT).append(TLAConstants.R_PAREN).append(TLAConstants.CR);
	            }
	
	            /*
	             * If the trace is a single state, make the next state
	             * action never enabled. The model will deadlock in the initial state.
	             * This adds:
	             * 
	             * /\ FALSE
	             */
				if (isSingleState) {
					subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
					subActionsAndConstraint.append("FALSE").append(TLAConstants.CR);
	            }
	
	            /*
	             * Iterate through next state variables. This adds:
	             * 
	             * /\ var1'=(
	             * expr3
	             * )
	             * /\ var2'=(
	             * expr4
	             * )
	             */
				for (int i = 0; i < currentStateVars.length; i++) {
	                final MCVariable nextStateVar = nextStateVars[i];
	                subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
	                subActionsAndConstraint.append(nextStateVar.getName()).append(TLAConstants.PRIME);
	                subActionsAndConstraint.append(TLAConstants.EQ).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
					subActionsAndConstraint.append(nextStateVar.getValueAsStringReIndentedAs(TRI_INDENT + TLAConstants.INDENT));
					subActionsAndConstraint.append(TLAConstants.CR);
					subActionsAndConstraint.append(TRI_INDENT).append(TLAConstants.R_PAREN).append(TLAConstants.CR);
	            }
	
	            /*
	             * Iterate through the trace explorer expressions if there are any. This adds:
	             * 
	             * /\ var3'=(
	             * texpr1
	             * )
	             * /\ var4'=(
	             * texpr2
	             * )'
	             * 
	             */
				if (expressionData != null) {
					for (int i = 0; i < expressionData.length; i++) {
	                    final TraceExpressionInformationHolder expressionInfo = expressionData[i];
		                subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
	                    subActionsAndConstraint.append(expressionInfo.getVariableName()).append(TLAConstants.PRIME);
	                    subActionsAndConstraint.append(TLAConstants.EQ).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	                    subActionsAndConstraint.append(TRI_INDENT);
	                    subActionsAndConstraint.append(expressionInfo.getIdentifier()).append(TLAConstants.CR);
	                    subActionsAndConstraint.append(TRI_INDENT).append(TLAConstants.R_PAREN);
	
						if (expressionInfo.getLevel() < 2) {
							subActionsAndConstraint.append(TLAConstants.PRIME);
	                    }
						subActionsAndConstraint.append(TLAConstants.CR);
	                }
	            }
	
				subActionsAndConstraint.append(TLAConstants.INDENT).append(TLAConstants.R_PAREN);
				subActionsAndConstraint.append(TLAConstants.CR).append(TLAConstants.CR);
	
				if (it.hasNext()) {
	                actionConstraintBuffer.append(TLAConstants.COMMA);
	            }
				actionConstraintBuffer.append(TLAConstants.CR);
	
	            currentState = nextState;
	
				if (it.hasNext()) {
					nextState = it.next();
				} else {
					nextState = null;
				}
	        }
	
	        initAndNext.append(TLAConstants.COMMENT).append("TRACE NEXT definition ");
	        initAndNext.append(TLAConstants.TraceExplore.TRACE_EXPLORE_NEXT).append(TLAConstants.CR);
	        initAndNext.append(nextDisjunctBuffer.toString());
			
			if (leaveStubsForTraceExpression) {
				initAndNext.append(TLAConstants.COMMENT).append(TLAConstants.TLA_AND).append(' ');
				initAndNext.append(TRACE_EXPRESSION_VARIABLE).append(TLAConstants.PRIME).append(TLAConstants.EQ);
				initAndNext.append(TRACE_EXPRESSION_VARIABLE).append(TLAConstants.CR);
			}
	        
			initAndNext.append(TLAConstants.CR).append(TLAConstants.CR);
	        
			
			/**
			 * Action Constraint
			 */
			subActionsAndConstraint.append(TLAConstants.COMMENT).append("TRACE Action Constraint definition ");
			subActionsAndConstraint.append(TLAConstants.TraceExplore.TRACE_EXPLORE_ACTION_CONSTRAINT);
			subActionsAndConstraint.append(TLAConstants.CR).append(actionConstraintBuffer.toString());
			subActionsAndConstraint.append(TLAConstants.END_TUPLE).append("[TLCGet(\"level\")]");

			subActionsAndConstraint.append(CLOSING_SEP).append(TLAConstants.CR);

			
	        return new StringBuilder[] { subActionsAndConstraint, initAndNext };
	    }
		
		return new StringBuilder[] { new StringBuilder(), new StringBuilder() };
	}

	public static String addTraceFunctionToBuffers(final StringBuilder tlaBuffer, final StringBuilder cfgBuffer,
			final List<MCState> input, final String id, final String configId) {
		// Filter stuttering or back2state instances from trace.
		final List<MCState> trace = input.stream()
				.filter(state -> !state.isBackToState() && !state.isStuttering())
				.collect(Collectors.toList());
		
		if (trace.isEmpty()) {
			return addArrowAssignmentIdToBuffers(tlaBuffer, cfgBuffer,
					new Assignment(TLAConstants.TraceExplore.TRACE, new String[0], TLAConstants.BEGIN_TUPLE + TLAConstants.END_TUPLE),
					id, configId);
	    }
		
		// Trace
		final StringBuilder traceFunctionDef = new StringBuilder();
		traceFunctionDef.append(TLAConstants.INDENT).append(TLAConstants.BEGIN_TUPLE).append(TLAConstants.CR);
		for (int j = 0; j < trace.size(); j++) {
			final MCState state = trace.get(j);

			traceFunctionDef.append(TLAConstants.INDENT).append(TLAConstants.L_PAREN).append(state.asSimpleRecord()).append(TLAConstants.R_PAREN);

			if (j < trace.size() - 1) {
				traceFunctionDef.append(TLAConstants.COMMA).append(TLAConstants.CR);
			}
		}
		traceFunctionDef.append(TLAConstants.CR).append(TLAConstants.INDENT).append(TLAConstants.END_TUPLE);
		traceFunctionDef.append(CLOSING_SEP).append(TLAConstants.CR);
		
		return addArrowAssignmentIdToBuffers(tlaBuffer, cfgBuffer,
				new Assignment(TLAConstants.TraceExplore.TRACE, new String[0], traceFunctionDef.toString()),
				id, configId);
	}
	
	
	public SpecTraceExpressionWriter() {
		super(true);
	}
	
	/**
	 * This only changes the tla file. This method generates and adds a variable declaration
	 * for each expression in the list. It also creates an identifier for each
	 * expression and defines the identifier to be that expression.
	 * It returns an array of {@link TraceExpressionInformationHolder} where each element
	 * contains the expression, the identifier, and the variable name.
	 * 
	 * If the expressions are x' + y and x > 3, The tla file will contain something like
	 * 
	 *\* comment line
	 * VARIABLES __trace_var_21034978347834, __trace_var_90234782309
	 * 
	 * \* comment line
	 * trace_def_3214234234234 ==
	 * x' + y
	 * ----
	 * 
	 * \* comment line
	 * trace_def_2342342342342 ==
	 * x > 3
	 * ----
	 * 
	 * @param expressions a list of formulas, each one an expression the user wants to have evaluated
	 * at each state of the trace
	 * @return array of {@link TraceExpressionInformationHolder} where each element
	 * contains the expression, the identifier, and the variable name
	 */
	public TraceExpressionInformationHolder[] createAndAddVariablesAndDefinitions(final List<Formula> expressions,
			final String attributeName) {
		final TraceExpressionInformationHolder[] expressionData
								= TraceExpressionInformationHolder.createHolders(expressions, attributeName);
	
	    addVariablesAndDefinitions(expressionData, attributeName, true);
	
	    return expressionData;
	}
	
	@Override
	public void addPrimer(final String moduleFilename, final String extendedModuleName) {
		addPrimer(moduleFilename, extendedModuleName, new HashSet<>());
	}

	/**
	 * Adds MODULE and EXTENDS statements.
	 */
	public void addPrimer(
			final String moduleFilename,
			final String extendedModuleName,
			final Set<String> extraExtendedModules) {
		if (extendedModuleName != null) {
			extraExtendedModules.add(extendedModuleName);
		}
		
		tlaBuffer.append(SpecWriterUtilities.getExtendingModuleContent(moduleFilename,
				extraExtendedModules.toArray(new String[extraExtendedModules.size()])));
	}
	
	/**
	 * Adds the trace expression stub to the TE spec.
	 * This is an alias function which applies the identity transformation
	 * to the spec's variables, with some comments explaining how to add
	 * additional transformations for custom trace expressions.
	 * @param moduleName Name of original module.
	 * @param teName Name of trace expression.
	 * @param variables Spec variables; transformed by identity.
	 */
	public void addTraceExpressionStub(String moduleName, String teName, final List<String> variables) {
		this.tlaBuffer.append(teName + TLAConstants.DEFINES + TLAConstants.CR);
		this.tlaBuffer
				.append(TLAConstants.INDENT + TLAConstants.L_SQUARE_BRACKET + TLAConstants.CR);

		// Create local string build for expression and comments so we can indent everything together in the end.
		StringBuilder localBuffer = new StringBuilder();

		localBuffer.append(TLAConstants.COMMENT).append(String.format("To hide variables of the `%s` spec from the error trace,", moduleName)).append(TLAConstants.CR);
		localBuffer.append(TLAConstants.COMMENT).append("remove the variables below.  The trace will be written in the order").append(TLAConstants.CR);
		localBuffer.append(TLAConstants.COMMENT).append("of the fields of this record.").append(TLAConstants.CR);
		
		localBuffer.append(
				variables.stream().map(var -> var + TLAConstants.RECORD_ARROW + var).collect(Collectors
						.joining(TLAConstants.CR + TLAConstants.COMMA))).append(TLAConstants.CR).append(TLAConstants.CR);	
						
		localBuffer.append(TLAConstants.COMMENT).append("Put additional constant-, state-, and action-level expressions here:").append(TLAConstants.CR);
		localBuffer.append(TLAConstants.COMMENT).append(",_stateNumber |-> _TEPosition").append(TLAConstants.CR);
		
		if (variables.size() > 0) {
			// Check that exists at least one variable so we can use
			// in the commented trace expressions.
			String someVar = variables.get(0);
			
			localBuffer.append(TLAConstants.COMMENT).append(String.format(",_%sUnchanged |-> %s = %s'", someVar, someVar, someVar)).append(TLAConstants.CR).append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append(String.format("Format the `%s` variable as Json value.", someVar)).append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append(String.format(",_%sJson |->", someVar)).append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT).append("LET J == INSTANCE Json").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT).append(String.format("IN J!ToJson(%s)", someVar))
				.append(TLAConstants.CR).append(TLAConstants.CR);
			
			localBuffer.append(TLAConstants.COMMENT).append("Lastly, you may build expressions over arbitrary sets of states by").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append("leveraging the _TETrace operator.  For example, this is how to").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append("count the number of times a spec variable changed up to the current").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append("state in the trace.").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT).append(String.format(",_%sModCount |->", someVar)).append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT).append("LET F[s \\in DOMAIN _TETrace] ==").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT + TLAConstants.INDENT).append("IF s = 1 THEN 0").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT + TLAConstants.INDENT)
				.append(String.format("ELSE IF _TETrace[s].%s # _TETrace[s-1].%s", someVar, someVar)).append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT + TLAConstants.INDENT + TLAConstants.INDENT)
				.append("THEN 1 + F[s-1] ELSE F[s-1]").append(TLAConstants.CR);
			localBuffer.append(TLAConstants.COMMENT + TLAConstants.INDENT).append("IN F[_TEPosition - 1]").append(TLAConstants.CR);		
		}
		
		this.tlaBuffer.append(indentString(localBuffer.toString(), 2));
		this.tlaBuffer.append(TLAConstants.CR + TLAConstants.INDENT + TLAConstants.R_SQUARE_BRACKET + TLAConstants.CR + TLAConstants.CR);		
	}

	public void addViewConfig(final String view) {
		cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.VIEW).append(TLAConstants.CR);
		cfgBuffer.append(TLAConstants.INDENT).append(view).append(TLAConstants.CR);
	}
	
	public void addView(String vars) {
		addViewConfig(TLAConstants.TraceExplore.VIEW);
		
		tlaBuffer.append(TLAConstants.CR).append(TLAConstants.TraceExplore.VIEW).append(TLAConstants.DEFINES_CR);
		tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.BEGIN_TUPLE)
				.append(vars + ", IF TLCGet(\"level\") = " + TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_END
						+ " + 1 THEN " + TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_START + " ELSE TLCGet(\"level\")")
				.append(TLAConstants.END_TUPLE);
		tlaBuffer.append(TLAConstants.CR);
	}

	public void addFooter() {
		tlaBuffer.append(getTLAModuleClosingTag());
	}
	
	/**
	 * This only changes the tla file. This method adds a variable declaration
	 * for each element of traceExpressionData and, if the flag addDefinitions is true,
	 * defines the identifier of each element to be the expression for that element.
	 * 
	 * If the expressions are x' + y and x > 3, The tla file will contain something like
	 * 
	 *\* comment line
	 * VARIABLES __trace_var_21034978347834, __trace_var_90234782309
	 * 
	 * \* comment line
	 * trace_def_3214234234234 ==
	 * x' + y
	 * ----
	 * 
	 * \* comment line
	 * trace_def_2342342342342 ==
	 * x > 3
	 * ----
	 * 
	 * @param traceExpressionData information about the trace expressions
	 * @param attributeName
	 * @param addDefinitions whether or not to define each identifier as the expression
	 */
	public void addVariablesAndDefinitions(final TraceExpressionInformationHolder[] traceExpressionData, final String attributeName,
			final boolean addDefinitions) {
		if (traceExpressionData.length == 0) {
	        return;
	    }
	
	    final StringBuilder variableDecls = new StringBuilder();
	    final StringBuilder definitions = new StringBuilder();
		for (int i = 0; i < traceExpressionData.length; i++) {
	        final TraceExpressionInformationHolder expressionInfo = traceExpressionData[i];
	
	        variableDecls.append(expressionInfo.getVariableName());
	        // we add a comma after every variable except for the last
	        if (i != traceExpressionData.length - 1)
	        {
	            variableDecls.append(TLAConstants.COMMA);
	        }
	
	        if (addDefinitions)
	        {
	            // define the identifier corresponding to this expression - looks like:
	            // \* comment line
	            // trace_def_213123123123 ==
	            // expression
	            // ----
	            definitions.append(TLAConstants.COMMENT).append("TRACE EXPLORER identifier definition ");
	            definitions.append(TLAConstants.ATTRIBUTE).append(attributeName).append(TLAConstants.COLON);
	            definitions.append(i).append(TLAConstants.CR);
	            definitions.append(expressionInfo.getIdentifier()).append(TLAConstants.DEFINES_CR);
	            definitions.append(expressionInfo.getExpression()).append(CLOSING_SEP).append(TLAConstants.CR);
	        }
	    }
	
	    // variable declaration
	    tlaBuffer.append(TLAConstants.COMMENT).append("TRACE EXPLORER variable declaration ");
	    tlaBuffer.append(TLAConstants.ATTRIBUTE).append(attributeName).append(TLAConstants.CR);
	    tlaBuffer.append("VARIABLES ").append(variableDecls.toString()).append(CLOSING_SEP).append(TLAConstants.CR);
	
		if (addDefinitions) {
	        // append the expression definitions
	        tlaBuffer.append(definitions.toString());
	    }
	}

	/**
	 * Adds the invariant ~(P) where P is the formula describing finalState. The format
	 * in the tla file is as follows:
	 * 
	 * _inv ==
	 * ~(
	 * P
	 * )
	 * ----
	 * 
	 * @param finalState
	 */
	private void addInvariant(final MCState finalState) {
	    final String id = SpecWriterUtilities.getValidIdentifierNoTimestamp(TLAConstants.Schemes.INVARIANT_SCHEME);
	    cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.INVARIANT).append(TLAConstants.CR);
	    cfgBuffer.append(TLAConstants.INDENT).append(id).append(TLAConstants.CR);
	
	    tlaBuffer.append(TLAConstants.CR).append(id).append(TLAConstants.DEFINES_CR);
	    tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.TLA_NOT).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	    
		// The main reason why we generate an invariant compared to the much simpler
		// deadlock checking is noted in addProperties below (thank you simulation mode).
		// Another reason is that we want to allow users to be able to amend the te
		// spec to check the original Init/Next or Spec in place of the generated
		// _init/_next (to a) quickly check if a spec change addresses the error causing
		// the error trace, and b) print the original action names). With this variant
	    // of the te spec, there might no longer be a deadlock (Worker.java doesn't report
	    // deadlocks if states are excluded from the model due to action- and
	    // state-constraints).
	    //
		// A less important side-effect of checking _inv -formulated as ~(SomeState)- is
		// that it brings the variable values in the canonical order defined by the
		// original invariant. Let  x # [ b |-> 42, a |-> 23 ]  be the invariant in the
	    // original spec.  With deadlock checking, the error trace might report the 
	    // value in the opposite order:  x = [ a |-> 23, b |-> 42 ].
	    // 
	    // An undesired side-effect of checking _inv are occasional silly expressions that
	    // some might call type mismatches. For example, let the value of the x variable
	    // above in first state of an error trace be a special "NULL" value and 
	    // [ b |-> 1, a |-> 2 ] in the other states leading up to the error state. 
	    // Checking the generated _inv on the initial state would cause TLC to fail with
	    // the evaluation error stemming from the silly expression
	    // "NULL" # [ b |-> 42, a |-> 23 ].  Thus, we conjoin  TLCGet("level") # Len(_TETrace)
	    // to  SomeState  to prevent evaluating silly expressions.  On the upside, this
	    // asserts the correct error trace should the previously described spec variant
	    // with the original Init/Next be checked; a trace could be too short if a state
	    // exluded by the action-constraint violated  SomeState.
		tlaBuffer.append(getStateConjunction(finalState, "TLCGet(\"level\") = Len(_TETrace)")).append(TLAConstants.CR);
		tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.R_PAREN);
	}

	public void addProperties(final List<MCState> trace) {
		addProperties(trace, null);
	}

	public void addProperties(final List<MCState> trace, String specName) {
        MCState finalState = trace.get(trace.size() - 1);
        boolean isBackToState = finalState.isBackToState();
        boolean isStuttering = finalState.isStuttering();

        // add temporal property or invariant depending on type of trace
        // read the method comments to see the form of the invariant or property
        if (isStuttering)
        {
            addStutteringProperty(trace.get(trace.size() - 2));
        } else if (isBackToState)
        {
            addBackToStateProperty(trace.get(trace.size() - 2), trace.get(finalState.getStateNumber() - 1));
        } else
        {
            // checking deadlock eliminates the need for the following
			// MAK 06/26/2020: write.addInvariant(finalState) below used to be commented
			// with the comment above about deadlock checking taking care of it. The
			// statement is wrong when an error-trace is not the shortest possible trace,
			// because bfs (run with TE) on such a trace might a) shorten it and b) no
			// longer deadlocks. This is possible with traces that come out of TLC's
			// simulation mode.
			// Assume any spec and an invariant such as TLCGet("level") < n for some n \in Nat
        	// (larger n increase the probability of a behavior with a sequence of stuttering
        	// steps). If the simulator happens to generate a behavior with a sequence of
			// stuttering step, the generated TE.tla will define a behavior that allows infinite
			// stuttering (for each stuttering step, there will be a disjunct in the disjuncts
			// of the next-state relation), which is not a deadlock. We could require the
        	// simulator to run with the "-difftrace" command-line parameter, which will remove
        	// successive stuttering steps.  However, it seems like an unnecessary requirement
        	// given that checking an invariant instead of deadlock has no drawback.
			// I ran into this issue when I used the simulator to generate very long traces
			// (1000+) for a spec (AsyncGameOfLife.tla) that models an Asynchronous Cellular
			// Automaton (https://uhra.herts.ac.uk/bitstream/handle/2299/7041/102007.pdf),
			// to use as input for Will Schultz's animation module (result at
			// https://github.com/lemmy/tlaplus_specs/blob/master/AsyncGameOfLifeAnimBlinker.mp4).
            addInvariant(finalState);
        }

		tlaBuffer.append(CLOSING_SEP).append(TLAConstants.CR);
        
		// Do not require to pass -deadlock on the command-line (properties assert that
		// TLC re-finds the error-trace).		
		cfgBuffer.append(TLAConstants.CR).append(ModelConfig.CheckDeadlock).append(TLAConstants.CR);
		cfgBuffer.append(TLAConstants.INDENT + TLAConstants.COMMENT).append(ModelConfig.CheckDeadlock).append(" off because of PROPERTY or INVARIANT above.")
				.append(TLAConstants.CR);
		cfgBuffer.append(TLAConstants.INDENT).append(TLAConstants.FALSE);
	}

	/**
	 * Adds the temporal property ~<>[](P) where P is the formula describing finalState.
	 * The format in the tla file is as follows:
	 * 
	 * _prop ==
	 * ~<>[](
	 * P
	 * )
	 * ----
	 * 
	 * @param finalState
	 */
	private void addStutteringProperty(final MCState finalState) {
	    String id = SpecWriterUtilities.getValidIdentifierNoTimestamp(TLAConstants.Schemes.PROP_SCHEME);
	    cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.PROPERTY).append(TLAConstants.CR);
	    cfgBuffer.append(TLAConstants.INDENT).append(id).append(TLAConstants.CR);
	
	    tlaBuffer.append(TLAConstants.CR).append(id).append(TLAConstants.DEFINES_CR);
	    tlaBuffer.append(TLAConstants.INDENT + TLAConstants.TLA_NOT).append(TLAConstants.TLA_EVENTUALLY_ALWAYS);
	    tlaBuffer.append(TLAConstants.L_PAREN).append(TLAConstants.CR).append(getStateConjunction(finalState));
	    tlaBuffer.append(TLAConstants.CR).append(TLAConstants.INDENT + TLAConstants.R_PAREN);
	}

	/**
	 * Adds the temporal property ~([]<>P /\ []<>Q), where P is the formula describing finalState and 
	 * Q the formula describing backToState. The formatting in the tla file is as follows:
	 * 
	 * _prop ==
	 * ~(([]<>(
	 * P
	 * ))/\([]<>(
	 * Q
	 * )))
	 * ----
	 * 
	 * @param finalState
	 * @param backToState
	 */
	private void addBackToStateProperty(final MCState finalState, final MCState backToState) {
	    final String id = SpecWriterUtilities.getValidIdentifierNoTimestamp(TLAConstants.Schemes.PROP_SCHEME);
	    cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.PROPERTY).append(TLAConstants.CR);
	    cfgBuffer.append(TLAConstants.INDENT).append(id).append(TLAConstants.CR);
	    
		tlaBuffer.append(TLAConstants.CR).append(id).append(TLAConstants.DEFINES_CR);

		StringBuilder localBuffer = new StringBuilder();
	    localBuffer.append(TLAConstants.TLA_NOT).append(TLAConstants.L_PAREN).append(TLAConstants.L_PAREN);
	    localBuffer.append(TLAConstants.TLA_INF_OFTEN).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	    localBuffer.append(getStateConjunction(finalState)).append(TLAConstants.CR).append(TLAConstants.R_PAREN);
	    localBuffer.append(TLAConstants.R_PAREN).append(TLAConstants.TLA_AND).append(TLAConstants.L_PAREN);
	    localBuffer.append(TLAConstants.TLA_INF_OFTEN).append(TLAConstants.L_PAREN).append(TLAConstants.CR);
	    localBuffer.append(getStateConjunction(backToState)).append(TLAConstants.CR).append(TLAConstants.R_PAREN);
	    localBuffer.append(TLAConstants.R_PAREN).append(TLAConstants.R_PAREN);

		// Writes local buffer back to tla buffer with some iation.
		tlaBuffer.append(indentString(localBuffer.toString(), 1));
	}

	/**
	 * Writes comments that will be used for associating variable names with expressions
	 * and will give the level of each expression. In particular, for each expression "expr"
	 * with level x and variable name ___trace_var_3242348934343 this
	 * will append the following comment to the tla file:
	 * 
	 * \* :x:___trace_var_3242348934343:expr"$!@$!@$!@$!@$!"
	 * 
	 * @param traceExpressionData
	 */
	public void addInfoComments(final TraceExpressionInformationHolder[] traceExpressionData) {
		for (final TraceExpressionInformationHolder expressionData : traceExpressionData) {
	        tlaBuffer.append(TLAConstants.COMMENT).append(TLAConstants.COLON).append(expressionData.getLevel());
	        tlaBuffer.append(TLAConstants.COLON).append(expressionData.getVariableName()).append(TLAConstants.COLON);
	        tlaBuffer.append(expressionData.getExpression()).append(TLAConstants.CONSTANT_EXPRESSION_EVAL_IDENTIFIER);
	        tlaBuffer.append(TLAConstants.CR);
	    }
	}

	/**
	 * @see #addInitNextToBuffers(StringBuilder, StringBuilder, List, TraceExpressionInformationHolder[])
	 */
	public String[] addInitNext(final List<MCState> trace) {
		return addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, null);
	}

	/**
	 * @see #addInitNextToBuffers(StringBuilder, StringBuilder, List, TraceExpressionInformationHolder[], String, String, String)
	 */
	public void addInitNext(final List<MCState> trace, final TraceExpressionInformationHolder[] expressionData,
							final String initId, String nextId, final String actionConstraintId) {
		addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId);
	}

	/**
	 * @see #addInitNextToBuffers(StringBuilder, StringBuilder, List, TraceExpressionInformationHolder[], String, String, String, String, boolean)
	 */
	public void addInitNext(final List<MCState> trace, final TraceExpressionInformationHolder[] expressionData,
							final String initId, String nextId, final String actionConstraintId,
							final String nextSubActionBasename) {
		addInitNextToBuffers(tlaBuffer, cfgBuffer, trace, expressionData, initId, nextId, actionConstraintId,
							 nextSubActionBasename, true);
	}
	
	public void addInitNext(final List<MCState> trace, final String initId, String nextId,
			final String actionConstraintId, final String nextSubActionBasename) {
		addInitNext(trace, null, initId, nextId, actionConstraintId, nextSubActionBasename);
	}

	public void addInitNextTraceFunction(final List<MCState> trace, final String teSpecModuleName, final List<String> vars, ModelConfig modelConfig) {
		/*******************************************************
         * Add the init definition.                            *
         *******************************************************/
		if (cfgBuffer != null) {
			cfgBuffer.append(TLAConstants.CR);
			cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.INIT).append(TLAConstants.CR);
			cfgBuffer.append(TLAConstants.INDENT).append(TLAConstants.TraceExplore.SPEC_TE_INIT).append(TLAConstants.CR);
		}

		tlaBuffer.append(TLAConstants.TraceExplore.SPEC_TE_INIT).append(TLAConstants.DEFINES_CR);
		
        // variables from spec
		for (String var : vars) {
            tlaBuffer.append(TLAConstants.INDENTED_CONJUNCTIVE);
            tlaBuffer.append(var).append(TLAConstants.EQ).append("_TETrace[1].").append(var);
            tlaBuffer.append(TLAConstants.CR);
        }
		
		tlaBuffer.append(TLAConstants.SEP).append(TLAConstants.CR).append(TLAConstants.CR);

		// Get final state so we can check if this trace is for a safety
		// or liveness property.
		final MCState finalState = trace.get(trace.size() - 1);		
				
		final String nextId = TLAConstants.TraceExplore.SPEC_TE_NEXT;

        /************************************************
         *  Now add the next state relation             *
         ************************************************/
		if (cfgBuffer != null) {	
			cfgBuffer.append(TLAConstants.CR).append(TLAConstants.KeyWords.NEXT).append(TLAConstants.CR);
			cfgBuffer.append(TLAConstants.INDENT).append(nextId).append(TLAConstants.CR);
		}		
		
		// _next ==
		tlaBuffer.append(nextId).append(TLAConstants.DEFINES_CR);

		if (trace.size() == 1) {
			tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
			tlaBuffer.append(TLAConstants.FALSE).append(TLAConstants.CR);
		} else {
			tlaBuffer.append(TLAConstants.INDENTED_CONJUNCTIVE).append("\\E i,j \\in DOMAIN _TETrace:")
					.append(TLAConstants.CR);
			tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE).append(TLAConstants.TLA_OR)
					.append(TLAConstants.SPACE).append(TLAConstants.TLA_AND).append(" j = i + 1")
					.append(TLAConstants.CR);
			tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENT).append(TLAConstants.SPACE)
					.append(TLAConstants.SPACE).append(TLAConstants.INDENTED_CONJUNCTIVE)
					.append("i = TLCGet(\"level\")").append(TLAConstants.CR);
			// Back to state?
			if (finalState.isBackToState()) {
				// Instead of this disjunct, we could append backToState to the trace function
				// (_TETrace). Len(_TETrace) would however be off by one.
				tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENT).append("   ")
						.append(TLAConstants.TLA_OR).append(TLAConstants.SPACE).append(TLAConstants.TLA_AND)						
						// `_TTraceLassoEnd` is a constant which contains the last state of the lasso.
						.append(" i = ").append(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_END).append(TLAConstants.CR);
				tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENT).append("  ")
						// `_TTraceLassoStart` is a constant which contains the first state of the lasso.
						.append(TLAConstants.INDENTED_CONJUNCTIVE).append("j = ").append(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_START)
						.append(TLAConstants.CR);
			}
			for (String var : vars) {
	            // x = _TETrace[_TEPosition].x
				tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
				tlaBuffer.append(var).append(" ").append(TLAConstants.EQ).append("_TETrace[i].")
						.append(var);
				tlaBuffer.append(TLAConstants.CR);

				// x' = _TETrace[_TEPosition+1].x
				tlaBuffer.append(TLAConstants.INDENT).append(TLAConstants.INDENTED_CONJUNCTIVE);
				tlaBuffer.append(var).append(TLAConstants.PRIME);
				tlaBuffer.append(TLAConstants.EQ).append("_TETrace[j].").append(var);
				tlaBuffer.append(TLAConstants.CR);
	        }
		}

		String jsonComment = TLAConstants.INDENT + TLAConstants.COMMENT;
		if (System.getProperty("TLC_TRACE_EXPLORER_JSON_UNCOMMENTED") != null) {
			// For tests, it's valuable to check the json output, so we remove the
			// comment through a JVM property.
			jsonComment = "";
		}

		tlaBuffer.append(TLAConstants.CR).append(TLAConstants.COMMENT)
			.append("Uncomment the ASSUME below to write the states of the error trace").append(TLAConstants.CR);
		tlaBuffer.append(TLAConstants.COMMENT).append("to the given file in Json format. Note that you can pass any tuple").append(TLAConstants.CR);
		tlaBuffer.append(TLAConstants.COMMENT).append("to `JsonSerialize`. For example, a sub-sequence of _TETrace.").append(TLAConstants.CR);
		tlaBuffer.append(jsonComment).append(TLAConstants.KeyWords.ASSUME).append(TLAConstants.CR);
		tlaBuffer.append(jsonComment + TLAConstants.INDENT).append("LET J == INSTANCE Json").append(TLAConstants.CR);
		tlaBuffer.append(jsonComment + TLAConstants.INDENT + TLAConstants.INDENT)
			.append(String.format("IN J!JsonSerialize(\"%s.json\", _TETrace)", teSpecModuleName)).append(TLAConstants.CR);		

		tlaBuffer.append(TLAConstants.CR);
	}

	public String addTraceFunction(final List<MCState> input) {
		final String identifier = SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.DEFOV_SCHEME);
		return addTraceFunctionToBuffers(tlaBuffer, cfgBuffer, input, identifier, identifier);
	}

	public String addTraceFunction(final List<MCState> input, final String id, final String configId) {
		return addTraceFunctionToBuffers(tlaBuffer, cfgBuffer, input, id, configId);
	}

	/*
	 * See https://github.com/tlaplus/tlaplus/issues/482 for why we create the
	 * _SpecTETraceDef symbol. In short, it leads to faster evaluation because TLC's
	 * caching kicks in.
	 * 
	 * The reason why the trace function is in a dedicated module (via monolith spec
	 * functionality) is to make it easy for users to edit SpecTE to replace the
	 * TLA+ encoded trace function with a significantly more efficient binary
	 * encoding to work around deficiencies in SANY and semantic processing.
	 */
	public void addTraceFunctionInstance(final String moduleName) {
		/* With EWD840_TE as moduleName:
           _trace ==
               LET EWD840_TETrace == INSTANCE EWD840_TETrace
               IN EWD840_EWD840_TETrace!trace
		   ----
		 */
		// This expression has temporal level because of the INSTANCE statement
		// and the fact that the module  EWD840_TETrace  indirectly extends
		// the original spec  EWD840.  The tlc2.tool.impl.SymbolNodeValueLookupProvider
		// over-approximates the level of expressions and cannot figure out that
		// the  EWD840_TETrace  module is a constant/variable-free spec.
		// Assuming the specs below, the fact that the expr has temporal level
		// has the following side effect. The first conjunct of  MyInit  is not
		// evaluated as part of the initial predicate.  Only the second conjunct,
		// i.e., the in-lined  Init  gets evaluated.
		//
		//   VARIABLES v
		//   Init == v \in 1..42
		//   Next == ...
		//   Spec == Init /\ [][Next]_v
		//
		// a te spec:
		//
		//   _trace == ...
		//   MyInit ==
		//       /\ v = _trace[1].v
		//       /\ v \in 1..42 \* Init in-lined
		//
		// and a config:
		//
		//   CONSTANT Init <- MyInit
		//   SPECIFICATION Spec
		//
		tlaBuffer
				.append(String.format("%s ==%s%sLET %s == INSTANCE %s%s%sIN %s!%s",
						TLAConstants.TraceExplore.SPEC_TETRACE_TRACE, TLAConstants.CR, TLAConstants.INDENT,
						moduleName, moduleName, TLAConstants.CR, TLAConstants.INDENT, moduleName,
						TLAConstants.TraceExplore.SPEC_TETRACE_TRACE_DEF))
				.append(TLAConstants.CR).append(TLAConstants.SEP).append(TLAConstants.CR);
	}

	public void addTraceExpressionInstance(final String moduleName) {
		/* With EWD840_TE as moduleName:
           _expression ==
               LET EWD840_TEExpression == INSTANCE EWD840_TEExpression
               IN EWD840_EWD840_TEExpression!expression
		   ----
		 */
		tlaBuffer
				.append(String.format("%s ==%s%sLET %s == INSTANCE %s%s%sIN %s!%s",
						TLAConstants.TraceExplore.SPEC_TE_TTRACE_EXPRESSION, TLAConstants.CR, TLAConstants.INDENT,
						moduleName, moduleName, TLAConstants.CR, TLAConstants.INDENT, moduleName,
						TLAConstants.TraceExplore.SPEC_TE_TRACE_EXPRESSION))
				.append(TLAConstants.CR).append(TLAConstants.SEP).append(TLAConstants.CR).append(TLAConstants.CR);
	}

    /**
     * Returns a string representing the formula describing the state.
     * If the state has var1=expr1, var2 = expr2, and var3=expr3, then this returns:
     * 
     * var1 = (expr1)
     * /\
     * var2 = (expr2)
	 * /\
	 * var3 = (expr3)          
     * 
     * The expressions expr1, expr2, and expr3 can take up multiple lines.
	 * 
	 * The expressions are idented twice.
     * 
     * This will return null if the state is stuttering or back to state.
     * 
     * @param state
     * @return
     */
	private static String getStateConjunction(final MCState state) {
		return getStateConjunction(state, null);
	}
	
	private static String getStateConjunction(final MCState state, final String prefixConjunct) {
		if (state.isBackToState()) {
			return null;
		} else if (state.isStuttering()) {
			return null;
		} else {
            final StringBuilder formula = new StringBuilder();
            if (prefixConjunct != null) {
            	formula.append(prefixConjunct).append(TLAConstants.CR).append(TLAConstants.TLA_AND).append(TLAConstants.CR);
            }
            final MCVariable[] vars = state.getVariables();
			for (int i = 0; i < vars.length; i++) {
				final MCVariable var = vars[i];
				formula.append(var.getName()).append(TLAConstants.EQ).append(TLAConstants.L_PAREN);
				formula.append(var.getValueAsString()).append(TLAConstants.R_PAREN);

				// append /\ except for the last variable
				if (i != (vars.length - 1)) {
                    formula.append(TLAConstants.CR).append(TLAConstants.TLA_AND).append(TLAConstants.CR);
                }
            }

            return indentString(formula.toString(), 2);
        }
    }

	public StringBuilder append(String str) {
		return tlaBuffer.append(str);
	}
	
	public String toString() {
		return tlaBuffer.toString();
	}

	public String getComment() {
		return tlaBuffer.toString().replaceFirst("^", "\\\\*").replaceAll("\n", "\n\\\\*");
	}

	/**
	 * Indent n times a entire multiline string.
	 */
	static public String indentString(String s, int n) {
		final String idnt = new String(new char[n]).replace("\0", TLAConstants.INDENT);
		return idnt + String.join(TLAConstants.CR + idnt, s.split(TLAConstants.CR));
	}

	public void wrapConfig(String moduleFilename) {
		// Header
		final StringBuilder buffer = new StringBuilder();
		buffer.append("\n").append(TLAConstants.SEP).append(' ').append("CONFIG").append(' ');
		buffer.append(moduleFilename).append(' ').append(TLAConstants.SEP).append('\n');
		cfgBuffer.insert(0, buffer);
		
		// Footer
		cfgBuffer.append(getTLAModuleClosingTag());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/TLCStateFun.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 15:29:58 PST by lamport
//      modified on Fri Jul 20 23:54:51 PDT 2001 by yuanyu

package tlc2.tool;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.SymbolNode;
import tlc2.util.Context;
import tlc2.value.IValue;
import tlc2.value.IValueInputStream;
import tlc2.value.IValueOutputStream;
import tlc2.value.impl.Value;
import util.UniqueString;
import util.WrongInvocationException;

/**
 * This class represents a TLA+ state, which simply is an assignment
 * of explicit values to the variables. This is the functional
 * version.  It is used for implementing the enabled predicate.  It
 * can not be used in getInitStates and getNextStates.
 */
public final class TLCStateFun extends TLCState {
  private SymbolNode name;
  private IValue value;
  private TLCStateFun next;

  public final static TLCState Empty = new TLCStateFun(null, null, null);
  
  private TLCStateFun(SymbolNode name, IValue value, TLCStateFun state) {
    this.name = name;
    this.value = value;
    this.next = state;
  }

  public final TLCState createEmpty() { return Empty; }

  public final TLCState bind(UniqueString name, IValue value) {
      throw new WrongInvocationException("TLCStateFun.bind: This is a TLC bug.");
  }

  public final TLCState bind(SymbolNode id, IValue value) {
    return new TLCStateFun(id, value, this);
  }
  
  public final TLCState unbind(UniqueString name) {
      throw new WrongInvocationException("TLCStateFun.unbind: This is a TLC bug.");
  }
  
  public final IValue lookup(UniqueString var) {
    for (TLCStateFun cur = this; cur != Empty; cur = cur.next) {
      if (var == cur.name.getName()) return cur.value;
    }
    return null;
  }
  
  public final boolean containsKey(UniqueString var) {
    return this.lookup(var) != null;
  }
  
  public final TLCState copy() {
      // The following code added blindly by LL on 28 May 2010
      // to fix a bug.  I have no idea what's going on here.
       return new TLCStateFun(this.name, this.value, this.next);
      // throw new WrongInvocationException("TLCStateFun.copy: This is a TLC bug.");
  }
  
  public final TLCState deepCopy() {
      throw new WrongInvocationException("TLCStateFun.deepCopy: This is a TLC bug.");
  }
  
  public final void deepNormalize() {
      throw new WrongInvocationException("TLCStateFun.normalizeFcns: This is a TLC bug.");
  }
  
  public final long fingerPrint() {
      throw new WrongInvocationException("TLCStateFun.fingerPrint: This is a TLC bug.");
  }

  public final boolean allAssigned() { return true; }  
  
  public final Set<OpDeclNode> getUnassigned() { return new HashSet<OpDeclNode>(); }

  public final Context addToContext(Context c) {
    Context c1 = c;
    for (TLCStateFun cur = this; cur != Empty; cur = cur.next) {
      c1 = c1.cons(cur.name, cur.value);
    }
    return c1;
  }

  public final StateVec addToVec(StateVec states) {
    return states.addElement(this);
  }
  
  public final void read(IValueInputStream vis) throws IOException {
      throw new WrongInvocationException("TLCStateFun.read: This is a TLC bug.");
  }

  public final void write(IValueOutputStream vos) throws IOException {
      throw new WrongInvocationException("TLCStateFun.write: This is a TLC bug.");
  }
  
  /* Returns a string representation of this state.  */
  public final String toString() {
    StringBuffer sb = new StringBuffer("[");
    if (this != Empty) {
      sb.append(this.name.getName().toString());
      sb.append(" -> ");
      sb.append(this.value.toString());

      for (TLCStateFun cur = this.next; cur != Empty; cur = cur.next) {
	sb.append(", ");
	sb.append(cur.name.getName().toString());
	sb.append("->");
	sb.append(cur.value);
      }
    }
    sb.append("]");
    return sb.toString();
  }
  
  public final String toString(TLCState lastState) {
      throw new WrongInvocationException("TLCStateFun.toString: This is a TLC bug.");
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/CommandPrefixDigitHandler.java<|end_filename|>
/**
 * Certain commands take a numeric prefix argument.  This argument
 * generally specifies the number of times the command should be repeated.
 * For example, giving a prefix argument of 42 to a command to move down a line
 * should move down 42 lines.  This prefix argument is entered by typing
 * Alt+4 followed by Alt+2 before typing the command.  
 * 
 * A prefix argument that is not immediately followed by a command should
 * be cleared if followed by some command that does not use the prefix
 * argument.  This is approximated by clearing any prefix typed so far
 * if the current selection has changed has changed since the prefix was
 * typed.  Thus if you type Alt+4, click somewhere else in the editor, then
 * type Alt+2, then the current prefix becomes 2 rather than 42.  
 * 
 * The absence of a prefix command is generally equivalent to a prefix of 1.
 * 
 * A command that uses the prefix for the number of times it should be repeated
 * calls the getAndResetRepeatValue method.
 * 
 */
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.parser.ParserDependencyStorage;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.SemanticNode;
import util.TLAConstants;

/**
 * @author lamport
 *
 */
public class CommandPrefixDigitHandler extends AbstractHandler implements IHandler
{
    // public static String alt1Id = "org.lamport.tla.toolbox.editor.basic.alt1" ;
    // public static String alt2Id = "org.lamport.tla.toolbox.editor.basic.alt2" ;
    // public static String alt3Id = "org.lamport.tla.toolbox.editor.basic.alt3" ;
    // public static String alt4Id = "org.lamport.tla.toolbox.editor.basic.alt4" ;
    // public static String alt5Id = "org.lamport.tla.toolbox.editor.basic.alt5" ;
    // public static String alt6Id = "org.lamport.tla.toolbox.editor.basic.alt6" ;
    // public static String alt7Id = "org.lamport.tla.toolbox.editor.basic.alt7" ;
    // public static String alt8Id = "org.lamport.tla.toolbox.editor.basic.alt8" ;
    // public static String alt9Id = "org.lamport.tla.toolbox.editor.basic.alt9" ;
    // public static String alt0Id = "org.lamport.tla.toolbox.editor.basic.alt0" ;

    // private TLAEditor editor;
    // private IDocument doc ; // The document being edited.
    // private ISelectionProvider selectionProvider ; //
    private static boolean existsPrefix = false; //
    // True iff a prefix value has been or is being typed.
    private static int prefixValue = 0; // The current prefix value
    // private TextSelection selection ; // The current selection.
    private static TextSelection lastSelection = new TextSelection(-1, -1);

    // The selection when handler last called.

    // private int offset ; // The current offset.
    // private IRegion lineInfo ; // The lineInfo for the current offset.

    /* (non-Javadoc)
     * The execute method is called when Alt plus a digit is typed.
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {

        ParserDependencyStorage pds = Activator.getModuleDependencyStorage();     
        String moduleName = EditorUtil.getTLAEditorWithFocus().getModuleName();
        List vec = pds.getListOfExtendedModules(moduleName + TLAConstants.Files.TLA_EXTENSION);
        System.out.println("ExtendedModules");
        for (int i = 0; i < vec.size(); i++) {
            System.out.println((String) vec.get(i));
        }
        vec = pds.getListOfModulesToReparse(moduleName + TLAConstants.Files.TLA_EXTENSION);
        System.out.println("ModulesToReparse");
        for (int i = 0; i < vec.size(); i++) {
            System.out.println((String) vec.get(i));
        }
        ModuleNode module = ResourceHelper.getModuleNode(moduleName);

        TLAEditor editor = EditorUtil.getTLAEditorWithFocus(); // gets the editor to which command applies
        if (editor == null)
        {
            return null;
        }
        IFile file = ((FileEditorInput) editor.getEditorInput()).getFile();

        SpecObj spec = ResourceHelper.getValidParseResult(file).getSpecObj();
        if (true) {
            return null;
        }

        System.out.println("ConstantDecls");
        SemanticNode[] nodes = module.getConstantDecls();
        for (int i = 0; i < nodes.length; i++)
        {
            System.out.println(" " // + nodes[i].getName()+ ": "
                    + nodes[i].getLocation().toString());
        }
        System.out.println("VariableDecls");
         nodes = module.getVariableDecls();
        for (int i = 0; i < nodes.length; i++)
        {
            System.out.println(" " // + nodes[i].getName()+ ": "
                    + nodes[i].getLocation().toString());
        }

        System.out.println("OpDefs");
        nodes = module.getOpDefs();
        for (int i = 0; i < nodes.length; i++)
        {
            System.out.println(" " // + nodes[i].getName()+ ": "
                    + nodes[i].getLocation().toString());
        }

        System.out.println("TopLevel");
        nodes = module.getTopLevel();
        for (int i = 0; i < nodes.length; i++)
        {
            System.out.println(" " // + nodes[i].getName()+ ": "
                    + nodes[i].getLocation().toString());
        }
        // IEditorReference[] references = UIHelper.getActivePage().getEditorReferences();
        //
        // StringAndLocation token = EditorUtil.getCurrentToken();
        // if (token == null) {
        // System.out.println("Null returned");
        // } else {
        // System.out.println(token.toString());
        // }
         editor = EditorUtil.getTLAEditorWithFocus(); // gets the editor to which command applies
        if (editor == null)
        {
            return null;
        }
         file = ((FileEditorInput) editor.getEditorInput()).getFile();

         spec = ResourceHelper.getValidParseResult(file).getSpecObj();

        // doc = editor.getDocumentProvider().getDocument(editor.getEditorInput()); // gets document being edited.
        ISelectionProvider selectionProvider = editor.getSelectionProvider();
        TextSelection selection = (TextSelection) selectionProvider.getSelection();

        // reset the prefix if the selection has changed
        if (existsPrefix && !selection.equals(lastSelection))
        {
            existsPrefix = false;

            prefixValue = 0;
        }
        lastSelection = selection;
        String cmdId = event.getCommand().getId();
        int digit = Integer.parseInt(cmdId.substring(cmdId.length() - 1));
        prefixValue = 10 * prefixValue + digit;
        existsPrefix = true;
        // offset = selection.getOffset();
        // TODO Auto-generated method stub
        return null;
    }

    /*
     * Returns the number of repetitions specified by the 
     * current prefix, which is 1 if there is no current prefix,
     * and it resets the current prefix.
     */

    public static int getAndResetRepeatValue(TLAEditor ed)
    {
        int returnVal = prefixValue;
        if ((!existsPrefix) || (!lastSelection.equals((TextSelection) ed.getSelectionProvider().getSelection())))
        {
            returnVal = 1;
        }
        existsPrefix = false;
        prefixValue = 0;
        return returnVal;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (EditorUtil.getTLAEditorWithFocus() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/TLCActivator.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc;

import org.eclipse.core.runtime.Status;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

/**
 * The activator class controls the plug-in life cycle
 */
public class TLCActivator extends AbstractUIPlugin {
	
    // TODO This is the only constant used in our Preferences that is not declared in ITLCPreferenceConstants
    //          because of package dependency issues. We should do something about that because this scattering
    //          feels meh.
	/**
     * This preference is exposed through the Toolbox preference pane and allows the
     * user to dictate how many snapshots are kept (with the oldest being pruned as
     * this value is reached or exceeded.)  A value of 0 here means that no snapshot
     * is taken as part of the pre-launch of TLC.
	 */
    public static final String I_TLC_SNAPSHOT_KEEP_COUNT = "numberOfSnapshotsToKeep";
	
	// The plug-in ID
	public static final String PLUGIN_ID = "org.lamport.tla.toolbox.tool.tlc";

	// The shared instance
	private static TLCActivator plugin;
	
	/**
	 * The constructor
	 */
	public TLCActivator() 
	{
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
	}

	/*
	 * (non-Javadoc)
	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		plugin = null;
		super.stop(context);
	}

	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static TLCActivator getDefault() {
		return plugin;
	}

    /**
     * Logs an error
     * @param message
     * @param e 
     */
    public static void logError(String message, Throwable e)
    {
        getDefault().getLog().log(new Status(Status.ERROR, TLCActivator.PLUGIN_ID, message, e));
    }

    /**
     * Prints a debug message
     * @param message to print
     */
    public static void logInfo(String message)
    {
        getDefault().getLog().log(new Status(Status.INFO, TLCActivator.PLUGIN_ID, message));
    }
    
    /**
     * Prints a debug message
     * @param message to print
     */
    public static void logDebug(String message)
    {
        System.out.println(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/EnumerableValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME> - added support for fingerprint stack trace
 ******************************************************************************/

package tlc2.value.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.math3.primes.Primes;

import tlc2.tool.FingerprintException;
import tlc2.util.RandomGenerator;
import tlc2.value.RandomEnumerableValues;

public abstract class EnumerableValue extends Value implements Enumerable {

  @Override
  public Value isSubsetEq(Value other) {
    try {
      final ValueEnumeration Enum = this.elements();
      Value elem;
      while ((elem = Enum.nextElement()) != null) {
        if (!other.member(elem)) {
          return BoolValue.ValFalse;
        }
      }
      return BoolValue.ValTrue;
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }
  
	@Override
	public EnumerableValue getRandomSubset(final int kOutOfN) {
		// By default, convert all EVs into SetEnumValue and delegate to its
		// getRandomSubset.
    	return ((SetEnumValue) this.toSetEnum()).getRandomSubset(kOutOfN);
	}

	@Override
	public ValueEnumeration elements(final Ordering ordering) {
		if (ordering == Ordering.NORMALIZED) {
			// By default, none of the EnumerableValues supports a ValueEnumeration that
			// provides normalized ordering. Thus, to traverse the elements in normalized
			// ordering, any EV type gets converted into a SetEnumValue - this effectively
			// enumerates the EV and normalizes the new SEV. Traversing the normalized
			// SEV with a ValueEnumeration returned by Enumerable#elements is guaranteed 
			// to be in normalized order (@see Ordering.NORMALIZED for what this means).
			// In case a subclass provides a more efficient ValueEnumeration that guarantees
			// normalized order, the subclass may override this default method. This is
			// so far done by SubsetValue.
			final Value enumerated = this.toSetEnum();
			if (enumerated != null) {
				return ((Enumerable) enumerated.normalize()).elements();
			}
		} else if (ordering == Ordering.RANDOMIZED) {
			return elements(size());
		}
		return elements();
	}
	
	@Override
	public ValueEnumeration elements(final int k) {
		// The generic implementation collects all n elements of the actual Enumerable
		// into the temporary variable values. The SubSetEnumerator then randomly
		// returns up to k elements.
		// The underlying assuming here is that the size of Enumerable (n) is
		// very small and this method is not called as part of the next-state relation.
		// If it gets called on larger sets or as part of the next-state relation,
		// subclasses can provide a more efficient implementation (e.g. see
		// IntervalValue and SetEnumValue which return a more efficient subclass
		// of SubsetEnumerator).
		final List<Value> values = elements().all();
		return new SubsetEnumerator(k) {
			@Override
			public Value nextElement() {
				if (!hasNext()) {
					return null;
				}
				return values.get(nextIndex());
			}
		};
  	}

	abstract class SubsetEnumerator implements ValueEnumeration {

		// n is the upper bound for the range for which nextIndex returns values.
		protected final int n;

		// k is the number of times nextIndex can be called.
		protected final int k;
		// i counts the number of calls.
		protected int i;
		
		// The seed, X, index, ...
		private int index; // X_i or seed
		// Multiplier (long because intermediate values in nextIndex can exceed Int.MAX_VALUE)
		protected long a;
		// Modulo
		private int m;
		// Increment
		private int c;

		public SubsetEnumerator(final int k) {
			this(k, size());	
		}
		
		public SubsetEnumerator(final int k, final int n) {
			if (n <= 0) {
				// For n < 1, hasNext is always going to return false.
				this.n = 0;
				this.k = 0;
				return;
			}
			
			this.n = n;
			this.k = k;

			// Calculating optimal parameters for the given n is expensive! We assume that
			// we will only have to calculate parameters for a small number of ns per
			// model-checker run.
			int[] vals = MULTIPLIERS.computeIfAbsent(n, j -> computeOptimalMandA(j));
			this.m = vals[0];
			this.a = vals[1];
			
			final Random random = RandomEnumerableValues.get();
			this.index = random.nextInt(n);
			// Choose a prime for c that is guaranteed to be co-prime with m. We randomly
			// choose a prime number on every invocation to better approximate a uniform
			// distribution for repeated evaluation of Randomization!RandomSubset(k, S) with
			// k and S fixed to some values.  Since TLC cheats and evaluates RandomSubset
			// simply by generating k indices in 0..|S|, repeatedly evaluating RandomSubset
			// will reveal a bias because -even though the individual indices are uniform-
			// the *sequences* of indices generated are not uniformly distributed. A more
			// costly implementation that's based on generating the indices of all ksubsets
			// of S and SubsetValue#getUnrank(k) would be robust against a static increment
			// c.  For S = 1..20 and k = 3, this implementation is roughly 2.5x better in
			// approximating a uniform distribution yet also 2.5x slower.
			this.c = RandomGenerator.nextPrime(random);
		}

		@Override
		public void reset() {
			i = 0;
		}

		public boolean hasNext() {
			return i < k;
		}

		/**
		 * @return A random (uniformly distributed) index in the range [0,n) where n is
		 *         {@link Enumerable#size()}.
		 */
		public int nextIndex() {
			if (n <= 0) {
				i++;
				return 0;
			}
			do {
				index = (int) ((this.a * index + this.c) % this.m);
			} while (index >= this.n);
			i++;
			assert 0 <= index && index < this.n;
			return index;
		}

		@Override
		public abstract Value nextElement();
	}
	
	// Consider bootstrapping the parameters for the upper range of Integers (where
	// prime factorization becomes more expensive)?
	private static Map<Integer, int[]> MULTIPLIERS = new ConcurrentHashMap<>();

	// https://en.wikipedia.org/wiki/Linear_congruential_generator#c_%E2%89%A0_0
	// When c # 0, correctly chosen parameters allow a period equal to m, for all seed values. This will occur iff:
	// m and c are relatively prime,
	// a-1 is divisible by all prime factors of m
	// a-1 is divisible by 4 if m is divisible by 4.
	static int[] computeOptimalMandA(int n) {
		if (n < 9) {
			// while loop will increment n to 9 for all values lower than 9 anyway.
			n = 9;
		}

		// Prime factorization is expensive!!! As a minor optimization, we could in-line
		// primeFactor and use counters and track the product while looping instead of
		// storing all primes in a list, comparing its size to the set, and calculating
		// the product of the set.  However, I don't want to spend the time to extract
		// Apache Commons Math's primeFactors implementation.
		List<Integer> primeFactors = Primes.primeFactors(n);
		while (n % 4 == 0 || new HashSet<>(primeFactors).size() == primeFactors.size()) {
			n = n + 1;
			primeFactors = Primes.primeFactors(n);
		}

		int a = 1;
		for (Integer prime : new HashSet<>(primeFactors)) {
			a *= prime;
		}
		a += 1;
		
		// Unfortunately, Java doesn't have tuples/pairs.
		return new int[] {n, a};
	}
}

/*
---- CONFIG ksubsets_random_subset ----
CONSTANTS 
    Elements={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}
    Limit=1000
SPECIFICATION   Spec
====

------------------------------ MODULE ksubsets_random_subset ------------------------------
EXTENDS Naturals, Randomization, FiniteSets, TLC

CONSTANT Elements,
         Limit

VARIABLES counts,
          total

vars == <<counts, total >>

AddSubset ==
    /\ total < Limit 
    /\ \E ss \in { RandomSubset(3, Elements) } :
        /\ IF ss \in DOMAIN counts
            THEN counts' = [counts EXCEPT ![ss] = @ + 1]
            ELSE counts' = counts @@ (ss :> 1)
        /\ total' = total + 1

PrintDist ==
    /\ total = Limit
    /\ total' = Limit + 1
    /\ UNCHANGED <<counts>>
    /\ \A ss \in DOMAIN counts : PrintT(<<total, ss, counts[ss]>>)
    /\ PrintT(<<"RESULT", Cardinality(DOMAIN counts)>>)

Init == 
    /\ counts = [ss \in {} |-> 0]
    /\ total = 0

Next ==
    \/ AddSubset
    \/ PrintDist

Spec == Init /\ [][Next]_vars  

=============================================================================
\* Modification History
\* Last modified Tue Oct 27 17:24:00 CET 2020 by jvanlightly
\* Created Tue Oct 27 09:55:35 CET 2020 by jvanlightly
*/

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/GeneralOutputParsingHelper.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * A set of parsing methods 
 * @author <NAME>
 * @version $Id$
 */
public class GeneralOutputParsingHelper
{

    public final static String OB = "(";
    public final static String CB = ")";
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * Parses the TLC start/finish time
     * @param message
     * @return
     */
    public static long parseTLCTimestamp(String message)
    {
        // handle errors
        if (message.indexOf(OB) != -1 && message.indexOf(CB) != -1)
        {
            final String time = message.substring(message.indexOf(OB) + 1, message.indexOf(CB));
            try {
            	return sdf.parse(time).getTime();
            } catch(ParseException e) {
                TLCUIActivator.getDefault().logDebug("Error parsing TLC Timestamp.");
                return new Date().getTime();
            }
        } else
        {
            TLCUIActivator.getDefault().logDebug("Error parsing TLC Timestamp.");
            return new Date().getTime();
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/UndefValue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Wed 12 Jul 2017 at 16:10:00 PST by <NAME>
//      modified on Mon 30 Apr 2007 at 13:21:06 PST by lamport
//      modified on Tue Aug 15 23:08:23 PDT 2000 by yuanyu

package tlc2.value.impl;

import tlc2.tool.FingerprintException;
import tlc2.value.IValue;
import tlc2.value.Values;
import util.Assert;

public class UndefValue extends Value {

  public static final UndefValue ValUndef = new UndefValue();

  public UndefValue() { /*SKIP*/ }

  @Override
  public byte getKind() { return UNDEFVALUE; }

  @Override
  public final int compareTo(Object obj) {
    try {
      return (obj instanceof UndefValue) ? 0 : 1;
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  public final boolean equals(Object obj) {
    try {
      return (obj instanceof UndefValue);
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final boolean member(Value elem) {
    try {
      Assert.fail("Attempted to check if the value:\n" + Values.ppr(elem.toString()) +
      "\nis an element " + Values.ppr(this.toString()), getSource());
      return false;    // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final boolean isFinite() {
    try {
      Assert.fail("Attempted to check if the value " + Values.ppr(this.toString()) +
      " is a finite set.", getSource());
      return false;    // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value takeExcept(ValueExcept ex) {
    try {
      if (ex.idx < ex.path.length) {
        Assert.fail("Attempted to apply EXCEPT construct to the value " +
        Values.ppr(this.toString()) + ".", getSource());
      }
      return ex.value;
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value takeExcept(ValueExcept[] exs) {
    try {
      if (exs.length != 0) {
        Assert.fail("Attempted to apply EXCEPT construct to the value " +
        Values.ppr(this.toString()) + ".", getSource());
      }
      return this;
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final int size() {
    try {
      Assert.fail("Attempted to compute the number of elements in the value " +
      Values.ppr(this.toString()) + ".", getSource());
      return 0;     // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public boolean mutates() {
	  return false;
  }

  @Override
  public final boolean isNormalized() { return true; }

  @Override
  public final Value normalize() { /*nop*/return this; }

  @Override
  public final boolean isDefined() { return false; }

  @Override
  public final IValue deepCopy() { return this; }

  @Override
  public final boolean assignable(Value val) { return true; }

  /* The string representation. */
  @Override
  public final StringBuffer toString(StringBuffer sb, int offset, boolean swallow) {
    try {
      return sb.append("UNDEF");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/PcalTranslateException.java<|end_filename|>
package pcal.exception;

import pcal.AST;

/**
 * @author <NAME>
 * @version $Id$
 */
public class PcalTranslateException extends UnrecoverablePositionedException
{

    /**
     * @param message
     * @param elementAt2
     */
    public PcalTranslateException(String message, AST elementAt2)
    {
        super(message, elementAt2);
    }

    /**
     * @param message
     */
    public PcalTranslateException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/statistics/FixedSizedBucketStatisticsTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINbucketStatistic IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util.statistics;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class FixedSizedBucketStatisticsTest {

	@SuppressWarnings("rawtypes")
	@Parameterized.Parameters
	public static Collection<Class> bucketStatistics() {
		return Arrays.asList(
				new Class[] { FixedSizedConcurrentBucketStatistics.class, FixedSizedBucketStatistics.class });
	}

	private final IBucketStatistics bucketStatistic;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public FixedSizedBucketStatisticsTest(Class bucketStatistic) throws InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		this.bucketStatistic = (IBucketStatistics) bucketStatistic.getConstructor(String.class, int.class)
				.newInstance("FixedSizedBucketStatisticsTest", 8);
	}
	
	@Test
	public void testMin() {
		assertEquals(-1, bucketStatistic.getMin());

		bucketStatistic.addSample(0);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertEquals(0, bucketStatistic.getMin());
	}

	@Test
	public void testMin2() {
		assertEquals(-1, bucketStatistic.getMin());

		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertEquals(1, bucketStatistic.getMin());
	}

	@Test
	public void testMax() {
		assertEquals(-1, bucketStatistic.getMax());

		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(3);
		assertEquals(3, bucketStatistic.getMax());
	}

	@Test
	public void testInvalidArgument() {
		try {
			bucketStatistic.addSample(-1);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail();
	}

	// NaN test
	@Test
	public void testGetPercentileNaN() {
		try {
			bucketStatistic.getPercentile(Double.NaN);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail("Parameter not a number");
	}

	@Test
	public void testMaximum() {
		bucketStatistic.addSample(16);
		bucketStatistic.addSample(16);
		bucketStatistic.addSample(16);
		assertEquals(7, bucketStatistic.getMax());
		assertEquals(7, bucketStatistic.getMedian());
		assertEquals(3, bucketStatistic.getObservations());
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PCalTLAGenerator.java<|end_filename|>
package pcal;

import java.util.Vector;

import pcal.exception.PcalFixIDException;
import pcal.exception.PcalSymTabException;
import pcal.exception.PcalTLAGenException;
import pcal.exception.PcalTranslateException;
import pcal.exception.RemoveNameConflictsException;

/**
 * Responsible for generation of TLA+ from PCal AST<br>
 * Note: this class is renamed from NotYetImplemented on 11th March 2009
 * 
 * @author <NAME>, <NAME>
 * @version $Id$
 */
public class PCalTLAGenerator
{

    private PcalSymTab st = null;
    private AST ast = null; 
             // This is set to the AST constructed by ParseAlgorithm.getAlgorithm

    /**
     * Constructs a working copy 
     * @param ast
     */
    public PCalTLAGenerator(AST ast)
    {
        this.ast = ast;
    }

    /********************************************************************
     * Called by trans.java.  Should go in a new .java file.            *
     ********************************************************************/
    public void removeNameConflicts() throws RemoveNameConflictsException
    {
        try
        {
            st = new PcalSymTab(ast);
        } catch (PcalSymTabException e)
        {
            throw new RemoveNameConflictsException(e.getMessage());
        }

        st.Disambiguate();
        if (st.disambiguateReport.size() > 0)
            // SZ March 11, 2009. Warning reporting moved to PCalDebug 
            PcalDebug.reportWarning("symbols were renamed.");
        if (st.errorReport.length() > 0)
            throw new RemoveNameConflictsException(st.errorReport);
        try
        {
            PcalFixIDs.Fix(ast, st);
        } catch (PcalFixIDException e)
        {
            throw new RemoveNameConflictsException(e.getMessage());
        }
    }

    /********************************************************************
     * The main translation method.  Should go in a new .java file.     *
     * Note that this requires RemoveNameConflicts to be called first   *
     * because of the grotty use of the class variable st.              *
     ********************************************************************/
    public Vector<String> translate() throws RemoveNameConflictsException
    {
        Vector<String> result = new Vector<String>();
        AST xast = null;  // Set to the exploded AST

        for (int i = 0; i < st.disambiguateReport.size(); i++)
            result.addElement((String) st.disambiguateReport.elementAt(i));
        // System.out.println("Before: " + ast.toString());
        // System.out.println("After renaming: " + ast.toString());
        try
        {
            xast = PcalTranslate.Explode(ast, st);
        } catch (PcalTranslateException e)
        {
            throw new RemoveNameConflictsException(e);
        }
        // System.out.println("After exploding: " + xast.toString());
        try
        {
            PcalTLAGen tlaGenerator = new PcalTLAGen();
//            result.addAll(tlaGenerator.generate(xast, st));
            result = tlaGenerator.generate(xast, st, result);
        } catch (PcalTLAGenException e)
        {
            throw new RemoveNameConflictsException(e);
        }

// tla-pcal debugging
//System.out.println("After Translation:");
//System.out.println(xast.toString());
        /*******************************************************************
        * Following test added by LL on 31 Aug 2007.                       *
        *******************************************************************/
        try
        {
            if (ParseAlgorithm.hasDefaultInitialization)
            {
                st.CheckForDefaultInitValue();
            }
        } catch (PcalSymTabException e)
        {
            throw new RemoveNameConflictsException(e.getMessage());
        }
        return result;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/BitVector.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:26 PST by lamport
//      modified on Thu Nov 29 21:53:11 PST 2001 by yuanyu
package tlc2.util;

/** A <code>BitVector</code> is an ordered list of bits
    of potentially unbounded size. The index of the first
    bit in a bit vector is 0.<p>
    
    This class is unmonitored; it is the responsibility
    of clients to guarantee thread safety. The read-only
    methods are <code>get</code> and <code>iterator</code>.

    Written by <NAME> and <NAME>
*/

import java.io.IOException;
import java.io.Serializable;

public class BitVector implements Serializable {

  private static final long serialVersionUID = 901734230891583097L;
  private long[] word;                   // words of this bit vector

  public BitVector() { this.word = null; }
  
  /**
   * Constructor for a new bit vector that is expected to contain bits
   * with indices 0 through <code>initCapacity-1</code>.
   */
  public BitVector(int initCapacity) {
    int len = (initCapacity == 0) ? 0 : ((initCapacity - 1)/64 + 1);
    this.word = new long[len];
  }
  
	/**
	 * Constructor for a new bit vector that is expected to contain bits with
	 * indices 0 through <code>initCapacity-1</code>. All bits are initially set
	 * to <code>true</code>
	 */
	public BitVector(int initCapacity, boolean initValue) {
		int len = (initCapacity == 0) ? 0 : ((initCapacity - 1) / 64 + 1);
		this.word = new long[len];
		if (initValue) {
			set(0, len);
		}
	}
   
  /** Initialize this bit vector to be a copy of <code>bv</code>. */
  public BitVector(BitVector bv) {
    int len = bv.word.length;
    this.word = new long[len];
    System.arraycopy(bv.word, 0, this.word, 0, len);
  }

  public boolean equals(Object o) {
    if (!(o instanceof BitVector)) return false;
    BitVector other = (BitVector)o;
    int minLen = Math.min(this.word.length, other.word.length);
    for (int i = 0; i < minLen; i++) {
      if (this.word[i] != other.word[i]) return false;
    }
    if (this.word.length != other.word.length) {
      int maxLen = Math.max(this.word.length, other.word.length);
      long[] tail = (maxLen == this.word.length) ? this.word : other.word;
      for (int i = minLen; i < maxLen; i++) {
	if (tail[i] != 0L) return false;
      }
    }
    return true;
  }

  public int hashCode() {
    int res = 0;
    for (int i = 0; i < this.word.length; i++) {
      long w = this.word[i];
      if (w != 0) {
	res ^= (int)(w & 0xffffL);
	res ^= (int)(w >>> 32);
      }
    }
    return res;
  }

  /** Reset all of this bit vector's bits. */
  public void clear() {
    for (int i = 0; i < this.word.length; i++) {
      this.word[i] = 0L;
    }
  }
    
  /** Return the bit at index <code>i</code>. */
  public boolean get(int i) {
    int wd = i / 64;
    if (wd >= this.word.length) return false;
    int bit = i % 64;
    return (this.word[wd] & (1L << bit)) != 0L;
  }
    
  /** Set the bit at index <code>i</code> to <code>true</code>. */
  public void set(int i) {
    int wd = i / 64;
    if (wd >= this.word.length) this.grow(wd);
    int bit = i % 64;
    this.word[wd] |= (1L << bit);
  }
    
  /** Set all the bits with indices in the closed interval
      <code>[lo, hi]</code>. */
  public void set(int lo, int hi) {
    int lwd = lo / 64;
    int hwd = hi / 64;
    if (hwd >= this.word.length) this.grow(hwd);
    int lbit = lo % 64;
    int hbit = hi % 64;
    if (lwd < hwd) {
      for (int i = lwd+1; i < hwd; i++) {
	this.word[i] = -1L;
      }
      this.word[lwd] = (-1L << lbit);
      this.word[hwd] = (-1L >>> (63-hbit));
    }
    else {
      if (lo <= hi) {
	this.word[lwd] = (-1L << lbit) & (-1L >>> (63-hbit));
      }
    }
  }
  
  	/**
	 * Returns this {@link BitVector} is a bit string with the MSB to the left
	 * and the LSB to the right.
	 * 
	 * @see java.lang.Object#toString()
	 */
  public String toString() {
	  final StringBuffer buf = new StringBuffer(this.word.length * 64);
	  for (int i = this.word.length * 64; i >= 0; i--) {
		  if (get(i)) {
			  buf.append("1");
		  } else {
			  buf.append("0");
		  }
	  }
	  buf.append("]");
	  return buf.toString().replaceAll("^0*","["); // Replace leading zeros with "["
  }
  public String toString(int start, int length) {
	  return toString(start, length, '1', '0');
  }
  
  public String toString(int start, int length, char one, char zero) {
	  final StringBuffer buf = new StringBuffer(length);
	  for (int i = 0; i < length; i++) {
		  if (get(start + i)) {
			  buf.append(one);
		  } else {
			  buf.append(zero);
		  }
	  }
	  return "[" + buf.reverse().toString() + "]";
  }
  
	/**
	 * @return The number of bits set true
	 */
	public int trueCnt() {
		int res = 0;
		for (int i = 0; i < this.word.length * 64; i++) {
			// addr in long[]
			int wd = i / 64;
			// addr in long[x]
			int bit = i % 64;
			if ((this.word[wd] & (1L << bit)) != 0L) {
				res++;
			}
		}
		return res;
	}
    
  /** Set the bit at index <code>i</code> to <code>false</code>. */
  public void reset(int i) {
    int wd = i / 64;
    if (wd >= this.word.length) this.grow(wd);
    int bit = i % 64;
    this.word[wd] &= ~(1L << bit);
  }
    
  /** Set the bit at index <code>i</code> to <code>val</code>. */
  public void set(int i, boolean val) {
    int wd = i / 64;
    if (wd >= this.word.length) this.grow(wd);
    int bit = i % 64;
    if (val) {
      this.word[wd] |= (1L << bit);
    } else {
      this.word[wd] &= ~(1L << bit);
    }
  }

  /** Write the bit vector to a file. */
  public void write(BufferedRandomAccessFile raf) throws IOException {
    int len = this.word.length;
    raf.writeNat(len);
    for (int i = 0; i < len; i++) {
      raf.writeLong(this.word[i]);
    }
  }

  /** Read a bit vector from a file */
  public void read(BufferedRandomAccessFile raf) throws IOException {
    int len = raf.readNat();
    this.word = new long[len];
    for (int i = 0; i < len; i++) {
      this.word[i] = raf.readLong();
    }
  }
  
  /** Grow this bit vector to contain at least <code>wd+1</code>
      words. */
  private void grow(int wd) {
    // Assert.check(wd >= this.word.length);
    int newLen = Math.max(this.word.length, wd + 1);
    long[] tmp = new long[newLen];
    System.arraycopy(this.word, 0, tmp, 0, this.word.length);
    this.word = tmp;
  }
    
  /** A <code>BitVector.Iter</code> is an object for enumerating the
      set bits of a given bit vector in order. While the iterator is 
      being used, the bit vector should not be modified.*/
  public static class Iter {
    /*@ non_null */
    long[] word;  // pointer to bit vector's 'word' array
    int wd;       // index of next word to consider
    int bit;      // index of next bit to consider
    long mask;    // mask of next bit to consider
        
    //@ invariant this.wd >= 0
    //@ invariant this.mask == (1L << this.bit)

    /** Construct an empty <code>Iter</code> object. The
	<code>init</code> method must be called before this
	iterator can be used. */
    public Iter() { /*SKIP*/ }
        
    /** Initialize this <code>Iter</code> object for iterating
	over <code>bv</code>. */
    public Iter(BitVector bv) { this.init(bv); }
        
    /** Reinitialize this <code>BVIter</code> object for iterating
	over <code>bv</code>. */
    public void init(BitVector bv) {
      this.word = bv.word;
      this.wd = 0;
      this.bit = 0;
      this.mask = 1L;
    }
        
    /** Return the index of the next set bit in this iterator's
	bit vector, or -1 if there are no more such bits. */
    public int next() {
      for (; this.wd < this.word.length; this.wd++) {
	long w = this.word[this.wd];
	for (; this.bit < 64; this.bit++, this.mask <<= 1) {
	  if ((w & this.mask) != 0L) {
	    int res = (this.wd * 64) + this.bit;
	    // advance to next bit for next call
	    this.bit++;
	    if (this.bit < 64) {
	      this.mask <<= 1;
	    } else {
	      this.wd++;
	      this.bit = 0;
	      this.mask = 1L;
	    }
	    return res;
	  }
	}
	this.bit = 0;
	this.mask = 1L;
      }
      return -1;
    }
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/DecimalNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.math.BigDecimal;
import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.xml.SymbolContext;

/**
 * Describes a decimal like 1347.052.  This number is represented by the
 * values
 *
 *   long mantissa() = 1347052
 *   int  exponent() = -3
 *   BigDecimal bigVal() = null
 *
 * so its value is mantissa() * 10^(exponent).  However, if the number
 * can't be represented in this way, then bigVal() is the value as a
 * BigDecimal and the other fields are meaningless.
 *
 * If bigVal() equals null, then mantissa() is either a positive integer
 * not divisible by 10, or else it equals 0 and exponent() equals 0.
 */
public class DecimalNode extends ExprNode {

  private long       mantissa;
  private int        exponent;
  private BigDecimal bigVal = null;
  private String     image;

  // Bug: should remove trailing 0's from b ?
  public DecimalNode(String a, String b, TreeNode stn) {
    super(DecimalKind, stn);
    image = a + "." + b;
    try {
      this.mantissa = Long.parseLong( a + b );
      this.exponent = - b.length();
     }
     catch (NumberFormatException e) {
      this.bigVal = new BigDecimal( image );
    }
   }

  /**
   * Returns the mantissa of the decimal number, i.e its value after scaling
   * by a power of 10 until the fractional part is zero; e.g. the mantissa of
   * 1.23 is 123.
   */
  public final long mantissa() { return this.mantissa; }

  /**
   * The power of 10 which, when multiplied by the mantissa, yields the original number,
   * e.g. the exponent of 1.23 is -2.
   */
  public final int exponent() { return this.exponent; }

  /**
   * Returns the number in BigDecimal form
   */
  public final BigDecimal bigVal() { return this.bigVal; }

  /**
   * Returns the value as a string, exactly the way the user typed it--e.g.,
   * without any normalization, removal of leading or trailing zero's, etc.
   */
  @Override
  public final String toString() { return this.image; }

  /* Level checking */
  @Override
  public final boolean levelCheck(int iter) {
    levelChecked = iter;
      /*********************************************************************
      * Set it just to show that levelCHeck was called.                    *
      *********************************************************************/
    return true;
  }

//  public final int getLevel() { return ConstantLevel; }
//
//  public final HashSet getLevelParams() { return EmptySet; }
//
//  public final SetOfLevelConstraints getLevelConstraints() {
//    return EmptyLC;
//  }
//
//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    return EmptyALC;
//  }
//
//  public final HashSet getArgLevelParams() { return EmptySet; }

  /**
   *  toString, levelDataToString(), and walkGraph methods to implement
   *  ExploreNode interface
   */
//  public final String levelDataToString() {
//    return "Level: "               + this.getLevel()               + "\n" +
//           "LevelParameters: "     + this.getLevelParams()         + "\n" +
//           "LevelConstraints: "    + this.getLevelConstraints()    + "\n" +
//           "ArgLevelConstraints: " + this.getArgLevelConstraints() + "\n" +
//           "ArgLevelParams: "      + this.getArgLevelParams()      + "\n" ;
//  }

  /**
   * walkGraph finds all reachable nodes in the semantic graph and
   * inserts them in the Hashtable semNodesTable for use by the
   * Explorer tool.
   */
  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;

    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    visitor.postVisit(this);
  }

  /**
   * Displays this node as a String, implementing ExploreNode
   * interface; depth parameter is a bound on the depth of the portion
   * of the tree that is displayed.
   */
  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";
    return( "\n*DecimalNode" + super.toString(depth) + "Mantissa: "
            + mantissa + "; exponent: " + exponent
            + "; big value: " + (bigVal != null ? bigVal.toString() : "<null>")
            + "\n; image = " + image
          );
  }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
    Element e = doc.createElement("DecimalNode");
    if (bigVal != null) {
      e.appendChild(appendText(doc,"mantissa",bigVal.unscaledValue().toString()));
      e.appendChild(appendText(doc,"exponent",Integer.toString(bigVal.scale())));
    }
    else {
      e.appendChild(appendText(doc,"mantissa",Long.toString(mantissa)));
      e.appendChild(appendText(doc,"exponent",Integer.toString(exponent)));
    }
    return e;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/pcal/IPCalReservedWords.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.pcal;

import org.lamport.tla.toolbox.editor.basic.tla.ITLAReserveredWords;

/**
 * @author <NAME>
 * @version $Id$
 */
public interface IPCalReservedWords {
	public final static String ALGORITHM = "--algorithm";

	public final static String ASSERT = "assert";
	public final static String AWAIT = "await";
	public final static String BEGIN = "begin";
	public final static String CALL = "call";
	public final static String DEFINE = ITLAReserveredWords.PDEFINE;
	public final static String DO = "do";
	public final static String EITHER = "either";
	public final static String ELSE = "else";
	public final static String ELSEIF = "elseif";
	public final static String END = "end";
	public final static String GOTO = "goto";
	public final static String IF = "if";
	public final static String MACRO = "macro";
	public final static String OR = "or";
	public final static String PRINT = "print";
	public final static String PROCEDURE = "procedure";
	public final static String PROCESS = "process";
	public final static String FAIR = "fair";
	public final static String RETURN = "return";
	public final static String SKIP = "skip";
	public final static String THEN = "then";
	public final static String VARIABLE = "variable";
	public final static String VARIABLES = "variables";
	public final static String WHILE = "while";
	public final static String WITH = "with";
	// public final static String WHEN = "";

	public final static String[] ALL_WORDS_ARRAY = new String[] { ASSERT, BEGIN, CALL, DO, EITHER, ELSE, ELSEIF, END,
			GOTO, IF, MACRO, OR, PRINT, PROCEDURE, PROCESS, FAIR, RETURN, SKIP, THEN, VARIABLE, VARIABLES, WHILE,
			WITH };

	// Just the complete PlusCal BNF
	public static final String ALGORITHM_HELP = "<Algorithm> ::= [--algorithm | --fair algorithm] <name>\r\n"
			+ "		{<VarDecls>{0,1}\r\n" + "		<Definitions>{0,1}\r\n" + "		<Macro>*\r\n"
			+ "		<Procedure>*\r\n" + "		[<CompoundStmt> | [fair [+]{0,1}]{0,1}<Process>+] }\r\n" + "\r\n"
			+ "<Definitions> ::= define { <Defs> } [;]{0,1}\r\n" + "\r\n"
			+ "<Macro> ::= macro<Name> ( [ <Variable>[, <Variable>]* ]{0,1} )\r\n" + "		<CompoundStmt> [;]{0,1}\r\n"
			+ "\r\n" + "<Procedure> ::= procedure<Name> ( [<PVarDecl> [,<PVarDecl>]*]{0,1} )\r\n"
			+ "		<PVarDecls>{0,1}\r\n" + "		<CompoundStmt> [;]{0,1}\r\n" + "\r\n"
			+ "<Process> ::= [fair [+]{0,1}]{0,1} process (<Name> [=|\\in] <Expr> )\r\n" + "		<VarDecls>{0,1}\r\n"
			+ "		<CompoundStmt> [;]{0,1}\r\n" + "\r\n" + "<VarDecls> ::= [variable | variables] <VarDecl>+\r\n"
			+ "<VarDecl> ::=<Variable> [[=|\\in] <Expr>]{0,1} [;|,]\r\n" + "\r\n"
			+ "<PVarDecls> ::= [variable | variables] [hPVarDecl> [;|,]]+\r\n"
			+ "<PVarDecl> ::=<Variable> [=<Expr>]{0,1}\r\n" + "\r\n"
			+ "<CompoundStmt> ::= {<Stmt> [;<Stmt>]* [;]{0,1} }\r\n"
			+ "<Stmt> ::= [<Label> : [+|-]{0,1}]{0,1} [<UnlabeledStmt> |<CompoundStmt>]\r\n"
			+ "<UnlabeledStmt> ::=<Assign> |<If> |<While> |<Either> |<With> | <Await> |<Print> |<Assert> |<Skip> |<Return> | <Goto> |<Call> |<MacroCall>\r\n"
			+ "\r\n" + "<Assign> ::=<LHS> := <Expr> [||<LHS> :=<Expr>]*\r\n"
			+ "<LHS> ::=<Variable> [[<Expr> [,<Expr>]*] | .<Field>]*\r\n" + "\r\n"
			+ "<If> ::=>f (<Expr> )<Stmt> [else<Stmt>]{0,1}\r\n" + "\r\n" + "<While> ::= while (<Expr>)<Stmt>\r\n"
			+ "\r\n" + "<Either> ::= either<Stmt> [or<Stmt>]+\r\n" + "<With> ::= with (<Variable> [=|\\in] <Expr>\r\n"
			+ "			[[; | ,]<Variable> [=|\\in] <Expr>]* [; | ,]{0,1}\r\n" + "		)<Stmt>\r\n" + "\r\n"
			+ "<Await> ::= [await | when]<Expr>\r\n" + "\r\n" + "<Print> ::= print<Expr>\r\n" + "\r\n"
			+ "<Assert> ::= assert<Expr>\r\n" + "\r\n" + "<Skip> ::= skip\r\n" + "\r\n" + "<Return> ::= return\r\n"
			+ "\r\n" + "<Goto> ::= goto<Label>\r\n" + "\r\n" + "<Call> ::= call<MacroCall>\r\n" + "\r\n"
			+ "<MacroCall> ::=<Name> ( [<Expr> [,<Expr>]*]{0,1} )\r\n" + "\r\n"
			+ "<Variable> ::= A TLA+ identifier that is not a PlusCal reserved word and\r\n"
			+ "is not pc, stack, or self.\r\n" + "\r\n" + "<Field> ::= A TLA+ record-component label.\r\n" + "\r\n"
			+ "<Name> ::= A TLA+ identifier that is not a PlusCal reserved word.\r\n" + "\r\n"
			+ "<Label>  ::= A TLA+ identifier that is not a PlusCal reserved word and\r\n" + "is not Done or Error.\r\n"
			+ "\r\n" + "<Expr> ::= A TLA+ expression not containing a PlusCal reserved word\r\n" + "or symbol.\r\n"
			+ "\r\n" + "<Defs> ::= A sequence of TLA+ definitions not containing a PlusCal\r\n"
			+ "reserved word or symbol.";

	public static final String ASSIGN_HELP = "<Assign> ::= <LHS> := <Expr> [ || <LHS> := <Expr>]*\r\n"
			+ "\t<LHS> ::= <Variable> [[ <Expr> [, <Expr>]* ] | . <Field>]*\n\n"
			+ "An assignment is either an assignment to a variable such as\r\n" + "\ty := A + B\r\n"
			+ "or else an assignment to a component, such as\r\n" + "\tx.foo[i+1] := y+3\r\n"
			+ "If the current value of x is a record with a foo component that is a function\r\n"
			+ "(array), then this assignment sets the component x.foo[i+1] to the current\r\n"
			+ "value of y+3. The value of this assignment is undefined if the value of x is not\r\n"
			+ "a record with a foo component, or if x.foo is not a function. Therefore, if\r\n"
			+ "such an assignment appears in the code, then x will usually be initialized to\r\n"
			+ "an element of the correct “type”, or to be a member of some set of elements\r\n"
			+ "of the correct type. For example, the declaration\r\n" + "\tvariable x \\in [bar : BOOLEAN,\r\n"
			+ "\t\tfoo : [1..N |-> {\"on\", \"off\"}] ] ;\r\n"
			+ "asserts that initially x is a record with a bar component that is a Boolean\r\n"
			+ "(equal to TRUE or FALSE) and a foo component that is a function with\r\n"
			+ "domain 1.. N such that x.foo[i] equals either “on” or “off” for each i in\r\n" + "1.. N.\r\n"
			+ "An assignment statement consists of one or more assignments, separated\r\n"
			+ "by “||” tokens, ending with a semicolon. An assignment statement contain-\r\n"
			+ "ing more than one assignment is called a multiple assignment. A multiple\r\n"
			+ "assignment is executed by first evaluating the right-hand sides of all its as-\r\n"
			+ "signments, and then performing those assignments from left to right. For\r\n"
			+ "example, if i = j = 3, then executing\r\n" + "\tx[i] := 1 || x[j] := 2\r\n" + "sets x[3] to 2.\r\n"
			+ "Assignments to the same variable cannot be made in two different as-\r\n"
			+ "signment statements within the same step. In other words, in any control\r\n"
			+ "path, a label must come between two statements that assign to the same\r\n"
			+ "variable. However, assignments to components of the same variable may\r\n"
			+ "appear in a single multiple assignment, as in\r\n" + "\tx.foo[7] := 13 || y := 27 || x.bar := x.foo";
	public static final String MULTI_ASSIGN_HELP = "A multiple\r\n"
			+ "assignment is executed by first evaluating the right-hand sides of all its as-\r\n"
			+ "signments, and then performing those assignments from left to right. For\r\n"
			+ "example, if i = j = 3, then executing\r\n" + "\tx[i] := 1 || x[j] := 2\r\n" + "sets x[3] to 2.\r\n"
			+ "Assignments to the same variable cannot be made in two different as-\r\n"
			+ "signment statements within the same step. In other words, in any control\r\n"
			+ "path, a label must come between two statements that assign to the same\r\n"
			+ "variable. However, assignments to components of the same variable may\r\n"
			+ "appear in a single multiple assignment, as in\r\n" + "\tx.foo[7] := 13 || y := 27 || x.bar := x.foo";
	public static final String DEFINE_HELP = "<Definitions> ::= define { <Defs> }[;]{0,1}\n\n"
			+ "An algorithm’s expressions can use any operators defined in the TLA + mod-\r\n"
			+ "ule before the “BEGIN TRANSLATION” line. Since the TLA + declaration of\r\n"
			+ "the algorithm’s variables follows that line, the definitions of those opera-\r\n"
			+ "tors can’t mention any algorithm variables. The PlusCal define statement\r\n"
			+ "allows you to write TLA + definitions of operators that depend on the algo-\r\n"
			+ "rithm’s global variables. For example, suppose the algorithm begins:\r\n" + "\t--algorithm Test {\r\n"
			+ "\tvariables x \\in 1..N ; y ;\r\n" + "\tdefine { zy == y*(x+y)\r\n" + "\t\tzx(a) == x*(y-a) }\r\n"
			+ "\t...\r\n" + "The operators zy and zx can then be\r\n"
			+ "used in expressions anywhere in the remainder of the algorithm. Observe\r\n"
			+ "that there is no semicolon or other separator between the two definitions.\r\n"
			+ "Section 5.11 on page 55 describes how to write TLA + definitions.\r\n"
			+ "The variables that may appear within the define statement are the ones\r\n"
			+ "declared in the variable statement that immediately precedes it and that\r\n"
			+ "follows the algorithm name, as well as the variable pc and, if there is a pro-\r\n"
			+ "cedure, the variable stack . Local process and procedure variables may not\r\n"
			+ "appear in the define statement. The define statement’s definitions need\r\n"
			+ "not mention the algorithm’s variables. You might prefer to put definitions\r\n"
			+ "in the define statement even when they don’t have to go there. However,\r\n"
			+ "remember that the define statement cannot mention any symbols defined\r\n"
			+ "or declared after the “END TRANSLATION” line; and the symbols it defines\r\n"
			+ "cannot be used before the “BEGIN TRANSLATION” line.\r\n"
			+ "Definitions, including ones in a define statement, are not expanded\r\n"
			+ "in the PlusCal to TLA + translation. All defined symbols appear in the\r\n"
			+ "translation exactly as they appear in the PlusCal code.";
	public static final String MACRO_HELP = "<Macro> ::= macro <Name> ( [<Variable>[, <Variable>]∗]{0,1})\n"
			+ "\t<CompoundStmt>[;]{0,1}\n\n"
			+ "A macro is like a procedure, except that a call of a macro is expanded at\r\n"
			+ "translation time. You can think of a macro as a procedure that is executed\r\n"
			+ "within the step from which it is called.\r\n"
			+ "A macro definition looks much like a procedure declaration - for example:\r\n"
			+ "\tmacro P(s, i) { await s ≥ i ;\r\n" + "\t\ts := s - i }\r\n"
			+ "The difference is that the body of the macro may contain no labels, no\r\n"
			+ "while, call, return, or goto statement. It may contain a call of a previously\r\n"
			+ "defined macro. Macro definitions come right after any global variable\r\n"
			+ "declarations and define section.\r\n"
			+ "A macro call is like a procedure call, except with the call omitted—for\r\n" + "example:\r\n"
			+ "\tP(sem, y + 17) ;\r\n"
			+ "The translation replaces the macro call with the sequence of statements ob-\r\n"
			+ "tained from the body of the macro definition by substituting the arguments\r\n"
			+ "of the call for the definition’s parameters. Thus, this call of the P macro\r\n" + "expands to:\r\n"
			+ "\tawait sem ≥ (y + 17) ;\r\n" + "\tsem := sem - (y + 17) ;\n"
			+ "When translating a macro call, substitution is syntactic in the sense that\r\n"
			+ "the meaning of any symbol in the macro definition other than a parameter\r\n"
			+ "is the meaning it has in the context of the call. For example, if the body of\r\n"
			+ "the macro definition contains a symbol q and the macro is called within a\r\n"
			+ "\"with ( q \\in ... )\" statement, then the q in the macro expansion is the q\r\n"
			+ "introduced by the with statement.\r\n"
			+ "When replacing a macro by its definition, the translation replaces every\r\n"
			+ "instance of a macro parameter id in an expression within the macro body\r\n"
			+ "by the corresponding expression. Every instance includes any uses of id as\r\n"
			+ "a bound variable, as in the expression\r\n" + "\t[id \\id 1..N |-> false]\r\n"
			+ "The substitution of an expression like y + 17 for id here will cause a mys-\r\n"
			+ "terious error when the translation is parsed. When using PlusCal, obey the\r\n"
			+ "TLA+ convention of never assigning a new meaning to any identifier that\r\n" + "already has a meaning.";
	public static final String GOTO_HELP = "<Goto> ::= goto <Label>\n\nExecuting the statement\r\n" + "\tgoto lab ;\r\n"
			+ "ends the execution of the current step and causes control to go to the state-\r\n"
			+ "ment labeled lab. In any control path, a goto must be immediately followed\r\n"
			+ "by a label. (Remember that the control path by definition ignores the mean-\r\n"
			+ "ing of the goto and continues to what is syntactically the next statement.)\r\n"
			+ "It is legal for a goto to jump into the middle of a while or if statement,\r\n"
			+ "but this sort of trickery should be avoided.";
	public static final String SKIP_HELP = "<Skip> ::= skip\n\nThe statement skip; does nothing.";
	public static final String ASSERT_HELP = "<Assert> ::= assert <Expr>\n\n" + "The statement" + "\tassert expr;"
			+ "is equivalent to skip if expression expr equals true. If expr equals false,\r\n"
			+ "executing the statement causes TLC to produce an error message saying\r\n"
			+ "that the assertion failed and giving the location of the assert statement.\r\n"
			+ "TLC may report a failed assertion even if the step containing the assert\r\n"
			+ "statement is not executed because of an await statement that appears later\r\n" + "in the step.\r\n"
			+ "An algorithm containing an assert statement must be in a module that\r\n" + "extends the TLC module.";
	public static final String PRINT_HELP = "<Print> ::= print <Expr>\n\n" + "Execution of the statement\r\n"
			+ "\tprint expr;\r\n"
			+ "is equivalent to skip, except it causes TLC to print the current value of expr.\r\n"
			+ "TLC may print the value even if the step containing the print statement is\r\n"
			+ "not executed because of an await statement that appears later in the step.\r\n"
			+ "An algorithm containing a print statement must be in a module that\r\n" + "extends the TLC module.";
	public static final String RETURN_HELP = "<Return> ::= return\n\nSee procedure!";
	public static final String AWAIT_HELP = "<Await> ::= [ await | when ] <Expr>\n\nA step containing the statement await expr can be executed only when the\r\n"
			+ "value of the Boolean expression expr is TRUE. Although it usually appears\r\n"
			+ "at the beginning of a step, an await statement can appear anywhere within\r\n" + "the step.\r\n"
			+ "\ta : x := y + 1 ;\r\n" + "\tb: ...\r\n"
			+ "The step from a to b can be executed only when the current value of y+1\r\n"
			+ "is positive. (Remember that an entire step must be executed; part of a step\r\n"
			+ "cannot be executed by itself.) The keyword when can be used instead of\r\n" + "await.";
	public static final String WITH_HELP = "<With> ::= with ( <Variable> [=|\\in] <Expr>\r\n"
			+ "\t[ [;|,] <Variable> [=|\\\\in] <Expr> ]* [;|,]{0,1}\r\n" + "\t) <Stmt>\n\n" + "The statement\r\n"
			+ "\twith ( id \\in S ) body\r\n"
			+ "is executed by executing the (possibly compound) statement body with identifier\r\n"
			+ " id equal to a nondeterministically chosen element of S.\r\n" + "Execution is impossible if S is empty.";
	public static final String EITHEROR_HELP = "<Either> ::= either <Stmt> [or <Stmt> ]+\n\n"
			+ "The either statement has the form:\r\n" + "\teither clause 1\r\n" + "\tor clause 2\r\n" + "\t.\r\n"
			+ "\t.\r\n" + "\tor clause n\r\n"
			+ "where each clause i is a (possibly compound) statement. It is executed by\r\n"
			+ "nondeterministically choosing any clause i that is executable and executing\r\n"
			+ "it. The either statement can be executed iff at least one of those clauses can\r\n"
			+ "be executed. If any clause i contains a call, return, or goto statement or a\r\n"
			+ "label, then the either statement must be followed by a labeled statement.\r\n" + "The statement\r\n"
			+ "\tif (test) t clause else e clause\r\n" + "is equivalent to the following statement.\r\n"
			+ "\teither { await test ; t clause }\r\n" + "\tor { await ¬test ; e clause }";
	public static final String IFTHENELSE_HELP = "<If> ::= if ( <Expr> ) <Stmt> [else <Stmt>]{0,1}\n\n"
			+ "The if statement has its usual meaning. The statement\r\n" + "\tif ( test ) t clause else e clause\r\n"
			+ "is executed by evaluating the expression test and then executing the (pos-\r\n"
			+ "sibly compound) statement t clause or e clause depending on whether test\r\n"
			+ "equals true or false. The else clause is optional. An if statement must\r\n"
			+ "have a non-empty then clause. An if statement that contains a call,\r\n"
			+ "return, or goto statement or a label within it must be followed by a\r\n"
			+ "labeled statement. (A label on the if statement itself is not considered to be\r\n"
			+ "within the statement.)";
	public static final String VARIABLE_HELP = "<VarDecls> ::= [variable|variables] <VarDecl>+\r\n"
			+ "\t<VarDecl> ::= <Variable> [ [= |\\in] <Expr> ]{0,1} [;|,]\n\n";
	public static final String WHILE_HELP = "<While> ::= while ( <Expr> ) <Stmt>\n\n"
			+ "The while statement has its usual meaning. The statement\r\n" + "\tlb : while ( test ) body\r\n"
			+ "where body is a (possibly compound) statement, is executed like the following\r\n" + "if statement.\r\n"
			+ "\tlb : if ( test ) { body ; goto lb }\r\n"
			+ "A while statement must be labeled. However, the statement following a\r\n"
			+ "while statement need not be labeled, even if there is a label in body.";
	public static final String PROCESS_HELP = "<Process> ::= [ fair [+]{0,1} ]{0,1} process ( <Name> [=|\\in] <Expr> )\r\n"
			+ "\t<VarDecls>{0,1}\r\n" + "\t<CompoundStmt> [;]{0,1}\n\n"
			+ "A multiprocess algorithm contains one or more processes. A process begins\r\n"
			+ "in one of two ways:\r\n" + "\tprocess ( ProcName \\in IdSet )\r\n" + "\tprocess ( ProcName = Id )\r\n"
			+ "The first form begins a process set, the second an individual process. The\r\n"
			+ "identifier ProcName is the process or process set’s name. The elements of\r\n"
			+ "the set IdSet and the element Id are called process identifiers. The process\r\n"
			+ "identifiers of different processes in the same algorithm must all be different.\r\n"
			+ "This means that the semantics of TLA + must imply that they are different,\r\n"
			+ "which intuitively usually means that they must be of the same “type”. (For\r\n"
			+ "example, the semantics of TLA + does not specify whether or not a string\r\n"
			+ "may equal a number.) For execution by TLC, this means that all process\r\n"
			+ "identifiers must be comparable values, as defined in Specifying\r\n" + "Systems.\r\n"
			+ "The name ProcName has no significance; changing it does not change\r\n"
			+ "the meaning of the process statement in any way. The name appears\r\n"
			+ "in the TLA + translation, and it should be different for different process\r\n" + "statements\r\n"
			+ "As explained above in Section 2.6 on page 11, the process statement is\r\n"
			+ "optionally followed by declarations of local variables. The process body is a\r\n"
			+ "sequence of statements enclosed by braces ({ }). Its first statement must be\r\n"
			+ "labeled. Within the body of a process set, self equals the current process’s\r\n" + "identifier.\r\n"
			+ "A multiprocess algorithm is executed by repeatedly choosing an arbitrary\r\n"
			+ "process and executing one step of that process, if that step’s execution is\r\n"
			+ "possible. Execution of the process’s next step is impossible if the process has\r\n"
			+ "terminated, if its next step contains an await statement whose expression\r\n"
			+ "equals false, or if that step contains a statement of the form “await x ∈ S ”\r\n"
			+ "and S equals the empty set. Fairness conditions may be specified on the choice\r\n"
			+ "of which processes’ steps are to be executed.";
	public static final String CALL_HELP = "<Call> ::= call <MacroCall>\r\n"
			+ "\t<MacroCall> ::= <Name> ( [ <Expr>[, <Expr>]* ]{0,1} )\n\nSee procedure!";
	public static final String PROCEDURE_HELP = "<Procedure> ::= procedure <Name> ( [<PVarDecl> [, <PVarDecl>]* ]{0,1} )\r\n"
			+ "\t<PVarDecls>{0,1}\r\n" + "\t<CompoundStmt> [;]{0,1}\n\n"
			+ "An algorithm may have one or more procedures. If it does, the algorithm\r\n"
			+ "must be in a TLA + module that extends the Sequences module.\r\n"
			+ "The algorithm’s procedures follow its global variable declarations and\r\n"
			+ "define section (if any) and precede the “{” that begins the body of a\r\n"
			+ "uniprocess algorithm or the first process of a multiprocess algorithm. A\r\n"
			+ "procedure named PName begins\r\n" + "\tprocedure PName ( param 1 , . . . , param n )\r\n"
			+ "where the identifiers param i are the formal parameters of the procedure.\r\n"
			+ "These parameters are treated as variables and may be assigned to. As ex-\r\n"
			+ "plained in Section 4.5 on page 37, there may also be initial-value assignments\r\n"
			+ "of the parameters.\r\n" + "The procedure statement is optionally followed by declarations of vari-\r\n"
			+ "ables local to the procedure. These have the same form as the declara-\r\n"
			+ "tions of global variables, except that initializations may only have the form\r\n"
			+ "“variable = expression”. The procedure’s local variables are initialized on\r\n"
			+ "each entry to the procedure.\r\n"
			+ "Any variable declarations are followed by the procedure’s body, which\r\n"
			+ "is a sequence of statements enclosed by braces ({ }). The body must begin\r\n"
			+ "with a labeled statement. There is an implicit label Error immediately\r\n"
			+ "after the body. If control ever reaches that point, then execution of either\r\n"
			+ "the process (multiprocess algorithm) or the complete algorithm (uniprocess\r\n" + "algorithm) halts.\r\n"
			+ "A procedure PName can be called by the statement\r\n" + "\tcall PName ( expr 1 , . . . , expr n )\r\n"
			+ "Executing this call assigns the current values of the expressions expr i to the\r\n"
			+ "corresponding parameters param i , initializes the procedure’s local variables,\r\n"
			+ "and puts control at the beginning of the procedure body.\r\n"
			+ "A return statement assigns to the parameters and local procedure vari-\r\n"
			+ "ables their previous values—that is, the values they had before the procedure\r\n"
			+ "was last called—and returns control to the point immediately following the\r\n" + "call statement.\r\n"
			+ "The call and return statements are considered to be assignments to the\r\n"
			+ "procedure’s parameters and local variables. In particular, they are included\r\n"
			+ "in the rule that a variable can be assigned a value by at most one assignment\r\n"
			+ "statement in a step. For example, if x is a local variable of procedure P ,\r\n"
			+ "then a step within the body of P that (recursively) calls P cannot also assign\r\n" + "a value to x.\r\n"
			+ "For a multiprocess algorithm, the identifier self in the body of a proce-\r\n"
			+ "dure equals the process identifier of the process within which the procedure\r\n" + "is executing.\r\n"
			+ "The return statement has no argument. A PlusCal procedure does not\r\n"
			+ "explicitly return a value. A value can be returned by having the procedure\r\n"
			+ "set a global variable and having the code immediately following the call\r\n"
			+ "read that variable. For example, in a multiprocess algorithm, procedure P\r\n"
			+ "might use a global variable rVal to return a value by executing\r\n" + "\trVal[self] := ... ;\r\n"
			+ "\treturn ;\r\n" + "From within a process in a process set, the code that calls P might look like\r\n"
			+ "this:\r\n" + "call P(17) ;\r\n" + "lab: x := ... rVal[self] ... ;\r\n"
			+ "For a call from within a single process, the code would contain the process’s\r\n"
			+ "identifier instead of self.\r\n"
			+ "In any control path, a return statement must be immediately followed\r\n"
			+ "by a label. A call statement must either be followed in the control path by\r\n"
			+ "a label or else it must appear immediately before a return statement in a\r\n"
			+ "statement sequence.\r\n" + "When a call P statement is followed immediately by a return, the\r\n"
			+ "return from procedure P and the return performed by the return statement\r\n"
			+ "are both executed as part of a single execution step. When these statements\r\n"
			+ "are in the (recursive) procedure P , this combining of the two returns is\r\n"
			+ "essentially the standard optimization of replacing tail recursion by a loop.";
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/ToolboxLifecycleParticipantManger.java<|end_filename|>
package org.lamport.tla.toolbox;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;

/**
 * Provides methods for accessing the extensions registered to the toolbox extension points
 *  
 * @author <NAME>
 */
public class ToolboxLifecycleParticipantManger
{
    private static final String POINT = "org.lamport.tla.toolbox.tool";
    private static final String CLASS_ATTR_NAME = "class";

    /**
     * Retrieves tools registered
     * @return
     */
    private static ToolboxLifecycleParticipant[] getRegisteredTools()
    {
        IConfigurationElement[] decls = Platform.getExtensionRegistry().getConfigurationElementsFor(POINT);
        ToolboxLifecycleParticipant[] extensions = new ToolboxLifecycleParticipant[decls.length];

        for (int i = 0; i < decls.length; i++)
        {
            try
            {
                extensions[i] = (ToolboxLifecycleParticipant) decls[i].createExecutableExtension(CLASS_ATTR_NAME);
            } catch (CoreException e)
            {
            	StandaloneActivator.getDefault().logError(e.getMessage(), e);
            	return new ToolboxLifecycleParticipant[0];
            }
        }
        return extensions;
    }

    /**
     * Distributes the initialize message
     * @param participants
     */
    public static void initialize()
    {
    	final ToolboxLifecycleParticipant[] participants = getRegisteredTools();
        Assert.isNotNull(participants);
        // Activator.getDefault().logDebug("Initializing the tools");
        for (int i = 0; i < participants.length; i++)
        {
            participants[i].initialize();
        }
    }

    public static void postWorkbenchWindowOpen() {
		final ToolboxLifecycleParticipant[] participants = getRegisteredTools();
		Assert.isNotNull(participants);
		for (int i = 0; i < participants.length; i++) {
			participants[i].postWorkbenchWindowOpen();
		}
    }
    	
    /**
     * Distributes the terminate message  
     * @param participants
     */
    public static void terminate()
    {
    	final ToolboxLifecycleParticipant[] participants = getRegisteredTools();
        Assert.isNotNull(participants);
        // Activator.getDefault().logDebug("Terminating the tools");
        for (int i = 0; i < participants.length; i++)
        {
            participants[i].terminate();
        }
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/REPLSpecWriter.java<|end_filename|>
package tlc2;

import java.io.ByteArrayOutputStream;
import java.util.List;

import tlc2.output.AbstractSpecWriter;
import tlc2.output.SpecWriterUtilities;

class REPLSpecWriter extends AbstractSpecWriter {
	private static final String EXPRESSION_OPEN = "\"EXPR_TLATE_BEGIN\"";
	private static final String EXPRESSION_CLOSE = "\"EXPR_TLATE_END\"";
	private static final String ASSUME_PREFIX = "ASSUME PrintT(" + EXPRESSION_OPEN + ") /\\ PrintT(\n";
	private static final String ASSUME_SUFFIX = "\n) /\\ PrintT(" + EXPRESSION_CLOSE + ")\n";

	REPLSpecWriter(final String specName, final List<String> expressions) {
		super(true);
		
		tlaBuffer.append(SpecWriterUtilities.getExtendingModuleContent(specName,
																	   "Naturals", "Reals", "Sequences", "Bags",
																	   "FiniteSets", "TLC"));
		tlaBuffer.append(ASSUME_PREFIX);
		tlaBuffer.append(String.join("\n", expressions));
		tlaBuffer.append(ASSUME_SUFFIX);
	}
	
	
	static class REPLLogConsumerStream extends ByteArrayOutputStream {
		private boolean inResponse;
		private boolean haveCollected;
		private StringBuilder currentLine;
		
		private String collectedContent;
		
		REPLLogConsumerStream() {
			inResponse = false;
			haveCollected = false;
			currentLine = new StringBuilder();
		}
		
		String getCollectedContent() {
			return collectedContent;
		}
		
		// Being wrapped in a Buffer invokes this method, we sub-optimally pass it off to our real digestion below
		@Override
		public void write(final byte b[], final int off, final int len) {
			for (int i = off; i < (off + len); i++) {
				write(b[i]);
			}
		}

		@Override
		public void write(final int b) {
			if (haveCollected) {
				return;
			} else {
				if (b == '\n') {
					if (inResponse) {
						if (EXPRESSION_CLOSE.equals(currentLine.toString())) {
							haveCollected = true;
							
							final String allCollectedContent = toString();
							final int length = allCollectedContent.length();
							collectedContent = allCollectedContent.substring(0, (length - (EXPRESSION_CLOSE.length() + 1)));
						} else {
							super.write(b);
						}
					} else if (EXPRESSION_OPEN.equals(currentLine.toString())) {
						inResponse = true;
					}
					
					currentLine = new StringBuilder();
 				} else {
					if (inResponse) {
						super.write(b);
					}
 					
 					// casting to char is probably not the best thing - suffices for the majority of the presumed cases
 					currentLine.append((char)b);
 				}
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/tool/SpecLifecycleParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.tool;

/**
 * A superclass for Spec Lifecycle Participant implementations used for 
 * registration on the <code>org.lamport.tla.toolbox.spec</code> extension point.<br />
 * This class should be overridden by the extensions.<br>
 * The overrides must provide an 0-argument constructor.
 * 
 * @see {@link SpecEvent}
 * @author <NAME>
 * @version $Id$
 */
public abstract class SpecLifecycleParticipant
{
    /**
     * Marks the point in time from which on, the participant starts to receive events
     */
    public void initialize()
    {
    }

    /**
	 * Is called on every spec event. The event can either come from a backend
	 * thread or the UI thread. There is no guarantee whatsoever.
	 * 
	 * @param event
	 *            the event containing the information about what is happening
	 * @return a boolean value indicating the reaction of the participant to the
	 *         event. Reserved for future use.
	 */
    public abstract boolean eventOccured(SpecEvent event);

    /**
     * Marks the point in time from which on, the participant stops to receive events
     */
    public void terminate()
    {
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/contribution/DynamicContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.contribution;

import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;

/**
 * An action contribution item that is dynamic (can react on internal state changes)
 * @author <NAME>
 * @version $Id$
 */
public class DynamicContributionItem extends ActionContributionItem
{
    public DynamicContributionItem(IAction action)
    {
        super(action);
    }

    public boolean isDynamic()
    {
        return true;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/statistics/BucketStatisticsTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINbucketStatistic IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util.statistics;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class BucketStatisticsTest {

	@SuppressWarnings("rawtypes")
	@Parameterized.Parameters
	public static Collection<Class> bucketStatistics() {
		return Arrays.asList(
				new Class[] { ConcurrentBucketStatistics.class, BucketStatistics.class });
	}

	private final IBucketStatistics bucketStatistic;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public BucketStatisticsTest(Class bucketStatistic) throws InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		this.bucketStatistic = (IBucketStatistics) bucketStatistic.getConstructor(String.class)
				.newInstance("BucketStatisticsTest");
	}

	@Test
	public void testInvalidArgument() {
		try {
			bucketStatistic.addSample(-1);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail();
	}

	@Test
	public void testMean() {
		assertTrue(Double.compare(-1.0d, bucketStatistic.getMean()) == 0);

		bucketStatistic.addSample(0);
		assertTrue(Double.compare(0.0d, bucketStatistic.getMean()) == 0);

		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		assertTrue(Double.compare(1.0d, bucketStatistic.getMean()) == 0);

		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertTrue(Double.compare(1.4d, bucketStatistic.getMean()) == 0);
	}

	@Test
	public void testMedian() {
		assertEquals(-1, bucketStatistic.getMedian());

		bucketStatistic.addSample(0);
		assertEquals(0, bucketStatistic.getMedian());

		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		assertEquals(1, bucketStatistic.getMedian());

		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertEquals(2, bucketStatistic.getMedian());
	}

	@Test
	public void testMin() {
		assertEquals(-1, bucketStatistic.getMin());

		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertEquals(0, bucketStatistic.getMin());
	}

	@Test
	public void testMin2() {
		assertEquals(-1, bucketStatistic.getMin());

		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		assertEquals(1, bucketStatistic.getMin());
	}

	@Test
	public void testMax() {
		assertEquals(-1, bucketStatistic.getMax());

		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(3);
		assertEquals(3, bucketStatistic.getMax());
	}

	@Test
	public void testStandardDeviation() {
		assertEquals(-1.0, bucketStatistic.getStdDev(), 0);

		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(0);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(3);
		assertTrue(Double.compare(1.005d, (Math.round(bucketStatistic.getStdDev() * 10000d) / 10000d)) == 0);
	}

	@Test
	public void testGetPercentile() {
		assertEquals(-1.0, bucketStatistic.getPercentile(1), 0);

		try {
			bucketStatistic.addSample(1); // <- first element
			bucketStatistic.getPercentile(1.1);
			bucketStatistic.getPercentile(-0.1);
		} catch (Exception e) {
			fail(e.getMessage());
		}

		bucketStatistic.addSample(1);
		bucketStatistic.addSample(1);
		bucketStatistic.addSample(2); // <- 0.5 percentile
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(2);
		bucketStatistic.addSample(3);
		assertTrue(Double.compare(2.0d, bucketStatistic.getPercentile(0.5d)) == 0);
		assertTrue(Double.compare(2.0d, bucketStatistic.getPercentile(0.5d)) == 0);
		assertTrue(Double.compare(2.0d, bucketStatistic.getPercentile(0.75d)) == 0);
		assertTrue(Double.compare(3.0d, bucketStatistic.getPercentile(0.999d)) == 0);
	}

	// NaN test
	@Test
	public void testGetPercentileNaN() {
		try {
			bucketStatistic.getPercentile(Double.NaN);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail("Parameter not a number");
	}

	@Test
	public void testToString() {
		try {
			// just invoke to check for exceptions
			bucketStatistic.toString();

			bucketStatistic.addSample(0);
			bucketStatistic.addSample(0);
			bucketStatistic.addSample(0);
			bucketStatistic.addSample(1);
			bucketStatistic.addSample(1);
			bucketStatistic.addSample(2);
			bucketStatistic.addSample(2);
			bucketStatistic.addSample(2);
			bucketStatistic.addSample(2);
			bucketStatistic.addSample(3);
			bucketStatistic.toString();
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/ObligationStatus.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IMarker;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;

import tla2sany.st.Location;

/**
 * A class that represents the current state of an obligation.
 * 
 * @author <NAME>
 *
 */
public class ObligationStatus
{

    /**
     * The parent step of this
     * obligation.
     */
    private StepTuple parent;
    /**
     * Marker containing attributes about the
     * obligation. The attributes
     * 
     * {@link ProverHelper#OBLIGATION_ID}
     * 
     * should always be present. However, for
     * dummy missing and omitted obligations,
     * the id is meaningless.
     */
    private IMarker obMarker;
    /**
     * A map from the String name of backends
     * to the String representing the most
     * recent status of the backend on this obligation.
     * Constants representing possible obligation
     * statuses on backends appear in {@link ProverHelper}.
     */
    private Map proverStatuses;
    
    /**
     * A map from the String name of backends to the
     * most recent reason given for the backend.
     */
    private Map proverReasons;
    /**
     * The pretty printed form of the obligation. This
     * can be null if the obligation string has not been sent.
     */
    private String obligationString;
    /**
     * The current obligation state. See
     * {@link ColorPredicate} for an explanation
     * of obligation states.
     */
    private int obState;
    /**
     * The id of the obligation given by tlapm.
     */
    private int id;
    /**
     * The location of the obligation that was reported by tlapm.
     * Note that this is not necessarily the current location of the marker
     * representing this obligation.
     */
    private Location location;

    /**
     * Create an obligation with the parent step,
     * the marker for the obligation, and initial state. The parent step
     * can be null if the parent is to be set later using
     * {@link #setParent(StepTuple)}.
     * Calls {@link #setState(long)} on the initialState
     * 
     * @param parent the parent step of the obligation. Can be null
     * if the parent is to be set later using {@link #setParent(StepTuple)}.
     * @param obMarker the marker for this obligation
     * which should already have the attributes
     * {@link ProverHelper#OBLIGATION_ID} set. Can be null if this
     * is a dummy obligation because the marker is never used.
     * @param initialState the initial state of the obligation. See
     * {@link ColorPredicate} for an explanation of obligation states.
     * @param location the location of the obligation as reported by tlapm
     * @param id the id of the obligation as given by tlapm
     */
    public ObligationStatus(StepTuple parent, IMarker obMarker, int initialState, Location location, int id)
    {
        this.parent = parent;
        this.proverStatuses = new HashMap();
        this.proverReasons = new HashMap();
        this.obState = initialState;
        this.id = id;
        this.location = location;
        this.obMarker = obMarker;
    }

    /**
     * Returns the current obligation state. See
     * {@link ColorPredicate} for an explanation
     * of obligation states.
     * 
     * @return
     */
    public int getObligationState()
    {
        return obState;
    }

    /**
     * Returns a map from the name of backends
     * to the String representing the most
     * recent status of the backend on this obligation.
     * @return
     */
    public Map getProverStatuses()
    {
        return proverStatuses;
    }

    /**
     * Returns the parent {@link StepTuple} of this
     * obligation. Will be null if it has not yet been
     * set using {@link #setParent(StepTuple)}.
     * @return
     */
    public StepTuple getParent()
    {
        return parent;
    }

    /**
     * Sets the parent step of this obligation.
     * @param parentStep
     */
    public void setParent(StepTuple parentStep)
    {
        this.parent = parentStep;
    }

    /**
     * Returns the id of the obligation.
     * @return
     */
    public int getId()
    {
        return id;
    }

    /**
     * Returns the pretty printed form of the obligation. This
     * can be null if the obligation string has not been sent.
     */
    public String getObligationString()
    {
        return obligationString;
    }

    /**
     * Returns a string description of the most
     * recent status of each prover on each backend.
     * 
     * Modified by LL on 16 April 2011 to add the reasons to the string.
     * This may have to be changed when the final exact form of the reason
     * field returned by tlapm is determined.
     * 
     * @return
     */
    public String getProverStatusString()
    {
        StringBuilder buffer = new StringBuilder();
        Set entrySet = proverStatuses.entrySet();
        for (Iterator it = entrySet.iterator(); it.hasNext();)
        {
            Map.Entry nextEntry = (Map.Entry) it.next();
            // the key is the name of the backend, the value is the status
            // on that backend
            String key = (String) nextEntry.getKey();
            String reason = (String) proverReasons.get(key);
            if (reason != null && !reason.equals("") && !reason.equals("false")) {
                reason = " (" + reason + ")";
            } else {
                reason = "";
            }
            buffer.append(key + " : " + nextEntry.getValue() + reason );
            if (it.hasNext())
            {
                buffer.append(" , ");
            }
        }

        return buffer.toString();
    }

    /**
     * Updates the obligation with information
     * from the message. In particular, this updates
     * the state of the obligation and set the pretty
     * printed form of the obligation if that information
     * is in the message.
     * 
     * If the state of this obligation changes because of the message,
     * this method updates the status of the parent.
     * 
     * @param message
     */
    public void updateObligation(ObligationStatusMessage message)
    {

        /*
         * If the backend in the message already has a status of "proved" for this obligation,
         * then this message should be ignored. All subsequent messages should also be ignored.
         * This is done because there is no guarantee of the order in which obligation
         * status messages will be sent. For example, if the user
         * interrupts a backend in the middle of proving an obligation, then runs the prover again
         * and that same backend succeeds on the obligation, then the fingerprint file stores the information
         * that the obligation was interrupted on that backend and that it succeeded on that backend.
         * When a status check is done, the prover will send the message that the backend was interrupted
         * and that it succeeded, but there is no guarantee about the order in which that will happen.
         * Thus, we ignore all messages for a given backend for a given obligation once we receive the message
         * that that backend has proved that obligation.
         */
        String oldStatusOnBackend = (String) proverStatuses.get(message.getBackend());
        if (oldStatusOnBackend != null && oldStatusOnBackend.equals(ProverHelper.PROVED))
        {
            return;
        }

        /*
         * The obligation string is not sent by the prover for every message.
         * It is only sent once when the obligation is first interesting.
         * Thus, message.getObString() can be null. If the obligation string
         * has not yet been sent, we set it to the value of the obligation string
         * in the message. After the first time the obligation string has been set,
         * we do not set it again. Subsequent messages may not contain the obligation string
         * after the first one that does.
         */
        if (this.obligationString == null || this.obligationString.length() == 0)
        {
            this.obligationString = message.getObString();
        }

        /*
         * Update the most recent status of the given backend.
         */
        if (message.getBackend() != null && message.getStatus() != null)
        {
            proverStatuses.put(message.getBackend(), message.getStatus());
        }
        
        /*
         * The following code added by LL on 16 April 2011.
         * Update the most recent reason of the given backend.
         */
        if (message.getBackend() != null && message.getReason() != null)
        {
            proverReasons.put(message.getBackend(), message.getReason());
        }

        int oldState = getObligationState();
        // the new state of the obligation
        int newState = ProverHelper.getIntFromStringStatus(message.getStatus(), oldState, message.getBackend());
        if (oldState != newState)
        {
            obState = newState;

            parent.updateStatus();
        }

    }

    /**
     * Returns the {@link IMarker} containing attributes about the
     * obligation. The attributes
     * 
     * {@link ProverHelper#OBLIGATION_ID}
     * 
     * should always be present. This marker
     * will be null for dummy obligations.
     * 
     * @return
     */
    public IMarker getObMarker()
    {
        return obMarker;
    }

    /**
     * Returns the location of the obligation that was reported by tlapm.
     * Note that this is not necessarily the current location of the marker
     * representing this obligation.
     * 
     * @return
     */
    public Location getTLAPMLocation()
    {
        return location;
    }

    public String toString()
    {
        return "ID : " + id + "\nLocation : " + location + "\nStatus : " + getProverStatusString() + "\nState : "
                + obState + "\nObligation : " + obligationString;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/util/ModelNameValidator.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.tool.tlc.util;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IInputValidator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;

public class ModelNameValidator implements IInputValidator
{
    private final Spec spec;
    
    public ModelNameValidator(Spec spec) {
    	this.spec = spec;
    }

    public String isValid(String newText)
    {

        if (newText == null || "".equals(newText))
        {
            return "Model name must be not empty";
        }
        Model existingModel = spec.getAdapter(TLCSpec.class).getModel(newText);
        if (existingModel != null)
        {
            return "Model with the name " + newText + " already exists. Please choose a different name";
        }
        // a model name cannot start with the name of the spec + __
        // this causes a NPE in OpenModelHandler because the method
        // ModelHelper.getModelByName() will not be able to find the model
        if (newText.indexOf(spec.getName()+"___") == 0)
        {
            return "Model name cannot begin with \"" + spec.getName() + "___\".";
        }
        if (newText.contains(":")) {
        	return "Model name cannot contain ':' characters.";
        }
        IStatus fileStatus = ResourcesPlugin.getWorkspace().validateName(newText, IResource.FILE);
        if (! fileStatus.isOK()) {
          return fileStatus.getMessage(); 
        }
        return null;
        
    }
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/data/CoverageInformationTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.output.data;

import static org.junit.Assert.assertTrue;
import static org.lamport.tla.toolbox.tool.tlc.output.data.Representation.*;
import static org.lamport.tla.toolbox.tool.tlc.output.data.Representation.Grouping.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.TreeSet;
import java.util.function.Function;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.TextPresentation;
import org.junit.BeforeClass;
import org.junit.Test;
import org.lamport.tla.toolbox.tool.tlc.output.data.Representation.Grouping;

public class CoverageInformationTest {

	private static ModuleCoverageInformation mci;

	@BeforeClass
	public static void setup() throws IOException, CoreException {
		// Create an IFile instance (this is a witness of why the Eclipse Resource API
		// is probably one of the worst APIs ever with the exception of those that I've
		// written).
		final String name = "CoverageInformationTestProject";
		final IProjectDescription desc = ResourcesPlugin.getWorkspace().newProjectDescription(name);
		final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
		project.create(desc, new NullProgressMonitor());
		project.open(new NullProgressMonitor());
		final IFile file = project.getFile("Simple.tla");
		final InputStream source = CoverageInformationTest.class.getResourceAsStream("Simple.tla");
		file.create(source, IFile.FORCE, null);

		final CoverageInformation ci = new CoverageInformation(Arrays.asList(new IFile[] { file }));

		ci.add(ActionInformationItem.parseInit("<Init line 28, col 1 to line 28, col 4 of module Simple>: 3:3", "M"));
		ci.add(CoverageInformationItem.parse("line 29, col 12 to line 29, col 35 of module Simple: 1", "M"));
		ci.add(CoverageInformationItem.parse("line 30, col 12 to line 30, col 35 of module Simple: 1", "M"));
		ci.add(CoverageInformationItem.parse("line 31, col 12 to line 31, col 21 of module Simple: 1", "M"));
		ci.add(CoverageInformationItem.parse("line 32, col 12 to line 32, col 42 of module Simple: 3", "M"));

		ci.add(ActionInformationItem.parseNext("<a line 34, col 1 to line 34, col 7 of module Simple>: 63:99", "M"));
		ci.add(CoverageInformationItem.parse("line 34, col 15 to line 34, col 28 of module Simple: 558", "M"));
		ci.add(CoverageInformationItem.parse("|line 34, col 15 to line 34, col 22 of module Simple: 459", "M"));
		ci.add(CoverageInformationItem.parse("line 35, col 15 to line 35, col 41 of module Simple: 99", "M"));
		ci.add(CoverageInformationItem.parse("line 36, col 15 to line 36, col 45 of module Simple: 99", "M"));
		ci.add(CoverageInformationItem.parse("line 37, col 15 to line 37, col 30 of module Simple: 99", "M"));
		ci.add(CoverageInformationItem.parse("line 38, col 15 to line 38, col 27 of module Simple: 99", "M"));
		ci.add(CoverageInformationItem.parse("|line 7, col 15 to line 7, col 65 of module Simple: 99", "M"));
		ci.add(CoverageInformationItem.parse("||line 7, col 35 to line 7, col 65 of module Simple: 792", "M"));
		ci.add(CoverageInformationItem.parse("|||line 7, col 35 to line 7, col 41 of module Simple: 792", "M"));
		ci.add(CoverageInformationItem.parse("|||line 7, col 46 to line 7, col 65 of module Simple: 693", "M"));
		ci.add(CoverageInformationItem.parse("||||line 7, col 59 to line 7, col 65 of module Simple: 1188", "M"));
		ci.add(CoverageInformationItem.parse("||||line 7, col 55 to line 7, col 56 of module Simple: 693", "M"));
		ci.add(CoverageInformationItem.parseCost("||line 7, col 25 to line 7, col 32 of module Simple: 99:1881", "M"));
		ci.add(CoverageInformationItem.parse("|line 38, col 23 to line 38, col 26 of module Simple: 99", "M"));

		ci.add(ActionInformationItem.parseNext("<b line 40, col 1 to line 40, col 7 of module Simple>: 87:261", "M"));
		ci.add(CoverageInformationItem.parse("line 40, col 15 to line 40, col 25 of module Simple: 720", "M"));
		ci.add(CoverageInformationItem.parse("|line 40, col 15 to line 40, col 21 of module Simple: 459", "M"));
		ci.add(CoverageInformationItem.parse("line 40, col 30 to line 40, col 40 of module Simple: 621", "M"));
		ci.add(CoverageInformationItem.parse("|line 40, col 30 to line 40, col 36 of module Simple: 360", "M"));
		ci.add(CoverageInformationItem.parse("line 41, col 15 to line 41, col 55 of module Simple: 261", "M"));
		ci.add(CoverageInformationItem.parse("line 42, col 15 to line 42, col 48 of module Simple: 261", "M"));
		ci.add(CoverageInformationItem.parse("line 43, col 15 to line 43, col 30 of module Simple: 261", "M"));
		ci.add(CoverageInformationItem.parse("line 44, col 15 to line 44, col 27 of module Simple: 261", "M"));
		ci.add(CoverageInformationItem.parse("|line 7, col 15 to line 7, col 65 of module Simple: 261", "M"));
		ci.add(CoverageInformationItem.parse("||line 7, col 35 to line 7, col 65 of module Simple: 8352", "M"));
		ci.add(CoverageInformationItem.parse("|||line 7, col 35 to line 7, col 41 of module Simple: 8352", "M"));
		ci.add(CoverageInformationItem.parse("|||line 7, col 46 to line 7, col 65 of module Simple: 8091", "M"));
		ci.add(CoverageInformationItem.parse("||||line 7, col 59 to line 7, col 65 of module Simple: 20880", "M"));
		ci.add(CoverageInformationItem.parse("||||line 7, col 55 to line 7, col 56 of module Simple: 8091", "M"));
		ci.add(CoverageInformationItem.parseCost("||line 7, col 25 to line 7, col 32 of module Simple: 261:28971",
				"M"));
		ci.add(CoverageInformationItem.parse("|line 44, col 23 to line 44, col 26 of module Simple: 261", "M"));

		ci.add(ActionInformationItem.parseNext("<Terminating line 49, col 1 to line 49, col 11 of module Simple>: 0:21",
				"M"));
		ci.add(CoverageInformationItem.parse("line 49, col 40 to line 49, col 56 of module Simple: 330", "M"));
		ci.add(CoverageInformationItem.parse("|line 49, col 40 to line 49, col 47 of module Simple: 267", "M"));
		ci.add(CoverageInformationItem.parse("line 49, col 31 to line 49, col 37 of module Simple: 153", "M"));
		ci.add(CoverageInformationItem.parse("line 50, col 19 to line 50, col 32 of module Simple: 21", "M"));

		mci = ci.projectionFor(file);
		mci.getRoot(); // initialize AII to CII parent-child relationship.
	}

	private static void monotonicallyIncreasing(TreeSet<CoverageInformationItem> set, Representation rep, Grouping grp,
			Function<CoverageInformationItem, Long> f) {
		long value = -1L;
		float hue = 240f;
		for (final CoverageInformationItem cii : set) {
			assertTrue(rep.getValue(cii, grp) == f.apply(cii));
			assertTrue(value <= f.apply(cii));
			value = f.apply(cii);

			// hue inversely correlates (non-linear relationship) with value, ie. value goes
			// up and hue goes down (but hue's actual value dependents on the set of all
			// values).
			final float h = rep.getColor(cii, grp).getRGB().getHSB()[0];
			assertTrue(hue >= h);
			hue = h;
		}
		assertTrue("legend was empty", value >= 0L);
	}

	private TreeSet<CoverageInformationItem> getNode(final int offset, final Representation rep) {
		final CoverageInformationItem node = mci.getNode(offset);
		// Style implicitly activates the children of node which getLegend requires.
		node.style(new TextPresentation(), rep);
		return node.getLegend(rep);
	}

	@Test
	public void rootLegendStates() {
		monotonicallyIncreasing(mci.getLegend(STATES), STATES, COMBINED, CoverageInformationItem::getCount);
		monotonicallyIncreasing(mci.getLegend(STATES), STATES, COMBINED, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void rootLegendDistinctStates() {
		monotonicallyIncreasing(mci.getLegend(STATES_DISTINCT), STATES_DISTINCT, COMBINED,
				CoverageInformationItem::getCost);
		monotonicallyIncreasing(mci.getLegend(STATES_DISTINCT), STATES_DISTINCT, COMBINED,
				CoverageInformationItem::getTotalCost);
	}

	@Test
	public void rootLegendInvocations() {
		monotonicallyIncreasing(mci.getLegend(INV), INV, COMBINED, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void rootLegendCost() {
		monotonicallyIncreasing(mci.getLegend(COST), COST, COMBINED, CoverageInformationItem::getTotalCost);
	}

	@Test
	public void rootLegendInvCost() {
		monotonicallyIncreasing(mci.getLegend(INVCOST), INVCOST, COMBINED,
				CoverageInformationItem::getTotalCountAndCost);
	}

	// Init predicate
	private static final int init = 775;

	@Test
	public void initLegendInv() {
		monotonicallyIncreasing(getNode(init, INV), INV, CoverageInformationItem::getCount);
	}

	@Test
	public void initLegendInvCost() {
		monotonicallyIncreasing(getNode(init, COST), COST, CoverageInformationItem::getCost);
	}

	@Test
	public void initLegendCost() {
		monotonicallyIncreasing(getNode(init, INVCOST), INVCOST, CoverageInformationItem::getCountAndCost);
	}

	@Test
	public void initLegendStates() {
		monotonicallyIncreasing(getNode(init, STATES), STATES, CoverageInformationItem::getCount);
		monotonicallyIncreasing(getNode(init, STATES), STATES, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void initLegendDistStates() {
		monotonicallyIncreasing(getNode(init, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getCost);
		monotonicallyIncreasing(getNode(init, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getTotalCost);
	}

	// sub-action a
	private static final int suba = 944;

	@Test
	public void aLegendInv() {
		monotonicallyIncreasing(getNode(suba, INV), INV, CoverageInformationItem::getCount);
	}

	@Test
	public void aLegendInvCost() {
		monotonicallyIncreasing(getNode(suba, COST), COST, CoverageInformationItem::getCost);
	}

	@Test
	public void aLegendCost() {
		monotonicallyIncreasing(getNode(suba, INVCOST), INVCOST, CoverageInformationItem::getCountAndCost);
	}

	@Test
	public void aLegendStates() {
		monotonicallyIncreasing(getNode(suba, STATES), STATES, CoverageInformationItem::getCount);
		monotonicallyIncreasing(getNode(suba, STATES), STATES, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void aLegendDistStates() {
		monotonicallyIncreasing(getNode(suba, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getCost);
		monotonicallyIncreasing(getNode(suba, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getTotalCost);
	}

	// sub-action b
	private static final int subb = 1121;

	@Test
	public void bLegendInv() {
		monotonicallyIncreasing(getNode(subb, INV), INV, CoverageInformationItem::getCount);
	}

	@Test
	public void bLegendInvCost() {
		monotonicallyIncreasing(getNode(subb, COST), COST, CoverageInformationItem::getCost);
	}

	@Test
	public void bLegendCost() {
		monotonicallyIncreasing(getNode(subb, INVCOST), INVCOST, CoverageInformationItem::getCountAndCost);
	}

	@Test
	public void bLegendStates() {
		monotonicallyIncreasing(getNode(subb, STATES), STATES, CoverageInformationItem::getCount);
		monotonicallyIncreasing(getNode(subb, STATES), STATES, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void bLegendDistStates() {
		monotonicallyIncreasing(getNode(subb, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getCost);
		monotonicallyIncreasing(getNode(subb, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getTotalCost);
	}

	// Termination
	private static final int term = 1447;

	@Test
	public void termLegendInv() {
		monotonicallyIncreasing(getNode(term, INV), INV, CoverageInformationItem::getCount);
	}

	@Test
	public void termLegendInvCost() {
		monotonicallyIncreasing(getNode(term, COST), COST, CoverageInformationItem::getCost);
	}

	@Test
	public void termLegendCost() {
		monotonicallyIncreasing(getNode(term, INVCOST), INVCOST, CoverageInformationItem::getCountAndCost);
	}

	@Test
	public void termLegendStates() {
		monotonicallyIncreasing(getNode(term, STATES), STATES, CoverageInformationItem::getCount);
		monotonicallyIncreasing(getNode(term, STATES), STATES, CoverageInformationItem::getTotalCount);
	}

	@Test
	public void termLegendDistStates() {
		monotonicallyIncreasing(getNode(term, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getCost);
		monotonicallyIncreasing(getNode(term, STATES_DISTINCT), STATES_DISTINCT, CoverageInformationItem::getTotalCost);
	}

	private static void monotonicallyIncreasing(TreeSet<CoverageInformationItem> set, Representation rep,
			Function<CoverageInformationItem, Long> f) {
		monotonicallyIncreasing(set, rep, INDIVIDUAL, f);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/OpDefOrDeclNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import tla2sany.st.TreeNode;
import util.UniqueString;

/**
 * A OpDefOrDeclNode represents the definition or declaration of
 * a symbol.  (For some symbols, it represents an imaginary          
 * definition.)  It has two subclasses, OpDeclNode and OpDefNode.    
 */
    
public abstract class OpDefOrDeclNode extends SymbolNode {

  ModuleNode originallyDefinedInModule;
     // The (external or inner) module in which this operator def or decl  
     // originally appears in (as opposed to having been inherited via
     // EXTENDS or INSTANCE-without-params).  A null in this field
     // means either that this is the OpDefNode for a built-in
     // operator, or that this is a nullODN node as declared in 
     // semantic.Generator.
  SymbolTable st;
    /***********************************************************************
    * For an OpDeclNode, this seems to contain the SymbolTable under       *
    * which it was generated.  This SymbolTable does not appear to be      *
    * used.  A comment in Generator.java asserts that, for an OpDecl node, *
    * it contains the formal parameters, but that comment appears to be    *
    * wrong.                                                               *
    ***********************************************************************/

  int arity;          // arity of -1 means no fixed arity, -2 is illegal

  public OpDefOrDeclNode(UniqueString name, int kind, int ar, ModuleNode modNode,
                         SymbolTable symbolTable, TreeNode stn ) {
    super(kind, stn, name);
    this.originallyDefinedInModule = modNode;
    this.arity = ar;
    this.st = symbolTable;
  }

  /**
   * This method returns the number of ordinary arguments--that is, the
   * arguments not part of the bound variable stuff.  For example, the 
   * $BoundedForAll operator has a single ordinary argument.           
   *                                                                   
   * If nA and nB are the nodes (of kind ConstantDeclKind) for the     
   * declarations of A and B in                                        
   *                                                                   
   *   CONSTANT  A, B(_,_)                                             
   *                                                                   
   * then nA.getNumberOfArgs() = 0 and nB.getNumberOfArgs() = 2.       
   *                                                                   
   * A VariableDecl or BoundSymbolKind node has getNumberOfArgs() equal
   * to 0.                                                             
   *                                                                   
   * For an operator like $CartesianProd that has a variable number of
   * arguments, this method returns the value -1.  Only BuiltIn nodes
   * (nodes of kind BuiltInKind) should have getNumberOfArgs equal to
   * -1.
   */
  public final int getNumberOfArgs() { return this.arity; }

  public final void setNumberOfArgs(int a) { this.arity = a; }

  public final ModuleNode getOriginallyDefinedInModuleNode() {
    return this.originallyDefinedInModule;
  }

  public final SymbolTable getSymbolTable() { return this.st; }

  /**
   * toString() method; part of implementation of ExploreNode
   * interface
   */
  public String toString(int depth) {
    if (depth <= 0) return "";
    return super.toString(depth) 
           + "  arity: " + arity 
           + "  orgDefInModule: " + (originallyDefinedInModule != null 
                             ? originallyDefinedInModule.getName().toString() 
                             : "<null>" );
  }

	public String getComment() {
		final StringBuffer buf = new StringBuffer();
		
		//TODO Support in-line comments found in the standard modules.
		final String[] preComments = getPreComments();
		for (String string : preComments) {
			buf.append(string);
			buf.append("\n");
		}
		
		return buf.toString().replace("\n$", "").trim();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/result/IResultPresenter.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.result;

import org.lamport.tla.toolbox.tool.tlc.model.Model;

/**
 * Interface for the TLC job result presenter used in the extension point 
 * @author <NAME>
 */
public interface IResultPresenter
{
    
    public String EXTENSION_ID = "org.lamport.tla.toolbox.tlc.processResultPresenter";

    /**
     * Show the results of the launch 
     */
    public void showResults(Model model);
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ExampleEditCommandHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.VerifyEvent;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.DocumentHelper;

/**
 * Performs a useless command to illustrate how to get keyboard input
 * and modify the contents of an editor.
 * 
 * When execute is called, if a TLA editor currently has focus, this
 * handler starts listening for key strokes and starts listening
 * for focus events on the editor's underlying widget. It will stop listening for key
 * strokes if the widget loses focus or after the first key stroke is entered.
 * 
 * If the first key stroke to be entered is a digit, this handler finds
 * the word currently containing the caret in the editor and repeats that word
 * the number of times equal to the digit pressed. If the key pressed
 * is not a digit, this does nothing to the document and
 * removes itself from subsequent key events.
 * 
 * @author <NAME>
 *
 */
public class ExampleEditCommandHandler extends AbstractHandler implements VerifyKeyListener, FocusListener
{

    private TLAEditor editor;

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        /********
        String[] testName = { ColorPredicate.PROVED_STATUS, ColorPredicate.PROVED_STATUS, ColorPredicate.PROVED_STATUS };
        System.out.println(testName[0]);
        System.out.println(testName[1]);
        System.out.println(testName[2]);

        System.out.println(testName[0] + ", " + testName[1] + ", " + testName[2] + " -> "
                + ColorPredicate.numberOfState(testName));
         System.out.println("Inverse of number = " +
         ColorPredicate.numberToState(ColorPredicate.numberOfState(testName)));
         
         System.out.println("BitVector Test");
         String[][] test = { {"untried", "proved"}, {"untried", "proving"}, {"untried"}};
         long bitVector = ColorPredicate.bitVectorOfStates(test);
         ColorPredicate.printBitVectorOfStates(bitVector);
         *****/
        int[] states = new int[] {ColorPredicate.numberOfState(new int[] {3, 2, 0}),
                ColorPredicate.numberOfState(new int[] {2, 3, 0}),
                1
                };
        for (int i= 0; i < ColorPredicate.PREDEFINED_MACROS.length; i++) {
//            System.out.println(ColorPredicate.PREDEFINED_MACROS[i][0]);
            ColorPredicate cp = new ColorPredicate(ColorPredicate.PREDEFINED_MACROS[i][0]);
            System.out.println(ColorPredicate.PREDEFINED_MACROS[i][0] +
                    " value: " + cp.satisfiedByObligations(states));
            
        }
       
        ColorPredicate cp = new ColorPredicate(
                " leaf None" ); //   
        System.out.println(cp.toString());
        
        

         /***
        editor = EditorUtil.getTLAEditorWithFocus();
        if (editor != null)
        {
            install();
        }
        **/
        return null;
    }

    /**
     * Listens for the first key to be pressed. If it is a digit, it
     * finds the word currently containing the caret and repeats that word
     * the number of times equal to the digit pressed. If the key pressed
     * is not a digit, this does nothing to the document and
     * removes itself from subsequent key events.
     */
    public void verifyKey(VerifyEvent event)
    {
        try
        {
            // no other listeners should respond to this event
            event.doit = false;

            // the state mask indicates what modifier keys (such as CTRL) were being
            // pressed when the character was pressed

            // the digit should be pressed without any modifier keys
            if (event.stateMask == SWT.NONE && Character.isDigit(event.character))
            {
                // get the digit input
                int input = Character.getNumericValue(event.character);

                // get the text selection
                ISelection selection = editor.getSelectionProvider().getSelection();

                if (selection != null && selection instanceof ITextSelection)
                {
                    ITextSelection textSelection = (ITextSelection) selection;

                    IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());

                    // if one or more characters are highlighted, do nothing
                    if (textSelection.getLength() == 0 && document != null)
                    {

                        // retrieve the region describing the word containing
                        // the caret
                        try
                        {
                        	IRegion region = DocumentHelper.getRegionExpandedBoth(document, textSelection.getOffset());

                            // generate the insertion string
                            String insertionText = " " + document.get(region.getOffset(), region.getLength());
                            StringBuilder sb = new StringBuilder();
                            for (int i = 0; i < input; i++)
                            {
                                sb.append(insertionText);
                            }

                            // insert the string
                            document.replace(region.getOffset() + region.getLength(), 0, sb.toString());
                        } catch (BadLocationException e)
                        {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
        } finally
        {

            uninstall();
        }
    }

    /**
     * This should never be called. The handler
     * should only be listening if there already is focus
     * and should be removed as a listener when focus
     * is lost.
     */
    public void focusGained(FocusEvent e)
    {
        // TODO Auto-generated method stub

    }

    /**
     * Uninstalls the handler.
     */
    public void focusLost(FocusEvent e)
    {
        uninstall();
    }

    /**
     * Should be called when the handler starts listening
     * for key strokes.
     * 
     * Adds this as a key stroke listener, adds to focus listeners
     * of the underlying text widget of the editor, and sets the
     * status line.
     * 
     * This is added as a focus listener so that it can uninstall()
     * itself if focus is lost.
     */
    public void install()
    {
        editor.getViewer().prependVerifyKeyListener(this);
        editor.getViewer().getTextWidget().addFocusListener(this);
        editor.setStatusMessage("Example command.");
    }

    /**
     * Should be called when the handler is done listening for
     * key strokes.
     * 
     * Removes itself as a key stroke listener, a focus listener, and sets
     * the status line to the empty string.
     */
    private void uninstall()
    {
        // do not listen to any other key strokes
        editor.getViewer().removeVerifyKeyListener(this);

        editor.getViewer().getTextWidget().removeFocusListener(this);

        editor.setStatusMessage("");
    }

    // TESTING
    public static class ColorPredicate
    {
        public boolean isLeaf; // true iff this predicate is true only for leaf proof steps
        public boolean isSome;
        public long set;

        // The prover names are used only for error messages. Provers are generally
        // referred to by number, where PROVER_NAMES[i] is the name of prover number i.
        public static final String[] PROVER_NAMES = { "isabelle", "other_backend", "tlapm" };

        // We name the possible prover statuses, so Java can catch misspellings.
        public static final String UNTRIED_STATUS = "untried";
        public static final String PROVING_STATUS = "proving";
        public static final String PROVED_STATUS = "proved";
        public static final String FAILED_STATUS = "failed";
        public static final String STOPPED_STATUS = "stopped";

        // The constant PROVER_STATUSES determines the set of possible obligation states.
        public static final String[] ISABELLE_STATUSES = { UNTRIED_STATUS, PROVING_STATUS, PROVED_STATUS, FAILED_STATUS,
                STOPPED_STATUS };
        public static final String[] OTHER_PROVER_STATUSES = ISABELLE_STATUSES;
        public static final String[] TLAPM_STATUSES = { UNTRIED_STATUS, PROVED_STATUS };
        public static final String[][] PROVER_STATUSES = { ISABELLE_STATUSES, OTHER_PROVER_STATUSES, TLAPM_STATUSES };

        public static final int NUMBER_OF_PROVERS = PROVER_NAMES.length;

        // The array of predefined macros
        public static final String[][] PREDEFINED_MACROS = { { "None", "some" }, //
                { "All", "every (,,)" }, //
                { "Proved", "every (proved, , ) (,proved,) (,,proved)" }, //
                { "ProvedOrOmitted", "every omitted (proved, , ) (,proved,) (,,proved)" }, //
                { "NotProved", "some (-proved, -proved, -proved)" }, //
                { "FailedUnproved", "some (failed,-proved,-proved) (-proved,failed,-proved)" }, //
                { "FailedOrStoppedUnproved", "some (failed stopped,-proved,-proved) (-proved,failed stopped,-proved)" }, //
                { "Failed", "some (failed,,) (,failed,)" }, //
                { "FailedOrStopped", "some (failed stopped,,) (,failed stopped,)" }, //
                { "BeingProved", "some (proving,,) (,proving,)" }, //            
                { "Missing", "some missing" }, //
                { "Omitted", "some omitted" }, //
                { "MissingOrOmitted", "some missing omitted" }, //
                { "ProvedByIsabelle", "every (proved,,)" }, //
                { "Stopped", "some (stopped,,) (,stopped,)" }, //
                { "StoppedUnproved", "some (stopped,-proved,-proved) (-proved,stopped,-proved)" }, //            
        };

        /**
         * Returns the macro with name macroName, else returns null if there
         * is none.  (Case of names is ignored.)  This implementation searches
         * only in the PREDEFINE_MACROS.  If users can define macros with
         * preferences, then we need to reimplement this.
         * 
         * @param macroName
         * @return
         */
        public static final String getMacro(String macroName)
        {
            for (int i = 0; i < PREDEFINED_MACROS.length; i++)
            {
                if (macroName.equalsIgnoreCase(PREDEFINED_MACROS[i][0]))
                {
                    return PREDEFINED_MACROS[i][1];
                }
            }
            return null;
        }

        /**
         * Returns the number of the status named statusName for prover numbered
         * proverNumber.  
         * 
         * @param proverNumber
         * @param statusName
         * @return
         * @throws IllegalArgumentException
         */
        public static final int numberOfProverStatus(int proverNumber, String statusName) throws IllegalArgumentException
        {
            if (proverNumber > NUMBER_OF_PROVERS || proverNumber < 0)
            {
                throw new IllegalArgumentException("No prover number " + proverNumber);
            }
            for (int i = 0; i < PROVER_STATUSES[proverNumber].length; i++)
            {
                if (statusName.equals(PROVER_STATUSES[proverNumber][i]))
                {
                    return i;
                }
            }
            throw new IllegalArgumentException("Prover " + PROVER_NAMES[proverNumber] + " has no status " + statusName);
        }

        /*
         * An obligation state is either Missing, Omitted, or an array indexed by
         * provers of prover statuses.  Each state has a unique number in the range
         * from 0 to one less than the total number of states.  Tge numbers of the 
         * Missing and Omitted states are: 
         */
        public static final int NUMBER_OF_MISSING_STATE = 0;
        public static final int NUMBER_OF_OMITTED_STATE = 1;

        /*
         * For other states, that number is returned by the following methods.
         */

        /**
         * Returns the obligation-state number for a state specified by an
         * array indexed by provers of of prover-status numbers.
         * 
         * @param statuses
         * @return
         * @throws IllegalArgumentException
         */
        public static final int numberOfState(int[] statuses) throws IllegalArgumentException
        {
            if (statuses.length != NUMBER_OF_PROVERS)
            {
                throw new IllegalArgumentException("Wrong number of provers specified");
            }
            int multiplier = 1;
            int result = 2;
            for (int i = 0; i < NUMBER_OF_PROVERS; i++)
            {
                if (statuses[i] >= PROVER_STATUSES[i].length || statuses[i] < 0)
                {
                    throw new IllegalArgumentException("Prover " + PROVER_NAMES[i] + " does not have status number "
                            + statuses[i]);
                }
                result = result + multiplier * statuses[i];
                multiplier = multiplier * PROVER_STATUSES[i].length;
            }
            return result;
        }

        /**
         * Returns the obligation-state number for a state specified by an
         * array indexed by provers of prover-status names.
         * 
         * @param statuses
         * @return
         * @throws IllegalArgumentException
         */
        public static final int numberOfState(String[] statuses) throws IllegalArgumentException
        {
            int[] statusNumbers = new int[statuses.length];
            for (int i = 0; i < statuses.length; i++)
            {
                statusNumbers[i] = numberOfProverStatus(i, statuses[i]);
            }
            return numberOfState(statusNumbers);
        }

        /** 
         * Returns a printable version of the state with number stateNumber.
         * Assumes that NUMBER_OF_PROVERS = 3.
         * 
         * @param stateNumber
         * @return
         */

        public static final String numberToState(int stateNumber)
        {
            if (stateNumber == NUMBER_OF_MISSING_STATE)
            {
                return "Missing";
            }
            if (stateNumber == NUMBER_OF_OMITTED_STATE)
            {
                return "Omitted";
            }
            int[] array = new int[3];
            if (3 != NUMBER_OF_PROVERS)
            {
                Activator.getDefault().logDebug("Method ColorPredicate.numberToState must be reimplemented"
                        + " when number of provers changes");
            }
            for (int i = 0; i < PROVER_STATUSES[0].length; i++)
            {
                array[0] = i;
                for (int j = 0; j < PROVER_STATUSES[1].length; j++)
                {
                    array[1] = j;
                    for (int k = 0; k < PROVER_STATUSES[2].length; k++)
                    {
                        array[2] = k;
                        if (numberOfState(array) == stateNumber)
                        {
                            return "(" + PROVER_STATUSES[0][i] + ", " + PROVER_STATUSES[1][j] + ", "
                                    + PROVER_STATUSES[2][k] + ")";
                        }
                    }
                }
            }
            return "No state with number " + stateNumber;
        }

        /**
         * Returns the bitVector with bit i set iff there exists some j_0, j_1, ...
         * such that i = numberOfState(array) where array[0] = statuses[0][j_0],
         * array[1] = statuses[1][j_1], etc.
         * 
         * This implementation works only for 3 provers.
         * 
         * @param statuses
         * @return
         */
        public static final long bitVectorOfStates(int[][] statuses) throws IllegalArgumentException
        {
            if (statuses.length != NUMBER_OF_PROVERS)
            {
                Activator.getDefault().logDebug("Method ColorPredicate.bitVectorOfStates must be reimplemented"
                        + " when number of provers changes");
            }
            long result = 0;
            int[] array = new int[3];
            for (int i = 0; i < statuses[0].length; i++)
            {
                array[0] = statuses[0][i];
                for (int j = 0; j < statuses[1].length; j++)
                {
                    array[1] = statuses[1][j];
                    for (int k = 0; k < statuses[2].length; k++)
                    {
                        array[2] = statuses[2][k];
                        result = result | (1L << numberOfState(array));
                    }
                }
            }
            return result;
        }

        public static final long bitVectorOfStates(String[][] statuses) throws IllegalArgumentException
        {
            int[][] arg = new int[statuses.length][];
            for (int i = 0; i < arg.length; i++)
            {
                arg[i] = new int[statuses[i].length];
                for (int j = 0; j < arg[i].length; j++)
                {
                    arg[i][j] = numberOfProverStatus(i, statuses[i][j]);
                }
            }
            return bitVectorOfStates(arg);
        }

        /**
         * For debugging.  Prints the list of states represented by a bit vector.
         * @param vector
         */
        public static final void printBitVectorOfStates(long vector)
        {
            System.out.println(bitVectorOfStatesToString(vector));
        }

        public static final String bitVectorOfStatesToString(long vector)
        {
            long rest = vector;
            String result = "";
            for (int i = 0; i < 60; i++)
            {
                if ((rest & 1) == 1)
                {
                    result = result + numberToState(i) + "\n";
                }
                rest = rest >>> 1;
            }
            return result;
        }

        /**
         * Returns true iff this color predicate is satisfied by a set of
         * obligations whose states have the numbers in the array
         * obligationStateNumbers.
         * 
         * @param obligationStateNumbers
         * @return
         */
        public boolean satisfiedByObligations(int[] obligationStateNumbers)
        {
            // Sets childValues[i] to true iff the i-th obligation state 
            // is in this.set; then calls satisfiedBasedOnChildrenValues.
            //
            boolean[] childValues = new boolean[obligationStateNumbers.length];
            for (int i = 0; i < obligationStateNumbers.length; i++)
            {
                long bit = 1L << obligationStateNumbers[i];
                childValues[i] = (bit & this.set) != 0;
            }
            return this.satisfiedBasedOnChildrenValues(childValues);
        }
       
        /**
         * Computes the value of this color predicate for a non-leaf proof
         * based on the values of the color predicate for its children.
         * 
         * @param childValues
         * @return
         */
        public boolean satisfiedBasedOnChildren(boolean[] childValues) {
            if (this.isLeaf) {
                return false;
            }
            return satisfiedBasedOnChildrenValues(childValues);
        }
        
        /**
         * Inner method for satisfiedBasedOnChildren for a non-leaf
         * color predicate.
         * 
         * @param childValues
         * @return
         */
        public boolean satisfiedBasedOnChildrenValues(boolean[] childValues)
        {
            boolean result = !this.isSome;
            if (this.isSome)
            {
                for (int i = 0; i < childValues.length; i++)
                {
                    result = result || childValues[i];
                }
            } else
            {
                for (int i = 0; i < childValues.length; i++)
                {
                    result = result && childValues[i];
                }
            }
            return result;
        }

        /**
         * Returns a ColorPredicate obtained by parsing its argument.
         * See the beginning of ProofStatus.tla for the grammar of
         * the input.
         * 
         * @param input
         */
        public ColorPredicate(String input) throws IllegalArgumentException
        {
            String rest = input.trim().toLowerCase();
            if (rest.startsWith("leaf"))
            {
                this.isLeaf = true;
                rest = rest.substring(4).trim();
            } else
            {
                this.isLeaf = false;
            }

            // if the next token is a macro name, set rest to the
            // macro definition
            int endOfStartToken = 0;
            while (endOfStartToken < rest.length() && Character.isLetter(rest.charAt(endOfStartToken)))
            {
                endOfStartToken++;
            }
            String startToken = rest.substring(0, endOfStartToken);
            String macro = getMacro(startToken);
            if (macro != null)
            {
                rest = macro;
            }

            if (rest.startsWith("some"))
            {
                this.isSome = true;
                rest = rest.substring(4).trim();
            } else if (rest.startsWith("every"))
            {
                this.isSome = false;
                rest = rest.substring(5).trim();
            } else
            {
                throw new IllegalArgumentException("Color predicate must have `every' or `some' specifier.");
            }

            this.set = 0;
            while (!rest.equals(""))
            {
                if (rest.startsWith("omitted"))
                {
                    this.set = this.set | (1 << NUMBER_OF_OMITTED_STATE);
                    rest = rest.substring(7).trim();
                } else if (rest.startsWith("missing"))
                {
                    this.set = this.set | (1 << NUMBER_OF_MISSING_STATE);
                    rest = rest.substring(7).trim();
                } else if (rest.startsWith("("))
                {
                    rest = rest.substring(1).trim();
                    // stateSetSpec[i] is set to the array of proof-status numbers
                    // specified for prover number i.
                    int[][] stateSetSpec = new int[NUMBER_OF_PROVERS][];
                    for (int i = 0; i < NUMBER_OF_PROVERS; i++)
                    {
                        // The body of the for loop computes stateSetSpec[i].

                        // Set invert to true iff there is a "=" specifier.
                        boolean invert = false;
                        if (rest.startsWith("-"))
                        {
                            invert = true;
                            rest = rest.substring(1).trim();
                        }
                        // We set appears[j] = true iff proof-status number
                        // j for prover i is to be included in stateSetSpec[i].
                        boolean[] appears = new boolean[PROVER_STATUSES[i].length];
                        for (int j = 0; j < appears.length; j++)
                        {
                            appears[j] = invert;
                        }
                        // endChar is the ending character for this prover's list of statuses.
                        String endChar = (i == NUMBER_OF_PROVERS - 1) ? ")" : ",";
                        // loop until the end character is found
                        while (rest.length() > 0 && !rest.startsWith(endChar))
                        {
                            // set token to the beginning string delimited by a
                            // non-letter
                            int endOfToken = 0;
                            while (endOfToken < rest.length() && Character.isLetter(rest.charAt(endOfToken)))
                            {
                                endOfToken++;
                            }
                            String token = rest.substring(0, endOfToken);
                            rest = rest.substring(endOfToken).trim();

                            // set statusNumber to number of status for prover i;
                            int statusNumber;
                            try
                            {
                                statusNumber = numberOfProverStatus(i, token);
                            } catch (IllegalArgumentException e)
                            {
                                String errorMsg = "Was expecting status of prover " + PROVER_NAMES[i] + " but found `"
                                        + token + "' followed by: \n `" + rest + "'";
                                throw new IllegalArgumentException(errorMsg);
                            }

                            // set appears[statusNumber]
                            appears[statusNumber] = !invert;
                        }

                        if (rest.length() == 0)
                        {
                            throw new IllegalArgumentException(
                                    "Color predicate specifier ended before `(...)' expression complete");
                        }

                        // Mustn't forget to remove the endChar
                        rest = rest.substring(1).trim();

                        // set count to the number of j for which appears[j] = true
                        int count = 0;
                        for (int j = 0; j < appears.length; j++)
                        {
                            if (appears[j])
                            {
                                count++;
                            }
                        }

                        // If no status was specified, then treat it as if every status
                        // was specified.
                        if (count == 0)
                        {
                            if (invert)
                            {
                                throw new IllegalArgumentException("A `-' must be followed by one or more statuses");
                            } else
                            {
                                count = appears.length;
                                for (int j = 0; j < count; j++)
                                {
                                    appears[j] = true;
                                }
                            }
                        }

                        // Finally, set stateSetSpec[i]
                        stateSetSpec[i] = new int[count];
                        int k = 0;
                        for (int j = 0; j < appears.length; j++)
                        {
                            if (appears[j])
                            {
                                stateSetSpec[i][k] = j;
                                k++;
                            }
                        }
                    }
                    // Having now computed stateSetSpec, we now convert it to
                    // a bit vector and OR it to this.set
                    this.set = this.set | bitVectorOfStates(stateSetSpec);

                } else
                {
                    throw new IllegalArgumentException("Unexpected token at: `" + rest + "'");
                }
            }
        }

        public String toString()
        {
            String result = "leaf: " + isLeaf + "\n";
            result = result + "type: " + ((isSome) ? "some" : "every") + "\n";
            result = result + "set of states:\n";
            try
            {
                result = result + bitVectorOfStatesToString(this.set);
            } catch (IllegalArgumentException e)
            {
                result = result + "Illegal Bit Vector\n";
            }

            return result;
        }
    }

 }


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/AbstractTLCActivator.java<|end_filename|>
// Copyright (c) Feb 13, 2012 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * @author <NAME>
 */
public abstract class AbstractTLCActivator extends AbstractUIPlugin {

	private static final int DEBUG_SEVERITY = -1;
	private final String pluginId;

	public AbstractTLCActivator(final String pluginId) {
		this.pluginId = pluginId;
	}

	/**
	 * Writes a string and a cause into the error category of the log
	 * 
	 * @param string
	 */
	public void logError(String message) {
		getLog().log(new Status(IStatus.ERROR, pluginId, message));
	}
	
	/**
	 * Writes a string and a cause into the error category of the log
	 * 
	 * @param string
	 * @param e
	 */
	public void logError(String message, Throwable cause) {
		getLog().log(new Status(IStatus.ERROR, pluginId, message, cause));
	}

	/**
	 * Writes a string and a cause into the warning category of the log
	 * 
	 * @param string
	 */
	public void logWarning(String message) {
		getLog().log(new Status(IStatus.WARNING, pluginId, message));
	}

	/**
	 * Writes a string and a cause into the warning category of the log
	 * 
	 * @param string
	 */
	public void logWarning(String message, Throwable cause) {
		getLog().log(new Status(IStatus.WARNING, pluginId, message, cause));
	}

	/**
	 * Writes a string into some debugging place
	 */
	public void logDebug(String message) {
		logDebug(message, null);
	}

	/**
	 * Writes a string into some debugging place
	 */
	public void logDebug(String message, Throwable cause) {
		getLog().log(new Status(IStatus.INFO, pluginId, DEBUG_SEVERITY, message, cause));
	}

	/**
	 * Writes a string into the info category of the log
	 * 
	 * @param string
	 */
	public void logInfo(String message) {
		getLog().log(new Status(IStatus.INFO, pluginId, message));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/provider/FormulaLabelProvider.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.provider;

import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ITableFontProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;

public class FormulaLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider {

	@Override
	public Font getFont(Object element, int columnIndex) {
		// Regardless of the element and its position, we want to use a monospaced font.
		return JFaceResources.getFont(JFaceResources.TEXT_FONT);
	}

	@Override
	public Image getColumnImage(Object element, int columnIndex) {
		return this.getImage(element);
	}

	@Override
	public String getColumnText(Object element, int columnIndex) {
		return this.getText(element);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/simulation/SimulatorMultiThreadTest.java<|end_filename|>
package tlc2.tool.simulation;

/**
 * Correctness tests of a multi-threaded Simulator.
 * 
 * This test intends to verify that, from a correctness perspective, running the
 * Simulator with multiple threads is equivalent to running it with a single
 * thread i.e. it should pass all of the same tests.
 */
public class SimulatorMultiThreadTest extends SimulatorTest {

	public int numWorkers() {
		// A somewhat arbitrary value, but 4 threads seems like a reasonable amount of
		// parallelism.
		return 4;
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/ResourceFileReader.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS ResourceFileReader                                                 *
*                                                                          *
* A ResourceFileReader returns an object for reading a resource file,      *
* which is a file kept in the same directory as the tlatex.Token class.    *
* The constructor takes a file name as argument.  The object's two public  *
* methods are                                                              *
*                                                                          *
*   getLine() : Returns the next line of the file as a string.  Returns    *
*               null after the last line.                                  *
*                                                                          *
*   close()   : Closes the file.                                           *
***************************************************************************/
package tla2tex;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ResourceFileReader
  { public ResourceFileReader(String fileName)
      /*********************************************************************
      * The constructor, where fileName is the name of a file that's       *
      * in the same directory as tlatex.Token.                             *
      *********************************************************************/
     { name = fileName ;
       Class cl = null ;
       try { cl = Class.forName("tla2tex.Token"); }
       catch (ClassNotFoundException e)
           { Debug.ReportError( 
               "Java could not find class tla2tex.Token.  There \n"
             + "    is probably something wrong with the way\n"
             + "    TLA2TeX is installed");
           } ;             
       InputStream input = cl.getResourceAsStream(fileName) ; 
       if (input == null)
         { Debug.ReportError( 
               "TLATeX could not find its resource file " + fileName + ".\n"
             + "    There is probably something wrong with the way\n"
             + "    TLA2TeX is installed");
         } ;  
       inputReader = new BufferedReader(new InputStreamReader(input)) ;
      };

    public String getLine()
      /*********************************************************************
      * Returns the next line of input.  After it returns the last line    *
      * of input, it returns null.                                         *
      *********************************************************************/
      { try { return inputReader.readLine();
            }
        catch (java.io.IOException e)
          { Debug.ReportError( 
                   "Error reading the TLATeX resource file " + name + ".\n"
                 + "    You may be having file system problems");
          } ; 
        return null ;
      }
    private boolean done = false;
      /*********************************************************************
      * If the last line of input doesn't end with a '\n', then getLine()  *
      * returns that line and sets done to true.                           *
      *********************************************************************/

    private BufferedReader inputReader ;
      /*********************************************************************
      * The actual reader for the resource file.                           *
      *********************************************************************/

    private String name ;
      /*********************************************************************
      * A copy of the resource file name, kept for error messages.         *
      *********************************************************************/
      
    public void close()
      { try { inputReader.close(); }
        catch (java.io.IOException e)
          { Debug.ReportError( 
               "Error trying to close the TLATeX resource file " + name + ".\n"
             + "    You may be having file system problems");
          } ;
      } ;


  }      


/* Last modified on Tue 18 Sep 2007 at  6:59:51 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/tool/queue/StateQueueBenachmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.queue;

import java.io.IOException;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Group;
import org.openjdk.jmh.annotations.GroupThreads;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;

import tlc2.tool.TLCState;
import tlc2.tool.TLCStates;

@State(Scope.Group)
public class StateQueueBenachmark {

	@Param({"1", "2", "4", "8", "16", "32", "64"})
	public int size;
	
	private IStateQueue s;

	private TLCState[] batch;

    @Setup
    public void up() throws IOException {
        s = new DiskStateQueue();
        
    	// balance off the costs for creating the TLCState[].
    	this.batch = new TLCState[size];
    	for (int i = 0; i < batch.length; i++) {
			batch[i] = TLCStates.createDummyState();
		}
    }
    
    @TearDown
    public void down() throws IOException {
    	this.s.delete();
    }
  
    @Benchmark
    @Group("single")
    @GroupThreads(2)
    public TLCState[] consumerSingle() {
    	final TLCState[] res = new TLCState[batch.length];
    	for (int i = 0; i < batch.length; i++) {
    		res[i] = this.s.sDequeue();
    	}
        return res;
    }

    @Benchmark
    @Group("single")
    @GroupThreads(2)
    public void producerSingle() {
    	for (int i = 0; i < batch.length; i++) {
    		this.s.sEnqueue(batch[i]);
		}
    }

    
    /* Batches of enqueue only */
    
    @Benchmark
    @Group("batchasym")
    @GroupThreads(2)
    public TLCState[] consumerBatch() {
    	final TLCState[] res = new TLCState[batch.length];
    	for (int i = 0; i < batch.length; i++) {
    		res[i] = this.s.sDequeue();
    	}
        return res;
    }

    @Benchmark
    @Group("batchasym")
    @GroupThreads(2)
    public void producerBatch() {
    	this.s.sEnqueue(batch);
    }

    
    /* Batches of dequeue & enqueue */
    
    @Benchmark
    @Group("batchsym")
    @GroupThreads(2)
    public TLCState[] consumerBatchSym() {
        return this.s.sDequeue(size);
    }

    @Benchmark
    @Group("batchsym")
    @GroupThreads(2)
    public void producerBatchSym() {
    	this.s.sEnqueue(batch);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/preference/ColorPredicatePreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.preference;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.ColorFieldEditor;
import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.editors.text.EditorsUI;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ColorPredicate;

/**
 * This class represents the prover preference page that
 * is contributed to the Preferences dialog. By 
 * subclassing <samp>FieldEditorPreferencePage</samp>, we
 * can use the field support built into JFace that allows
 * us to create a page that is small and knows how to 
 * save, restore and apply itself.
 * <p>
 * This page is used to modify preferences only. They
 * are stored in the preference store returned by
 * EditorUI.getPreferenceStore(). That way, preferences can
 * be accessed directly via the preference store.
 * 
 * We use the preference store from EditorUI.getPreferenceStore() because
 * that is where the preferences for annotation colors are stored by
 * eclipse, and we use marker annotations to show step status colors
 * in the editor.
 * 
 * There is some hackery involved in setting the color preference values.
 * For each logical color that appears on this preference page, there are
 * two marker types and thus two annotation types. One annotation type
 * corresponds to leaf steps and one to non-leaf steps. Each annotation type
 * has a key in the preference store that maps to that annotation's color.
 * Both annotation types for a given logical color should always be bound to the
 * same physical color. Thus, when the user changes the value of a logical
 * color, the two color preference keys for the two annotation types must both
 * map to the new physical color.
 * 
 * The original implementation used the same color preference key for both
 * annotation types. However, this does not seem to work. It appears that when
 * the physical color preference is changed for a given logical color, the editor
 * only recognizes the change to the color for one of the annotation types even though
 * the color has changed for both annotation types because they both have the same
 * color preference key.
 * 
 * The solution is the following. Use different color preference keys for two
 * annotation types corresponding to a given logical color. Only one of the keys
 * can be bound to the color field editor on the preference page. This page listens
 * for changes to the value of that key. When the value is changed, it sets the value
 * of its partner key to be the same. This is done in the method {@link #propertyChange(PropertyChangeEvent)}.
 * 
 * There is also a slight hack involved in laying out the field editors as we want them.
 * Check out {@link #adjustGridLayout()} to read more about this.  This hack works only
 * because there are no other preferences besides the 12 color-predicate ones.  If we
 * want to put other preferences on the page, the obvious thing to do is to put the
 * color-predicate preferences inside a Composite that is formatted appropriately.
 * Experimentation shows that this doesn't work in the obvious way.  Instead, each
 * field editor has to be put inside a separate composite inside the multi-column
 * composite.  The following code seems to work:
 *     protected void createFieldEditors()
 *    {
 *        Composite composite = new Composite(getFieldEditorParent(), SWT.NONE);
 *        GridLayout layout = new GridLayout();
 *        layout.numColumns = 4;
 *        layout.horizontalSpacing = 20;
 *        composite.setLayout(layout);
 *
 *        for (int i = 1; i <= NUM_STATUS_COLORS; i++)
 *        {
 *            Composite c = new Composite(composite, SWT.NONE);
 *            addField(new ColorFieldEditor(getMainColorPrefName(i), "Color "  + i + (i>9?"":"  "), c));
 *            c = new Composite(composite, SWT.NONE);
 *            addField(new ComboFieldEditor(getColorPredPrefName(i), "Predicate", ColorPredicate.PREDEFINED_MACROS, c));
 *            c = new Composite(composite, SWT.NONE);
 *            addField(new BooleanFieldEditor(getLeafSideBarPrefName(i), "Show Leaf Steps in Side Bar", c));
 *            c = new Composite(composite, SWT.NONE);
 *            addField(new BooleanFieldEditor(getAppliesToLeafPrefName(i), "Applies to Leaf Steps Only", c));
 *        }
 *    }
 *
 * However, the documentation warns that getFieldEditorParent() should be called 
 * separately for each field.  This doesn't seem to be necessary for a GRID layout,
 * but Dan & LL decided not to risk it and instead to put other preferences on a
 * separate page.
 * 
 * @author <NAME>
 *
 */
public class ColorPredicatePreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{

    public static final String PREDICATE = "predicate";

    public static final String APPLIES_TO_LEAF_ONLY = "appliesToLeafOnly";

    public static final String STEP_STATUS_COLOR = "stepStatusColor";

    public static final String STEP_STATUS_OVERVIEW = "stepStatusOverview";

	/**
     * The number of logical status colors for proof steps.
     */
    public static final int NUM_STATUS_COLORS = 12;

    /**
     * The prefix for the keys used for color preferences.
     */
    public static final String COLOR_PREF_KEY_PREFIX = STEP_STATUS_COLOR;

    public ColorPredicatePreferencePage()
    {
        super(GRID);
        // Using somebody's else PreferenceStore is not a good idea!
        // @see Bug #261 in general/bugzilla/index.html
        final IPreferenceStore[] preferenceStores = new IPreferenceStore[2];
        preferenceStores[0] = EditorsUI.getPreferenceStore();
        preferenceStores[1] = ProverUIActivator.getDefault().getPreferenceStore();
        
        setPreferenceStore(new TLCChainedPreferenceStore(preferenceStores));
        getPreferenceStore().addPropertyChangeListener(this);
        setDescription("Color Predicates");
    }

    /**
     * Creates the field editors. Field editors are abstractions of
     * the common GUI blocks needed to manipulate various types
     * of preferences. Each field editor knows how to save and
     * restore itself.
     */
    protected void createFieldEditors()
    {

        for (int i = 1; i <= NUM_STATUS_COLORS; i++)
        {
            addField(new ColorFieldEditor(getMainColorPrefName(i), "Color " + i, getFieldEditorParent()));
            addField(new ComboFieldEditor(getColorPredPrefName(i), "Predicate", ColorPredicate.PREDEFINED_MACROS,
                    getFieldEditorParent()));
            addField(new BooleanFieldEditor(getLeafSideBarPrefName(i), "Show Leaf Steps in Side Bar",
                    getFieldEditorParent()));
            addField(new BooleanFieldEditor(getAppliesToLeafPrefName(i), "Applies to Leaf Steps Only",
                    getFieldEditorParent()));
        }
    }

    /**
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
    public void init(IWorkbench workbench)
    {
    }

    /**
     * Returns the preference name for the color value for logical
     * color colorNum. This is the name used to store the preference
     * in the preference store. This is the name used for the color field editor.
     * There is another "partner" key that should also be bound to the same color.
     * See the class documentation for an explanation.
     * 
     * Implementation note : The name returned
     * here must equal the name used for the colorPreferenceKey
     * field of the org.eclipse.ui.editors.markerAnnotationSpecification
     * extension for the non-leaf marker corresponding to colorNum.
     * 
     * @param colorNum
     * @return
     */
    public static final String getMainColorPrefName(int colorNum)
    {

        return COLOR_PREF_KEY_PREFIX + colorNum + "A";

    }

    /**
     * Returns the preference name for the color value for logical
     * color colorNum. This is the name used to store the preference
     * in the preference store. This is NOT the name used for the color field editor.
     * This is the partner key of the key used for the color field editor.
     * See the class documentation for an explanation.
     * 
     * Implementation note : The name returned
     * here must equal the name used for the colorPreferenceKey
     * field of the org.eclipse.ui.editors.markerAnnotationSpecification
     * extension for the leaf marker corresponding to colorNum.
     * 
     * @param colorNum
     * @return
     */
    public static final String getPartnerColorPrefName(int colorNum)
    {
        return COLOR_PREF_KEY_PREFIX + colorNum + "B";
    }

    /**
     * Gets the number of the color given the color preference
     * key for that color. Note that this is the color preference
     * key for the color field editor. These keys are produced using the
     * method {@link #getMainColorPrefName(int)}.
     * There is another "partner" key that should also be bound to the same color.
     * See the class documentation for an explanation.
     * 
     * @param key
     * @return
     */
    public static final int getNumFromMainColorPref(String key)
    {
        // the number is from the end of the prefix to the second to last character
        // the last character is "A" or "B".
        return Integer.parseInt(key.substring(COLOR_PREF_KEY_PREFIX.length(), key.length() - 1));
    }

    /**
     * Returns the preference name for the color predicate
     * for logical color colorNum. This is the name used to store
     * the preference in the preference store.
     * 
     */
    public static final String getColorPredPrefName(int colorNum)
    {

        return STEP_STATUS_COLOR + colorNum + PREDICATE;

    }

    /**
     * Returns the preference name for the boolean preference
     * of showing leaf markers in the side bar. That is, if selected
     * whenever the physical color corresponding to colorNum is shown
     * in the editor on a leaf step, it will appear in the side bar as well.
     * This is the name used to store the preference in the preference store.
     * 
     * @param colorNum
     * @return
     */
    public static final String getLeafSideBarPrefName(int colorNum)
    {

        return STEP_STATUS_OVERVIEW + colorNum + "B";

    }

    /**
     * Returns the preference name for the boolean preference of whether the
     * color applies only to leaf steps. This is the name used to store the preference
     * in the preference store.
     * 
     * @param colorNum
     * @return
     */
    public static final String getAppliesToLeafPrefName(int colorNum)
    {
        String string = APPLIES_TO_LEAF_ONLY;
		return string + colorNum;
    }

    /**
     * This method makes sure pairs of annotation types corresponding
     * to a given logical color are always bound to the same physical color.
     * When the color preference is changed for the key which is bound to the color
     * field editors for this page, this method sets the value for the partner key
     * to be the same.
     * See the documentation for this class to read more about this.
     */
    public void propertyChange(PropertyChangeEvent event)
    {
        if (event.getProperty().contains(COLOR_PREF_KEY_PREFIX) && event.getProperty().endsWith("A"))
        {
            /*
             * Setting preferences is a bit strange. The strangeness occurs
             * when calling IPreferenceStore.setValue(name,value) when the value
             * is equal to the default value for that name.
             * 
             * When the value is NOT equal to the default value and is not equal to the old
             * value, the preference store sets name to map to the new value and
             * informs all interested listeners of the change. I believe that
             * the eclipse text editors are among these interested listeners. This
             * is how they update the colors used for annotations.
             * 
             * However, when the value is equal to the default value for name, the preference
             * store removes the preference mapping for name (I assume the defaults are stored
             * somewhere else in the store) and informs all listeners that the preference
             * for name has been removed and does not inform them that it has been set to
             * the default value. The method comments for setValue() indicate that the correct
             * way to restore default preference values is to call store.setToDefault(). Thus,
             * it appears that we have to check whether the value we are setting is the default
             * value. If it is, we use setToDefault(). If it isn't, we use setValue().
             * 
             * Note that this strange behavior only seems to be for ScopedPreferenceStore, which
             * is the type of preference store used for this page.
             */
            int colorNum = getNumFromMainColorPref(event.getProperty());
            IPreferenceStore store = getPreferenceStore();
            String partnerPrefName = getPartnerColorPrefName(colorNum);
            /*
             * You might be wondering why in the following I did not use event.getNewValue() to
             * retrieve the new color value. It turns out that sometimes
             * that method returns an object of type RGB and sometimes a String.
             * For all I know, it could return another type entirely in certain
             * situations. Thus, it seems that the best thing is to get the value
             * directly from the preference store instead of from the event. The preference
             * store keeps the value of a color as a String, so the type returned is a string
             * and the type to set for the partner preference name is also a String.
             */
            String newValue = getPreferenceStore().getString(event.getProperty());
            if (store.getDefaultString(partnerPrefName).equals(newValue))
            {
                store.setToDefault(partnerPrefName);
            } else
            {
                getPreferenceStore().setValue(partnerPrefName, newValue);
            }
        }

        super.propertyChange(event);
    }

    /**
     * This overrides the method in {@link FieldEditorPreferencePage} in order
     * to place multiple field editors on a single line. The superclass implementation
     * of this method puts one field editor per line of preference page. However,
     * we want to put all the field editors for each logical color on a single
     * line so that the page is a little more compact.
     */
    protected void adjustGridLayout()
    {
        /*
         * All that needs to be done is adjusting the number of columns of the layout
         * of widgets on the page. Each logical color seems to have 6 widgets:
         * 
         * 1.) Color label
         * 2.) Color selection widget
         * 3.) Predicate label
         * 4.) Predicate selection widget
         * 5.) Show leaf steps in side bar (the label and check box are somehow one widget)
         * 6.) Applies to leaf steps (the label and check box are somehow one widget)
         * 
         * If the field editors change on this page, this method will have to change.
         */
        ((GridLayout) getFieldEditorParent().getLayout()).numColumns = 6;
    }

    public static String makeAtLeastThreeDigitsWide(int value)
    {
        String result = "";
        if (value < 100)
        {
            result = result + "0";
            if (value < 10)
            {
                result = result + "0";
            }
        }
        return result + value;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/TableauNodePtrTableTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;

import org.junit.Test;

public class TableauNodePtrTableTest {

	@Test
	public void testSetDone() {
		final TableauNodePtrTable tbl = new TableauNodePtrTable(0); // init with 0 so that grow is tested
		
		final long fingerprint = 1L;
		assertFalse(tbl.isDone(fingerprint));
		
		tbl.setDone(fingerprint);
		assertTrue(tbl.isDone(fingerprint));
		
		tbl.put(fingerprint, 1, TableauNodePtrTable.UNDONE);
		// This ends up as -2 for the high part of the long and thus tbl isn't
		// done anymore.
		assertFalse(tbl.isDone(fingerprint));

		// Add another node BUT with different tableau index. The done state
		// does NOT change.
		tbl.put(fingerprint, 2, 4711L);
		assertFalse(tbl.isDone(fingerprint));

		tbl.setDone(fingerprint);
		assertTrue(tbl.isDone(fingerprint));
	}
	
	// Test various methods which apparently all yield pretty much the same result
	@Test
	public void testRedundantMethodYieldSameResult() {
		final TableauNodePtrTable tbl = new TableauNodePtrTable(0); // init with 0 so that grow is tested
		
		final long fingerprint = 1L;
		
		assertEquals(-1, tbl.getNodesLoc(fingerprint));
		
		final int loc = tbl.setDone(fingerprint);
		assertTrue(tbl.isDone(fingerprint));

		assertTrue(tbl.getNodesLoc(fingerprint) != -1);
		assertEquals(tbl.getNodesLoc(fingerprint), loc);

		assertTrue(Arrays.equals(tbl.getNodesByLoc(loc), tbl.getNodes(fingerprint)));

		assertEquals(-1, tbl.getLoc(fingerprint, 1));
		tbl.addElem(fingerprint, 1, 2342);
		// Cannot lookup after addElem
		assertEquals(-1, tbl.getLoc(fingerprint, 1));
		
		//...have to put instead
		tbl.put(fingerprint, 1, 2342);
		assertTrue(tbl.getLoc(fingerprint, 1) != -1);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/TLCConsumptionProfile.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

import org.lamport.tla.toolbox.tool.tlc.job.TLCProcessJob;

import util.TLCRuntime;

/**
 * This enum represents the profile types of TLC running.
 */
public enum TLCConsumptionProfile {

	LOCAL_MOST("Most", 0.7, 0.8, null, "local most"),
	LOCAL_NORMAL("Medium", 0.5, 0.4, null, "local nomal"),
	LOCAL_MINIMAL("Minimal", 0.2, ((double)TLCProcessJob.HEAP_SIZE_DEFAULT / 100.0), null, "local minimal"),
	REMOTE_AD_HOC("Ad Hoc", 0, 0.3, "ad hoc", "ad hoc"),
	REMOTE_AZURE("Azure", 0, 0, MainModelPage.CLOUD_CONFIGURATION_KEY, "Azure"),
	REMOTE_AWS("Amazon", 0, 0, MainModelPage.CLOUD_CONFIGURATION_KEY, "aws-ec2"),
	REMOTE_PACKET_NET("PacketNet", 0, 0, MainModelPage.CLOUD_CONFIGURATION_KEY, "PacketNet");
	
	public static TLCConsumptionProfile getProfileWithPreferenceValue(final String value) {
		for (final TLCConsumptionProfile profile : TLCConsumptionProfile.values()) {
			if (value.equals(profile.getPreferenceValue())) {
				return profile;
			}
		}
		
		return null;
	}
	
	public static TLCConsumptionProfile getProfileWithDisplayName(final String displayName) {
		for (final TLCConsumptionProfile profile : TLCConsumptionProfile.values()) {
			if (displayName.equals(profile.getDisplayName())) {
				return profile;
			}
		}
		
		return null;
	}
	
	
	private final double m_workerThreadPercentage;
	private final double m_memoryPercentage;
	private final String m_displayName;
	
	private final String m_configurationKey;
	
	private final String m_preferenceValue;
	
	private TLCConsumptionProfile(final String name, final double threadPercentage, final double memoryPercentage,
			final String uiConfigurationKey, final String preferenceValue) {
		m_displayName = name;
		
		m_workerThreadPercentage = threadPercentage;
		m_memoryPercentage = memoryPercentage;
		
		m_configurationKey = uiConfigurationKey;
		
		m_preferenceValue = preferenceValue;
	}
	
	public String getDisplayName() {
		return m_displayName;
	}
	
	public boolean profileIsForRemoteWorkers() {
		return (m_configurationKey != null);
	}
	
	public String getConfigurationKey() {
		return m_configurationKey;
	}
	
	public String getPreferenceValue() {
		return m_preferenceValue;
	}
	
	/**
	 * @return the 0-100 representation of percentage
	 */
	public int getMemoryPercentage() {
		return (int)(100.0 * m_memoryPercentage);
	}
	
	public long getMemory() {
		return TLCRuntime.getInstance().getAbsolutePhysicalSystemMemory(m_memoryPercentage);
	}
	
	public int getWorkerThreads() {
		return (int)Math.ceil((float)Runtime.getRuntime().availableProcessors() * m_workerThreadPercentage);
	}
	
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/ReadersWriterLock.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:39 PST by lamport
//      modified on Mon Jun 19 14:29:07 PDT 2000 by yuanyu
package tlc2.util;

import java.io.Serializable;

import tlc2.output.EC;
import util.Assert;

/** A <code>ReadersWriterLock</code> is a class that can be
    used to synchronize multiple readers and a single writer.
    There are <code>BeginRead</code> and <code>EndRead</code>
    methods that should be called before and after a read-only
    critical section, and <code>BeginWrite</code> and <code>EndWrite</code>
    methods that should be called before and after a critical
    section in which writes are performed. The <code>ReadersWriterLock</code>
    guarantees that no writers will be in the critical section
    while at least one reader is, and vice-versa. It also guarantees
    that at most one writer will be in the critical section at
    a time.<p>
    
    This implementation gives priority to writers. That is, if
    both writers and readers are blocked waiting to enter the
    critical section, then the writer will be given preference.<p>
    
    IMPORTANT NOTE: The methods of a <code>ReadersWriterLock</code>
    are unsynchronized. It is the caller's responsibility to ensure
    that the mutex associated with a <code>ReadersWriterLock</code>
    object <code>rwl</code> is held when any of <code>rwl</code>'s
    methods are called. This requirement is denoted in this module
    by "REQUIRES LL = SELF".

    Written by <NAME> and <NAME>
*/

public class ReadersWriterLock implements Serializable {
    /** Acquire a share of the object's read lock. This call will
        block until no writer holds the lock and there are no writers
        waiting to acquire the lock.<p>
        REQUIRES LL = SELF. */
    public void BeginRead() {
        while (this.hasWriter || this.waitingWriters > 0) {
            try {
                this.wait();
            } catch (InterruptedException e) 
            {
                Assert.fail(EC.SYSTEM_INTERRUPTED);
            }
        }
        this.numReaders++;
    }
    
    /** Release the calling thread's portion of this object's
        read lock.<p>
        REQUIRES LL = SELF. */
    public void EndRead() {
        this.numReaders--;
        if (this.numReaders == 0) {
            this.notifyAll();
        }
    }
    
    /** Acquire this object's write lock. This call will block
        until all readers release their shares of this object's
        read lock.<p>
        REQUIRES LL = SELF. */
    public void BeginWrite() {
        while (this.numReaders > 0 || this.hasWriter) {
            this.waitingWriters++;
            try {
                this.wait();
            } catch (InterruptedException e) {
                Assert.fail(EC.SYSTEM_INTERRUPTED);
            }
            this.waitingWriters--;
        }
        this.hasWriter = true;
    }
    
    /** Release this object's write lock.<p>
        REQUIRES LL = SELF. */
    public void EndWrite() {
        this.hasWriter = false;
        this.notifyAll();
    }
    
    /* The following fields are protected by SELF. */
    private int numReaders = 0;        // # of threads that hold a share of the read lock
    private boolean hasWriter = false; // a thread holds the write lock
    private int waitingWriters = 0;    // # of threads waiting to acquire write lock
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/traceexplorer/TraceExplorerHelper.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.traceexplorer;

import java.io.ByteArrayInputStream;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError.Length;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCModelLaunchDataProvider;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCOutputSourceRegistry;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.util.ModelHelper;

import tlc2.output.MP;

/**
 * Provides utility methods for the trace explorer
 * @author <NAME>
 *
 */
public class TraceExplorerHelper
{

    /**
     * Returns the error that has a trace most recently produced by running model checking
     * on the config or null if none found.
     * 
     * @param model
     * @return
     */
    public static TLCError getErrorOfOriginalTrace(Model model)
    {
        /*
         * The trace explorer should not be run for a model while TLC is being run for
         * model checking on that model. Therefore, the original trace can be retrieved
         * from the tlc output source registry for model checking.
         */
        TLCModelLaunchDataProvider originalTraceProvider = TLCOutputSourceRegistry.getModelCheckSourceRegistry()
                .getProvider(model);
        List<TLCError> errors = originalTraceProvider.getErrors();
        if (errors != null)
        {
            Iterator<TLCError> it = errors.iterator();
            while (it.hasNext())
            {
                TLCError error = it.next();
                if (error.hasTrace())
                {
                    return error;
                }
            }
        }

        // no trace found
        return null;
    }

    /**
     * Writes the trace to MC_TE.out.
     * @param trace
     */
    public static void serializeTrace(Model model)
    {
        try
        {
            List<TLCState> trace = getErrorOfOriginalTrace(model).getStates(Length.ALL);
            Assert.isNotNull(trace);
            Iterator<TLCState> it = trace.iterator();
            IFile traceSourceFile = model.getTraceSourceFile();
            ModelHelper.createOrClearFiles(new IFile[] { traceSourceFile }, new NullProgressMonitor());
            while (it.hasNext())
            {
                traceSourceFile.appendContents(new ByteArrayInputStream((MP.DELIM + MP.STARTMSG + "0000" + MP.COLON
                        + MP.STATE + " " + MP.DELIM + "\n").getBytes()), IResource.FORCE | IWorkspace.AVOID_UPDATE,
                        new NullProgressMonitor());
                TLCState state = (TLCState) it.next();
                StringBuffer toAppend = new StringBuffer();
                toAppend.append(state.getStateNumber()).append(": ").append(state.getLabel()).append("\n").append(
                        state.toString());

                traceSourceFile.appendContents(new ByteArrayInputStream(toAppend.toString().getBytes()),
                        IResource.FORCE | IWorkspace.AVOID_UPDATE, new NullProgressMonitor());

                traceSourceFile.appendContents(new ByteArrayInputStream(
                        (MP.DELIM + MP.ENDMSG + "0000" + " " + MP.DELIM + "\n").getBytes()), IResource.FORCE
                        | IWorkspace.AVOID_UPDATE, new NullProgressMonitor());

            }
        } catch (CoreException e)
        {
            TLCUIActivator.getDefault().logError("Error writing trace contents to file", e);
        }
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/SpecificationParserLauncher.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.TLAMarkerHelper;

/**
 * A specification parser parses the root file of the specification
 * @author <NAME>
 * @version $Id$
 */
public class SpecificationParserLauncher
{
    private ModuleParserLauncher moduleParser = null;

    public SpecificationParserLauncher(ModuleParserLauncher moduleParser)
    {
         this.moduleParser = moduleParser;
    }
    
    /**
     * Launches the spec parsing
     * @param spec specification handle
     * @param monitor the monitor to report progress
     * @return the parse status (which is also saved in the spec)
     */
    public int parseSpecification(Spec spec, IProgressMonitor monitor)
    {
        // parsed resource is the root file
        IResource parseResource = spec.getRootFile();

        // reset problems from previous run
        TLAMarkerHelper.removeProblemMarkers(parseResource.getProject(), monitor, TLAMarkerHelper.TOOLBOX_MARKERS_TLAPARSER_MARKER_ID);
        
        // call module parse on the root file
        ParseResult result = moduleParser.parseModule(parseResource, monitor);

        // set the status back into the spec
        spec.setStatus(result.getStatus());
        
        if (!AdapterFactory.isProblemStatus(result.getStatus())) 
        {
            spec.setSpecObj(result.getSpecObj());
        }
        
        return result.getStatus();
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/WindowUtils.java<|end_filename|>
package org.lamport.tla.toolbox;

/**
 * Window toolkit
 * @author <NAME>
 * @version $Id$
 */
public class WindowUtils
{
    /**
     * Determines if the window is a root window
     * @param window a window to be checked
     * @return true, if the window is considered to be a root window
     */
//    public static boolean isRootWindow(IWorkbenchWindow window)
//    {
//        // HACK: note this could change in future
//        if (window instanceof WorkbenchWindow  && ((WorkbenchWindow)window).getNumber() == 1 ) 
//        {
//            return true;
//        }
//        return false;
//    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/preference/DoubleFieldEditor.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.preference;

import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.widgets.Composite;

/**
 * This field editor overrides some methods of StringFieldEditor
 * to only allow real numbers in the given range to be entered and stored.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class DoubleFieldEditor extends StringFieldEditor
{

    private double minVal;
    private double maxVal;

    public DoubleFieldEditor(String name, String labelText, Composite parent, double min, double max)
    {
        super(name, labelText, parent);
        minVal = min;
        maxVal = max;
    }

    protected boolean checkState()
    {
        String errorMessage = "Enter a real number between " + minVal + " and " + maxVal + ".";
        try
        {
            String text = getTextControl().getText();
            if (text.endsWith("d") || text.endsWith("f") || text.contains("e"))
            {
                showErrorMessage(errorMessage);
                return false;
            }
            double value = Double.parseDouble(text);
            clearErrorMessage();
            return value >= minVal && value <= maxVal;
        } catch (NumberFormatException e)
        {
            showErrorMessage(errorMessage);
            return false;
        }

    }

    protected void doStore()
    {
        try
        {
            getPreferenceStore().setValue(getPreferenceName(), Double.parseDouble(getTextControl().getText()));
        } catch (NumberFormatException e)
        {
            getPreferenceStore().setValue(getPreferenceName(),
                    getPreferenceStore().getDefaultDouble(getPreferenceName()));
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/pprint/Format.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:20:42 PST by lamport
//      modified on Wed Jun 16 14:35:25 EDT 1999 by tuttle
//      modified on Fri Jun 11 17:50:44 PDT 1999 by yuanyu

package tlc2.pprint;

public class Format {

/***************************************************************************/
/* This class provides a format method that accepts the parse tree for a   */
/* TLC value and returns a nicely-formatted version of the value.  The     */
/* value is split across as many lines as necessary for the value to fit   */
/* within a specified number of columns.                                   */
/***************************************************************************/

/***************************************************************************/
/* The following constants determine how each type of value should         */
/* be formatted.                                                           */
/*                                                                         */
/* Open and Close give the strings like "{" and "}" used as the opening    */
/* and closing delimters for a value like a set.                           */
/*                                                                         */
/* Pad gives the string appended to the left of lines two and higher to    */
/* indent the components of the value so that they line up correctly on    */
/* adjacent lines.  This should be a string of spaces with length equal    */
/* to the Open string.                                                     */
/*                                                                         */
/* Sep gives the string that should follow the component of a value to     */
/* separate it from the next component, like "," between elements of a     */
/* set or " @@" between pairs of values defining the function.             */
/*                                                                         */
/* Div gives the string like " |->" separating elements of pairs like the  */
/* name/value pairs defining a field in a record or like " :>" separating  */
/* the argument/value pairs defining a function.                           */
/*                                                                         */
/* DivPad gives the string appended to the left of lines containing the    */
/* second element of a pair (like the value element of a argument/value    */
/* pair) when the argument and value must be printed on separate lines.    */
/* This padding is in addition to the Pad padding.  It should be a string  */
/* of spaces.  Its length can be arbitrary, but it should probably be      */
/* a bit longer than Pad for easy reading.                                 */
/***************************************************************************/

  private static final String setOpen  = "{ ";
  private static final String setClose = " }";
  private static final String setPad   = "  ";
  private static final String setSep   = ",";
	 
  private static final String seqOpen  = "<< ";
  private static final String seqClose = " >>";
  private static final String seqPad   = "   ";
  private static final String seqSep   = ",";
	 
  private static final String funOpen   = "( ";
  private static final String funClose  = " )";
  private static final String funPad    = "  ";
  private static final String funSep    = " @@";
  private static final String funDiv    = " :>";
  private static final String funDivPad = "    ";

  private static final String recOpen   = "[ ";
  private static final String recClose  = " ]";
  private static final String recPad    = "  ";
  private static final String recSep    = ",";
  private static final String recDiv    = " |->";
  private static final String recDivPad = "    ";

  private static final String subsetOpen  = "SUBSET ";
  private static final String subsetClose = " ";
  private static final String subsetPad   = " ";
  private static final String subsetSep   = ",";
  
/***************************************************************************/
/* Format a TLC value.                                                     */
/*                                                                         */
/* Value is a parse tree for the TLC value.  Width is the number of        */
/* characters available on each line for formatting the value.             */
/* Trailerwidth is the number of characters that must not be used at the   */
/* end of the last line of the formatted value, so that trailers like      */
/* closing "}" characters can be appended and not extend past the          */
/* specified number of characters on each line.  Padding is a string       */
/* (usually spaces) tacked to the front of lines two and higher to indent  */
/* these lines in the event that the value must be formatted over          */
/* multiple lines.                                                         */
/***************************************************************************/

  public static String format(Node value, 
			      int columnwidth, 
			      int trailerwidth,
			      String leftpad) throws FormatException {

    // Use the value's original format if it will fit on the line
    if (value.length() <= columnwidth-trailerwidth) return value.value();

    // Break the value over multiple lines since it won't fit on one line
    //
    // Sets and sequences are simple lists of values enclosed by
    // delimiters.  Functions and records are more complex lists of
    // pairs of values, where each pair is a functional argument/value
    // or record field/value pair.  We use two methods to format the
    // two types of lists.

    switch (value.type()) {
    case Node.CONSTANT: 
      return value.value();
    case Node.SET: 
      return formatSimpleValue(value,columnwidth,trailerwidth,leftpad,
			       setOpen, setClose, setPad, setSep);
    case Node.SEQUENCE: 
      return formatSimpleValue(value,columnwidth,trailerwidth,leftpad,
			       seqOpen, seqClose, seqPad, seqSep);
    case Node.FUNCTION: 
      return formatPairValue(value,columnwidth,trailerwidth,leftpad,
			     funOpen, funClose, funPad, funSep, 
			     funDiv, funDivPad);
    case Node.RECORD: 
      return formatPairValue(value,columnwidth,trailerwidth,leftpad,
			     recOpen, recClose, recPad, recSep,
			     recDiv, recDivPad);
    case Node.SUBSET:
      return formatSimpleValue(value,columnwidth,trailerwidth,leftpad,
			       subsetOpen, subsetClose, subsetPad,
			       subsetSep);
    default:
      throw new FormatException("TLC Bug: while formating output," +
				" the formatter called with an expression" +
				" of type " + value.type() + 
				" while formatting " + value.value() +
				" and this should never happen");
    }
  }

/***************************************************************************/
/* Format a simple value like a set or a sequence that is a simple list    */
/* of values enclosed by delimiters.                                       */
/*                                                                         */
/* This formatting method uses a second method to format the actual list   */
/* of values, remembering to leave room for the opening and closing        */
/* delimiters when formatting this list, and then surrounds the result     */
/* with the delimiters.                                                    */
/***************************************************************************/

  private static String formatSimpleValue(Node list, 
					 int columnwidth, 
					 int trailerwidth, 
					 String leftpad,
					 String open, 
					 String close, 
					 String pad,
					 String sep) throws FormatException {
    try {
      return 
	open +
	formatValues(list.children(),
		     columnwidth-Math.max(open.length(),pad.length()),
		     trailerwidth+close.length(),
		     leftpad+pad,
		     sep) +
	close;
    }
    catch (FormatException e) {
      throw e;
    }
  }

/***************************************************************************/

  private static String formatValues(Node values, 
				    int columnwidth, 
				    int trailerwidth, 
				    String leftpad, 
				    String sep) throws FormatException {
    try {
      String pp = "";
      for (Node value = values; value != null; value = value.next()) {
	if (value.next() != null) {
	  // this is not the last value in the list, so leave room for sep
	  pp = pp + 
	    format(value,columnwidth,sep.length(),leftpad) +
	    sep + "\n" + leftpad;
	} else {
	  // this is the last value in the list
	  pp = pp +
	    format(value,columnwidth,trailerwidth,leftpad);
	}
      }
      return pp;
    }
    catch (FormatException e) {
      throw e;
    }
  }

/***************************************************************************/
/* Format a complex value like a record or a function that is a list of    */
/* pairs of values enclosed by delimiters, where each pair is a record     */
/* field/value or function argument/value pair.                            */
/*                                                                         */
/* This formatting method uses a second method to format the actual list   */
/* of values, remembering to leave room for the opening and closing        */
/* delimiters when formatting this list, and then surrounds the result     */
/* with the delimiters.                                                    */
/***************************************************************************/

  private static String formatPairValue(Node list, 
				       int columnwidth, 
				       int trailerwidth, 
				       String leftpad,
				       String open, 
				       String close, 
				       String pad,
				       String sep,
				       String div,
				       String divpad) throws FormatException {
    try {
      return 
	open +
	formatPairs(list.children(),
		    columnwidth-Math.max(open.length(),pad.length()),
		    trailerwidth+close.length(),
		    leftpad+pad,
		    sep,
		    div,
		    divpad) +
	close;
    }
    catch (FormatException e) {
      throw e;
    }
  }

/***************************************************************************/

  private static String formatPairs(Node pairs, 
				   int columnwidth,
				   int trailerwidth,
				   String leftpad,
				   String sep,
				   String div,
				   String divpad) throws FormatException {
    try {
      String pp = "";
      for (Node pair = pairs; pair != null; pair = pair.next()) {
	Node arg = pair.children();
	Node val = arg.next();

	// First suppose this pair is not the last pair in
	// the list.  In this case, don't forget to append sep to the
	// end of the value; but don't bother keeping the last
	// trailerwidth characters open at the end of the line, go
	// ahead and use them to format the value.

	if (pair.next() != null) {

	  // put argument and value on one line if they will fit
	  if (arg.length() + div.length()+ 1 + val.length() + sep.length()
	      <= columnwidth) {
	    pp = pp 
	      + arg.value() + div + " " + val.value() + sep 
              + "\n" + leftpad;
	    continue;
	  }

	  // put argument on one line if it will fit
	  if (arg.length() + div.length() <= columnwidth) {
	    pp = pp
	      + arg.value() + div 
	      + "\n" + leftpad + divpad + format(val,
						 columnwidth-divpad.length(),
						 sep.length(),
						 leftpad+divpad) + sep
	      + "\n" + leftpad;
	    continue;
	  }

	  // format the argument on multiple lines and then the value
	  pp = pp
	    + format(arg,columnwidth,trailerwidth+div.length(),leftpad) + div
	    + "\n" + leftpad + divpad + format(val,
					       columnwidth-divpad.length(),
					       sep.length(),
					       leftpad+divpad) + sep
	    + "\n" + leftpad;
	  continue;
	}

	// Now suppose this pair is the last pair in the list.
	// Remember to leave trailerwidth space at the end of the line,
	// but don't worry about appending sep to the end of the line.

	// put argument and value on one line if they will fit
	if (arg.length() + div.length() + 1 + val.length()
	    <= columnwidth-trailerwidth) {
	  pp = pp + arg.value() + div + " " + val.value();
	  continue;
	}

	// put argument alone on one line if it will fit
	if (arg.length() + div.length() <= columnwidth) {
	  pp = pp
	    + arg.value() + div 
	    + "\n" + leftpad + divpad + format(val,
					       columnwidth-divpad.length(),
					       trailerwidth,
					       leftpad+divpad);
	  continue;
	}

	// format the argument on multiple lines and then the value
	pp = pp
	  + format(arg,columnwidth,trailerwidth+div.length(),leftpad) + div
	  + "\n" + leftpad + divpad + format(val,
					     columnwidth-divpad.length(),
					     trailerwidth,
					     leftpad+divpad);
	continue;
      }
      return pp;
    }
    catch (FormatException e) {
      throw e;
    }
  }

/***************************************************************************/

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/fp/DynamicFPSetManagerTest.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.distributed.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.Test;

import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.MemFPSet;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

public class DynamicFPSetManagerTest {

	/**
	 * Test that the ctor rejects invalid values.
	 */
	@Test
	public void testCtorInvalidZero() throws RemoteException {
		try {
			new DynamicFPSetManager(0);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail("Exception expected");
	}
	
	/**
	 * Test that the ctor rejects invalid values.
	 */
	@Test
	public void testCtorInvalidMin1() throws RemoteException {
		try {
			new DynamicFPSetManager(-1);
		} catch (IllegalArgumentException e) {
			return;
		}
		fail("Exception expected");
	}
	
	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtor1() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(1);
		long mask = dynamicFPSetManager.getMask();
		assertEquals(1L, mask);
	}
	
	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtor10() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(10);
		long mask = dynamicFPSetManager.getMask();
		assertEquals(15L, mask);
	}
	
	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtor31() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(31);
		long mask = dynamicFPSetManager.getMask();
		assertEquals(31L, mask);
	}
	
	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtor32() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(32);
		long mask = dynamicFPSetManager.getMask();
		assertEquals(63L, mask);
	}
	
	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtor33() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(33);
		long mask = dynamicFPSetManager.getMask();
		assertEquals(63L, mask);
	}

	/**
	 * Test that the ctor correctly calculates its mask used to index fpset
	 * servers for valid values.
	 */
	@Test
	public void testCtorMax() throws RemoteException {
		DynamicFPSetManager dynamicFPSetManager = new DynamicFPSetManager(Integer.MAX_VALUE);
		long mask = dynamicFPSetManager.getMask();
		assertEquals((Integer.MAX_VALUE), mask);
	}

	/**
	 * Test that the {@link DynamicFPSetManager} correctly indexes into the
	 * table of FPSet servers.
	 */
	@Test
	public void testGetIndexSingleFPSet() throws RemoteException {
		// Simple case with a single FPSet server
		final Map<Long, Integer> pairs = new HashMap<Long, Integer>();
		pairs.put(Long.MAX_VALUE, 0);
		pairs.put(Long.MIN_VALUE, 0);
		pairs.put(0L, 0);
		pairs.put(1L, 0);
		
		doTestGetIndex(1, pairs);
	}

	/**
	 * Test that the {@link DynamicFPSetManager} correctly indexes into the
	 * table of FPSet servers.
	 */
	@Test
	public void testGetIndex10FPSet() throws RemoteException {
		final Map<Long, Integer> pairs = new HashMap<Long, Integer>();
		
		pairs.put(Long.MAX_VALUE, 5);
		pairs.put(Long.MIN_VALUE, 0);

		// Test all fpsets get addressed
		pairs.put(0L, 0);
		pairs.put(1L, 1);
		pairs.put(2L, 2);
		pairs.put(3L, 3);
		pairs.put(4L, 4);
		pairs.put(5L, 5);
		pairs.put(6L, 6);
		pairs.put(7L, 7);
		pairs.put(8L, 8);
		pairs.put(9L, 9);

		// Test to correctly wrap over
		pairs.put(10L, 0);
		pairs.put(11L, 1);
		pairs.put(12L, 2);
		
		pairs.put(48L, 0);
		pairs.put(49L, 1);
		pairs.put(50L, 2);
		pairs.put(51L, 3);
		
		doTestGetIndex(10, pairs);
	}
	
	// Create the given amount of FPSetManagers and check if the return the integer for the given fingerprint (long)
	private void doTestGetIndex(final int expectedNumOfServers, final Map<Long, Integer> pairs) throws RemoteException {
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		for (int i = 0; i < expectedNumOfServers; i++) {
			dfm.register(new MemFPSet(), "localhost" + i);
		}
		
		for (Entry<Long, Integer> pair : pairs.entrySet()) {
			long fp = pair.getKey();
			int index = dfm.getFPSetIndex(fp);
			int expected = pair.getValue();
			assertEquals(expected, index);
		}
	}
	
	/**
	 * Tests that reassign doesn't accept invalid values
	 */
	@Test
	public void testReassingInvalidMin1() throws RemoteException {
		int expectedNumOfServers = 1;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		for (int i = 0; i < expectedNumOfServers; i++) {
			dfm.register(new MemFPSet(), "localhost" + i);
		}

		// invalid input
		try {
			dfm.reassign(-1);
		} catch (IllegalArgumentException e){
			// expected
			return;
		}
		fail();
	}
	
	/**
	 * Tests that reassign doesn't accept invalid values
	 */
	@Test
	public void testReassingInvalid2() throws RemoteException {
		int expectedNumOfServers = 1;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		for (int i = 0; i < expectedNumOfServers; i++) {
			dfm.register(new MemFPSet(), "localhost" + i);
		}

		// invalid input
		try {
			dfm.reassign(expectedNumOfServers);
		} catch (IllegalArgumentException e){
			// expected
			return;
		}
		fail();
	}
	
	/**
	 * Tests that reassign correctly terminates with -1 when reassignment to
	 * next FPSet impossible (no FPSets left)
	 */
	@Test
	public void testReassingTerminate() throws RemoteException {
		int expectedNumOfServers = 1;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		for (int i = 0; i < expectedNumOfServers; i++) {
			dfm.register(new MemFPSet(), "localhost" + i);
		}

		int reassign = dfm.reassign(0);
		assertEquals(-1, reassign);
	}
	
	/**
	 * Tests that reassign correctly assigns to the next FPSet
	 */
	@Test
	public void testReassing() throws RemoteException {
		int expectedNumOfServers = 10;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		for (int i = 0; i < expectedNumOfServers; i++) {
			dfm.register(new MemFPSet(), "localhost" + i);
		}

		// subsequently replace all FPSets until we 
		// hit the end of the list (-1)
		int reassign = dfm.reassign(1);
		assertEquals(2, reassign);
		
		reassign = dfm.reassign(2);
		assertEquals(3, reassign);

		reassign = dfm.reassign(3);
		assertEquals(4, reassign);
		
		reassign = dfm.reassign(4);
		assertEquals(5, reassign);
		
		reassign = dfm.reassign(5);
		assertEquals(6, reassign);
		
		reassign = dfm.reassign(6);
		assertEquals(7, reassign);
		
		reassign = dfm.reassign(7);
		assertEquals(8, reassign);
		
		reassign = dfm.reassign(8);
		assertEquals(9, reassign);
		
		reassign = dfm.reassign(9);
		assertEquals(0, reassign);
		
		reassign = dfm.reassign(0);
		assertEquals(-1, reassign);
	}
	
	/**
	 * Tests if the {@link FPSetManager} correctly fails over to the replacement {@link FPSet}
	 */
	@Test
	public void testFailoverPut() throws RemoteException {
		int expectedNumOfServers = 2;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		dfm.register(new FaultyFPSet(), "TestFPSet");
		dfm.register(new MemFPSet(), "RegularFPSet");
		
		final long fp = 2L;
		
		assertEquals("Assert fingerprint corresponds to TestFPSet", 0, dfm.getFPSetIndex(fp));
		
		// Test DFM correctly behaves first time when TestFPSet works as expected
		assertFalse(dfm.put(fp));
		assertTrue(dfm.contains(fp));
		
		// Test DFM correctly fails over to successor of TestFPSet
		// (Here one can observe the behavior that a fingerprint is thought to
		// be new when a FPSet crashes).
		assertFalse(dfm.put(fp));
		assertTrue(dfm.contains(fp));
	}

	/**
	 * Tests if the {@link FPSetManager} correctly fails over to the replacement {@link FPSet}
	 */
	@Test
	public void testFailoverPutBlock() throws RemoteException {
		int expectedNumOfServers = 2;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		dfm.register(new FaultyFPSet(), "TestFPSet");
		dfm.register(new MemFPSet(), "RegularFPSet");
		
		final int numOfServers = dfm.numOfServers();

		// LongVec has to have same size of IFPSetManager#numServers (putBlock
		// method contract)
		final LongVec[] fps = new LongVec[numOfServers]; 
		fps[0] = new LongVec();
		fps[0].addElement(0L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 0, dfm.getFPSetIndex(0L));
		fps[1] = new LongVec();
		fps[1].addElement(1L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 1, dfm.getFPSetIndex(1L));
		
		/* Test DFM correctly behaves first time when TestFPSet works as expected */

		BitVector[] bvs = dfm.putBlock(fps);
		assertEquals(1, bvs[0].trueCnt());
		assertEquals(1, bvs[1].trueCnt());

		bvs = dfm.containsBlock(fps);
		// all (the same) fingerprints are now known (meaning corresponding
		// bit in bvs[x] is zero).
		assertEquals(0, bvs[0].trueCnt());
		assertEquals(0, bvs[1].trueCnt());
		
		/*
		 * Test DFM correctly fails over to successor of TestFPSet (Here one can
		 * observe the behavior that a fingerprint is thought to be new when a
		 * FPSet crashes).
		 */

		bvs = dfm.putBlock(fps);
		assertEquals(1, bvs[0].trueCnt()); // fingerprint is unknown after fpset crash
		assertEquals(0, bvs[1].trueCnt());

		// The previous putBlock call has caused the FPSetManager to detect the
		// failure state of the first FPSets and reassigned the replacement FPSet.
		// Thus, it reports two alive servers
		assertEquals(1, dfm.numOfAliveServers());

		bvs = dfm.containsBlock(fps);
		assertEquals(0, bvs[0].trueCnt()); // fingerprint is known again
		assertEquals(0, bvs[1].trueCnt());
	}

	/**
	 * Tests if the {@link FPSetManager} correctly terminates if all nested FPSets fail
	 */
	@Test
	public void testFailoverTerminationPutBlock() throws RemoteException {
		int expectedNumOfServers = 2;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		dfm.register(new FaultyFPSet(), "TestFPSet1");
		dfm.register(new FaultyFPSet(), "TestFPSet2");
		
		final int numOfServers = dfm.numOfServers();

		// LongVec has to have same size of IFPSetManager#numServers (putBlock
		// method contract)
		final LongVec[] fps = new LongVec[numOfServers]; 
		fps[0] = new LongVec();
		fps[0].addElement(0L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 0, dfm.getFPSetIndex(0L));
		fps[1] = new LongVec();
		fps[1].addElement(1L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 1, dfm.getFPSetIndex(1L));
		
		/* Test DFM correctly behaves first time when TestFPSet works as expected */

		BitVector[] bvs = dfm.putBlock(fps);
		assertEquals(1, bvs[0].trueCnt());
		assertEquals(1, bvs[1].trueCnt());

		bvs = dfm.containsBlock(fps);
		// all (the same) fingerprints are now known (meaning corresponding
		// bit in bvs[x] is zero).
		assertEquals(0, bvs[0].trueCnt());
		assertEquals(0, bvs[1].trueCnt());
		
		/*
		 * Test DFM correctly fails over to successor of TestFPSet (Here one can
		 * observe the behavior that a fingerprint is thought to be new when a
		 * FPSet crashes).
		 */

		bvs = dfm.putBlock(fps);
		assertEquals(2, bvs[0].trueCnt()); // fingerprint is unknown after fpset crash
		assertEquals(2, bvs[1].trueCnt());
		
		// The previous putBlock call has caused the FPSetManager to detect the
		// failure state of both FPSets
		assertEquals(0, dfm.numOfAliveServers());
		
		bvs = dfm.containsBlock(fps);
		assertEquals(2, bvs[0].trueCnt()); // fingerprint is known again
		assertEquals(2, bvs[1].trueCnt());
	}
	
	/**
	 * Tests if the {@link FPSetManager} correctly terminates if all nested FPSets fail
	 */
	@Test
	public void testFailoverTerminationPutBlockConcurrent() throws RemoteException {
		int expectedNumOfServers = 2;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		dfm.register(new FaultyFPSet(), "TestFPSet1");
		dfm.register(new FaultyFPSet(), "TestFPSet2");
		
		final int numOfServers = dfm.numOfServers();
		

		// LongVec has to have same size of IFPSetManager#numServers (putBlock
		// method contract)
		final LongVec[] fps = new LongVec[numOfServers]; 
		fps[0] = new LongVec();
		fps[0].addElement(0L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 0, dfm.getFPSetIndex(0L));
		fps[1] = new LongVec();
		fps[1].addElement(1L);
		assertEquals("Assert fingerprint corresponds to TestFPSet", 1, dfm.getFPSetIndex(1L));
		
		/* Test DFM correctly behaves first time when TestFPSet works as expected */
		final ExecutorService es = Executors.newCachedThreadPool();
		try {
			BitVector[] bvs = dfm.putBlock(fps, es);
			assertEquals(1, bvs[0].trueCnt());
			assertEquals(1, bvs[1].trueCnt());
			
			bvs = dfm.containsBlock(fps, es);
			// all (the same) fingerprints are now known (meaning corresponding
			// bit in bvs[x] is zero).
			assertEquals(0, bvs[0].trueCnt());
			assertEquals(0, bvs[1].trueCnt());
			
			/*
			 * Test DFM correctly fails over to successor of TestFPSet (Here one can
			 * observe the behavior that a fingerprint is thought to be new when a
			 * FPSet crashes).
			 */
			
			bvs = dfm.putBlock(fps, es);
			assertEquals(2, bvs[0].trueCnt()); // fingerprint is unknown after fpset crash
			assertEquals(2, bvs[1].trueCnt());
			
			// The previous putBlock call has caused the FPSetManager to detect the
			// failure state of both FPSets
			assertEquals(0, dfm.numOfAliveServers());
			
			bvs = dfm.containsBlock(fps, es);
			assertEquals(2, bvs[0].trueCnt()); // fingerprint is known again
			assertEquals(2, bvs[1].trueCnt());
		} finally {
			es.shutdown();
		}
	}
	
	/**
	 * Tests if the {@link FPSetManager} returns the BitVector[] with correct
	 * order.
	 * <p>
	 * Due to the nature of concurrency, this test can pass by chance (inversely
	 * proportional probability to expectedNumOfServers). However, repeatedly
	 * test execution is expected to fail most of the time if
	 * {@link DynamicFPSetManager} is indeed faulty (pay attention to
	 * intermittent test failures).
	 */
	@Test
	public void testPutBlockConcurrentOrder() throws IOException {
		int expectedNumOfServers = 20;
		final DynamicFPSetManager dfm = new DynamicFPSetManager(expectedNumOfServers);
		
		// expectedNumOfServers - 1 empty fpsets
		for (int i = 0; i < expectedNumOfServers - 1; i++) {
			dfm.register(new MemFPSet(), "TestFPSet" + i);
		}

		final long fp = 1L;
		
		// add a single non-empty fpset at the last position
		FPSet nonEmptyFPSet = new MemFPSet();
		nonEmptyFPSet.put(fp);
		dfm.register(nonEmptyFPSet, "localhost");
		
		
		final LongVec[] fps = new LongVec[expectedNumOfServers]; 
		for (int i = 0; i < expectedNumOfServers; i++) {
			fps[i] = new LongVec();
			fps[i].addElement(fp);
		}
		
		// Check if the last element in the resulting bitvector has the bit for the fp set
		final ExecutorService es = Executors.newCachedThreadPool();
		try {
			final BitVector[] bvs = dfm.containsBlock(fps, es);
			// The first expectedNumOfServers - 1 must not contain the fp
			for (int i = 0; i < expectedNumOfServers - 1; i++) {
				assertEquals(1, bvs[i].trueCnt());
			}

			// The last element is expected to contain the fingerprint
			assertEquals(0, bvs[expectedNumOfServers - 1].trueCnt());
		} finally {
			es.shutdown();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SymbolTable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import tla2sany.utilities.Stack;
import tla2sany.utilities.Vector;
import util.UniqueString;

// The Symbol Table builds the stack of context tables.  The stack
// model for symbol resolution is straightforward, but not
// necessarily very efficient as we may create and push a lot of
// contexts as inner modules contexts, LET expression contexts, bound
// variable contexts, and formal parameter contexts.

// The context at the bottom of the stack initially is a copy of the
// built-in symbols.  All top level definitions of the module will be
// added to it, to become eventually the global context of this
// module (including symbols added by Extends and Instance)

public class SymbolTable implements ASTConstants {

   
  private Stack               contextStack;  
     // A SymbolTable is a stack of contexts.  New contexts are
     // pushed on the stack for LET, for formal param lists, 
     // for bound variables sets, and for inner modules
  private Context             topContext;    
     // The top context on the stack
  private Context             baseContext;   
    // The bottom context on the stack; holds builtin op symbols
    //   and also all top-level symbols of External module
  private ExternalModuleTable mt;            
    // The ExternalModuleTable for the spec to which THIS
    //   SymbolTable and its external module belongs
  private ModuleNode          modNode;       
    // The ModuleNode of the module (internal or external)
    //   with which THIS SymbolTable is associated
  private Errors              errors;        
    // The Errors object to which error messages involving
    //   THIS SymbolTable should be appended.

  // This form for external modules
  public SymbolTable( ExternalModuleTable mt, Errors errs ) {
    // Makes copy of context containing built-in symbols:
    topContext = Context.getGlobalContext().duplicate(mt);
    baseContext = topContext;

    errors = errs;
    contextStack = new Stack();
    contextStack.push( topContext );
    this.mt = mt;
  };

  // This form for internal modules
  public SymbolTable(ExternalModuleTable mt, Errors errs, SymbolTable st) {
    modNode = st.modNode;
    errors = errs;
    contextStack = new Stack();
    for (int i = 0; i < st.contextStack.size(); i++) {
      contextStack.push( st.contextStack.elementAt( i ) );
    }
    baseContext = (Context)contextStack.elementAt(0);
    this.mt = mt;
  }

  // Return the Outer context for this external module, i.e. builtin symbols,
  // and all symbols declared or defined in that module (but not in inner
  // modules, or param lists, or bound var lists, or LET clauses)
  public final Context getExternalContext() { return baseContext; }

  public final Context getContext() { return topContext; }

  public final void pushContext( Context ct ) {
    contextStack.push( ct ); 
    topContext = ct;
  }

  public final void popContext() {
    contextStack.pop();
    topContext = (Context) contextStack.peek();
  }

  public final void setModuleNode(ModuleNode mn) { modNode = mn; }

  public final ModuleNode getModuleNode() { return this.modNode; }

  /*************************************************************************
  * Looks up `name' in the symbol table and returns the node it finds, or  *
  * null if there is no entry for `name'.                                  *
  *************************************************************************/
	public final SymbolNode resolveSymbol(UniqueString name) {
		for (int c = contextStack.size() - 1; c >= 0; c--) {
			Context ct = (Context) contextStack.elementAt(c);
			SymbolNode r = ct.getSymbol(name);
			if (r != null)
				return r;
		}
		return null;
	}

  public final ModuleNode resolveModule(UniqueString name) {
    ModuleName modName = new ModuleName(name);

    for (int c = contextStack.size()-1; c >= 0; c--) {
      Context ct = (Context)contextStack.elementAt(c);
      SymbolNode res = ct.getSymbol(modName);
      if (res != null) return (ModuleNode)res;
    }

    // See if "name" refers to an external module
    return mt.getModuleNode(name);
  }
  
  /**
   * The addSymbol method attempts to bind the name "name" to the
   * SymbolNode "symbol" in THIS SymbolTable, and returns true if that
   * succeeds, i.e. if the name was previously unbound, or if the
   * declaration causing symbol to be bound to "name" is the same
   *
   * In other cases, it appends a message to "errors" and returns false.
   * 
   * As of 31 Oct 2012, the return value was not used by any calling method.
   */
  public final boolean addSymbol(UniqueString name, SymbolNode symbol) {
    SymbolNode currentBinding = resolveSymbol(name);
// System.out.println("*** Resolving " + name.toString() + ", in binding ");
    // If "name" is already bound to the argument "symbol", then
    // nothing needs to be done; this call is redundant
    if (currentBinding == symbol) { return true; }
// System.out.println("*** No matching same symbol " + name.toString());

    // If "name" was not already present in THIS SymbolTable, then add
    // it and bind it to "symbol"
    if (currentBinding == null)  { 
      topContext.addSymbolToContext(name, symbol);
      return true;
    }

// System.out.println("*** Was found in symbol table " + symbol.getKind());

    // If the currentBinding is to a different SymbolNode that does
    // not have the same kind or arity as "symbol" then this is
    // definitely an erroneous duplicate definition.  Also, even if it
    // *IS* the same kind and arity, if we are attempting to bind a
    // name to a FormalParamNode when that name has already been used
    // then that is an error, since formal param names must be "new".
    if (symbol.getKind() == FormalParamKind ||
	symbol.getKind() == BoundSymbolKind ||
	currentBinding.getKind() != symbol.getKind() ||
        currentBinding.getArity() != symbol.getArity()) {
      errors.addError(symbol.getTreeNode().getLocation(),
		      "Multiply-defined symbol '" + name +
                      "': this definition or declaration conflicts \nwith the one at " +
                      currentBinding.getTreeNode().getLocation().toString() + ".");
      return false;
    }
// System.out.println("*** Was found in symbol table " + symbol.getKind());
 
    // If the symbol being redefined is a built-in symbol, this is definitely an error
    if (currentBinding.getTreeNode().getLocation().source().equals("--TLA+ BUILTINS--")) {
      errors.addError(symbol.getTreeNode().getLocation(),
		      "Symbol " + name + " is a built-in operator, and cannot be redefined.");  
      return false;
    } 

// The following test is misguided. The problem we need to worry about is merging symbols
// from the same module twice or more through EXTENDS or INSTANCE. Not multiple definitions.

    // If "name" resolves to a different SymbolNode than "symbol", 
    // but of the same kind and arity, and is not a FormalParamNode,
    // then we must test to see if the new definition 
    // is the "same" definition or "different".

// System.out.println("*** We made it here " + symbol.getKind());
    // If the two decls or defs of the same name originate in the same
    // original, parameter-free external module, then they are clearly
    // "the same" and no error or warning is necessary.
//     if (symbol instanceof OpDefOrDeclNode &&
//         ((OpDefOrDeclNode)symbol).getOriginallyDefinedInModuleNode() == 
// 	((OpDefOrDeclNode)currentBinding).getOriginallyDefinedInModuleNode() &&
// 	((OpDefOrDeclNode)currentBinding).getOriginallyDefinedInModuleNode().isParameterFree()) {
//       return true;
//     }

// System.out.println("*** Not legitimate duplicate " + symbol.getKind());
    /*
    // Debug
    System.out.println("\nsymbol '" + symbol.getName() + "' originally defined in: " + 
                       ((OpDefOrDeclNode)symbol).getOriginallyDefinedInModuleNode().getName() +
                       "\ncurrentBinding '" + currentBinding.getName() + "' originally defined in: " +
                       ((OpDefOrDeclNode)currentBinding).getOriginallyDefinedInModuleNode().getName() );
    System.out.println("Module '" +
		       ((OpDefOrDeclNode)currentBinding).getOriginallyDefinedInModuleNode().getName() +
		       "' parameter free?  " +
		       ((OpDefOrDeclNode)currentBinding).getOriginallyDefinedInModuleNode().isParameterFree());
    */
    

    // If we survive the above tests, however, then this is a case of
    // multiple definitions.  We report this as a warning unless both definitions
    // come from the same module.  
    // Test for same module added by LL on 31 Oct 2012 to fix problem caused by
    // the same module being both EXTENDed and imported with a LOCAL INSTANCE.  
    // Previously, it always added the warning.
    if (symbol.sameOriginallyDefinedInModule(currentBinding)) {
        return true ;
    }
    errors.addWarning(symbol.getTreeNode().getLocation(), 
		      "Multiple declarations or definitions for symbol " + name +
		      ".  \nThis duplicates the one at " +
		      currentBinding.getTreeNode().getLocation().toString()
		      + "."
		      // This part of message commented out by LL on 24 Oct 2009
//		      The original declaration or definition will be used, " +
//		      "and this one will be ignored." 
		      ); 

    return true; 
  } // end addSymbol() 

  public final boolean addModule(UniqueString name, ModuleNode symbol) {
    SymbolNode currentBinding = resolveModule(name);

    // If "name" is already bound to the argument "symbol", then
    // nothing needs to be done; this call is redundant
    if (currentBinding == symbol) { return true; }

    // If "name" was not already present in THIS SymbolTable, then add
    // it and bind it to "symbol"
    if (currentBinding == null)  {
      ModuleName modName = new ModuleName(name);
      topContext.addSymbolToContext(modName, symbol);
      return true;
    }

    errors.addError(symbol.getTreeNode().getLocation(),
		    "Multiply-defined module '" + name +
		    "': this definition or declaration conflicts \nwith the one at " +
		    currentBinding.getTreeNode().getLocation().toString() + ".");
    return false;
  }
  
  // return a string with all symbols in all contexts, from top to bottom
  public String toString() {
    String ret = "\n\n***SymbolTable\n\n*** top context";

    for (int c = contextStack.size()-1; c >= 0; c--) {
      Context ct = (Context) contextStack.elementAt(c);
      Vector v = ct.getContextEntryStringVector(1,true);

      for (int i = 0; i < v.size(); i++) {
        ret += (String)v.elementAt(i);
      }
      ret += "\n\n*** next context\n";
    }
    return ret; 
  }

  static class ModuleName {
    UniqueString name;

    ModuleName(UniqueString name) {
      this.name = name;
    }

    public final int hashCode() { return this.name.hashCode(); }

    public final boolean equals(Object obj) {
      return ((obj instanceof ModuleName) &&
	      this.name.equals(((ModuleName)obj).name));
    }

    public final String toString() {
      return this.name.toString();
    }
	
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/NewSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.HashMap;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.progress.UIJob;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.ui.wizard.NewSpecWizard;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Command handler for new Specifications
 * 
 * @author zambrovski
 */
public class NewSpecHandler extends AbstractHandler implements IHandler
{

    public static final String COMMAND_ID = "toolbox.command.spec.new";
	public static final String PARAM_PATH = "toolbox.command.spec.new.param";

    /**
     * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);

        // Create the wizard
        NewSpecWizard wizard = new NewSpecWizard(event.getParameter(PARAM_PATH));
        // we pass null for structured selection, cause we just not using it
        wizard.init(window.getWorkbench(), null);
        Shell parentShell = window.getShell();
        // Create the wizard dialog
        WizardDialog dialog = new WizardDialog(parentShell, wizard);
        dialog.setHelpAvailable(true);
        
        // Open the wizard dialog
        if (Window.OK == dialog.open() && wizard.getRootFilename() != null)
        {
        	// read UI values from the wizard page
        	final boolean importExisting = wizard.isImportExisting();
        	final String specName = wizard.getSpecName();
        	final String rootFilename = wizard.getRootFilename();
            
            // the moment the user clicks finish on the wizard page does
            // not correspond with the availability of the spec object
            // it first has to be created/parsed fully before it can be shown in
            // the editor. Thus, delay opening the editor until parsing is done.        	
            createModuleAndSpecInNonUIThread(rootFilename, importExisting, specName);
        }

        return null;
    }

	/**
     * This triggers a build which might even be blocked due to the job
     * scheduling rule, hence decouple and let the UI thread continue.
	 * @param lock 
	 */
	private void createModuleAndSpecInNonUIThread(final String rootFilename,
			final boolean importExisting, final String specName) {
		Assert.isNotNull(rootFilename);
		Assert.isNotNull(specName);
		
		final Job job = new NewSpecHandlerJob(specName, rootFilename, importExisting);
		job.schedule();
	}
	
	public static class NewSpecHandlerJob extends ToolboxJob {

		private final String specName;
		private final String rootFilename;
		private final boolean importExisting;

		public NewSpecHandlerJob(String specName, String rootFilename, boolean importExisting) {
			super("NewSpecWizard job");
			this.specName = specName;
			this.rootFilename = rootFilename;
			this.importExisting = importExisting;
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			final IProject project = ResourceHelper.getProject(specName);
			if (project.exists() && Activator.getSpecManager().getSpecByName(specName) == null) {
				// There exists a project by that name already without
				// a corresponding spec instance. This is most likely
				// the result of an earlier delete that went south. Ask the user
				// if the project should be deleted.
				Activator.getSpecManager().addSpec(new Spec(project, project.getFile("Delete me")));
				UIHelper.runUIAsync(new Runnable() {
					public void run() {
						// This refresh should not be necessary when the
						// ToolboxExplorer would correctly listen for the spec
						// created event fired by the spec manager.
						ToolboxExplorer.refresh();
					}
				});
				return new Status(Status.ERROR, "org.lamport.tla.toolbox",
						String.format(
								"The workspace already contains a spec by the name '%1$s' located at '%2$s'. "
										+ "Please delete the spec '%1$s [ %3$s ]' from the Spec Explorer. "
										+ "Afterwards, try to create your new spec again.\n"
										+ "If there is no spec '%1$s [ %3$s ]' in the Spec Explorer, then "
										+ "this is a bug. Please file a bug report and choose a different "
										+ "specification name when you create a new spec in the meantime.",
								specName, project.getLocation().toOSString(), "Delete me"));
			}
			
			// if the root file does not exist, a module has to be created
			final IPath rootNamePath = new Path(rootFilename);
			try {
				if (!rootNamePath.toFile().exists()) {
					IWorkspaceRunnable createTLAModuleCreationOperation = ResourceHelper
							.createTLAModuleCreationOperation(rootNamePath);
					ResourcesPlugin.getWorkspace().run(createTLAModuleCreationOperation, monitor);
				}
				
				// create and add spec to the spec manager
				final Spec spec = Spec.createNewSpec(specName, rootFilename, importExisting, monitor);
				Activator.getSpecManager().addSpec(spec);

				// open editor since the spec has been created now
				openEditorInUIThread(spec);
			} catch (final CoreException e) {
				final String message = "Error creating module " + rootNamePath;
				Activator.getDefault().logError(message, e);
				// exception, no chance to recover
				return new Status(Status.ERROR, "org.lamport.tla.toolbox", message, e);
			}

			return Status.OK_STATUS;
		}

		/**
		 * Opens the editor for the given spec (needs access to the UI thus has to
		 * run as a UI job)
		 */
		private void openEditorInUIThread(final Spec spec) {
			// with parsing done, we are ready to open the spec editor
			final UIJob uiJob = new UIJob("NewSpecWizardEditorOpener") {
				@Override
				public IStatus runInUIThread(final IProgressMonitor monitor) {
		            // create parameters for the handler
		            final HashMap<String, String> parameters = new HashMap<String, String>();
		            parameters.put(OpenSpecHandler.PARAM_SPEC, spec.getName());

		            // runs the command
		            UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
					return Status.OK_STATUS;
				}
			};
			uiJob.schedule();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/module/TLCTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.module;

import java.util.HashSet;
import java.util.Set;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import tlc2.util.FP64;
import tlc2.value.impl.Enumerable;
import tlc2.value.impl.FcnRcdValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.TupleValue;
import tlc2.value.impl.Value;
import tlc2.value.impl.ValueEnumeration;

public class TLCTest {

	@BeforeClass
	public static void setup() {
		FP64.Init();
	}
	
	/**
	 * func2 == <<1,2,3>>
	 * ASSUME (3 :> 11 @@ func2) = <<1,2,11>>
	 */
	@Test
	public void testA() {
		final Value f = new FcnRcdValue(new Value [] { IntValue.gen(3) }, new Value [] { IntValue.gen(11) }, true);
		final Value g = new TupleValue(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(3) });

		final Value  combined = TLC.CombineFcn(f, g);
		Assert.assertTrue(combined instanceof FcnRcdValue);
		final FcnRcdValue rcdVal = (FcnRcdValue) combined;
		// Have to normalize to bring values/domain into natural order expected by assertions below
		rcdVal.normalize();

		// domain
		Assert.assertEquals(3, rcdVal.domain.length);
		Assert.assertArrayEquals(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(3) }, rcdVal.domain);

		// values
		Assert.assertEquals(3, rcdVal.values.length);
		Assert.assertArrayEquals(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(11) }, rcdVal.values);
	}

	/**
	 * func2 == <<1,2,3>>
	 * ASSUME (4 :> 11 @@ func2) = <<1,2,3,11>>
	 */
	@Test
	public void testB() {
		final Value f = new FcnRcdValue(new Value [] { IntValue.gen(4) }, new Value [] { IntValue.gen(11) }, true);
		final Value g = new TupleValue(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(3), IntValue.gen(11) });

		final Value  combined = TLC.CombineFcn(f, g);
		Assert.assertTrue(combined instanceof FcnRcdValue);
		final FcnRcdValue rcdVal = (FcnRcdValue) combined;
		// Have to normalize to bring values/domain into natural order expected by assertions below
		rcdVal.normalize();
		
		// domain
		Assert.assertEquals(4, rcdVal.domain.length);
		Assert.assertArrayEquals(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(3), IntValue.gen(4) },
				rcdVal.domain);

		// values
		Assert.assertEquals(4, rcdVal.values.length);
		Assert.assertArrayEquals(new Value [] { IntValue.gen(1), IntValue.gen(2), IntValue.gen(3), IntValue.gen(11) },
				rcdVal.values);
	}

	@Test
	public void testPermutations() {
		final SetEnumValue in = (SetEnumValue) new IntervalValue(1, 5).toSetEnum();
		Assert.assertEquals(5, in.size());
		
		final Value  permutations = TLC.Permutations(in);
		Assert.assertTrue(permutations instanceof Enumerable);
		Assert.assertEquals(120, permutations.size());

		final Set<Value > values = new HashSet<>(permutations.size());
		
		final ValueEnumeration elements = ((Enumerable) permutations).elements();
		Value  val = null;
		while ((val = elements.nextElement()) != null) {
			Assert.assertEquals(in.size(), val.size());
			values.add(val);
		}
		
		Assert.assertEquals(120, values.size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/DotLivenessStateWriter.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import java.io.IOException;

import tlc2.tool.TLCState;
import tlc2.util.BitVector;
import tlc2.util.DotStateWriter;
import tlc2.util.IStateWriter;

public class DotLivenessStateWriter extends DotStateWriter implements ILivenessStateWriter {
	
	public DotLivenessStateWriter(IStateWriter aStateWriter) throws IOException {
		super(aStateWriter.getDumpFileName().replace(".dot", "_liveness.dot"), "");
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILivenessStateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.liveness.TBGraphNode)
	 */
	public void writeState(TLCState state, TBGraphNode tableauNode) {
		
		// Marker the state as an initial state by using a filled style.
		this.writer.append("\"");
		this.writer.append(Long.toString(state.fingerPrint()));
		this.writer.append(".");
		this.writer.append(Integer.toString(tableauNode.getIndex()));
		this.writer.append("\"");
		this.writer.append(" [style = filled]");
		this.writer.append(" [label=\"");
		this.writer.append(states2dot(state));
		this.writer.append("\n#" + Long.toString(state.fingerPrint()) + "."
				+ tableauNode.getIndex() + "#");
		this.writer.append("\"]");
		this.writer.append("\n");
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILivenessStateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.liveness.TBGraphNode, tlc2.tool.TLCState, tlc2.tool.liveness.TBGraphNode, boolean)
	 */
	public void writeState(TLCState state, TBGraphNode tableauNode, TLCState successor,
			TBGraphNode tableauNodeSuccessor, BitVector actionChecks, int from, int length, boolean successorStateIsNew) {
		writeState(state, tableauNode, successor, tableauNodeSuccessor, actionChecks, from, length, successorStateIsNew, Visualization.DEFAULT);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILivenessStateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.liveness.TBGraphNode, tlc2.tool.TLCState, tlc2.tool.liveness.TBGraphNode, boolean, tlc2.util.IStateWriter.Visualization)
	 */
	public void writeState(TLCState state, TBGraphNode tableauNode, TLCState successor,
			TBGraphNode tableauNodeSuccessor, BitVector actionChecks, int from, int length, boolean successorStateIsNew, Visualization visualization) {

		final String successorsFP = Long.toString(successor.fingerPrint());

		// Write the transition
		this.writer.append("\"");
		this.writer.append(Long.toString(state.fingerPrint()));
		this.writer.append(".");
		this.writer.append(Integer.toString(tableauNode.getIndex()));
		this.writer.append("\"");
		this.writer.append(" -> ");
		this.writer.append("\"");
		this.writer.append(successorsFP);
		this.writer.append(".");
		this.writer.append(Integer.toString(tableauNodeSuccessor.getIndex()));
		this.writer.append("\"");
		if (visualization == Visualization.STUTTERING) {
			this.writer.append(" [style=\"dashed\"]");
		}
		if (visualization == Visualization.DOTTED) {
			this.writer.append(" [style=\"dotted\"]");
		}
		if (length > 0) {
			this.writer.append(" [label=\"" + actionChecks.toString(from, length, 't', 'f') + "\"]");
		}
		this.writer.append(";\n");

		// If the successor is new, print the state's label. Labels are printed
		// when writeState sees the successor. It does not print the label for
		// the current state. If it would print the label for the current state,
		// the init state labels would be printed twice.
		if (successorStateIsNew) {
			// Write the successor's label
			this.writer.append("\"");
			this.writer.append(successorsFP);
			this.writer.append(".");
			this.writer.append(Integer.toString(tableauNodeSuccessor.getIndex()));
			this.writer.append("\"");
			this.writer.append(" [label=\"");
			this.writer.append(states2dot(successor));
			this.writer.append(
					"\n#" + Long.toString(successor.fingerPrint()) + "."
							+ tableauNodeSuccessor.getIndex() + "#");
			this.writer.append("\"]");
			this.writer.append(";\n");
		}
	}

	protected static String tableauNode2dot(final TBGraphNode tableauNode) {
		// Replace "\" with "\\" and """ with "\"".	
		return tableauNode.toString().replace("\\", "\\\\").replace("\"", "\\\"").trim();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jnlp/src/org/lamport/tla/toolbox/distributed/IndexServlet.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation. All rights reserved.
package org.lamport.tla.toolbox.distributed;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IndexServlet extends URLHttpServlet {
	private static final long serialVersionUID = -653938914619406447L;
	private static final String TLA2TOOLS_JAR = "tla2tools.jar";

	
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
		super.doGet(req, resp);

		resp.setContentType("text/html");

		final PrintWriter writer = resp.getWriter();
		writer.println("<!DOCTYPE html>");

		writer.println(
				"<html><head>\n" + 
						"<title>Distributed TLC</title>\n" + 
				"</head><body>");
		
		// boostrap JRE on Windows systems
		writer.println(
				"<object codebase=\"http://java.sun.com/update/1.7.0/jinstall-7u80-windows-i586.cab#Version=7,0,0,0\" classid=\"clsid:5852F5ED-8BF4-11D4-A245-0080C6F74284\" height='0' width='0'>" +
						"<param name=\"app\" value=\"" + addr + "\"/>" +
						"<param name=\"back\" value=\"false\"/>" +
				"</object>");
		
		writer.println(
				"<p style=\"margin: 12px 20px;\">" +
				"<b>Please note:</b> " +
				"Starting with the 1.7.0 release of the Toolbox, we have removed the JNLP functionality previously " +
				"found on this page. This is due to our move towards full Java 11+ usage (support for Java WebStart " +
				"was removed beginning with Java 9.)" + 
				"<br/>" +
				"<ul>" + 
				"<li>If you found the JNLP functionality to be critical to your usage, please open an issue at " +
				"<a href=\"https://github.com/tlaplus/tlaplus/issues\" target=_blank>our GitHub repository.</a></li>" +
				"<li>If you would like to take over development and deployment support for the JNLP related " +
				"functionality, please contact us.</li>" +
				"</ul>" + 
				"</p>" +
				"<hr style=\"margin-left: auto; margin-right: auto; width: 67%\"/>");
		
		// TLC worker
		printTable(writer, JNLPGeneratorServlet.JNLP, JNLPGeneratorServlet.MAINCLASS, "worker",
				JNLPGeneratorServlet.INDEX_DESC);

		// Fingerprint server
		printTable(writer, FPSetJNLPGeneratorServlet.JNLP, FPSetJNLPGeneratorServlet.MAINCLASS, "fingerprint set",
				FPSetJNLPGeneratorServlet.INDEX_DESC);
		
		// Combined fingerprint server and TLC worker
		printTable(writer, CombinedJNLPGeneratorServlet.JNLP, CombinedJNLPGeneratorServlet.MAINCLASS, "combined",
				CombinedJNLPGeneratorServlet.INDEX_DESC);
		
		// d) dist-tlc.zip OSGi fw that acts as a TLCWorker daemon
		writer.println(
				"<table id=\"header\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\">\n" + 
					"<p style=\"font-size: 125%; font-weight: 700;\">Start a daemon-stlye TLCWorker (no need " +
						"to restart the worker for each model checker run)</p>\n" + 
					"<tr><td>\n" + 
					"<ul>");
			
		writer.println(
				"<li>\n" + 
					"<p>Run from slave command line (works best with <a href=\"http://www.oracle.com/technetwork/java/javase/downloads/index.html\">Java 8</a>):</p>\n" + 
					// Linux
					"<h4>bash</h4>" +
					"<pre>\n" + 
						"wget <a href=\"" + addr + "/files/dist-tlc.zip\">" + addr + "/files/dist-tlc.zip</a>\n" + 
						"unzip dist-tlc.zip\n" + 
						"cd disttlc/\n" + 
						 "java -Djava.rmi.server.hostname="
														+ remoteAddr
														+ " -Dorg.lamport.tla.distributed.consumer.TLCWorkerConsumer.uri=rmi://"
														+ url.getHost()
														+ ":10997 "
//														+ "-Dorg.lamport.tla.distributed.consumer.DistributedFPSetConsumer.uri=rmi://"
//														+ url.getHost()	+ ":10997 "
														+ "-jar dist-tlc.jar "
														+					"\n</pre>\n" + 
					// Windows Powershell 2.0 with manually created C:\\tmp folder ($env:temp does not seem to work) and x86 Java installed in default location
					"<h4>Windows Powershell 2.0:</h4>" +
					"<pre>\n" + 
						"(new-object System.Net.WebClient).DownloadFile(\"" + addr + "/files/dist-tlc.zip\", \"C:\\tmp\\dist-tlc.zip\")\n" + 
						"(new-object -com shell.application).namespace(\"C:\\tmp\").CopyHere((new-object -com shell.application).namespace(\"C:\\tmp\\dist-tlc.zip\").Items(),16)\n" +
						 "& 'C:\\Program Files (x86)\\Java\\jre7\\bin\\java.exe' \"-Djava.rmi.server.hostname="
														+ remoteAddr
														+ "\" \"-Dorg.lamport.tla.distributed.consumer.TLCWorkerConsumer.uri=rmi://"
														+ url.getHost()
														+ ":10997\" "
//														+ "\"-Dorg.lamport.tla.distributed.consumer.DistributedFPSetConsumer.uri=rmi://"
//														+ url.getHost()	+ ":10997\" "
														+ "-jar C:\\tmp\\disttlc\\dist-tlc.jar"
														+				"\n</pre>\n" + 
				"</li>");
		writer.println(
				"</ul>\n" + 
				"</td></tr></table>\n");
		
		writer.println(
				"</body></html>");
	}

	private void printTable(final PrintWriter writer, final String jnlpName, final String mainClass, final String name, final String description) throws IOException {
		writer.println(
				"<table id=\"header\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\">\n" + 
					"<p style=\"font-size: 125%; font-weight: 700;\">" + description + "</p>\n" + 
					"<tr><td>\n");// + 
//					"<ul>");
			
		// a) direct link
//		writer.println(
//				"<li>\n" + 
//						"<p><a href=\"" + jnlpName + "\" id=\"jnlp-link\"><img alt=\"launch FPSet\" src=\"/files/webstart.gif\" /> Launch "
//								+ name + " from browser</a></p>\n" + 
//				"</li>");
		
		// b) command line
//		writer.println(
//				"<li>\n" + 
//					"<p>Run from slave command line:</p>\n" + 
//					"<p><pre>" + 
//						"javaws " + addr + "/" + jnlpName +
//					"</pre></p>\n" + 
//				"</li>");
		
		// c) headless
		writer.println(
//				"<li>\n" + 
//					"<p>Or if the slave is headless:</p>\n" + 
					"<pre>\n" + 
						"wget " + addr + "/files/" + TLA2TOOLS_JAR + "\n" + 
						"java -Djava.rmi.server.hostname=" + remoteAddr
								+ " -cp <a href=\"/files/" + TLA2TOOLS_JAR + "\">" + TLA2TOOLS_JAR + "</a> " + mainClass
						+ " " + url.getHost() + "\n" +
					"</pre>\n"); // + 
//				"</li>");
		
		writer.println(
//				"</ul>\n" + 
				"</td></tr></table>\n" +
				"<hr style=\"margin-left: auto; margin-right: auto; width: 67%\"/>");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/FPSetRMI.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:13:35 PST by lamport
//      modified on Fri Dec 15 15:24:57 PST 2000 by yuanyu
package tlc2.tool.distributed.fp;

import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;

import tlc2.tool.TLCTrace;
import tlc2.tool.fp.FPSet;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

/**
 * @author <NAME>
 */
/**
 * @author markus
 *
 */
public interface FPSetRMI extends Remote {

	void addThread() throws IOException;

	void beginChkpt() throws IOException;

	void beginChkpt(String filename) throws IOException;

	/**
	 * @return The minimum distance of all fingerprints in this {@link FPSet}.
	 *         This distance reflects the probability of a fingerprint
	 *         collision.
	 */
	long checkFPs() throws IOException;
	
	/**
	 * @see FPSet#checkInvariant()
	 */
	boolean checkInvariant() throws IOException;
	
	/**
	 * Disposes this {@link FPSet}. It cannot be used afterwards anymore.
	 * 
	 * @see FPSetRMI#exit(boolean)
	 */
	void close() throws RemoteException;

	void commitChkpt() throws IOException;

	void commitChkpt(String filename) throws IOException;

    /**
     * Returns <code>true</code> iff the fingerprint <code>fp</code> is
     * in this {@link FPSet}.
     */
	boolean contains(long fp) throws IOException;

	/**
	 * Checks existence in the {@link FPSet} for each fingerprints contained in
	 * the given {@link LongVec}.
	 * <p>
	 * Contrary to {@link FPSet#contains(long)}, bits in the resulting
	 * {@link BitVector} are set if the fingerprints are _not_ in this
	 * {@link FPSet}.
	 * 
	 * @see FPSetRMI#contains(long)
	 */
	BitVector containsBlock(LongVec fpv) throws IOException;

	/**
	 * Disposes this {@link FPSet}. The {@link FPSet} will be unusable after
	 * calling {@link FPSet#exit(boolean)}.
	 * 
	 * @param cleanup
	 *            if disk storage used by the {@link FPSet} should be removed
	 */
	void exit(boolean cleanup) throws IOException;

	/**
	 * @return The amount of states seen by this FPSet (not distinct states!)
	 */
	long getStatesSeen() throws RemoteException;

    /**
     * Returns <code>true</code> iff the fingerprint <code>fp</code> is
     * in this set. If the fingerprint is not in the set, it is added to
     * the {@link FPSet} as a side-effect.
     */
	boolean put(long fp) throws IOException;

	/**
	 * Checks existence in the {@link FPSet} for each fingerprints contained in
	 * the given {@link LongVec}. As a side-effect, new fingerprints are added
	 * to the {@link FPSet}.
	 * <p>
	 * Contrary to {@link FPSet#put(long)}, bits in the resulting
	 * {@link BitVector} are set if the fingerprints have _not_ been in this
	 * {@link FPSet}.
	 * 
	 * @see FPSet#put(long)
	 */
	BitVector putBlock(LongVec fpv) throws IOException;

	void recover(TLCTrace trace) throws IOException;

	void recover(String filename) throws IOException;

	/**
	 * @return Corresponds to the amount of distinct states seen by this
	 *         {@link FPSet} instance (if only a single {@link FPSet} is used
	 *         for model checking, this number corresponds to the distinct
	 *         states found overall).
	 */
	long size() throws IOException;
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/wizard/AssignmentWizard.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.wizard;

import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;

import tlc2.model.Assignment;

/**
 * Wizard for editing a constant assignement
 * @author <NAME>
 */
public class AssignmentWizard extends Wizard
{
    /**
     * Currently, this flag is not used.
     */
    public final static int NONE = 0;
    /**
     * This is a flag for showing the model value,
     * ordinary assignment, set of model values,
     * and symmetric options.
     * This is currently only used by constant assignments.
     */
    public final static int SHOW_OPTION = 1;
    /**
     *  This is a flag for showing the model value
     *  and ordinary assignment options.
     *  This is currently only used by definition overrides.
     */
    public final static int SHOW_MODEL_VALUE_OPTION = 2;

    private Assignment assignment;
    private AssignmentWizardPage assignmentPage;
	private WizardDialog wizardDialog;

    /**
     * Constructs the wizard that assigns values to constants, 
     * I believe it also constructs the wizard that overrides definitions. (LL)
     * @param fieldFlags bit mask determining fields that are visible
     * @see {@link AssignmentWizard} constants 
     */
    public AssignmentWizard(String action, String description, Assignment assignment, int fieldFlags, String helpId)
    {
        super();
        this.assignment = assignment;
        this.assignmentPage = new AssignmentWizardPage(action, description, fieldFlags, helpId);

    }

    @Override
    public void addPages()
    {
        addPage(this.assignmentPage);
    }

    /**
     * retrieves the formula
     * @return
     */
    public Assignment getFormula()
    {
        return this.assignment;
    }

    /**
     * This returns whether the Finish button
     * should be enabled. In order for this to be
     * evaluated, getContainer().updateButtons() must
     * be called by the page whose buttons are to be
     * updated. For this particular wizard, that page
     * is a AssignmentWizardPage. Within the method
     * createControl a listener is added to the
     * text field which calls updateButtons() whenever
     * the input text is modified.
     */
    @Override
    public boolean canFinish()
    {
        String inputText = this.assignmentPage.getInputText();
        // either on the first page, but no typing of MV set is possible, or on the second page
        // also, if on the first page, there must be an input that is not only white space
        // Modified by LL on 5 Nov 2009 to return true regardless of inputText if the model value
        // option is selected.
        return ((inputText != null && inputText.trim().length() != 0)
        		     || this.assignmentPage.modelValueSelected());
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.wizard.Wizard#performFinish()
     */
    public boolean performFinish()
    {
        return true;
    }

	public void setWizardDialog(WizardDialog dialog) {
	    this.wizardDialog = dialog;
	}
	
	public int getWizardDialogReturnCode() {
		return this.wizardDialog.getReturnCode();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/Striped.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.util;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public final class Striped {

	public static Striped readWriteLock(final int lockCnt) {
		return new Striped(lockCnt);
	}

	private final ReadWriteLock[] locks;

	public Striped(int lockCnt) {
		this.locks = new ReadWriteLock[lockCnt];
		for (int i = 0; i < locks.length; i++) {
			locks[i] = new ReentrantReadWriteLock();
		}
	}

	public final ReadWriteLock getAt(int lockIndex) {
		return this.locks[lockIndex];
	}

	public final int size() {
		return locks.length;
	}

	public final void releaseAllLocks() {
		for (int i = size() - 1; i >= 0; i--) {
			this.locks[i].writeLock().unlock();
		}
	}

	public final void acquireAllLocks() {
		//TODO find way to do this more efficiently
		for (int i = 0; i < size(); i++) {
			this.locks[i].writeLock().lock();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/TLCWorkerRMI.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:41 PST by lamport
//      modified on Mon Jan  1 23:05:27 PST 2001 by yuanyu

package tlc2.tool.distributed;

import java.net.URI;
import java.rmi.Remote;
import java.rmi.RemoteException;

import tlc2.tool.TLCState;
import tlc2.tool.WorkerException;

/**
 * @author <NAME>
 * @version $Id$
 */
public interface TLCWorkerRMI extends Remote {

	/**
	 * @param states The initial states to work with
	 * @return The next states for the initial state wet
	 * @throws RemoteException
	 * @throws WorkerException
	 */
	public NextStateResult getNextStates(TLCState[] states) throws RemoteException,
			WorkerException;
	
	/**
	 * @return true iff worker is still alive
	 */
	public boolean isAlive() throws RemoteException;
	
	/**
	 * Kills/exits this worker
	 * @throws RemoteException
	 */
	public void exit() throws RemoteException;
	
	/**
	 * @return The {@link URI} address of this worker
	 * @throws RemoteException
	 */
	public URI getURI() throws RemoteException;

	/**
	 * @return The ratio of cache hits to cache misses
	 */
	public double getCacheRateRatio() throws RemoteException;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ExprOrOpArgNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import tla2sany.st.TreeNode;

/**
 * This class represents a semantic node that is either an OpArgNode
 * or is the root node of an expression (ExprNode).
 *
 * The reason both kinds of nodes are classified together in this
 * abstract class is that they can both be used as arguments to
 * operators and in substitutions.
 *
 * Extended by ExprNode and OpArgNode
 *
 * Further extended by AtNode, DecimalNode, LetInNode, NumeralNode,
 *                     OpApplNode, StringNode, SubstInNode
 */
public abstract class ExprOrOpArgNode extends LevelNode {

  ExprOrOpArgNode(int kind, TreeNode stn) { super(kind, stn); }
  
}


<|start_filename|>tlatools/org.lamport.tlatools.api/src/tlc2/ITLCWorker.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2;

import java.net.URI;

public interface ITLCWorker {

	/**
	 * Connects this {@link ITLCWorker} to a TLCServer at the given target {@link URI} 
	 * @param uri The target {@link URI}
	 * @return true iff connected successfully
	 */
	boolean connect(URI uri);
	
	/**
	 * Block the caller for as long as the connected worker is computing. The
	 * behavior on calling this on a disconnected worker is undefined.
	 */
	void awaitTermination();
	
	/**
	 * Disconnects from the remote TLCServer
	 * @return true iff disconnected successfully
	 */
	boolean disconnect();
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/callable/ContainsBlockCallable.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp.callable;

import java.util.List;

import tlc2.tool.distributed.fp.FPSetManager;
import tlc2.tool.distributed.fp.FPSetManager.FPSets;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

public class ContainsBlockCallable extends FPSetManagerCallable {
	
	public ContainsBlockCallable(FPSetManager fpSetManager, List<FPSets> fpSets, LongVec[] fps, int index) {
		super(fpSetManager, fpSets, fps, index);
	}
	
	/* (non-Javadoc)
	 * @see java.util.concurrent.Callable#call()
	 */
	public BitVectorWrapper call() throws Exception {
		try {
			BitVector bv = fpset.get(index).containsBlock(fps[index]);
			return new BitVectorWrapper(index, bv);
		} catch (Exception e) {
			return reassign(e);
		}
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/debug/DebugTLCVariableTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.debug;

import static org.junit.Assert.assertEquals;

import java.util.List;
import java.util.Random;

import org.junit.Test;

import tlc2.module.Strings;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.TLCVariable;
import tlc2.value.impl.TupleValue;

public class DebugTLCVariableTest {
	private static final Random rnd = new Random();

	@Test
	public void testFiniteEmptySetValue() {
		assertEquals(0, new DebugTLCVariable("4711").setInstance(new SetEnumValue()).getNested(rnd).size());
	}

	@Test
	public void testFiniteSetValue() {
		List<TLCVariable> outer = new DebugTLCVariable("4711").setInstance(new SetEnumValue(new SetEnumValue()))
				.getNested(rnd);
		assertEquals(1, outer.size());
		assertEquals(0, outer.get(0).getNested(rnd).size());
	}

	@Test
	public void testFiniteNestedValue() {
		List<TLCVariable> vars = new DebugTLCVariable("4711")
				.setInstance(new SetEnumValue(new SetEnumValue(new TupleValue(IntValue.ValZero, IntValue.ValOne))))
				.getNested(rnd);
		assertEquals(1, vars.size());

		vars = vars.get(0).getNested(rnd);
		assertEquals(1, vars.size());

		vars = vars.get(0).getNested(rnd);
		assertEquals(2, vars.size());

		for (TLCVariable var : vars) {
			assertEquals(0, var.getNested(rnd).size());
		}
	}

	@Test
	public void testInfiniteValue() {
		assertEquals(0, new DebugTLCVariable("4711").setInstance(Strings.STRING()).getNested(rnd).size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalFixIDs.java<|end_filename|>
/***************************************************************************
* CLASS PcalFixIDs                                                         *
* last modified on Wed 12 January 2011 at 18:33:34 PST by lamport          *
*      modified on Tue 24 Jan 2006 at 13:21:20 PST by lamport              *
*      modified on Tue 30 Aug 2005 at 19:30:45 UT by keith                 *
*                                                                          *
* Given an AST (not necessarily exploded), change the ids to their         *
*   disambiguated values. There is one public method in this class:        *
*                                                                          *
*   void Fix (AST ast, PcalSymTab stab)                                    *
*                                                                          *
* This also fixes the tables st.procs and st.processes.                    *
*                                                                          *
* In Jan 2011, modified the FixProcedure and FixProcess methods as         *
* part of the enhancement of Version 1.5 to allow fairness                 *
* modifiers on labels.                                                     *
****************************************************************************/

package pcal;

import java.util.Vector;

import pcal.exception.PcalFixIDException;
import pcal.exception.TLAExprException;

public class PcalFixIDs {
    private static PcalSymTab st = null;

    public static void Fix(AST ast, PcalSymTab stab) throws PcalFixIDException {
        st = stab;
        FixSym(ast, "");
        // Fix entry point for uniprocess algorithm
        if (st.iPC != null)
            st.iPC = st.UseThis(PcalSymTab.LABEL, st.iPC, "");
    }

    private static void FixSym (AST ast, String context) throws PcalFixIDException {
        if (ast.getClass().equals(AST.UniprocessObj.getClass()))
            FixUniprocess((AST.Uniprocess) ast, context);
        else if (ast.getClass().equals(AST.MultiprocessObj.getClass()))
            FixMultiprocess((AST.Multiprocess) ast, context);
        else if (ast.getClass().equals(AST.ProcedureObj.getClass()))
            FixProcedure((AST.Procedure) ast, context);
        else if (ast.getClass().equals(AST.ProcessObj.getClass()))
            FixProcess((AST.Process) ast, context);
        else if (ast.getClass().equals(AST.LabeledStmtObj.getClass()))
            FixLabeledStmt((AST.LabeledStmt) ast, context);
        else if (ast.getClass().equals(AST.WhileObj.getClass()))
            FixWhile((AST.While) ast, context);
        else if (ast.getClass().equals(AST.AssignObj.getClass()))
            FixAssign((AST.Assign) ast, context);
        else if (ast.getClass().equals(AST.SingleAssignObj.getClass()))
            FixSingleAssign((AST.SingleAssign) ast, context);
        else if (ast.getClass().equals(AST.LhsObj.getClass()))
            FixLhs((AST.Lhs) ast, context);
        else if (ast.getClass().equals(AST.IfObj.getClass()))
            FixIf((AST.If) ast, context);
        else if (ast.getClass().equals(AST.WithObj.getClass()))
            FixWith((AST.With) ast, context);
        else if (ast.getClass().equals(AST.WhenObj.getClass()))
            FixWhen((AST.When) ast, context);
        else if (ast.getClass().equals(AST.PrintSObj.getClass()))
            FixPrintS((AST.PrintS) ast, context);
        else if (ast.getClass().equals(AST.AssertObj.getClass()))
            FixAssert((AST.Assert) ast, context);
        else if (ast.getClass().equals(AST.SkipObj.getClass()))
            FixSkip((AST.Skip) ast, context);
        else if (ast.getClass().equals(AST.LabelIfObj.getClass()))
            FixLabelIf((AST.LabelIf) ast, context);
        else if (ast.getClass().equals(AST.CallObj.getClass()))
            FixCall((AST.Call) ast, context);
        else if (ast.getClass().equals(AST.ReturnObj.getClass()))
            FixReturn((AST.Return) ast, context);
        else if (ast.getClass().equals(AST.CallReturnObj.getClass()))
            FixCallReturn((AST.CallReturn) ast, context);
        else if (ast.getClass().equals(AST.CallGotoObj.getClass()))
            FixCallGoto((AST.CallGoto) ast, context);
        else if (ast.getClass().equals(AST.GotoObj.getClass()))
            FixGoto((AST.Goto) ast, context);

        /*******************************************************************
        * Handling of Either and LabelEither added by LL on 24 Jan 2006.   *
        *******************************************************************/
        else if (ast.getClass().equals(AST.EitherObj.getClass()))
            FixEither((AST.Either) ast, context);
        else if (ast.getClass().equals(AST.LabelEitherObj.getClass()))
            FixLabelEither((AST.LabelEither) ast, context);
        else PcalDebug.ReportBug("Unexpected AST type" + ast.toString());
    }

    private static void FixUniprocess (AST.Uniprocess ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.decls.size(); i++)
            FixVarDecl((AST.VarDecl) ast.decls.elementAt(i), "");
        for (int i = 0; i < ast.prcds.size(); i++)
            FixProcedure((AST.Procedure) ast.prcds.elementAt(i), "");
        for (int i =0; i < ast.body.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i), "");
    }
        
    private static void FixMultiprocess (AST.Multiprocess ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.decls.size(); i++)
            FixVarDecl((AST.VarDecl) ast.decls.elementAt(i), "");
        
        // procedureNames and proceduresCalled represents the mapping
        // from procedure Names to the set of names of procedures that
        // they call.
        Vector  procedureNames = new Vector();   // Vector of Strings
        Vector  proceduresCalled = new Vector(); // Vector of Vectors of Strings
        for (int i = 0; i < ast.prcds.size(); i++) {
            AST.Procedure prcd = (AST.Procedure) ast.prcds.elementAt(i);
            FixProcedure(prcd, "");
// System.out.println("Start\n" + prcd.toString());
            procedureNames.addElement(prcd.name);
            proceduresCalled.addElement(prcd.proceduresCalled);
        }
        // We now use the Floyd-Warshall algorithm to compute the transitive
        //  closure of the procedures' call graph, as represented by
        // the proceduresNames and proceduresCalled vectors.  This algorithm
        // is in the file FloydWarshall.tla, appended to the end of this
        // file.
        
        // We first initialize the algorithm's main variable, path, where
        // path[i][j] will be true iff the i-th procedure calls (perhaps
        // indirectly the j-th procedure.  (Java counting.)  
        //
        // On 2 April 2013, LL discovered that the initialization code actually
        // set path[i][j] true iff the j-th procedure calls the i-th procedure,
        // resulting in the proceduresCalled field of the AST.Procedure object
        // to list the procedures that call the given procedure.  He fixed this
        int n = procedureNames.size();
        boolean path[][] = new boolean[n][] ;
        for (int i=0; i < n; i++) {
            path[i] = new boolean[n];
            // following commented out 2 Apr 2013
            // String nm = (String) procedureNames.elementAt(i);
            for (int j = 0; j < n; j++) {
                // following commented out 2 Apr 2013
                // path[i][j] = (-1 != nameToNum(nm, (Vector) proceduresCalled.elementAt(j)));
                
                // following added 2 Apr 2013
                String nm = (String) procedureNames.elementAt(j);
                path[i][j] = (-1 != nameToNum(nm, (Vector) proceduresCalled.elementAt(i)));
            }
        }
        
        // Here is the main loop of the Floyd-Warshall algorithm.
        for (int k=0 ; k < n; k++) {
            for (int i = 0; i < n ; i++) {
                for (int j = 0; j < n; j++) {
                    path[i][j] = path[i][j] || (path[i][k] && path[k][j]); 
                }
            }
        }
        
        // We now set the procedures' proceduresCalled fields to the
        // set of procedures called directly or indirectly.  This is
        // unnecessary, and should be commented out.
        for (int i = 0; i < ast.prcds.size(); i++) {
            AST.Procedure prcd = (AST.Procedure) ast.prcds.elementAt(i);
            Vector pCalled = new Vector();
            for (int j = 0; j < n; j++) {
                if (path[i][j]) {
                    pCalled.addElement(procedureNames.elementAt(j));
                }
            }
            prcd.proceduresCalled = pCalled;
// System.out.println(prcd.toString());            
        }
        
        for (int i = 0; i < ast.procs.size(); i++) {
            AST.Process proc = (AST.Process) ast.procs.elementAt(i);
            FixProcess(proc, "");
            
            // We now fix proc.proceduresCalled by, for each procedure p in
            // it, we add all the procedures that p calls.
            Vector pCalled = proc.proceduresCalled;
            for (int j = 0; j < pCalled.size(); j++) {
                // Set idx to the value such that pCalled.elementAt(j)
                // is the name of the idx-th element in procedureNames.
                String pName = (String) pCalled.elementAt(j);
                int pNum = nameToNum(pName, procedureNames);
                if (pNum == -1) {
                	// For some reason, this originally called PcalDebug.ReportBug.
                	// Since it can occur just because there is no procedure by that
                	// name in the code, it occurs on an error.  Fixed 31 May 2013 by LL.
                	// This fix caused the for loop that follows to throw an ArrayIndexOutOfBounds
                	// exception.  When run from the Toolbox, this caused the error message
                	// to be lost and the Translate command to fail with no message.
                	// It appears that it's not necessary to report the error here, because
                	// it will be caught later.  Moreover, when caught later, the location
                	// of the bad procedure name is indicated.  That location doesn't seem to
                	// available here.  However, I'm hesitant to remove the error report in case
                	// the error isn't caught later in all cases.  So I have added the return
                	// to avoid the exception.  Hopefully, no further exceptions can be caused
                	// by the error.  However, I don't know how to make sure that's the
                	// case without figuring out how the code works.  
                	// I also removed an unhelpful part of the message.  LL 30 Aug 2015
                    PcalDebug.reportError(
                     "Could not find procedure name `" + pName +"'"
                     // + "' in method FixMultiprocess"
                     ) ;
                    return ; // Added 30 Aug 2015 

               }
                // For each k such that path[pNum][k] is true
                // (meaning that procedure number pNum calls
                // procedure number k), add 
                // procedureNames.elementAt(k) to proc.proceduresCalled
                // if it is not already in it.
                for (int k = 0; k < n; k++) {
                  if (path[pNum][k]) {
                      String callee = (String) procedureNames.elementAt(k);
                      if (! InVector(callee, proc.proceduresCalled)) {
                          proc.proceduresCalled.addElement(callee); 
                      }
                  }
                }
//          System.out.println(proc.toString());                
            }
        }
    }

    /**
     * If nm is the i-th element of names, then return i.  Otherwise,
     * return -1 if nm is not any element of names.
     * @return
     */
    private static int nameToNum(String nm, Vector names) {
        for (int i = 0; i < names.size(); i++) {
            if (names.elementAt(i).equals(nm)) {
                return i;
            }
        }
        return -1;
    }
    /**
     * FixProcedure modified by LL on 12 January 2011 so it also fixes the
     * plusLabels and minusLabels entries.
     * 
     * @param ast
     * @param context
     * @throws PcalFixIDException
     */
    private static void FixProcedure (AST.Procedure ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.decls.size(); i++)
            FixPVarDecl((AST.PVarDecl) ast.decls.elementAt(i), ast.name);
        for (int i = 0; i < ast.params.size(); i++)
            FixPVarDecl((AST.PVarDecl) ast.params.elementAt(i), ast.name);
        for (int i = 0; i < ast.body.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i), ast.name);
        PcalSymTab.ProcedureEntry p = 
            (PcalSymTab.ProcedureEntry)
            st.procs.elementAt(st.FindProc(ast.name));
        for (int i = 0; i < ast.plusLabels.size(); i++) {
        	String lbl = (String) ast.plusLabels.elementAt(i);
        	String newLbl = st.UseThis(PcalSymTab.LABEL, lbl, ast.name);
        	ast.plusLabels.setElementAt(newLbl, i) ;
        }
       for (int i = 0; i < ast.minusLabels.size(); i++) {
	       String lbl = (String) ast.minusLabels.elementAt(i);
	       String newLbl = st.UseThis(PcalSymTab.LABEL, lbl, ast.name);
	       ast.minusLabels.setElementAt(newLbl, i) ;
         }
        p.iPC = st.UseThis(PcalSymTab.LABEL, p.iPC, ast.name);
        ast.name = st.UseThis(PcalSymTab.PROCEDURE, ast.name, "");
        p.name = ast.name;
    }
        
    /**
     * FixProcess modified by LL on 12 January 2011 so it also fixes the
     * plusLabels and minusLabels entries.
     * @param ast
     * @param context
     * @throws PcalFixIDException
     */
    private static void FixProcess(AST.Process ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.decls.size(); i++)
            FixVarDecl((AST.VarDecl) ast.decls.elementAt(i), ast.name);
        for (int i = 0; i < ast.body.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.body.elementAt(i), ast.name);
        PcalSymTab.ProcessEntry p = 
            (PcalSymTab.ProcessEntry)
            st.processes.elementAt(st.FindProcess(ast.name));
        for (int i = 0; i < ast.plusLabels.size(); i++) {
        	String lbl = (String) ast.plusLabels.elementAt(i);
        	String newLbl = st.UseThis(PcalSymTab.LABEL, lbl, ast.name);
        	ast.plusLabels.setElementAt(newLbl, i) ;
        }
       for (int i = 0; i < ast.minusLabels.size(); i++) {
         String lbl = (String) ast.minusLabels.elementAt(i);
         String newLbl = st.UseThis(PcalSymTab.LABEL, lbl, ast.name);
         ast.minusLabels.setElementAt(newLbl, i) ;
         }
        p.iPC = st.UseThis(PcalSymTab.LABEL, p.iPC, ast.name);
        ast.name = st.UseThis(PcalSymTab.PROCESS, ast.name, "");
        p.name = ast.name;
   }

    private static void FixVarDecl(AST.VarDecl ast, String context) throws PcalFixIDException {
        ast.var = st.UseThisVar(ast.var, context);
        FixExpr(ast.val, context);
    }

    private static void FixPVarDecl(AST.PVarDecl ast, String context) throws PcalFixIDException {
        ast.var = st.UseThisVar(ast.var, context);
        FixExpr(ast.val, context);
    }

    private static void FixLabeledStmt(AST.LabeledStmt ast, String context) throws PcalFixIDException {
        ast.label = st.UseThis(PcalSymTab.LABEL, ast.label, context);
        for (int i = 0; i < ast.stmts.size(); i++)
            FixSym((AST) ast.stmts.elementAt(i), context);
    }

    private static void FixWhile(AST.While ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.unlabDo.size(); i++)
            FixSym((AST) ast.unlabDo.elementAt(i), context);
        for (int i = 0; i < ast.labDo.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.labDo.elementAt(i), context);
        /*******************************************************************
        * The following statement added by LL on 24 Jan 2006.              *
        *******************************************************************/
        FixExpr((TLAExpr) ast.test, context);
    }

    private static void FixAssign(AST.Assign ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.ass.size(); i++)
            FixSingleAssign((AST.SingleAssign) ast.ass.elementAt(i), context);
    }

    private static void FixSingleAssign(AST.SingleAssign ast, String context) throws PcalFixIDException {
        FixLhs(ast.lhs, context);
        FixExpr(ast.rhs, context);
    }

    private static void FixLhs(AST.Lhs ast, String context) throws PcalFixIDException {
        ast.var = st.UseThisVar(ast.var, context);
        FixExpr(ast.sub, context);
    }

    private static void FixIf(AST.If ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.Then.size(); i++)
            FixSym((AST) ast.Then.elementAt(i), context);
        for (int i = 0; i < ast.Else.size(); i++)
            FixSym((AST) ast.Else.elementAt(i), context);
        FixExpr((TLAExpr) ast.test, context);
   }

    private static void FixWith(AST.With ast, String context) throws PcalFixIDException {
        FixExpr(ast.exp, context);
        for (int i = 0; i < ast.Do.size(); i++)
            FixSym((AST) ast.Do.elementAt(i), context);
    }

    private static void FixWhen(AST.When ast, String context) throws PcalFixIDException {
        FixExpr(ast.exp, context);
   }

    private static void FixPrintS(AST.PrintS ast, String context) throws PcalFixIDException {
        FixExpr(ast.exp, context);
    }

    private static void FixAssert(AST.Assert ast, String context) throws PcalFixIDException {
        FixExpr(ast.exp, context);
   }

    private static void FixSkip(AST.Skip ast, String context) {
    }

    private static void FixLabelIf(AST.LabelIf ast, String context) throws PcalFixIDException {
        FixExpr(ast.test, context);
        for (int i = 0 ; i < ast.unlabThen.size(); i++)
            FixSym((AST) ast.unlabThen.elementAt(i), context);
        for (int i = 0; i < ast.labThen.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.labThen.elementAt(i), context);
        for (int i = 0; i < ast.unlabElse.size(); i++)
            FixSym((AST) ast.unlabElse.elementAt(i), context);
        for (int i = 0;  i < ast.labElse.size(); i++)
            FixLabeledStmt((AST.LabeledStmt) ast.labElse.elementAt(i), context);
    }

    private static void FixCall(AST.Call ast, String context) throws PcalFixIDException {
        ast.returnTo = st.UseThis(PcalSymTab.PROCEDURE, ast.returnTo, context);
        ast.to = st.UseThis(PcalSymTab.PROCEDURE, ast.to, context);
        for (int i = 0; i < ast.args.size(); i++)
            FixExpr((TLAExpr) ast.args.elementAt(i), context);
    }

    private static void FixReturn(AST.Return ast, String context) {
        ast.from = st.UseThis(PcalSymTab.PROCEDURE, ast.from, context);
    }

    private static void FixCallReturn(AST.CallReturn ast, String context) throws PcalFixIDException {
        ast.from = st.UseThis(PcalSymTab.PROCEDURE, ast.from, context);
        ast.to = st.UseThis(PcalSymTab.PROCEDURE, ast.to, context);
        for (int i = 0; i < ast.args.size(); i++)
            FixExpr((TLAExpr) ast.args.elementAt(i), context);
    }

    private static void FixCallGoto(AST.CallGoto ast, String context) throws PcalFixIDException {
        ast.after = st.UseThis(PcalSymTab.PROCEDURE, ast.after, context);
        ast.to = st.UseThis(PcalSymTab.PROCEDURE, ast.to, context);
        for (int i = 0; i < ast.args.size(); i++)
            FixExpr((TLAExpr) ast.args.elementAt(i), context);
    }

    private static void FixGoto(AST.Goto ast, String context) throws PcalFixIDException {
        /*
         * Report an error if the goto destination is not a label.  This check
         * added by LL on 29 Dec 2011.
         */
        if (st.FindSym(PcalSymTab.LABEL, ast.to, context) == st.symtab.size()
              && ! ast.to.equals("Done")) {
            throw new PcalFixIDException("goto to non-existent label `" + ast.to + 
                    "' at line " + ast.line + ", column " + ast.col);
        }
        ast.to = st.UseThis(PcalSymTab.LABEL, ast.to, context);
    }

    /***********************************************************************
    * Handling of Either and LabelEither added by LL on 24 Jan 2006.       
     * @throws PcalFixIDException *
    ***********************************************************************/
    private static void FixEither(AST.Either ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.ors.size(); i++)
              { Vector orClause = (Vector) ast.ors.elementAt(i) ;
                for (int j = 0; j < orClause.size(); j++)
                  FixSym((AST) orClause.elementAt(j), context);
               } ;
    }

    private static void FixLabelEither(AST.LabelEither ast, String context) throws PcalFixIDException {
        for (int i = 0; i < ast.clauses.size(); i++)
              { AST.Clause orClause = (AST.Clause) ast.clauses.elementAt(i) ;
                for (int j = 0; j < orClause.unlabOr.size(); j++)
                  FixSym((AST) orClause.unlabOr.elementAt(j), context);
                for (int j = 0; j < orClause.labOr.size(); j++)
                  FixLabeledStmt((AST.LabeledStmt) 
                                   orClause.labOr.elementAt(j), 
                                  context);
               } ;

    }

    private static void FixExpr(TLAExpr expr, String context) throws PcalFixIDException {
        /**
         * Set stringVec to the vector of identifiers (strings) that come from IDENT tokens
         * in expr, and set exprVect to the vector of expressions, each of which
         * contains a single token whose string is the identifier substituted for the
         * corresponding identifier of stringVec.
        */
        Vector exprVec = new Vector();   // the substituting exprs
        Vector stringVec = new Vector(); // the substituted  ids
        Vector tokenVec = new Vector();  // the 

        for (int i = 0; i < expr.tokens.size(); i++) {
            Vector tv = (Vector) expr.tokens.elementAt(i);
            String useMe = null;
            for (int j = 0; j < tv.size(); j++) {
                int shift = 0;
                TLAToken tok = (TLAToken) tv.elementAt(j);
                tok.column = tok.column + shift;
                if (tok.type == TLAToken.IDENT) {
                    useMe = st.UseThisVar(tok.string, context);
                    if (InVector(tok.string, stringVec)
                        || useMe.equals(tok.string)) continue;
                    stringVec.addElement(tok.string);
                    TLAExpr exp = new TLAExpr();
                    exp.addLine();
                    exp.addToken(new TLAToken(useMe, 0, TLAToken.IDENT));
                    exp.normalize();
                    exprVec.addElement(exp);
                }
            }
        }
        if (exprVec.size() > 0)
            try
            {
                expr.substituteForAll(exprVec,  stringVec, false);
            } catch (TLAExprException e)
            {
                throw new PcalFixIDException(e.getMessage());
            }
    }

    /****************************************************************/
    /* Returns whether the string is present in a vector of string. */
    /****************************************************************/
    private static boolean InVector(String var, Vector v) {
        for (int i = 0; i < v.size(); i++)
            if (var.equals((String) v.elementAt(i))) return true;
        return false;
    }

}

/***************************  the file FloydWarshall *************************************

--------------------------- MODULE FloydWarshall ---------------------------
(***************************************************************************)
(*                                                                         *)
(* The following is the Floyd-Warshall algorithm for computing the path    *)
(* with the smallest total weight of all paths between any two nodes in a  *)
(* completely connected graph, where edgeCost(i,j) is the weight on the    *)
(* edge from i to j.  At the end of the computation, path[i][j] is the     *)
(* minimum path weight of all paths from i to j.  It assumes that the      *)
(* nodes are numbers in 1..n.  This algorith comes from Wikipedia          *)
(*                                                                         *)
(*   1 (* Assume a function edgeCost(i,j) which returns the cost           *)
(*   2    of the edge from i to j (infinity if there is none).             *)
(*   3    Also assume that n is the number of vertices and                 *)
(*   4    edgeCost(i,i) = 0 *)                                             *)
(*   5                                                                     *)
(*   6 int path[][];                                                       *)
(*   7 (* A 2-dimensional matrix. At each step in the algorithm,           *)
(*   8    path[i][j] is the shortest path from i to j using intermediate   *)
(*   9    vertices (1..k-1).  Each path[i][j] is initialized to            *)
(*  10    edgeCost(i,j). *)                                                *)
(*  11                                                                     *)
(*  12 procedure FloydWarshall ()                                          *)
(*  13    for k := 1 to n                                                  *)
(*  14       for i := 1 to n                                               *)
(*  15          for j := 1 to n                                            *)
(*  16             path[i][j] = min ( path[i][j], path[i][k]+path[k][j] ); *)
(*                                                                         *)
(* We use modify it to an algorithm for computing connectivity in a        *)
(* directed graph.  As observed in the Wikipedia page, we just replace     *)
(* weights by Booleans, where FALSE is equivalent to a weight of infinity  *)
(* (not connected) and TRUE is equivalent to a weight of zero (connected). *)
(* Then min becomes disjunction and + becomes conjunction                  *)
(***************************************************************************)
EXTENDS Naturals, Sequences, TLC
(***************************************************************************)
(* We let 1..n be the set of nodes, and Nbrs be a function such that       *)
(* Nbrs[i] is the set of neighbors of node i, which is the set of nodes j  *)
(* such that there is an edge from i to j.                                 *)
(***************************************************************************)
CONSTANT n, Nbrs

ASSUME /\ n \in Nat 
       /\ Nbrs \in [1..n -> SUBSET (1..n)]

(***************************************************************************)
(* To be able to express correctness, we define Connected(i, j) to be true *)
(* for nodes i and j if there is a path from i to j.  Correctness of the   *)
(* algorithm then means that it terminates with                            *)
(*                                                                         *)
(*    path[i][j] = Connected(i, j)                                         *)
(*                                                                         *)
(* for all nodes i and j.                                                  *)
(*                                                                         *)
(* To define Connected, we observe that for a directed graph with n nodes, *)
(* there is a path from node i to node j iff there is a path from i to j   *)
(* of length at most n.  (A path of length k is a sequence of k+1 nodes,   *)
(* each of which has an edge from it to the next one.) We therefore define *)
(* Paths to be the set of all paths of length between 1 and n.  (In the    *)
(* definition, P(m) is the set of all paths with m nodes, and hence of     *)
(* length m-1.) We then define Connected in terms of Paths.                *)
(***************************************************************************)
Paths == LET P(m) == { f \in [1..m -> 1..n] : 
                         \A q \in 1..(m-1) : f[q+1] \in Nbrs[f[q]] }
         IN  UNION {P(m) : m \in 2..(n+1)}
                       
Connected(i, j) ==  \E p \in Paths : p[1] = i /\ p[Len(p)] = j

(***********************************
options (termination)
--algorithm FloydWarshall {
    variables path = [a \in 1..n |-> 
                       [b \in 1..n |-> b \in Nbrs[a]]],
    i, j, k;
    { k := 1;
      while (k =< n) {
        i := 1 ;
        while (i =< n) {
          j := 1;
          while (j =< n) {
            path[i][j] := path[i][j] \/ (path[i][k] /\ path[k][j]); 
            j := j+1;
          } ;
          i := i+1;
        } ;
        k := k+1
      } ;
      assert \A a, b \in 1..n : path[a][b] = Connected(a, b)
    }
}
***********************************)
\* BEGIN TRANSLATION
\* END TRANSLATION
=============================================================================
\* Modification History
\* Last modified Thu Jan 20 08:48:36 PST 2011 by lamport
\* Created Wed Jan 19 10:05:18 PST 2011 by lamport


*****************************************************************************************/




<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/ITLCOutputSource.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.ITLCOutputListener;

/**
 * Represents source of TLC output
 * @author <NAME>
 * @version $Id$
 */
public interface ITLCOutputSource
{
    public final static int PRIO_LOW = 1;
    public final static int PRIO_MEDIUM = 2;
    public final static int PRIO_HIGH = 4;

    /**
     * Adds a listener
     * @param listener
     */
    public void addTLCOutputListener(ITLCOutputListener listener);

    /**
     * Removes a listener
     * @param listener
     */
    public void removeTLCOutputListener(ITLCOutputListener listener);

    /**
     * Retrieves the listeners registered by this source
     */
    public ITLCOutputListener[] getListeners();

    /**
     * Retrieves the source name, which is the id of the source
     */
    public Model getModel();

    /**
     * Retrieves the source priority
     * one of the {@link ITLCOutputSource#PRIO_LOW}, {@link ITLCOutputSource#PRIO_MEDIUM}, {@link ITLCOutputSource#PRIO_HIGH}
     */
    public int getSourcePrio();

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/spec.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/spec/main.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Managing Your Specifications</title>
</head>
<!-- a comment -->

<body>
<h1>Managing Your Specifications</h1>

 <P> 
If you are using the Toolbox, you should have some knowledge of
the TLA+ specification language.&nbsp;  (See the <a href="../gettingstarted/resources.html">
TLA+ Resources</a> help page for information on how to acquire this knowledge.).&nbsp;
You should therefore have a basic understanding of what a TLA+ specification is.&nbsp;
We usually use the term <em>spec</em> instead of <em>specification</em>.
</P>
<p>The Toolbox allows you to create, edit, and check one spec at a time.&nbsp;
See the subtopics listed below to find out how to create, modify,
view, and parse your spec.&nbsp;
</P>

<p> If you want to use the same spec on different computers, see
    <A href="opening-closing.html#multiple-copies">Keeping Copies of a 
               Spec on Different Computers</a>.
</p>

 <p> 
Running the <A href="../model/model.html">TLC Model Checker</A> on a spec can
sometimes create a lot of data associated with the spec.&nbsp;

See the <A href="../gettingstarted/tla-preferences.html">TLA+ Preferences</A>
help page to learn how to find out how much storage your spec is using and
what to do if it is using too much.  
 </p>

<p>
You may want to use the same modules in different specs--for example, ones that define
data structures that you want to re-use.&nbsp;  

The best way to do that is to put those modules in one or more <em>library folders</em>.
See the <A href="../gettingstarted/tla-preferences.html">TLA+ Preferences</A>
help page.
</p>

 <p>
You can run only one instance of the Toolbox at a time.&nbsp; 
 </p>
<hr> 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href ="what-is.html"> What is a Spec?</A></dd>
<dd> <A href ="opening-closing.html"> Manipulating Specs </A></dd>
<dd> <A href ="parsing.html"> Parsing </A></dd>
<dd> <A href ="editing-modules.html"> Editing Modules </A></dd>
<dd> <A href ="pretty-printing.html"> Pretty-Printing Modules </A></dd>

</dl>
<a href = "../contents.html">&uarr; TLA+ Toolbox User's Guide</a>
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/BlockSelector.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.TLCState;
import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.TLCWorker;
import tlc2.tool.distributed.TLCWorkerRMI;
import tlc2.tool.queue.IStateQueue;
import tlc2.tool.queue.StateQueue;
import util.Assert;

public class BlockSelector implements IBlockSelector {
	/**
	 * A (lossy!) average block size statistic. Better not use for anything else than statistics! 
	 */
	protected volatile long averageBlockCnt = 0L;
	/**
	 * A reference to {@link TLCServer} for which this {@link IBlockSelector} selects blocks
	 */
	protected final TLCServer tlcServer;

	/**
	 * Functor pattern used to make the block size configurable that gets assigned to workers
	 * @param aTLCServer
	 */
	BlockSelector(final TLCServer aTLCServer) {
	    // LL modified error message on 7 April 2012
		Assert.check(aTLCServer != null, "TLC found a null TLCServer");
		tlcServer = aTLCServer;
	}
	
	/**
	 * Calculates the number of states a worker should be assigned. This
	 * calculation is based on the current number of workers registered with the
	 * server assigning each worker 1/N of the {@link StateQueue} with N being the
	 * current amount of {@link TLCWorker}.
	 * 
	 * The block size essentially load balances the workers by deciding how much
	 * work they get assigned.
	 * 
	 * @param stateQueue Current queue of new states
	 * @param worker {@link TLCWorker} requesting work units ({@link TLCState})
	 * @return The states that will be assigned to the given remote {@link TLCWorker} or null if no work is available
	 */
	public TLCState[] getBlocks(final IStateQueue stateQueue, final TLCWorkerRMI worker) {
		// current size of new states
		final long amountOfStates = stateQueue.size();
		// the amount of blocks that will be assigned to the work
		long blockSize = getBlockSize(amountOfStates, worker);
		// At least request a single state to guarantee StateQueue#isAvail() will be triggered
		// do not request more than what is available 
		blockSize = Math.min(blockSize, amountOfStates);
		// make sure it is positive > 0
		blockSize = Math.max(blockSize, 1);
		// can only read Integer.MAX_VALUE at max
		blockSize = Math.min(Integer.MAX_VALUE, blockSize);
		// synchronized removal from the state queue
		final TLCState[] sDequeue = stateQueue.sDequeue((int)blockSize);
		// maintain statistics with what we really got from the state queue.
		setAverageBlockCnt(sDequeue != null ? sDequeue.length : 0);
		return sDequeue;
	}

	/**
	 * @param size
	 *            The current size of the state queue.
	 * @return The intended block size.
	 */
	protected long getBlockSize(long size, final TLCWorkerRMI aWorker) {
		final int workerCount = tlcServer.getWorkerCount();
		return (long) Math.ceil(size * (1.0 / workerCount));
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.selector.IBlockSelector#setMaxTXSize(int)
	 */
	public void setMaxTXSize(int aMaximum) {
		// nop
	}
	
	protected void setAverageBlockCnt(long blockCnt) {
		// Get meaningful results right from the start
		if (averageBlockCnt > 0L) {
			averageBlockCnt = (blockCnt + averageBlockCnt) / 2L;
		} else {
			averageBlockCnt = blockCnt;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.selector.IBlockSelector#getAverageBlockCnt()
	 */
	public long getAverageBlockCnt() {
		return averageBlockCnt;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SetOfArgLevelConstraints.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

class SetOfArgLevelConstraints extends HashMap<ParamAndPosition, Integer> implements LevelConstants {
  // Implements a map mapping arg-level parameters (ParamAndPosition)
  // to levels (Integer). An entry <pap,x> means that the argument
  // pap.position of the operator pap.param must have a level >= x.
  /*************************************************************************
  * An element in this HashMap has key that is a ParamAndPosition and      *
  * value that is an int.  Such an element with key k and value v means    *
  * that the operator parameter described by the SymbolNode k.param must   *
  * be able to accept an argument of level v in its argument number        *
  * k.position.                                                            *
  *************************************************************************/
  
  /**
   * This method adds <pap, level> into this set, and "subsumes"
   * it with another one for the same parameter if one is there, or
   * ignoring the constraint if it is vacuous.
   */
  @Override
  public final Integer put(ParamAndPosition pap, Integer level) {
    int newLevel = level.intValue();
    Integer old = this.get(pap);

    int oldLevel = (old == null) ? MinLevel : old.intValue();
    super.put(pap, new Integer(Math.max(newLevel, oldLevel)));
    return old;
  }

  public final Integer put(SymbolNode param, int position, int level) {
    ParamAndPosition pap = new ParamAndPosition(param, position);
    return this.put(pap, new Integer(level));
  }

  /**
   * This method adds all of the elements of its argument s to this
   * map, in each case "subsuming" it with any constraint already
   * present for the same parameter if one is there.
   */
  @Override
  public final void putAll(Map<? extends ParamAndPosition, ? extends Integer> s) {
    for (Iterator<? extends ParamAndPosition> iter = s.keySet().iterator(); iter.hasNext(); ) {
    	  ParamAndPosition key = iter.next();
      this.put(key, s.get(key));
    }
  }

  @Override
  public final String toString() {
    StringBuffer sb = new StringBuffer("{ ");
    for (Iterator<ParamAndPosition> iter = this.keySet().iterator(); iter.hasNext(); ) {
      ParamAndPosition pap = iter.next();
      sb.append(pap.toString() + " -> " + this.get(pap));
      if (iter.hasNext()) sb.append(", ");
    }
    sb.append("}");
    return sb.toString();
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/LegacyFileDocumentProvider.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.util;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.ui.editors.text.FileDocumentProvider;

public class LegacyFileDocumentProvider extends FileDocumentProvider {
	
	// Overrides the implementation of refreshFile introduced with Bug 482354 - "SVN
	// checkout deadlocks Eclipse" with corresponding commit
	// Id742d98403cc546fad4a21d25eb18ab7bef48776 (eclipse git repository).
	// Use this implementation to check if the file is in sync before a refresh
	// operation is executed.
	protected void refreshFile(IFile file, IProgressMonitor monitor) throws CoreException {
		try {
			file.refreshLocal(IResource.DEPTH_INFINITE, monitor);
		} catch (OperationCanceledException notExpectedToHappen) {
			notExpectedToHappen.printStackTrace();
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/preferences/AutomaticUpdatesPreferencePage.java<|end_filename|>
/*******************************************************************************
 *  Copyright (c) 2007, 2016 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     <NAME> <<EMAIL>> - Bug 321568 -  [ui] Preference for automatic-update-reminder doesn't work in multilanguage-environments
 *     <NAME> <<EMAIL>> - Bug 432887 - Setting to show update wizard w/o notification popup
 *     <NAME> (Eclipse Foundation) - Bug 498116
 *******************************************************************************/
package org.lamport.tla.toolbox.preferences;

import java.net.URI;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdateMessages;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdatePlugin;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdateScheduler;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.AutomaticUpdatesPopup;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.IAutomaticUpdaterHelpContextIds;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.LastAutoCheckForUpdateMemo;
import org.eclipse.equinox.internal.p2.ui.sdk.scheduler.PreferenceConstants;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;

/**
 * Preference page for automated updates.
 * 
 * @since 3.4
 * 
 */
@SuppressWarnings("restriction")
public class AutomaticUpdatesPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

	private Button enabledCheck;
	private Button enabledBeta;
	private Button showUpdateWizard;
	private Button onStartupRadio, onFuzzyScheduleRadio;
	private Combo fuzzyRecurrenceCombo;
	private Button searchOnlyRadio, searchAndDownloadRadio;
	private Button remindOnceRadio, remindScheduleRadio;
	private Combo remindElapseCombo;
	private Group updateScheduleGroup, downloadGroup, remindGroup;

	private URI uri;
	private IMetadataRepositoryManager metadataRepositoryManager;
	private IArtifactRepositoryManager artifactRepositoryManager;

	public void init(IWorkbench workbench) {
		final ProvisioningUI ui = ProvUIActivator.getDefault().getProvisioningUI();
		uri = URI.create("http://lamport.org/tlatoolbox/ci/toolboxUpdate/");
		artifactRepositoryManager = ProvUI.getArtifactRepositoryManager(ui.getSession());
		metadataRepositoryManager = ProvUI.getMetadataRepositoryManager(ui.getSession());
	}

	protected Control createContents(Composite parent) {
		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IAutomaticUpdaterHelpContextIds.AUTOMATIC_UPDATES_PREFERENCE_PAGE);

		Composite container = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.marginWidth = layout.marginHeight = 0;
		container.setLayout(layout);

		enabledCheck = new Button(container, SWT.CHECK);
		enabledCheck.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_findUpdates);

		createSpacer(container, 1);
		
		container = new Composite(parent, SWT.NULL);
		layout = new GridLayout();
		layout.marginWidth = layout.marginHeight = 0;
		container.setLayout(layout);

		enabledBeta = new Button(container, SWT.CHECK);
		enabledBeta.setText("Receive experimental features for the TLA Toolbox.");

		createSpacer(container, 1);

		updateScheduleGroup = new Group(container, SWT.NONE);
		updateScheduleGroup.setText(NLS.bind(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_UpdateSchedule, lastCheckForUpdateDateString()));
		layout = new GridLayout();
		layout.numColumns = 3;
		updateScheduleGroup.setLayout(layout);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		updateScheduleGroup.setLayoutData(gd);

		onStartupRadio = new Button(updateScheduleGroup, SWT.RADIO);
		IProduct product = Platform.getProduct();
		String productName = product != null && product.getName() != null ? product.getName() : AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_GenericProductName;
		onStartupRadio.setText(NLS.bind(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_findOnStart, productName));
		gd = new GridData();
		gd.horizontalSpan = 3;
		onStartupRadio.setLayoutData(gd);
		onStartupRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		onFuzzyScheduleRadio = new Button(updateScheduleGroup, SWT.RADIO);
		onFuzzyScheduleRadio.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_findOnSchedule);
		gd = new GridData();
		gd.horizontalSpan = 3;
		onFuzzyScheduleRadio.setLayoutData(gd);
		onFuzzyScheduleRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		fuzzyRecurrenceCombo = new Combo(updateScheduleGroup, SWT.READ_ONLY);
		fuzzyRecurrenceCombo.setItems(AutomaticUpdateScheduler.FUZZY_RECURRENCE);
		gd = new GridData();
		gd.widthHint = 200;
		gd.horizontalIndent = 30;
		gd.horizontalSpan = 3;
		fuzzyRecurrenceCombo.setLayoutData(gd);

		createSpacer(container, 1);

		downloadGroup = new Group(container, SWT.NONE);
		downloadGroup.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_downloadOptions);
		layout = new GridLayout();
		layout.numColumns = 3;
		downloadGroup.setLayout(layout);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		downloadGroup.setLayoutData(gd);

		searchOnlyRadio = new Button(downloadGroup, SWT.RADIO);
		searchOnlyRadio.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_searchAndNotify);
		gd = new GridData();
		gd.horizontalSpan = 3;
		searchOnlyRadio.setLayoutData(gd);
		searchOnlyRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		searchAndDownloadRadio = new Button(downloadGroup, SWT.RADIO);
		searchAndDownloadRadio.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_downloadAndNotify);
		gd = new GridData();
		gd.horizontalSpan = 3;
		searchAndDownloadRadio.setLayoutData(gd);
		searchAndDownloadRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		createSpacer(container, 1);

		remindGroup = new Group(container, SWT.NONE);
		remindGroup.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_RemindGroup);
		layout = new GridLayout();
		layout.numColumns = 3;
		remindGroup.setLayout(layout);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		remindGroup.setLayoutData(gd);

		remindOnceRadio = new Button(remindGroup, SWT.RADIO);
		remindOnceRadio.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_RemindOnce);
		gd = new GridData();
		gd.horizontalSpan = 3;
		remindOnceRadio.setLayoutData(gd);
		remindOnceRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		remindScheduleRadio = new Button(remindGroup, SWT.RADIO);
		remindScheduleRadio.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_RemindSchedule);
		gd = new GridData();
		gd.horizontalSpan = 3;
		remindScheduleRadio.setLayoutData(gd);
		remindScheduleRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		remindElapseCombo = new Combo(remindGroup, SWT.READ_ONLY);
		remindElapseCombo.setItems(AutomaticUpdatesPopup.ELAPSED_LOCALIZED_STRINGS);

		gd = new GridData();
		gd.widthHint = 200;
		gd.horizontalIndent = 30;
		gd.horizontalSpan = 3;
		remindElapseCombo.setLayoutData(gd);

		showUpdateWizard = new Button(remindGroup, SWT.CHECK);
		showUpdateWizard.setText(AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_directlyShowUpdateWizard);
		GridDataFactory.fillDefaults().span(3, 1).grab(true, false).applyTo(showUpdateWizard);

		initialize();

		enabledCheck.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});

		enabledBeta.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				pageChanged();
			}
		});
		
		Dialog.applyDialogFont(container);
		return container;
	}

	private static String lastCheckForUpdateDateString() {
		Date lastCheckDate = new LastAutoCheckForUpdateMemo(AutomaticUpdatePlugin.getDefault().getAgentLocation()).read();
		if (lastCheckDate == null) {
			return AutomaticUpdateMessages.AutomaticUpdatesPreferencePage_never;
		}

		DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT, Locale.getDefault());
		return formatter.format(lastCheckDate);
	}

	protected void createSpacer(Composite composite, int columnSpan) {
		Label label = new Label(composite, SWT.NONE);
		GridData gd = new GridData();
		gd.horizontalSpan = columnSpan;
		label.setLayoutData(gd);
	}

	private void initialize() {
		IPreferenceStore pref = AutomaticUpdatePlugin.getDefault().getPreferenceStore();
		enabledCheck.setSelection(pref.getBoolean(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED));
		enabledBeta.setSelection(artifactRepositoryManager.isEnabled(uri));
		setSchedule(pref.getString(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE));

		fuzzyRecurrenceCombo.setText(AutomaticUpdateScheduler.FUZZY_RECURRENCE[getFuzzyRecurrence(pref, false)]);

		remindScheduleRadio.setSelection(pref.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE));
		remindOnceRadio.setSelection(!pref.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE));
		remindElapseCombo.setText(AutomaticUpdatesPopup.getElapsedTimeString(pref.getString(PreferenceConstants.PREF_REMIND_ELAPSED)));
		searchOnlyRadio.setSelection(!pref.getBoolean(PreferenceConstants.PREF_DOWNLOAD_ONLY));
		searchAndDownloadRadio.setSelection(pref.getBoolean(PreferenceConstants.PREF_DOWNLOAD_ONLY));
		showUpdateWizard.setSelection(pref.getBoolean(PreferenceConstants.PREF_SHOW_UPDATE_WIZARD));

		pageChanged();
	}

	private void setSchedule(String value) {
		if (value.equals(PreferenceConstants.PREF_UPDATE_ON_STARTUP)) {
			onStartupRadio.setSelection(true);
		} else {
			onFuzzyScheduleRadio.setSelection(true);
		}
	}

	void pageChanged() {
		boolean master = enabledCheck.getSelection();
		updateScheduleGroup.setEnabled(master);
		onStartupRadio.setEnabled(master);
		onFuzzyScheduleRadio.setEnabled(master);
		fuzzyRecurrenceCombo.setEnabled(master && onFuzzyScheduleRadio.getSelection());
		downloadGroup.setEnabled(master);
		searchOnlyRadio.setEnabled(master);
		searchAndDownloadRadio.setEnabled(master);
		remindGroup.setEnabled(master);
		remindScheduleRadio.setEnabled(master);
		remindOnceRadio.setEnabled(master);
		remindElapseCombo.setEnabled(master && remindScheduleRadio.getSelection());
		showUpdateWizard.setEnabled(master);
		
		boolean beta = enabledBeta.getSelection();
		artifactRepositoryManager.setEnabled(uri, beta);
		metadataRepositoryManager.setEnabled(uri, beta);
	}

	protected void performDefaults() {
		super.performDefaults();
		IPreferenceStore pref = AutomaticUpdatePlugin.getDefault().getPreferenceStore();
		enabledCheck.setSelection(pref.getDefaultBoolean(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED));
		
		enabledBeta.setSelection(false);
		artifactRepositoryManager.setEnabled(uri, false);
		metadataRepositoryManager.setEnabled(uri, false);

		setSchedule(pref.getDefaultString(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE));

		remindOnceRadio.setSelection(!pref.getDefaultBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE));
		remindScheduleRadio.setSelection(pref.getDefaultBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE));
		remindElapseCombo.setText(AutomaticUpdatesPopup.getElapsedTimeString(pref.getDefaultString(PreferenceConstants.PREF_REMIND_ELAPSED)));

		searchOnlyRadio.setSelection(!pref.getDefaultBoolean(PreferenceConstants.PREF_DOWNLOAD_ONLY));
		searchAndDownloadRadio.setSelection(pref.getDefaultBoolean(PreferenceConstants.PREF_DOWNLOAD_ONLY));

		showUpdateWizard.setSelection(pref.getDefaultBoolean(PreferenceConstants.PREF_SHOW_UPDATE_WIZARD));

		pageChanged();
	}

	/**
	 * Method declared on IPreferencePage. Subclasses should override
	 */
	public boolean performOk() {
		IPreferenceStore pref = AutomaticUpdatePlugin.getDefault().getPreferenceStore();
		pref.setValue(PreferenceConstants.PREF_AUTO_UPDATE_ENABLED, enabledCheck.getSelection());
		
		artifactRepositoryManager.setEnabled(uri, enabledBeta.getSelection());
		metadataRepositoryManager.setEnabled(uri, enabledBeta.getSelection());

		if (onStartupRadio.getSelection()) {
			pref.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, PreferenceConstants.PREF_UPDATE_ON_STARTUP);
		} else if (onFuzzyScheduleRadio.getSelection()) {
			pref.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, PreferenceConstants.PREF_UPDATE_ON_FUZZY_SCHEDULE);
			new LastAutoCheckForUpdateMemo(AutomaticUpdatePlugin.getDefault().getAgentLocation()).readAndStoreIfAbsent(Calendar.getInstance().getTime());
		} else {
			pref.setValue(PreferenceConstants.PREF_AUTO_UPDATE_SCHEDULE, PreferenceConstants.PREF_UPDATE_ON_SCHEDULE);
		}

		if (remindScheduleRadio.getSelection()) {
			pref.setValue(PreferenceConstants.PREF_REMIND_SCHEDULE, true);
			pref.setValue(PreferenceConstants.PREF_REMIND_ELAPSED, AutomaticUpdatesPopup.ELAPSED_VALUES[remindElapseCombo.getSelectionIndex()]);
		} else {
			pref.setValue(PreferenceConstants.PREF_REMIND_SCHEDULE, false);
		}

		pref.setValue(AutomaticUpdateScheduler.P_FUZZY_RECURRENCE, fuzzyRecurrenceCombo.getText());

		pref.setValue(PreferenceConstants.PREF_DOWNLOAD_ONLY, searchAndDownloadRadio.getSelection());

		pref.setValue(PreferenceConstants.PREF_SHOW_UPDATE_WIZARD, showUpdateWizard.getSelection());

		AutomaticUpdatePlugin.getDefault().savePreferences();
		AutomaticUpdatePlugin.getDefault().getScheduler().rescheduleUpdate();
		return true;
	}

	private int getFuzzyRecurrence(IPreferenceStore pref, boolean useDefault) {
		String day = useDefault ? pref.getDefaultString(AutomaticUpdateScheduler.P_FUZZY_RECURRENCE) : pref.getString(AutomaticUpdateScheduler.P_FUZZY_RECURRENCE);
		for (int i = 0; i < AutomaticUpdateScheduler.FUZZY_RECURRENCE.length; i++)
			if (AutomaticUpdateScheduler.FUZZY_RECURRENCE[i].equals(day))
				return i;
		return 0;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/job/TLCProcessJob.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.job;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.launch.TraceExplorerDelegate;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink;
import org.lamport.tla.toolbox.tool.tlc.output.internal.BroadcastStreamListener;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tlc2.TLC;
import tlc2.output.EC;
import tlc2.tool.fp.FPSetFactory;
import tlc2.tool.fp.NoopFPSet;
import tlc2.tool.fp.OffHeapDiskFPSet;
import util.TLCRuntime;

/**
 * A job to launch TLC as a separate process
 * @author <NAME>
 * @version $Id$
 */
public class TLCProcessJob extends TLCJob
{
    public static final int HEAP_SIZE_DEFAULT = 25;
	protected IProcess process = null;
    private BroadcastStreamListener listener = null;

    /**
     * The tlc start time in milliseconds as given
     * by {@link System#currentTimeMillis()}.
     */
    private long tlcStartTime;
    /**
     * The tlc end time in milliseconds as given
     * by {@link System#currentTimeMillis()}.
     */
    private long tlcEndTime;

    /**
     * Constructs a process job
     * @param workers 
     * @param name
     */
    public TLCProcessJob(String specName, String modelName, ILaunch launch, int workers)
    {
        super(specName, modelName, launch, workers);
    }

    /* (non-Javadoc)
     * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
     */
    protected IStatus run(IProgressMonitor monitor)
    {
        try
        {

            // start the monitor ( we don't know the )
            monitor.beginTask("Running TLC model checker", IProgressMonitor.UNKNOWN);

            // step 1
            monitor.worked(STEP);
            monitor.subTask("Preparing the TLC Launch");

            // classpath
            final String runtimeClasspath = ToolboxHandle.getTLAToolsClasspath().toOSString();
			// Add 3rd party libraries to classpath. Star acts as wildcard
			// picking up all .jar files (added by MAK on 07/31/2012)
			final String libClasspath = runtimeClasspath + File.separator + "lib" + File.separator + "*";
			final String libMailClasspath = runtimeClasspath + File.separator + "lib" + File.separator + "javax.mail"
					+ File.separator + "*";
			final String libJsonClasspath = runtimeClasspath + File.separator + "lib" + File.separator + "gson"
					+ File.separator + "*";
			// classpath during toolbox development within Eclipse (will simply not
			// exist in packaged toolbox)
			final String devClasspath = runtimeClasspath + File.separator + "class";
			
			// Add TLA+ library path entries to the class path in case any one of them
			// includes module overwrites.  It is the last element on the classpath.
			final Spec spec = Activator.getSpecManager().getSpecByName(specName);
			final String libraryPathClassPath = spec.getTLALibraryPathAsClassPath();
			
			final String[] classPath = new String[] { runtimeClasspath, libClasspath, libMailClasspath, devClasspath, libJsonClasspath, libraryPathClassPath };

            // arguments
            String[] arguments = constructProgramArguments();

            final List<String> vmArgs = new ArrayList<String>();

            // get max heap size as fraction from model editor
            int maxHeapSize = launch.getLaunchConfiguration().getAttribute(LAUNCH_MAX_HEAP_SIZE, HEAP_SIZE_DEFAULT);
            if (maxHeapSize < 1 || maxHeapSize > 99) {
				TLCActivator.logInfo(String.format(
						"Defaulting fraction of physical memory to %s because %s is out of range (0,100). Value can be adjusted on the model editor's \"Advanced TLC option\" tab.",
						HEAP_SIZE_DEFAULT, maxHeapSize));
            	// Dealing with a legacy model (absolute memory values) or somehow bogus input.
            	maxHeapSize = HEAP_SIZE_DEFAULT;
            }
			final TLCRuntime instance = TLCRuntime.getInstance();
			long absolutePhysicalSystemMemory = instance.getAbsolutePhysicalSystemMemory(maxHeapSize / 100d);

			// Get class name of the user selected FPSet. If it is unset, try and load the
			// OffHeapDiskFPSet (which might not be supported). In unsupported, revert to
			// TLC's default set.
			// If the user happened to select OffHeapDiskFPSet, the -XX:MaxDirectMemorySize
			// is set by getVMArguments.
			String clazz = getOptimalFPsetImpl();
			if (!hasSpec(launch.getLaunchConfiguration())) {
				// If a spec has no behaviors, TLC won't need a fingerprint set. Thus, use the
				// NoopFPSet whose initialization cost is next to nothing. Real fpsets on the
				// other hand - such as OffHeapDiskFPSet - do heavy weight initialization at startup.
				clazz = NoopFPSet.class.getName();
			}
			if (clazz == null || clazz.equals(OffHeapDiskFPSet.class.getName())) {
				if (OffHeapDiskFPSet.isSupported()) {
					// ...good, can use lock-free/scalabe fpset, but need to divide assigned memory
					// into JVM heap and non-heap/off-heap memory. Let's assign 2/3 to the off-heap
					// FPSet.
					final long offheapMemory = (long) (absolutePhysicalSystemMemory * 0.6666d);
					vmArgs.add(FPSetFactory.getVMArguments(OffHeapDiskFPSet.class.getName(), offheapMemory));

					// Rest goes to the heap (state queue/...).
					vmArgs.add(FPSetFactory.getVMArguments(FPSetFactory.getImplementationDefault(),
							absolutePhysicalSystemMemory - offheapMemory));
					
					vmArgs.add("-D" + FPSetFactory.IMPL_PROPERTY + "=" + OffHeapDiskFPSet.class.getName());
				} else {
					// Off-heap fpset couldn't be loaded. Use default fpset and assign all memory to
					// heap memory.
					vmArgs.add(FPSetFactory.getVMArguments(FPSetFactory.getImplementationDefault(),
							absolutePhysicalSystemMemory));
					vmArgs.add("-D" + FPSetFactory.IMPL_PROPERTY + "=" + FPSetFactory.getImplementationDefault());
				}
			} else {
				vmArgs.add(FPSetFactory.getVMArguments(clazz, absolutePhysicalSystemMemory));
				vmArgs.add("-D" + FPSetFactory.IMPL_PROPERTY + "=" + clazz);
			}
			
			// specify Java8+ acceptable GC
			vmArgs.add("-XX:+UseParallelGC");
			
            // add remaining VM args
            vmArgs.addAll(getAdditionalVMArgs());


            // assemble the config
            VMRunnerConfiguration tlcConfig = new VMRunnerConfiguration(getMainClass().getName(), classPath);
            // tlcConfig.setProgramArguments(new String[] { ResourceHelper.getModuleName(rootModule) });
            tlcConfig.setProgramArguments(arguments);
            tlcConfig.setVMArguments((String[]) vmArgs.toArray(new String[vmArgs.size()]));
            tlcConfig.setWorkingDirectory(ResourceHelper.getParentDirName(rootModule));
            // Following added for testing by LL on 6 Jul 2012
            final IVMInstall vmInstall = getVMInstall();
            
            
			final IVMRunner runner = vmInstall.getVMRunner(ILaunchManager.RUN_MODE);

            launch.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, "true");

            // step 2
            monitor.worked(STEP);
            monitor.subTask("Launching TLC");

            try
            {
                // step 3
                runner.run(tlcConfig, launch, new NullProgressMonitor());
                tlcStartTime = System.currentTimeMillis();
            } catch (CoreException e)
            {
            	// Include command-line for users to figure out what failed.
				return new Status(IStatus.ERROR, TLCActivator.PLUGIN_ID,
						String.format("Error launching TLC with command-line (CWD: %s): %s%sbin%sjava -cp %s %s %s %s",
								tlcConfig.getWorkingDirectory(), vmInstall.getInstallLocation(), File.separator,
								File.separator, String.join(File.pathSeparator, tlcConfig.getClassPath()),
								String.join(" ", tlcConfig.getVMArguments()),
								String.join(" ", tlcConfig.getClassToLaunch()), String.join(" ", arguments)),
						e);
            }

            // find the running process
            this.process = findProcessForLaunch(launch);

            // step 4
            monitor.worked(STEP);
            monitor.subTask("Connecting to running instance");

            // process found
            if (this.process != null)
            {
				// Log command-line that can (almost) copied&pasted verbatim to a shell to
				// run TLC directly.
				// (Working directory needed because TLC does not find MC.tla even if -metadir
				// is set).
            	final String cmd = this.process.getAttribute(IProcess.ATTR_CMDLINE);
            	final String cwd = this.process.getAttribute(DebugPlugin.ATTR_WORKING_DIRECTORY);
            	TLCActivator.logInfo(String.format("TLC COMMAND-LINE (CWD: %s): %s", cwd, cmd));
            	
                // step 5
                monitor.worked(STEP);
                monitor.subTask("Model checking...");

                // register the broadcasting listener

                final Model model = launch.getLaunchConfiguration().getAdapter(Model.class);

                /*
                 * If TLC is being run for model checking then the stream kind passed to
                 * BroadcastStreamListener (second argument) is IProcessOutputSink.TYPE_OUT.
                 * If TLC is being run for trace exploration, then it is
                 * IProcessOutputSink.TYPE_TRACE_EXPLORE.
                 */

                int kind = IProcessOutputSink.TYPE_OUT;

                if (launch.getLaunchMode().equals(TraceExplorerDelegate.MODE_TRACE_EXPLORE))
                {
                    kind = IProcessOutputSink.TYPE_TRACE_EXPLORE;
                }

                listener = new BroadcastStreamListener(model, kind);

                // stdout, stderr, stdin of the forked TLC process.
                final IStreamsProxy streamsProxy = process.getStreamsProxy();
				streamsProxy.getOutputStreamMonitor().addListener(listener);
				streamsProxy.getErrorStreamMonitor().addListener(listener);
				
				// This is a reader wrapping the input stream of the Toolbox console. In other
				// words, if a user types a string into the Toolbox console, we can read the
				// string from the reader. Iff consoleStdIn is not null (there is a Toolbox
				// console), the loop below reads from consoleStdIn and writes (forwards) the
				// string to stdin of the TLC process.  Because the while loop sleeps for a
				// second, the response time isn't perfect but is good enough for now.
				final BufferedReader consoleReader = getConsoleReader();
				
                // loop until the process is terminated
				while (checkAndSleep()) {
					// check the cancellation status
					if (monitor.isCanceled()) {
						// cancel the TLC
						try {
							process.terminate();
						} catch (DebugException e) {
							// react on the status code
							switch (e.getStatus().getCode()) {
							case DebugException.TARGET_REQUEST_FAILED:
							case DebugException.NOT_SUPPORTED:
							default:
								// MAK 11/2012: Remove e.getStatus().getCode()
								// and e (throwable) once Chris' problem
								// cancellation has been diagnosed
								return new Status(
										IStatus.ERROR,
										TLCActivator.PLUGIN_ID,
										e.getStatus().getCode(),
										"Error terminating the running TLC instance. This is a bug. Make sure to exit the toolbox.",
										e);
							}
						}

						// Wait for the process to terminate. Otherwise, it
						// opens the door to a race condition in
						// org.lamport.tla.toolbox.tool.tlc.model.Model such
						// that isRunning returns true querying the Launch (which
						// is directly connected to the Process instance), even
						// after the outer TLCProcessJob's JobListener
						// ...launch.TLCModelLaunchDelegate.TLCJobChangeListener
						// has setRunning(false). 
						int i = 0;
						while (!process.isTerminated() || i++ >= 10) {
							try {
								Thread.sleep(100L);
							} catch (InterruptedException e) {
								e.printStackTrace();
								return new Status(IStatus.ERROR, TLCActivator.PLUGIN_ID,
										"Error waiting for process termination.", e);
							}
						}
						if (!process.isTerminated()) {
							TLCActivator.logInfo(
									"TLC process failed to terminate within expected time window. Expect Toolbox to show an incorrect model state.");
						}
						
						// abnormal termination
						tlcEndTime = System.currentTimeMillis();
						return Status.CANCEL_STATUS;
					}
					
					
					try {
						if (consoleReader != null && consoleReader.ready()) {
							streamsProxy.write(consoleReader.readLine() + "\n");
						}
					} catch (IOException e) {
						throw new CoreException(new Status(IStatus.ERROR, TLCActivator.PLUGIN_ID,
								"Error reading from Toolbox console or writing to stdin of TLC process", e));
					}
				}

                // step 6
                monitor.worked(STEP);
                monitor.subTask("Model checking finished.");

                // handle finish
                doFinish();

                tlcEndTime = System.currentTimeMillis();

                return Status.OK_STATUS;

            } else
            {
                // process not found
                return new Status(IStatus.ERROR, TLCActivator.PLUGIN_ID,
                        "Error launching TLC, the launched process cound not be found");
            }

        } catch (CoreException e)
        {
            return new Status(IStatus.ERROR, TLCActivator.PLUGIN_ID, "Error reading model parameters", e);
        } finally
        {
            // send the notification about completion
            if (listener != null)
            {
                listener.streamClosed();
                // remove this listener from the stream to avoid memory leak
                if (process != null && process.getStreamsProxy() != null)
                {
                    if (process.getStreamsProxy().getOutputStreamMonitor() != null)
                    {
                        process.getStreamsProxy().getOutputStreamMonitor().removeListener(listener);
                    }
                    if (process.getStreamsProxy().getErrorStreamMonitor() != null)
                    {
                        process.getStreamsProxy().getErrorStreamMonitor().removeListener(listener);
                    }
                }
            }
            // make sure to complete the monitor
            monitor.done();
        }
    }

	private static BufferedReader getConsoleReader() {
		final IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();
		final List<IConsole> tlcConsole = Arrays.asList(consoleManager.getConsoles()).stream()
				.filter(c -> "TLC-Console".equals(c.getName())).collect(Collectors.toList());
		if (!tlcConsole.isEmpty()) {
			final IConsole iConsole = tlcConsole.get(0);
			if (iConsole instanceof IOConsole) {
				IOConsoleInputStream inputStream = ((IOConsole) iConsole).getInputStream();
				return new BufferedReader(new InputStreamReader(inputStream));
			}
		}
		return null;
	}

	protected String getOptimalFPsetImpl() throws CoreException {
		return launch.getLaunchConfiguration().getAttribute(LAUNCH_FPSET_IMPL, (String) null);
	}

	/**
	 * @return A list of additional vm arguments
	 */
	protected List<String> getAdditionalVMArgs() throws CoreException {
		final List<String> result = new ArrayList<String>(0);
		
		// Library Path
		final Spec spec = Activator.getSpecManager().getSpecByName(specName);
		final String tlaLibraryPathAsVMArg = spec.getTLALibraryPathAsVMArg();
		if (!"".equals(tlaLibraryPathAsVMArg)) {
			result.add(tlaLibraryPathAsVMArg);
		}

		// JVM arguments/system properties
		final ILaunchConfiguration launchConfig = launch.getLaunchConfiguration();
		final String vmArgs = launchConfig.getAttribute(LAUNCH_JVM_ARGS, (String) null);
		if(vmArgs != null) {
			result.addAll(sanitizeString(vmArgs));
		}

		return result;
	}
	
	/**
	 * @param vmArgs may look like " -Djava.rmi.foo=bar  -Djava.tralla=avalue  "
	 * @return a {@link List} with ["-Djava.rmi.foo=bar", "-Djava.tralla=avlue"]
	 */
	private List<String> sanitizeString(final String vmArgs) {
		final String[] strings = vmArgs.split(" ");
		final List<String> results = new ArrayList<String>(strings.length);
		for (int i = 0; i < strings.length; i++) {
			final String string = strings[i];
			if(!"".equals(string) && !" ".equals(string)) {
				results.add(string.trim());
			}
			// additional sanity checks could go here, but the nested process will report errors anyway
		}
		return results;
	}

	@SuppressWarnings("rawtypes")
	protected Class getMainClass() {
		return TLC.class;
	}

    protected boolean checkCondition() {
        // return true if the TLC is still calculating
    	return !process.isTerminated();
    }
    
    /**
     * Retrieves a process to a given ILaunch
     * @param launch
     * @return
     */
    private static IProcess findProcessForLaunch(ILaunch launch)
    {
        // find the process
        IProcess[] processes = DebugPlugin.getDefault().getLaunchManager().getProcesses();
        for (int i = 0; i < processes.length; i++)
        {
            if (processes[i].getLaunch().equals(launch))
            {
                return processes[i];
            }
        }
        return null;
    }

    /**
     * Returns the tlc start time in milliseconds as given
     * by {@link System#currentTimeMillis()}.
     * @return
     */
    public long getTlcStartTime()
    {
        return tlcStartTime;
    }

    /**
     * Returns the tlc end time in milliseconds as given
     * by {@link System#currentTimeMillis()}.
     * @return
     */
    public long getTlcEndTime()
    {
        return tlcEndTime;
    }

	/**
	 * @return The processee's exit/return value or -1 if unknown.
	 */
    public int getExitValue() {
    	if (this.process != null) {
    		try {
    			return this.process.getExitValue();
    		} catch (DebugException shouldNotHappen) {
    			shouldNotHappen.printStackTrace();
    		}
    	}
    	return 255;
    }

	public boolean hasCrashed() {
		return EC.ExitStatus.exitStatusToCrash(getExitValue());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TBTriple.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:53 PST by lamport
//      modified on Thu Sep 21 22:17:17 PDT 2000 by yuanyu

package tlc2.tool.liveness;

public class TBTriple {
	/**
	 * TBTriple are used in tableau construction. There are two kinds of
	 * triples. The alpha triples are (p/\q, p, q) and ([]p, p, O[]p). The beta
	 * triples are (p\/q, p, q) and (<>p, p, O<>q).
	 */
	private final LiveExprNode fa;
	private final LiveExprNode fb;
	private final LiveExprNode fc;

	public TBTriple(LiveExprNode a, LiveExprNode b, LiveExprNode c) {
		this.fa = a;
		this.fb = b;
		this.fc = c;
	}

	public final LiveExprNode getA() {
		return this.fa;
	}

	public final LiveExprNode getB() {
		return this.fb;
	}

	public final LiveExprNode getC() {
		return this.fc;
	}

	public final boolean isAlpha() {
		// TODO Comment above says that O[]p is part of alpha too, but LNNext (with
		// nested LNAll) does not appear.
		return ((this.fa instanceof LNConj) || (this.fa instanceof LNAll));
	}

	public final boolean isBeta() {
		// TODO Comment above says that O<>p is part of beta too, but LNNext (with
		// nested LNEven) does not appear.
		return ((this.fa instanceof LNDisj) || (this.fa instanceof LNEven));
	}

	public final String toString() {
		return "<" + this.fa + ",\n " + this.fb + ",\n " + this.fc + ">";
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/Context.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

// Last modified on Tue 15 May 2007 at  9:35:56 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.semantic;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.Location;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import util.UniqueString;

// A context contains def/declNodes only.
// Implements a simple context for symbol decls and defs. Also
// supports the intial (or global) context of built-in operators.

// The pair construct is used to maintain a linked list of
// definitions.  This in turn will allow the extraction of a full
// context from anywhere in the tree, from the englobing definition.

// Merging: different forms of merging should be offered, depending
// what is being merged.  We always start with a clone of the
// initialContext.  Alterwards, we can Extend or Instantiate.  In one
// case, we import defs and decls; in the other, only defs; but we
// need to keep track of substitutions.

/**
 * A Context is an assignment of meanings to module names and to
 * symbol names, where a meaning is a SemNode.  At the moment, there
 * seems to be no need to provide methods to manipulate or do anything
 * with contexts except pass them to the Front End.
 */
public class Context implements ExploreNode {

  class Pair {
    Pair       link;
    SymbolNode info;

    // Note: Does not set lastPair
    Pair(Pair lnk, SymbolNode inf) {
      this.link = lnk;
      this.info = inf;
    }

    // Note: Does set lastPair
    Pair(SymbolNode inf) {
      this.link = lastPair;
      this.info = inf;
      lastPair = this;
    }

    public SymbolNode getSymbol() { return this.info; }

    /**
     * For a Pair node pr, let List(pr) be the sequence of
     * Pair nodes of length n defined by
     *
     *   List(pr)[1] = pr
     *   List(pr)[n].link = null
     *   \A i \in 1..(n-1) : List(pr)[i+1] = List(pr)[i].link
     *
     * Then reversePairList() is a Pair node such that
     * List(reversePairList()) has the same length n as
     * List(this), and whose elements are new Pair nodes such
     * that
     *
     *   \A i \in 1..n : List(reversePairList())[i].info =
     *                      List(this)[n-i+1].info
     */
    public Pair reversePairList() {
        Pair curResult = new Pair(null, this.info) ;
        Pair nextOriginal = this.link  ;
        while (nextOriginal != null) {
            curResult = new Pair(curResult, nextOriginal.info) ;
            nextOriginal = nextOriginal.link ;
        }
        return curResult ;
    }
  } // class Pair

  public class InitialSymbolEnumeration {

    Enumeration<Pair> e = initialContext.content();

    public boolean hasMoreElements() { return e.hasMoreElements(); }

    public SymbolNode nextElement() {
      return e.nextElement().getSymbol();
    }
  }

  public class ContextSymbolEnumeration {

    Enumeration<Pair> e = Context.this.content();

    public boolean hasMoreElements() { return e.hasMoreElements(); }

    public SymbolNode nextElement() {
      return e.nextElement().getSymbol();
    }

   /* public Element export(Document doc) {
      Element ret = doc.createElement("context");
      while (hasMoreElements()) {
        SymbolNode sn = nextElement();
        Element en = doc.createElement("entry");
        Element nm = doc.createElement("uniquename");
        nm.appendChild(doc.createTextNode(sn.getName().toString()));
        en.appendChild(nm);
        en.appendChild(sn.exportDefinition(doc));
        ret.appendChild(en);
      }
      return ret;
    }*/
  }

  private static Context initialContext = new Context(null, new Errors());
                                      // the one, static unique Context with builtin operators
                                      // null ModuleTable arg because this is shared by all modules

  private ExternalModuleTable exMT;   // The external ModuleTable that this context's SymbolTable
                                      // belongs to is null for global contex shared by all modules.

  private Errors         errors;      // Object in which to register errors
  private Hashtable<Object, Pair>      table;       // Mapping from symbol name to Pair's that include SymbolNode's
  private Pair           lastPair;    // Pair added last to the this.table

  /**
   * exMT is the ExternalModuleTable containing the module whose
   * SymbolTable this Context is part of (or null).
   */
  public Context(ExternalModuleTable mt, Errors errs) {
    table = new Hashtable<>();
    this.exMT = mt;
    this.errors = errs;
    this.lastPair = null;
  }

  /*
   * Reinitialize the initialContext module so that a new spec file
   * can be parsed; must be called at the beginning of each root file
   * of a spec.
   */
  public static void reInit() {
    initialContext =  new Context(null, new Errors()); // null because outside of any module
  }

  /**
   * This method returns a copy of the context that contains
   * declarations only of the built-in operators of TLA+.  This
   * context assigns no meanings to module names.
   */
  public static Context getGlobalContext() {
    return initialContext;
  }
  
	public static boolean isBuiltIn(final ExploreNode exploreNode) {
		final Collection<Pair> pairs = initialContext.table.values();
		for (Pair p : pairs) {
			if (exploreNode == p.info) {
				return true;
			}
		}
		return false;
	}

  public Errors getErrors() { return errors; }

  // Adds a symbol to the (unique) initialContext; aborts if already there
  public static void addGlobalSymbol(UniqueString name, SymbolNode sn, Errors errors)
  throws AbortException {
    if (initialContext.getSymbol(name) != null) {
      errors.addAbort(Location.nullLoc,
		      "Error building initial context: Multiply-defined builtin operator " +
		      name + " at " + sn, false );
    }
    else {
      initialContext.addSymbolToContext( name, sn );
      return;
    }
  }

  /**
   * Returns symbol node associated with "name" in this Context, if
   * one exists; else returns null
   */
  public SymbolNode getSymbol(Object name) {
    Pair r = (Pair)table.get(name);
    if (r != null) {
      return r.info;
    }
    return null;
  }

  /**
   * Adds a (UniqueString, SymbolNode) pair to this context; no-op if
   * already present
   * @param name the UniqueString representing the string, see {@link UniqueString#uniqueStringOf(String)}
   * @param s the symbol node to be put in
   */
  public void addSymbolToContext(Object name, SymbolNode s) {
    table.put(name, new Pair(s));    // Links to & updates lastPair
  }


  /**
   * Tests whether a name is present in this context
   * @param name the UniqueString representing the string, see {@link UniqueString#uniqueStringOf(String)}
   * @return true iff the UniqueString provided occurs as a key in the symbol table
   */
  public boolean occurSymbol(Object name) {
    return table.containsKey(name);
  }

  /**
   * Returns Enumeration of the elements of the Hashtable "Table",
   * which are pair of the form (Pair link, SymbolNode sn)
   */
  public Enumeration<Pair> content() {
    return table.elements();
  }

  /**
   * Returns a new ContextSymbolEnumeration object, which enumerates
   * the SymbolNodes of THIS context
   */
  public ContextSymbolEnumeration getContextSymbolEnumeration() {
    return new ContextSymbolEnumeration();
  }

  /**
   * Returns a Vector of those SymbolNodes in this Context that are
   * instances of class "template" (or one of its subclasses)
   */
  public Vector<SymbolNode> getByClass( Class<?> template ) {
    Vector<SymbolNode> result = new Vector<>();
    Enumeration<Pair> list = table.elements();
    while (list.hasMoreElements()) {
      Pair elt = list.nextElement();
      if (template.isInstance(elt.info)) {
        result.addElement( elt.info );
      }
    }
    return result;
  }

  /**
   * Returns a Vector of those SymbolNodes in this Context that are
   * instances of class OpDefNode and that are NOT of kind BuiltInKind
   * or ModuleInstanceKind
   */
  public Vector<OpDefNode> getOpDefs() {
      // SZ Apr 21, 2009: not used instance
      // Class template = OpDefNode.class;
    Pair nextPair = lastPair;

    Vector<OpDefNode> result = new Vector<>();
    while (nextPair != null) {
      if ( nextPair.info instanceof OpDefNode &&     // true for superclasses too.
           ((OpDefNode)nextPair.info).getKind() != ASTConstants.ModuleInstanceKind &&
           ((OpDefNode)nextPair.info).getKind() != ASTConstants.BuiltInKind  )
        result.addElement( (OpDefNode)(nextPair.info) );
      nextPair = nextPair.link;
    }
    return result;
  }

  /*************************************************************************
  * Returns a Vector of those SymbolNodes in this Context that are         *
  * instances of class ThmOrAssumpDefNode or ModuleInstanceKind            *
  * Code copied from getOpDefs().                                          *
  *************************************************************************/
  public Vector<ThmOrAssumpDefNode> getThmOrAssDefs() {
      // SZ Apr 21, 2009: not used instance
      // Class template = ThmOrAssumpDefNode.class;
    Pair nextPair = lastPair;

    Vector<ThmOrAssumpDefNode> result = new Vector<>();
    while (nextPair != null) {
      if ( nextPair.info instanceof ThmOrAssumpDefNode)
        { result.addElement( (ThmOrAssumpDefNode)(nextPair.info) );} ;
      nextPair = nextPair.link;
    }
    return result;
  }

  /**
   * Returns vector of OpDeclNodes that represent CONSTANT declarations
   */
  public Vector<SemanticNode> getConstantDecls() {
    Class<? extends SemanticNode> templateClass = OpDeclNode.class;
    Enumeration<Pair> list = table.elements();

    Vector<SemanticNode> result = new Vector<>();
    while (list.hasMoreElements()) {
      Pair elt = list.nextElement();
      if (templateClass.isInstance(elt.info) &&     // true for superclasses too.
         ((OpDeclNode)elt.info).getKind() == ASTConstants.ConstantDeclKind  )
        result.addElement( (SemanticNode)(elt.info) );

    }
    return result;
  }

  /* Returns vector of OpDeclNodes that represent CONSTANT declarations  */
  public Vector<SemanticNode> getVariableDecls() {
    Class<? extends SemanticNode> templateClass = OpDeclNode.class;
    Enumeration<Pair> list = table.elements();

    Vector<SemanticNode> result = new Vector<>();
    while (list.hasMoreElements()) {
      Pair elt = list.nextElement();
      if (templateClass.isInstance(elt.info) &&     // true for superclasses too.
           ((OpDeclNode)elt.info).getKind() == ASTConstants.VariableDeclKind  )
        result.addElement( (SemanticNode)(elt.info) );
    }
    return result;
  }

  /**
   * Returns a Vector of those SymbolNodes in this Context that are
   * instances of class ModuleNode
   */
  public Vector<SemanticNode> getModDefs() {
    Class<? extends SemanticNode> template = ModuleNode.class;
    Enumeration<Pair> list = table.elements();

    Vector<SemanticNode> result = new Vector<>();
    while (list.hasMoreElements()) {
      Pair elt = list.nextElement();
      if (template.isInstance(elt.info))    // true for superclasses too.
        result.addElement( (SemanticNode)(elt.info) );
    }
    return result;
  }

  // The following is a revised version of mergeExendContext that
  // fixes an apparent bug in the original in which elements of
  // Context ct are added to this context in the inverse order.
  // Corrected version written by LL on 12 Mar 2013
  /**
   * Restricted Context merge.  Invoked once in Generator class.
   * Merges Context "ct" into THIS Context, except for local symbols
   * in "ct" Two symbols clash if they have the same name AND a different
   * class; that is an error.  If they have the same name and class, they
   * are considered to be two inheritances of the same (or at least
   * compatible) declarations, and there is only a warning.  Returns
   * true if there is no error or there are only warnings; returns
   * false if there is an error.
   *
   * The original implementation added the elements of Context ct to
   * this context in the inverse order as they appear in ct.  It was
   * changed on 12 Mar 2013 by LL to add them in the same order.
   * 
   * Note that the return value is never used in our code base. (2020.03.06)
   */
	public boolean mergeExtendContext(final Context ct) {
		if (ct.lastPair == null) {
			// If the context represents an inner module that defines no EXTENDS, ct.lastPair will be null
			return true;
		}
		
		boolean erc = true;
		// check locality, and multiplicity
		// the .reversePairList was added to the following statement
		// by LL on 12 Mar 2013
		Pair p = ct.lastPair.reversePairList();
		while (p != null) {
			// Walk back along the list of pairs added to Context "ct"
			SymbolNode sn = p.info;

			// Ignore local symbols in Context "ct"
			if (!sn.isLocal()) {
				Object sName;
				if (sn instanceof ModuleNode) {
					sName = new SymbolTable.ModuleName(sn.getName());
				} else {
					sName = sn.getName();
				}

				if (!table.containsKey(sName)) {
					// If this context DOES NOT contain this name, add it:
					table.put(sName, new Pair(sn));
				} else {
					// If this Context DOES contain this name
					SymbolNode symbol = ((Pair) table.get(sName)).info;
					if (symbol != sn) {
						// if the two SymbolNodes with the same name are distinct nodes,
						// We issue a warning or do nothing if they are instances of the same Java
						// class--i.e. FormalParamNode, OpDeclNode, OpDefNode, or ModuleNode--doing
						// nothing if they are both definitions coming from the same module.
						// otherwise, it is considered to be an error.
						// Option of doing nothing if from same module added by LL on 31 Oct 2012 to
						// fix problem caused by the same module being both EXTENDed and imported with
						// a LOCAL INSTANCE. Previously, it always added the warning.
						if (symbol.getClass() == sn.getClass()) {
							if (!symbol.sameOriginallyDefinedInModule(sn)) {
								errors.addWarning(sn.getTreeNode().getLocation(),
										"Warning: the " + kindOfNode(symbol) + " of '" + sName.toString()
												+ "' conflicts with \nits " + kindOfNode(symbol) + " at "
												+ symbol.getTreeNode().getLocation() + ".");
							}
						} else {
							errors.addError(sn.getTreeNode().getLocation(),
									"The " + kindOfNode(symbol) + " of '" + sName.toString() + "' conflicts with \nits "
											+ kindOfNode(symbol) + " at " + symbol.getTreeNode().getLocation() + ".");

//                               "Incompatible multiple definitions of symbol '" +
//                               sName.toString() +
//                               "'; \nthe conflicting declaration is at " +
//                               symbol.getTreeNode().getLocation()+ ".");
							erc = false;
						} // end else
					} // end if
				} // end else
			}
			p = p.link;
		}
		return erc;
  }

  private static String kindOfNode(SymbolNode symbol) {
      if (symbol instanceof OpDefNode) {return "definition";}
      if (symbol instanceof FormalParamNode) {return "definition";}
      return "declaration";
  }

  /**
   * Returns a duplicate of this Context.  Called once from
   * SymbolTable class.  The tricky part is duplicating the
   * linked-list of Pairs starting from this.lastpair.
   */
  public Context duplicate(ExternalModuleTable exMT) {    // Added argument exMT (DRJ)
    Context dup       = new Context(exMT, errors);
    Pair    p         = this.lastPair;
    Pair    current   = null;
    boolean firstTime = true;

    while (p != null) {
      if (firstTime) {
        current = new Pair(null, p.info);     // Does NOT link to or update this.lastPair
        dup.lastPair = current;
        firstTime = false;
      }
      else {
	current.link = new Pair(null,p.info); // Note: causes sharing of reference in link.info
        current = current.link;
      }
      dup.table.put(current.info.getName(), current);
      p = p.link;
    }
    return dup;
  }

  /**
   * toString, levelDataToString, and walkGraph methods to implement
   * ExploreNode interface
   */
  public String levelDataToString() { return "Dummy level string"; }

  public String toString(int depth) {
    return "Please use Context.getContextEntryStringVector()" +
      " instead of Context.toString()";
  }

  /* Returns a vector of strings */

  /*************************************************************************
  * When trying to use SANY's -d (debug) option, this method throws a      *
  * NullPointerException if the spec has an inner module.  See the         *
  * comment in the walkGraph method of this file for a bit more            *
  * information.                                                           *
  *************************************************************************/
  public Vector<String> getContextEntryStringVector(int depth, boolean b) {
    Vector<String> ctxtEntries = new Vector<>(100);  // vector of Strings
    Context naturalsContext =
               exMT.getContext(UniqueString.uniqueStringOf("Naturals"));

    if (depth <= 0) return ctxtEntries;

    Pair p = lastPair;
    while (p != null) {
      UniqueString key = p.info.getName();

      // If b is false, don't bother printing the initialContext--too long--
      // and, don't bother printing elements of the Naturals module either
      if (b || (!initialContext.table.containsKey(key) &&
		(naturalsContext == null ||
		 !naturalsContext.table.containsKey(key)))) {
        SymbolNode symbNode  = ((Pair)(table.get(key))).info;
	ctxtEntries.addElement("\nContext Entry: " + key.toString() + "  "
                    + String.valueOf(((SemanticNode)symbNode).myUID).toString() + " "
                    + Strings.indentSB(2,(symbNode.toString(depth-1))));
      }
      p = p.link;
    }

    // Reverse the order of elements in the vector so they print properly
    String obj;
    int n = ctxtEntries.size();
    for (int i = 0; i < n/2; i++) {
      obj = ctxtEntries.elementAt(i);
      ctxtEntries.setElementAt(ctxtEntries.elementAt(n-1-i),i);
      ctxtEntries.setElementAt(obj, n-1-i);
    }
    return ctxtEntries;
  }

  public void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
	  visitor.preVisit(this);
    UniqueString key;
    Enumeration<?>  e = table.keys();

    while (e.hasMoreElements()) {
      /*********************************************************************
      * Bug fix attempted by LL on 19 Apr 2007.                            *
      *                                                                    *
      * The original code expected Enum.nextElement() to be a              *
      * UniqueString.  However, it can also be a SymbolTable.ModuleName    *
      * for an inner module.  I attempted to fix that by just getting key  *
      * from the right place in the object.  However, that caused a        *
      * NullPointerException because table.get(key) equaled null.  So, I   *
      * just had the code print a warning and ignore the entry for the     *
      * inner module.  However, this caused a NullPointerException in      *
      * getContextEntryStringVector later on.  I decided to stop wasting   *
      * time on this.                                                      *
      *********************************************************************/
      Object next = e.nextElement();
      if (next instanceof SymbolTable.ModuleName) {
         key = ((SymbolTable.ModuleName) next).name ;
         System.out.println("Bug in debugging caused by inner module " +
                             key.toString());
         System.out.println("SANY will throw a null pointer exception.");
        }
      else {
        key = (UniqueString) next;
        ((Pair)table.get(key)).info.walkGraph(semNodesTable, visitor);
       } ;
       visitor.postVisit(this);
    }

  }

  /*public Element export(Document doc) {
    return getContextSymbolEnumeration().export(doc);
  }*/
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/BEGraph.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:31 PST by lamport
//      modified on Wed Dec  5 22:41:28 PST 2001 by yuanyu

package tlc2.tool.liveness;

import tlc2.output.EC;
import tlc2.tool.EvalException;
import tlc2.util.MemObjectQueue;
import tlc2.util.MemObjectStack;
import tlc2.util.Vect;

public class BEGraph {
	/**
	 * BEGraph represents the behaviour graph.
	 */
	public Vect<BEGraphNode> initNodes;
	public String metadir;
	public NodeTable allNodes;

	public BEGraph(String metadir, boolean isBT) {
		this.initNodes = new Vect<>();
		this.metadir = metadir;
		this.allNodes = new NodeTable(127, isBT);
	}

	/**
	 * This method resets the number field of all nodes in this behavior graph
	 * to 0. Assume that all the nodes have non-zero number fields.
	 */
	public final void resetNumberField() {
		MemObjectStack stack = new MemObjectStack(this.metadir, "resetstack");
		for (int i = 0; i < this.initNodes.size(); i++) {
			BEGraphNode node = (BEGraphNode) this.initNodes.elementAt(i);
			if (node.resetNumberField() != 0) {
				stack.push(this.initNodes.elementAt(i));
			}
		}
		while (stack.size() != 0) {
			BEGraphNode node = (BEGraphNode) stack.pop();
			for (int i = 0; i < node.nextSize(); i++) {
				BEGraphNode node1 = node.nextAt(i);
				if (node1.resetNumberField() != 0) {
					stack.push(node1);
				}
			}
		}
	}

	/* Returns the ith initial node. */
	public final BEGraphNode getInitNode(int i) {
		return (BEGraphNode) this.initNodes.elementAt(i);
	}

	public final void addInitNode(BEGraphNode node) {
		this.initNodes.addElement(node);
	}

	/* Returns the number of initial nodes. */
	public final int initSize() {
		return this.initNodes.size();
	}

	/* Returns the shortest path from start to end (inclusive). */
	public static BEGraphNode[] getPath(BEGraphNode start, BEGraphNode end) {
		if (start.equals(end)) {
			start.setParent(null);
		} else {
			boolean unseen = start.getVisited();
			MemObjectQueue queue = new MemObjectQueue(null); // bomb if
			// checkpoint
			start.flipVisited();
			queue.enqueue(new NodeAndParent(start, null));
			boolean found = false;
			while (!found) {
				NodeAndParent np = (NodeAndParent) queue.dequeue();
				if (np == null) {
					throw new EvalException(EC.TLC_LIVE_BEGRAPH_FAILED_TO_CONSTRUCT);
				}
				BEGraphNode curNode = np.node;
				for (int i = 0; i < curNode.nextSize(); i++) {
					BEGraphNode nextNode = curNode.nextAt(i);
					if (nextNode.getVisited() == unseen) {
						if (nextNode.equals(end)) {
							end.setParent(curNode);
							found = true;
							break;
						}
						nextNode.flipVisited();
						queue.enqueue(new NodeAndParent(nextNode, curNode));
					}
				}
				curNode.setParent(np.parent);
			}
		}
		// Get the path following parent pointers:
		Vect<BEGraphNode> path = new Vect<>();
		BEGraphNode curNode = end;
		while (curNode != null) {
			path.addElement(curNode);
			curNode = curNode.getParent();
		}
		int sz = path.size();
		BEGraphNode[] bpath = new BEGraphNode[sz];
		for (int i = 0; i < sz; i++) {
			bpath[i] = (BEGraphNode) path.elementAt(sz - i - 1);
		}
		return bpath;
	}

	/**
	 * This method assumes that the visited field of all the nodes is set to the
	 * same value.
	 */
	public final String toString() {
		StringBuffer buf = new StringBuffer();
		int sz = this.initNodes.size();
		if (sz != 0) {
			boolean seen = this.getInitNode(0).getVisited();
			for (int i = 0; i < this.initNodes.size(); i++) {
				BEGraphNode node = this.getInitNode(i);
				node.toString(buf, seen);
			}
		}
		return buf.toString();
	}

	private static class NodeAndParent {
		BEGraphNode node;
		BEGraphNode parent;

		NodeAndParent(BEGraphNode node, BEGraphNode parent) {
			this.node = node;
			this.parent = parent;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.uitest/src/org/lamport/tla/toolbox/SmokeTests.java<|end_filename|>
package org.lamport.tla.toolbox;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.lamport.tla.toolbox.tool.tlc.ui.test.ModelCheckerTest;
import org.lamport.tla.toolbox.ui.handler.CloneModelTest;
import org.lamport.tla.toolbox.ui.handler.RenameSpecHandlerTest;

@RunWith(Suite.class)
@SuiteClasses({
    ModelCheckerTest.class,
    CloneModelTest.class,
    RenameSpecHandlerTest.class
})

public class SmokeTests {}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/callable/BitVectorWrapper.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp.callable;

import tlc2.util.BitVector;

public class BitVectorWrapper {
	
	private final int index;
	private final BitVector bitVector;
	
	public BitVectorWrapper(final int index, final BitVector bv) {
		this.index = index;
		this.bitVector = bv;
	}

	/**
	 * @return the bitVector
	 */
	public BitVector getBitVector() {
		return bitVector;
	}

	/**
	 * @return the index
	 */
	public int getIndex() {
		return index;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/StopLaunchHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.tool.tlc.model.Model;

/**
 * Stops model launches
 * @author <NAME>
 */
public class StopLaunchHandler extends AbstractHandler
{
    public static final String ID = "toolbox.tool.tlc.commands.model.stop";

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        ISelection selection = HandlerUtil.getCurrentSelection(event);
        if (selection instanceof IStructuredSelection && !((IStructuredSelection) selection).isEmpty())
        {
            IStructuredSelection structSelection = ((IStructuredSelection) selection);

            Iterator modelIterator = structSelection.iterator();
            while (modelIterator.hasNext())
            {
                Object element = modelIterator.next();
                if (element instanceof Model)
                {
                	Model model = (Model) element;
                    if (model.isRunning())
                    {
                        Job[] runningSpecJobs = Job.getJobManager().find(model.getLaunchConfiguration());
                        for (int i = 0; i < runningSpecJobs.length; i++)
                        {
                            // send cancellations to all jobs...
                            runningSpecJobs[i].cancel();
                        }
                    }
                }
            }
        }
        return null;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/creating-model.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/creating-model.html  -->


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Creating a Model</title>
</head>
<!-- a comment here -->

<body>
<h1>Creating a Model</h1>

<P>
When you open a model, you open it in a <em>model editor</em>.&nbsp;  The model editor then
shows only one page if the model has never been run before, and if it has been opened before,
no other pages were kept open: &mdash; the  <A href="overview-page.html"> Model Overview Page.</A>
<br/>
If the model has been run before, the <A href="results-page.html"> Model Checking Results Page</A> will
be opened showing what the checker did the last time it was
run.&nbsp; The Model Overview Page contains links that open three other pages,
the <A href="spec-options-page.html">Spec Options</A> page, the
<A href="tlc-options-page.html">TLC Options</A> page, and the Results / Constant Expressions page(s)
should you want to work with Constant Expressions having not yet run the model a first time.

You can switch between the pages using the tabs at the upper-left of the
model editor <a href="../gettingstarted/views.html">view</a>, or with the&nbsp;
<samp>Alt+PageUp</samp>&nbsp; and&nbsp;
<samp>Alt+PageDown</samp>&nbsp; keys.
 </P>

<p>You edit these pages in the usual way.&nbsp;  Sections can be opened or closed by clicking
the&nbsp;
<samp>+</samp>&nbsp; or&nbsp;
<samp>-</samp>&nbsp;.  When entering text in fields, you can use your system's
standard editing commands.
</p>


<p>Whenever you enter a TLA<sup>+</sup> expression as part of the model,
that expression can use any
symbols that you could use in a new definition placed at the end of the spec's root module.&nbsp;
It can also contain any <a href="model-values.html">model values</a> that are declared
in the model, as well as additional definitions entered in the
<a href="spec-options-page.html#additional">Additional Definitions</a> section
of the Spec Options page.
</p>

<hr>
<!-- delete rest of line to comment out -->
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href="overview-page.html"> Model Overview Page</A></dd>
<dd> <A href="results-page.html"> Model Checking Results Page</A></dd>
<dd> <A href="spec-options-page.html">Spec Options Page</A></dd>
<dd> <A href="tlc-options-page.html">TLC Options Page</A></dd>

</dl>
<!-- -->
<!-- delete rest of line to comment out -->
<a href = "model.html">&uarr; Model Checking</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MultiFPSetConfiguration.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

@SuppressWarnings("serial")
class MultiFPSetConfiguration extends FPSetConfiguration {

	public MultiFPSetConfiguration(final FPSetConfiguration fpSetConfig) {
		// Do not use getter method as it does not necessarily return the member
		// value
		this.memoryInBytes = fpSetConfig.memoryInBytes;
		// Set wrapper to values of config to be wrapped
		this.fpBits = fpSetConfig.getFpBits();
		this.ratio = fpSetConfig.getRatio();
		this.implementation = fpSetConfig.getImplementation();		
		// Sanity check configuration right away
		if (getMemoryInFingerprintCnt() <= 0) {
			throw new IllegalArgumentException(
					"Given fpSetConfig results in zero or negative fp count.");
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSetConfiguration#allowsNesting()
	 */
	public boolean allowsNesting() {
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSetConfiguration#getMemoryInBytes()
	 */
	public long getMemoryInBytes() {
		return super.getMemoryInBytes() / getMultiFPSetCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSetConfiguration#getMemoryInFingerprintCnt()
	 */
	public long getMemoryInFingerprintCnt() {
		// No need to divide by getMultiFPSetCnt because calls to
		// super.getMemoryInFingerprintCnt eventually calls getMemoryInBytes above.
		// Dividing by getMultiFPSetCnt here again will waste half the
		// available memory.
		return super.getMemoryInFingerprintCnt();
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/AbstractBucketStatistics.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util.statistics;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NavigableMap;

import javax.management.NotCompliantMBeanException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.management.TLCStandardMBean;
import tlc2.util.statistics.management.BucketStatisticsMXWrapper;

public abstract class AbstractBucketStatistics implements IBucketStatistics {

	/**
	 * Human readable statistics name (used in toString())
	 */
	protected final String title;

	public AbstractBucketStatistics(String aTitle) {
		super();
		this.title = aTitle;
	}

	/**
	 * @param aTitle
	 *            A title for console pretty printing
	 * @param pkg
	 *            A package name for this statistics, e.g. tlc2.tool.liveness
	 *            for stats are from classes in the liveness package.
	 * @param name
	 *            The (class) name of the source of the statistics.
	 */
	public AbstractBucketStatistics(final String aTitle, final String pkg, final String name) {
		this(aTitle);
		try {
			//TODO unregister somehow
			new BucketStatisticsMXWrapper(this, name, pkg);
		} catch (NotCompliantMBeanException e) {
			// not expected to happen would cause JMX to be broken, hence just log and
			// continue
			MP.printWarning(
					EC.GENERAL,
					"Failed to create MBean wrapper for BucketStatistics. No statistics/metrics will be avaiable.",
					e);
			TLCStandardMBean.getNullTLCStandardMBean();
		}
	}

	public String toString() {
		final StringBuffer buf = new StringBuffer();
		buf.append("============================%n");
		buf.append("=" + title + "=%n");
		buf.append("============================%n");
		buf.append(String.format("Observations: %d%n", getObservations()));
		buf.append(String.format("Min: %d%n", getMin()));
		buf.append(String.format("Max: %d%n", getMax()));
		buf.append(String.format("Mean: %.2f%n", getMean()));
		buf.append(String.format("Median: %d%n", getMedian()));
		buf.append(String.format("Standard deviation: %.2f%n", getStdDev()));
		buf.append(String.format("75%%: %.2f%n", getPercentile(0.75d)));
		buf.append(String.format("95%%: %.2f%n", getPercentile(0.95d)));
		buf.append(String.format("98%%: %.2f%n", getPercentile(0.98d)));
		buf.append(String.format("99%%: %.2f%n", getPercentile(0.99d)));
		buf.append(String.format("99.9%%: %.2f%n", getPercentile(0.999d)));
		buf.append("numEdges/occurrences (log scale)%n");
		buf.append("--------------------------------%n");
		final Iterator<Entry<Integer, Long>> iterator = getSamples().entrySet().iterator();
		while(iterator.hasNext()) {
			Entry<Integer, Long> next = iterator.next();
			long amount = next.getValue();
			int i = next.getKey();
			buf.append(String.format("%02d", i));
			buf.append(":");
			buf.append(String.format("%02d", amount));
			buf.append(" ");
			for (int j = 0; j < Math.log(amount); j++) {
				buf.append("#");
			}
			buf.append("%n");
		}
		buf.append("============================");
		return buf.toString();
	}

	public int getMedian() {
		long l = getObservations();
		if (l <= 0) {
			return -1;
		}
		// skip forward for as many elements as 1/2 observations. The 
		// corresponding bucket is the median.
		long sum = 0L;
		final Iterator<Entry<Integer, Long>> iterator = getSamples().entrySet().iterator();
		while(iterator.hasNext()) {
			final Entry<Integer, Long> next = iterator.next();
			sum += next.getValue();
			if (sum > (l / 2)) {
				return next.getKey();
			}
		}
		// make compiler happy
		throw new RuntimeException("bug, shoud not get here");
	}

	public double getMean() {
		long sum = 0L;
		// Sum up values and count
		final Iterator<Entry<Integer, Long>> iterator = getSamples().entrySet().iterator();
		while(iterator.hasNext()) {
			final Entry<Integer, Long> next = iterator.next();
			final long value = next.getValue();
			final int i = next.getKey();
			sum += value * i;
		}
		if (getObservations() > 0) {
			return (sum / (getObservations() * 1.0d));
		} else {
			// No mean yet
			return -1;
		}
	}

	public int getMin() {
		if (getObservations() <= 0) {
			return -1;
		}
		return getSamples().firstKey();
	}

	public int getMax() {
		if (getObservations() <= 0) {
			return -1;
		}
		return getSamples().lastKey();
	}

	public double getStdDev() {
		final long N = getObservations();
		if (N <= 0) {
			return -1.0d;
		}
		final double mean = getMean() * 1.0d;
		double sum = 0.0d;
		final Iterator<Entry<Integer, Long>> iterator = getSamples().entrySet().iterator();
		while(iterator.hasNext()) {
			Entry<Integer, Long> next = iterator.next();
			double Xi = next.getKey() * 1.0d;
			double diff = Xi - mean;
			sum += (diff * diff) * ((next.getValue() * 1.0d)); // diff^2
		}
		double variance = sum / (N * 1.0d);
		double stdDev = Math.sqrt(variance);
		return stdDev;
	}

	public double getPercentile(double quantile) {
		if (Double.isNaN(quantile)) {
			throw new IllegalArgumentException("NaN");
		}
		final long obsv = getObservations();
		if (obsv <= 0) {
			return -1.0;
		}
		// adjust values to valid range
		quantile = Math.min(1.0, quantile);
		quantile = Math.max(0, quantile);
		
		final NavigableMap<Integer, Long> samples = getSamples();

		// calculate the elements position for the
		// given quantile
	    final int pos = (int) ((obsv * 1.0d) * quantile);
		if (pos > obsv) {
	    	return samples.size();
	    }
	    if (pos < 0) {
	    	return 0;
	    }
	    
	    // advance to the bucket at position
	    long cnt = 0l;
		final Iterator<Entry<Integer, Long>> iterator = samples.entrySet().iterator();
		while(iterator.hasNext()) {
			Entry<Integer, Long> next = iterator.next();
			int i  = next.getKey();
			cnt += next.getValue();
			if (cnt > pos) {
				return i;
			}
		}
		return quantile;
	}

}

<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/FoldAllRegionsHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.util.ResourceBundle;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.ui.editors.text.IFoldingCommandIds;
import org.eclipse.ui.texteditor.TextOperationAction;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;

/**
 * Collapse all foldable regions in the editor in focus.
 */
public class FoldAllRegionsHandler extends AbstractHandler {
	private static final String BUNDLE_NAME= "org.eclipse.jdt.internal.ui.actions.FoldingMessages";
	private static final ResourceBundle RESOURCE_BUNDLE= ResourceBundle.getBundle(BUNDLE_NAME);

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
        final TLAEditor editor = EditorUtil.getTLAEditorWithFocus();

		if (editor != null) {
			final TextOperationAction action = new TextOperationAction(RESOURCE_BUNDLE, "Projection.CollapseAll.", editor,
					ProjectionViewer.COLLAPSE_ALL, true);

			action.setActionDefinitionId(IFoldingCommandIds.FOLDING_COLLAPSE_ALL);
			action.run();
        }

        return null;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/BuiltInLevel.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

// Last modified on Mon 16 February 2009 at 10:05:22 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.semantic;

import java.util.HashMap;

import util.WrongInvocationException;

public class BuiltInLevel implements LevelConstants {

  /** 
   * The builtInLevelData array of strings contains level data for
   * each built-in operator in the language. When the arity of an
   * operator is -1, then the argWeight and argMaxLevel are just
   * at the top parenthetical level.
   */
  static class Data {
    int arity;
    int opLevel;
    int[] argMaxLevels;
    int[] argWeights;

    Data(int arity, int opLevel, int[] argMaxLevels, int[] argWeights) {
      this.arity = arity;
      this.opLevel = opLevel;
      this.argMaxLevels = argMaxLevels;
      this.argWeights = argWeights;
    }
  }
    
  private static HashMap LevelData = new HashMap();

  static int[] make() { return new int[0]; }

  static int[] make(int x) {
    int[] res = { x };
    return res;
  }

  static int[] make(int x, int y) {
    int[] res = { x, y };
    return res;
  }

  static int[] make(int x, int y, int z) {
    int[] res = { x, y, z };
    return res;
  }

  static Data data(int arity, int opLevel, int[] argMaxLevels, int[] argWeights) {
    return new Data(arity, opLevel, argMaxLevels, argWeights);
  }
  
  static {
    //                                       arity  opLevel  argMaxLevels   argWeights
    LevelData.put("STRING",               data(0,     0,       make(),       make()));
    LevelData.put("FALSE",                data(0,     0,       make(),       make()));
    LevelData.put("TRUE",                 data(0,     0,       make(),       make()));
    LevelData.put("BOOLEAN",              data(0,     0,       make(),       make()));
    LevelData.put("=",                    data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("/=",                   data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("'",                    data(1,     2,       make(1),      make(0)));
    LevelData.put("\\lnot",               data(1,     0,       make(3),      make(1)));
    LevelData.put("\\land",               data(2,     0,       make(3,3),    make(1,1)));
    LevelData.put("\\lor",                data(2,     0,       make(3,3),    make(1,1)));
    LevelData.put("\\equiv",              data(2,     0,       make(3,3),    make(1,1)));
    LevelData.put("=>",                   data(2,     0,       make(3,3),    make(1,1)));
    LevelData.put("SUBSET",               data(1,     0,       make(2),      make(1)));
    LevelData.put("UNION",                data(1,     0,       make(2),      make(1)));
    LevelData.put("DOMAIN",               data(1,     0,       make(2),      make(1)));
    LevelData.put("\\subseteq",           data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\in",                 data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\notin",              data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\",                   data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\intersect",          data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\union",              data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("\\times",              data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("~>",                   data(2,     3,       make(3,3),    make(0,0)));
    LevelData.put("[]",                   data(1,     3,       make(3),      make(0)));
    LevelData.put("<>",                   data(1,     3,       make(3),      make(0)));
    LevelData.put("ENABLED",              data(1,     1,       make(2),      make(0)));
    LevelData.put("UNCHANGED",            data(1,     2,       make(1),      make(0)));
    LevelData.put("\\cdot",               data(2,     2,       make(2,2),    make(0,0)));
    LevelData.put("-+->",                 data(2,     3,       make(3,3),    make(0,0)));
    LevelData.put("$AngleAct",            data(2,     2,       make(2,1),    make(0,0)));
    LevelData.put("$BoundedChoose",       data(-1,    0,       make(2),      make(1)));
    LevelData.put("$BoundedExists",       data(-1,    0,       make(3),      make(1)));
    LevelData.put("$BoundedForall",       data(-1,    0,       make(3),      make(1)));
    LevelData.put("$CartesianProd",       data(-1,    0,       make(2),      make(1)));
    LevelData.put("$Case",                data(-1,    0,       make(3),      make(1)));
    LevelData.put("$ConjList",            data(-1,    0,       make(3),      make(1)));    
    LevelData.put("$DisjList",            data(-1,    0,       make(3),      make(1)));
    LevelData.put("$Except",              data(-1,    0,       make(2),      make(1)));
    LevelData.put("$FcnApply",            data(2,     0,       make(2,2),    make(1,1)));
    LevelData.put("$FcnConstructor",      data(-1,    0,       make(3),      make(1)));
    LevelData.put("$IfThenElse",          data(3,     0,       make(3,3,3),  make(1,1,1)));
    LevelData.put("$NonRecursiveFcnSpec", data(1,     0,       make(3),      make(1)));
    LevelData.put("$Pair",                data(2,     0,       make(3,3),    make(1,1)));
    LevelData.put("$RcdConstructor",      data(-1,    0,       make(3),      make(1)));
    LevelData.put("$RcdSelect",           data(2,     0,       make(2,0),    make(1,1)));
    LevelData.put("$RecursiveFcnSpec",    data(1,     0,       make(3),      make(1)));
    LevelData.put("$Seq",                 data(-1,    0,       make(2),      make(1)));
    LevelData.put("$SetEnumerate",        data(-1,    0,       make(2),      make(1)));
    LevelData.put("$SetOfAll",            data(-1,    0,       make(2),      make(1)));
    LevelData.put("$SetOfFcns",           data(-1,    0,       make(2),      make(1)));
    LevelData.put("$SetOfRcds",           data(-1,    0,       make(2),      make(1)));
    LevelData.put("$SF",                  data(2,     3,       make(1,2),    make(0,0)));
    LevelData.put("$SquareAct",           data(2,     2,       make(2,1),    make(0,0)));
    LevelData.put("$SubsetOf",            data(1,     0,       make(2),      make(1)));
    LevelData.put("$TemporalExists",      data(1,     3,       make(3),      make(0)));
    LevelData.put("$TemporalForall",      data(1,     3,       make(3),      make(0)));
    LevelData.put("$TemporalWhile",       data(2,     3,       make(3,3),    make(0,0)));
    LevelData.put("$Tuple",               data(-1,    0,       make(2),      make(1)));
    LevelData.put("$UnboundedChoose",     data(1,     0,       make(2),      make(1)));
    LevelData.put("$UnboundedExists",     data(1,     0,       make(3),      make(1)));
    LevelData.put("$UnboundedForall",     data(1,     0,       make(3),      make(1)));
    LevelData.put("$WF",                  data(2,     3,       make(1,2),    make(0,0)));

    /***********************************************************************
    * The following added by LL on 2 Aug 2007.                             *
    ***********************************************************************/
    //                                       arity  opLevel  argMaxLevels   argWeights
    LevelData.put("$Nop",                 data(1,     0,       make(3),      make(1)));
    LevelData.put("$Qed",                 data(0,     0,       make(),       make()));
    LevelData.put("$Pfcase",              data(1,     0,       make(3),      make(1)));
    LevelData.put("$Have",                data(1,     0,       make(3),      make(1)));
    LevelData.put("$Take",                data(1,     0,       make(3),      make(1)));
    LevelData.put("$Pick",                data(1,     0,       make(3),      make(1)));
    LevelData.put("$Witness",             data(-1,    0,       make(2),       make(1)));

    /***********************************************************************
    * $Suffices added by LL 16 Feb 2009.                                   *
    ***********************************************************************/
    LevelData.put("$Suffices",            data(1,     0,       make(3),      make(1)));
  }   

  /**
   * Set up level data for built-in operators using LevelData.
   */
  public static void load () {
    Context gcon = Context.getGlobalContext();
    Context.ContextSymbolEnumeration Enum = gcon.getContextSymbolEnumeration();

    while (Enum.hasMoreElements()) {
      SymbolNode sn = Enum.nextElement();
      Data d = (Data)LevelData.get(sn.getName().toString());
      if (d != null) {
	OpDefNode opDef = (OpDefNode)gcon.getSymbol(sn.getName());
	if (opDef.getArity() != d.arity) {
	    throw new WrongInvocationException("Level data for " + sn.getName() + " has the wrong arity");
	}
	opDef.setBuiltinLevel(d);
      }	
    }
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/ConsoleProverProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui;

import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.console.MessageConsole;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;
import org.lamport.tla.toolbox.tool.prover.output.IProverProcessOutputSink;

/**
 * This output sink sends text to the TLAPM console.
 * 
 * This class receives output by registering at the extension point
 * org.lamport.tla.toolbox.tool.prover.processOutputSink.
 * 
 * @author <NAME>
 *
 */
public class ConsoleProverProcessOutputSink implements IProverProcessOutputSink
{

    private MessageConsole console;
    private IOConsoleOutputStream outputStream;

    public ConsoleProverProcessOutputSink()
    {
        this.console = TLAPMConsoleFactory.getTLAPMConsole();
        this.outputStream = this.console.newOutputStream();
    }

    /**
     * Sends text to the TLAPM console.
     */
    public void appendText(String text)
    {
        try
        {
            this.outputStream.write(text.getBytes());
        } catch (IOException e)
        {
            ProverUIActivator.getDefault().logError("Error printing a console message: >" + text + "<", e);
        }
    }

    public void initializeSink(IFile moduleFile, ProverJob proverJob, IProgressMonitor monitor)
    {
        // TODO Auto-generated method stub

    }

    public void processFinished()
    {
        // TODO Auto-generated method stub

    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/ui/util/UtilTests.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import junit.framework.Test;
import junit.framework.TestSuite;

public class UtilTests
{

    public static Test suite()
    {
        TestSuite suite = new TestSuite("Test for org.lamport.tla.toolbox.tool.tlc.ui.util");
        // $JUnit-BEGIN$
        suite.addTestSuite(ParsingToolkitTest.class);
        suite.addTestSuite(FormHelperTest.class);
        suite.addTestSuite(SemanticHelperTest.class);
        // $JUnit-END$
        return suite;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/PosAndCol.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS PosAndCol                                                          *
*                                                                          *
* A PosAndCol object is a Position extended by a column field.  It has a   *
* the method:                                                              *
*                                                                          *
*   void sort(PosAndCol[] array)                                           *
*                                                                          *
*      Sorts the array first by column and, within column, by line.        *
***************************************************************************/
package tla2tex;
// import tlatex.Position;
//import java.util.Comparator;
public class PosAndCol extends Position implements Comparable<PosAndCol>
 { public int column ;

   public PosAndCol(int l, int i, int c)
    { item = i ;
      line = l ;
      column = c ;
    } ;
   
 
   public String toString()
    { return   "[line |-> " + line + ", item |-> " + item 
             + ", col |-> " + column + "]";
    }

	@Override
	public int compareTo(final PosAndCol other) {
		if (column == other.column) {
			return Integer.compare(line, other.line);
		}
		return Integer.compare(column, other.column);
	}
  }

/* Last modified on Tue 18 Sep 2007 at  6:51:12 PST0by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/CheckModelHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.forms.editor.IFormPage;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.page.BasicFormPage;
import org.lamport.tla.toolbox.util.UIHelper;

public class CheckModelHandler extends AbstractHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        IEditorPart activeEditor = UIHelper.getActiveEditor();
        if (activeEditor != null)
        {
            if (activeEditor instanceof ModelEditor)
            {
                ModelEditor activeModelEditor = (ModelEditor) activeEditor;
                IFormPage page = activeModelEditor.getActivePageInstance();
                if (page instanceof BasicFormPage)
                {
                    BasicFormPage activePage = (BasicFormPage) page;
                    activePage.doRun();
                }
            }
        }
        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActiveEditor() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/ByteUtilsTest.java<|end_filename|>
package tlc2.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Random;

import org.junit.Before;
import org.junit.Test;

import util.ToolIO;

/**
 * Test case for BinUtils
 * @author <NAME>
 * @version $Id$
 */
public class ByteUtilsTest
{
    public static final int ARRAYSIZE = 10000;
    public static final int BITS = 1000;
    
    private File testFileB;
    private File testFileA;

    BigInteger Arr[];
    BigInteger Arr2[];
    BigInteger Arr3[];
    BigInteger Arr4[];
    BigInteger Arr5[];
    long t1;
    long t2;

    @Before
	public void setUp() throws Exception
    {
        Arr = new BigInteger[ARRAYSIZE];
        Arr2 = new BigInteger[ARRAYSIZE];
        Arr3 = new BigInteger[ARRAYSIZE];
        Arr4 = new BigInteger[ARRAYSIZE];
        Arr5 = new BigInteger[ARRAYSIZE];

        // create temp files for unit tests
        testFileA = File.createTempFile("ByteUtilsTestA", null);
        testFileA.deleteOnExit();

        testFileB = File.createTempFile("ByteUtilsTestB", null);
        testFileB.deleteOnExit();
        
        // SZ Feb 20, 2009: no ide what it is for...
        // to load classes ?
        // Class args[] = { Class.forName("java.math.BigInt"), Class.forName("java.math.BigInt") };

    }

    @Test
	public void test1()
    {
        t1 = System.currentTimeMillis();
        mainTestinttoByte();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing IntToByteArray took " + (t2 - t1) + "ms");
    }

    @Test
	public void test2() throws FileNotFoundException, IOException
    {
        t1 = System.currentTimeMillis();
        mainTestWriteIntReadInt();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing WriteInt, ReadInt took " + (t2 - t1) + "ms");
    }

    @Test
	public void test3()
    {
        t1 = System.currentTimeMillis();
        mainTestlongtoByte();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing longToByteArray took " + (t2 - t1) + "ms");
    }

    @Test
	public void test4() throws FileNotFoundException, IOException
    {
        t1 = System.currentTimeMillis();
        mainTestWriteLongReadLong();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing WriteLong, ReadLong took " + (t2 - t1) + "ms");
    }

    @Test
	public void test5() throws FileNotFoundException, IOException
    {
        t1 = System.currentTimeMillis();
        mainTestWriteReadSizeByteArray();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing Write, Read took " + (t2 - t1) + "ms");
    }

    @Test
	public void test6() throws FileNotFoundException, IOException
    {
        t1 = System.currentTimeMillis();
        mainTestAppend();
        t2 = System.currentTimeMillis();
        ToolIO.out.println("Testing Append took " + (t2 - t1) + "ms");
    }

    private void mainTestinttoByte()
    {
        int i, j;
        byte[] b;
        Random r = new Random();

        for (j = 0; j < 10000; j += 1)
        {
            i = r.nextInt();
            b = ByteUtils.intToByteArray(i);
            if ((i != ByteUtils.byteArrayToInt(b)) || (b.length != 4))
                ToolIO.out.println("i :" + i + "    byte :" + b + "    i: " + ByteUtils.byteArrayToInt(b)
                        + "    size: " + b.length);
        }
    }

    private void mainTestWriteIntReadInt() throws IOException, FileNotFoundException
    {
        FileOutputStream fout = new FileOutputStream(testFileA);

        int i, j;
        int A[] = new int[10000];

        Random r = new Random();

        for (j = 0; j < 10000; j += 1)
        {
            A[j] = r.nextInt();
            ByteUtils.writeInt(fout, A[j]);
        }

        fout.flush();
        fout.close();

        FileInputStream fin = new FileInputStream(testFileA);

        for (j = 0; j < 10000; j += 1)
        {
            i = ByteUtils.readInt(fin);
            if (i != A[j])
                ToolIO.out.println("i :" + i + "   A[j]: " + A[j]);
        }
    }

    private void mainTestlongtoByte()
    {
        long i, j;
        byte[] b;
        Random r = new Random();

        for (j = 0; j < 10000; j += 1)
        {
            i = r.nextLong();
            b = ByteUtils.longToByteArray(i);
            if ((i != ByteUtils.byteArrayToLong(b)) || (b.length != 8))
                ToolIO.out.println("i :" + i + "    byte :" + b + "    i: " + ByteUtils.byteArrayToLong(b)
                        + "    size: " + b.length);
        }
    }

    private void mainTestWriteLongReadLong() throws IOException, FileNotFoundException
    {
        FileOutputStream fout = new FileOutputStream(testFileA);

        long i;
        int j;
        long A[] = new long[10000];

        Random r = new Random();

        for (j = 0; j < 10000; j += 1)
        {
            A[j] = r.nextLong();
            ByteUtils.writeLong(fout, A[j]);
        }

        fout.close();

        FileInputStream fin = new FileInputStream(testFileA);

        for (j = 0; j < 10000; j += 1)
        {
            i = ByteUtils.readLong(fin);
            if (i != A[j])
                ToolIO.out.println("i :" + i + "   A[j]: " + A[j]);
        }
    }

    private void mainTestWriteReadSizeByteArray() throws IOException, FileNotFoundException
    {
        FileOutputStream fout = new FileOutputStream(testFileA);

        int j;
        BigInt[] A = new BigInt[ARRAYSIZE];
        BigInt[] B = new BigInt[ARRAYSIZE];
        BigInt[] C;

        mainInitialize(A, B);
        int half = (ARRAYSIZE - 1) / 2;

        ByteUtils.writeSizeArrayOfSizeBigInts(A, 0, half - 1, fout);
        ByteUtils.writeSizeArrayOfSizeBigInts(A, half, ARRAYSIZE - 1, fout);

        fout.flush();
        fout.close();

        FileInputStream fin = new FileInputStream(testFileA);

        B = ByteUtils.readSizeArrayOfSizeBigInts(fin);
        ByteUtils.readInt(fin);
        C = ByteUtils.readArrayOfSizeBigInts(fin);

        for (j = 0; j < half; j++)
        {
            if (!A[j].equals(B[j]))
                ToolIO.out.println("A[" + j + "] :" + A[j] + "   B[" + j + "]: " + B[j]);
        }

        for (j = half; j < ARRAYSIZE; j++)
        {
            if (!A[j].equals(C[j - half]))
                ToolIO.out.println("A[" + j + "] :" + A[j] + "   C[" + (j - half) + "]: " + C[j - half]);
        }
    }

    private void mainTestAppend() throws IOException, FileNotFoundException
    {
        FileOutputStream fout = new FileOutputStream(testFileA);

        int j;
        BigInt[] A = new BigInt[ARRAYSIZE];
        BigInt[] B = new BigInt[ARRAYSIZE];
        BigInt[] C;

        mainInitialize(A, B);
        int half = (ARRAYSIZE - 1) / 2;

        ByteUtils.writeSizeArrayOfSizeBigInts(A, 0, half - 1, fout);
        ByteUtils.writeSizeArrayOfSizeBigInts(A, half, ARRAYSIZE - 1, fout);

        fout.flush();
        fout.close();

        FileInputStream fin = new FileInputStream(testFileA);
        fout = new FileOutputStream(testFileB);

        try
        {
            ByteUtils.appendSizeByteArray(fin, fout);
            ByteUtils.appendSizeByteArray(fin, fout);
            ByteUtils.appendSizeByteArray(fin, fout);
        } catch (IOException e)
        {
        }

        fin.close();
        fout.flush();
        fout.close();

        fin = new FileInputStream(testFileB);

        B = ByteUtils.readSizeArrayOfSizeBigInts(fin);
        ByteUtils.readInt(fin);
        C = ByteUtils.readArrayOfSizeBigInts(fin);

        for (j = 0; j < half; j++)
        {
            if (!A[j].equals(B[j]))
                ToolIO.out.println("A[" + j + "] :" + A[j] + "   B[" + j + "]: " + B[j]);
        }

        for (j = half; j < ARRAYSIZE; j++)
        {
            if (!A[j].equals(C[j - half]))
                ToolIO.out.println("A[" + j + "] :" + A[j] + "   C[" + (j - half) + "]: " + C[j - half]);
        }
    }

    private void mainInitialize(BigInt[] Arr, BigInt[] Arr2)
    {
        Random r = new Random();

        for (int i = 0; i < ARRAYSIZE; i++)
        {
            Arr[i] = new BigInt(BITS, r);
            Arr2[i] = Arr[i];
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/TraceExplorationSpec.java<|end_filename|>
package tlc2;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import tlc2.model.MCError;
import tlc2.model.MCState;
import tlc2.output.EC;
import tlc2.output.ErrorTraceMessagePrinterRecorder;
import tlc2.output.MP;
import tlc2.output.SpecTraceExpressionWriter;
import tlc2.tool.Defns;
import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.tool.impl.ModelConfig;
import tlc2.value.impl.ModelValue;
import util.TLAConstants;

/**
 * Logic for generating a trace exploration (TE) spec.
 */
public class TraceExplorationSpec {

	/**
	 * Records TLC output as it runs, capturing the error trace if one is found.
	 */
	private final ErrorTraceMessagePrinterRecorder recorder;

	private final Path outputPath;

	private final String originalModuleName;

	private final String teSpecModuleName;

	/**
	 * Initializes a new instance of the {@link TraceExplorationSpec} class.
	 * 
	 * @param output    Directory to which to output the TE spec.
	 * @param timestamp Timestamp to include in TE spec filename.
	 * @param recorder  Recorder to record TLC as it runs; assumed to already be
	 *                  subscribed.
	 */
	public TraceExplorationSpec(Path output, Date timestamp, String originalModuleName,
			ErrorTraceMessagePrinterRecorder recorder) {
		this.outputPath = output;
		this.teSpecModuleName = deriveTESpecModuleName(originalModuleName, timestamp);
		this.originalModuleName = originalModuleName;
		this.recorder = recorder;
	}

	public TraceExplorationSpec(Path output, String teModuleName, String originalModuleName,
			ErrorTraceMessagePrinterRecorder recorder) {
		this.outputPath = output;
		this.teSpecModuleName = teModuleName;
		this.originalModuleName = originalModuleName;
		this.recorder = recorder;
	}

	public void generate(ITool specInfo) {
		if (this.recorder.getMCErrorTrace().isEmpty()) {
			return;
		}
		final MCError errorTrace = this.recorder.getMCErrorTrace().get();
		// TODO Handle the case that TLC threw an unexpected exception, which generally
		// translates into EC.General and should be interceptable with a
		// tlc2.output.IMessagePrinterRecorder.
		// If TLC started from a checkpoint (`-recover`), we don't want to generate a TE
		// spec.
		if ((errorTrace.getStates().size() <= 1)
				|| (TLCGlobals.mainChecker != null && TLCGlobals.mainChecker.isRecovery())) {
			return;
		}

		final List<String> variables = Arrays.asList(TLCState.Empty.getVarsAsStrings());

		// Create any intermediate folders if they don't exist.
		this.outputPath.toFile().mkdirs();

		final Path teSpecPath = this.outputPath.resolve(teSpecModuleName + TLAConstants.Files.TLA_EXTENSION);
		try (OutputStream tlaStream = new FileOutputStream(teSpecPath.toFile());) {
			writeSpecTEStreams(teSpecModuleName, originalModuleName, specInfo.getModelConfig(), variables, errorTrace,
					specInfo, tlaStream);
			MP.printMessage(EC.TLC_TE_SPEC_GENERATION_COMPLETE, teSpecPath.toString());
		} catch (SecurityException | IOException e) {
			MP.printMessage(EC.TLC_TE_SPEC_GENERATION_ERROR, e.getMessage());
		}
	}

	private void writeSpecTEStreams(final String teSpecModuleName, final String originalSpecName,
			final ModelConfig modelConfig, final List<String> variables, final MCError error, final ITool specInfo,
			final OutputStream specTETLAOutStream) throws IOException {

		final List<MCState> trace = error.getStates();

		final SpecTraceExpressionWriter writer = new SpecTraceExpressionWriter();

		// It is tempting to lookup the constant defns in the SpecProcessor instead of
		// going through the mumbo-jumbo of parsing and converting entries in
		// ModelConfig. However, the constant defns have already been evaluated by
		// SpecProcessor and turned into IValue instances. Serializing those IValue
		// instances via their toString method will probably cause invalid config
		// values. Additionally, the constant defns are a superset of what is in
		// declared and defined in ModelConfig.
		final List<List<String>> constants = modelConfig.getConstantsAsList();

		// The original spec might declare model-values implicitly by just declaring a
		// set of model-values. This works for the original spec as long as those
		// model-values do not appear explicitly. However, the model-values will
		// likely appear in the error-trace, which is why the trace spec has to
		// declare them. Imagine, for example, a CONSTANT P in the spec and a CONSTANT P
		// = {p1,p2} in the config (e.g. modeling a set of two processes) and an
		// error-trace that shows one process to enter some critical section.
		// Add all the model values as constants, they have to be reified (to mean
		// something) in a TLA module.
		// First we set all the model values seen, the values will be at the static
		// field ModelValue.mvs.
		ModelValue.setValues();
		final Set<String> declaredConstantNames = constants.stream().map(l -> l.get(0)).collect(Collectors.toSet());
		final Set<ModelValue> reifiedConstants = new HashSet<ModelValue>();
		reifiedConstants.addAll(Arrays.asList(ModelValue.mvs));
		reifiedConstants.stream().filter(m -> !declaredConstantNames.contains(m.toString()))
				.collect(Collectors.toSet());

		/**
		 * Write content of config file (SpecTE).
		 * <p>
		 * Contrary to the Toolbox's TraceExplorerDelegate, which reads constants,
		 * overrides, ... from the TLC model, this implementation copies all CONSTANT
		 * and CONSTANTS verbatim from the existing config file with which TLC ran. The
		 * definition that appear in the .tla file (e.g. MC.tla) don't have to be copied
		 * because SpecTE extends MC. We also add the model values as constants so they
		 * can be used for the traces at the TLA modules. (see
		 * TraceExplorerDelegate#writeModelInfo)
		 */

		List<String> indentedConstants = new ArrayList<String>();
		// Ordinary constants:
		for (List<String> keyValuePair : constants) {
			if (keyValuePair.size() > 1) {
				String key = keyValuePair.get(0).toString();
				String value = keyValuePair.get(1).toString();
				indentedConstants.add(SpecTraceExpressionWriter.indentString(String.format("%s = %s", key, value), 1));
			} else {
				String line = keyValuePair.get(0).toString();
				indentedConstants.add(SpecTraceExpressionWriter.indentString(line, 1));
			}
		}

		// Reified model-values:
		for (ModelValue mv : reifiedConstants) {
			indentedConstants.add(SpecTraceExpressionWriter.indentString(String.format("%s = %s", mv, mv), 1));
		}

		// If it has a lasso, add the TTrace lasso constants to the configuration file.
		if (error.isLasso()) {
			indentedConstants.add(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_START + " = "
					+ trace.get(trace.size() - 1).getStateNumber());
			indentedConstants.add(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_END + " = " + (trace.size() - 1));
		}

		writer.addConstants(indentedConstants);

		// If needed, create module which contain the reified constants.
		// First we need to handle the case where a model value is defined in
		// the config file, but, for some reason, it's not used in any of the
		// model specs. E.g. I define `p1 = p1` in the `CONSTANTS` header of the
		// config file, but I do not use it (through `CONSTANTS`) in the model spec.
		// So we add these remaining constants to `mvsStr` so they are added to the
		// `TE` spec.
		Defns defns = specInfo.getSpecProcessor().getDefns();
		ArrayList<String> modConstants = new ArrayList<String>();
		for (ModelValue mv : ModelValue.mvs) {
			if (defns.get(mv.toString()) == null) {
				modConstants.add(mv.toString());
			}
		}
		// If it has a lasso, add the TTrace lasso constants to the modules constants
		// so we can have it in a more convenient place (so other tools, like the
		// Toolbox,
		// can, for example, highlight the lasso).
		if (error.isLasso()) {
			modConstants.add(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_START);
			modConstants.add(TLAConstants.TraceExplore.SPEC_TETRACE_LASSO_END);
		}
		// Create TEConstant module.
		final String teConstantSpecName = String.format("%s_%s", originalSpecName,
				TLAConstants.TraceExplore.SPEC_TECONSTANTS_NAME);
		final Set<String> teConstantModuleHashSet = new HashSet<>();
		teConstantModuleHashSet.add(TLAConstants.BuiltInModules.TLC);
		String modelValuesAsConstants;
		if (!modConstants.isEmpty()) {
			teConstantModuleHashSet.add(teConstantSpecName);
			modelValuesAsConstants = String.format("CONSTANTS %s\n", String.join(", ", modConstants));
		} else {
			modelValuesAsConstants = "";
		}

		/**
		 * Write SpecTE.
		 */
		final Set<String> specTEExtendedModules = new HashSet<>();
		// A TE spec has to extend Toolbox to have access to _TETrace and _TEPosition
		// operators.
		specTEExtendedModules.add(TLAConstants.BuiltInModules.TRACE_EXPRESSIONS);
		specTEExtendedModules.add("TLCExt");
		// EXTEND Naturals for next-state relation:
		// _next ==
		// /\ \E i,j \in DOMAIN _TETrace:
		// /\ \/ j = i + 1 \* <--- Here!
		// /\ x = _TETrace[i].x
		// /\ x' = _TETrace[j].x
		//
		specTEExtendedModules.add("Naturals");
		// Len(..) operator appearing in _inv (not added by the Toolbox because the
		// Toolbox checks deadlock).
		specTEExtendedModules.add("Sequences");
		specTEExtendedModules.addAll(teConstantModuleHashSet);

		writer.addPrimer(teSpecModuleName, originalSpecName, specTEExtendedModules);

		writer.addTraceExpressionInstance(
				String.format("%s_%s", originalSpecName, TLAConstants.TraceExplore.EXPLORATION_MODULE_NAME));

		final String teTraceName = String.format("%s_%s", originalSpecName,
				TLAConstants.TraceExplore.SPEC_TETRACE_NAME);

		writer.addTraceFunctionInstance(teTraceName);

		writer.addProperties(trace, originalSpecName);

		// Write Init and Next with vars instead of extracting the vars from trace to
		// always write a syntactically correct behavior spec even if trace = <<>>.
		writer.addInitNextTraceFunction(trace, teSpecModuleName, variables, modelConfig);

		if (error.isLassoWithDuplicates()) {
			// The same state or states may appear multiple times in a (liveness) trace. For
			// example, a trace could be s -> t -> s -> u with u closing the lasso back to
			// the *first* s. (trace violates e.g. a property s.t. <>[]t \/ <>[]u. In other
			// words, t and u are mutually exclusive). Unless we add a VIEW to the trace
			// spec
			// that causes different fingerprints for the s states to be calculated, the
			// trace won't be recreated. The view is such that the start and end states of
			// the lasso get the same value.
			//
			// <<vars, IF TLCGet("level") = _TTraceLassoEnd + 1
			// THEN _TTraceLassoStart
			// ELSE TLCGet("level")>>
			//
			// As an alternative, an auxiliary _index variable could be added to every spec
			// that gets incremented. This would be the explicit variant of TLCGet("level")
			// above.
			// However, that has the risk of runaway traces s.t. _index keeps incrementing
			// forever.
			//
			// /\ \/ /\ _index < _TTraceLassoEnd
			// /\ _index' = _index + 1
			// \/ /\ _index = _TTraceLassoEnd
			// /\ _index' = _TTraceLassoStart
			// /\ x = _TETrace[_index].x
			// /\ x' = _TETrace[_index'].x
			writer.addView(String.join(", ", variables));
		}

		writer.addFooter();

		/**
		 * Write definition of trace expression into new module.
		 */
		writer.append(TLAConstants.CR);

		final SpecTraceExpressionWriter te = new SpecTraceExpressionWriter();
		final String teModuleName = String.format("%s_%s", originalSpecName,
				TLAConstants.TraceExplore.EXPLORATION_MODULE_NAME);
		te.append(TLAConstants.CR);

		writer.append(String.format(" Note that you can extract this module `%s`", teModuleName))
				.append(TLAConstants.CR);
		writer.append("  to a dedicated file to reuse `expression` (the module in the ").append(TLAConstants.CR);
		writer.append(String.format("  dedicated `%s.tla` file takes precedence ", teModuleName))
				.append(TLAConstants.CR);
		writer.append(String.format("  over the module `BlockingQueue_TEExpression` below).", teModuleName));

		te.addPrimer(teModuleName, originalSpecName, specTEExtendedModules);
		te.addTraceExpressionStub(originalSpecName, TLAConstants.TraceExplore.SPEC_TE_TRACE_EXPRESSION, variables);
		te.addFooter();
		writer.append(TLAConstants.CR + te.toString() + TLAConstants.CR + TLAConstants.CR);

		/**
		 * Write commented definition of trace def override into new module. A user
		 * simply has to provide the serialized trace and uncomment the module.
		 */
		writer.append(TLAConstants.CR);
		writer.append("Parsing and semantic processing can take forever if the trace below is long.")
				.append(TLAConstants.CR);
		writer.append(" In this case, it is advised to deserialize the trace from a binary file.")
				.append(TLAConstants.CR);
		writer.append(" To create the file, replace your spec's invariant F with:").append(TLAConstants.CR);
		writer.append("  Inv == IF F THEN TRUE ELSE ~IOSerialize(Trace, \"file.bin\", TRUE)").append(TLAConstants.CR);
		writer.append(" (IOUtils module is from https://modules.tlapl.us/)");

		final Set<String> extendedModulesWithIOUtils = new HashSet<>();
		extendedModulesWithIOUtils.add("IOUtils");
		extendedModulesWithIOUtils.addAll(teConstantModuleHashSet);

		final SpecTraceExpressionWriter w = new SpecTraceExpressionWriter();
		w.append(TLAConstants.CR);
		w.addPrimer(teTraceName, originalSpecName, extendedModulesWithIOUtils);
		w.append(TLAConstants.TraceExplore.SPEC_TETRACE_TRACE_DEF).append(TLAConstants.DEFINES)
				.append("IODeserialize(\"file.bin\", TRUE)\n\n");
		w.addFooter();
		// Users can uncomment the module if they wish to read the serialized trace.
		writer.append(TLAConstants.CR + w.getComment() + TLAConstants.CR + TLAConstants.CR);

		/**
		 * Write definition of trace def into new module.
		 */
		final Set<String> teTraceExtendedModules = new HashSet<>();
		teTraceExtendedModules.addAll(teConstantModuleHashSet);
		writer.addPrimer(teTraceName, originalSpecName, teTraceExtendedModules);

		writer.addTraceFunction(trace, TLAConstants.TraceExplore.SPEC_TETRACE_TRACE_DEF,
				TLAConstants.TraceExplore.SPEC_TETRACE_TRACE);

		writer.addAliasToCfg(TLAConstants.TraceExplore.SPEC_TE_TTRACE_EXPRESSION);

		/**
		 * Write TEConstants module, if needed.
		 */
		if (modelValuesAsConstants != "") {
			writer.addFooter();
			writer.append(TLAConstants.CR);
			writer.addPrimer(teConstantSpecName, originalSpecName);
			writer.append(modelValuesAsConstants).append(TLAConstants.CR);
		}

		writer.wrapConfig(teSpecModuleName);
		
		/**
		 * Write to streams.
		 */
		writer.writeStreams(specTETLAOutStream, specTETLAOutStream);
	}

	public static String teModuleId(Date timestamp) {
		final long secondsSinceEpoch = timestamp.getTime() / 1_000L;
		return Long.toString(secondsSinceEpoch);
	}

	/**
	 * Derives the TE spec module name.
	 * 
	 * @param ogModuleName Original module name.
	 * @return The TE spec module name.
	 */
	public static String deriveTESpecModuleName(String ogModuleName, Date timestamp) {
		// millis to secondPaths
		return String.format("%s_%s_%s", ogModuleName, TLAConstants.TraceExplore.TRACE_EXPRESSION_MODULE_NAME,
				teModuleId(timestamp));
	}

	/**
	 * Determines whether the given spec is a TE spec.
	 * 
	 * @param tlaFilePath Path to the TLA file.
	 * @return Whether the given spec is a TE spec.
	 */
	public static boolean isTESpecFile(String tlaFilePath) {
		if (null == tlaFilePath) {
			return false;
		}

		try {
			// TODO: branch based on something better than the filename such as the module
			// name that we choose above, or check for special tokens/symbols generated in
			// trace spec.
			String filename = Paths.get(tlaFilePath).getFileName().toString();
			// see tlc2.TraceExplorationSpec.deriveTESpecModuleName(String)
			return filename.matches("^.*_" + TLAConstants.TraceExplore.TRACE_EXPRESSION_MODULE_NAME + ".*(.tla)?$");
		} catch (InvalidPathException e) {
			return false;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/IntWrapper.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

package tla2sany.utilities;

public class IntWrapper {
  private int i;
  public IntWrapper() { i = 0 ; }
  public IntWrapper( int initial ) { i = initial ; }

  public final void inc() { i++; }
  public final void inc( int increment ) { i+=increment; }

  public final int value() { return i; }

  public final void set( int value ) { i = value; }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/MultiFPSetTest.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * @author <NAME>
 */
public class MultiFPSetTest {

	protected static final String tmpdir = System.getProperty("java.io.tmpdir") + File.separator + "MultiFPSetTest"
			+ System.currentTimeMillis();

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	@Before
	public void setUp() throws Exception {
		new File(tmpdir).mkdirs();
	}

	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#new}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testCTorLowerMin() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MemFPSet.class.getName());
		try {
			System.setProperty(FPSetFactory.IMPL_PROPERTY, MemFPSet.class.getName());
			FPSetConfiguration conf = new FPSetConfiguration();
			conf.setFpBits(0);
			new MultiFPSet(conf);
		} catch (RuntimeException e) {
			return;
		}
		fail("Negative fpbits must fail");
	}
	
	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#new}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testCTorMin() throws IOException {
		try {
			FPSetConfiguration conf = new FPSetConfiguration();
			conf.setFpBits(1);
			new MultiFPSet(conf);
		} catch (RuntimeException e) {
			fail();
		}
		return;
	}

	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#new}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testCTorMax() throws IOException {
		try {
			FPSetConfiguration conf = new FPSetConfiguration();
			conf.setFpBits(30);
			new MultiFPSet(conf);
		} catch (OutOfMemoryError e) {
			// might happen depending on test machine setup
			return;
		} catch (IllegalArgumentException e) {
			// Happens when MultiFPSetConfiguration is invalid (too many fpsets
			// leaving no room/memory for each individual fpset).
			if (e.getMessage().equals("Given fpSetConfig results in zero or negative fp count.")) {
				return;
			}
			// some other cause for the IAE
			fail();
		} catch (RuntimeException e) {
			fail();
		}
		return;
	}

	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#new}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testCTorHigherMax() throws IOException {
		try {
			FPSetConfiguration conf = new FPSetConfiguration();
			conf.setFpBits(31);
			new MultiFPSet(conf);
		} catch (RuntimeException e) {
			return;
		}
		fail();
	}
	
	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#put(long)}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testPutMax() throws IOException {
		FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		final MultiFPSet mfps = new MultiFPSet(conf);

		// put a random fp value into set
		try {
			mfps.put(Long.MAX_VALUE);
		} catch (ArrayIndexOutOfBoundsException e) {
			fail();
		}
	}

	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#put(long)}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testPutMin() throws IOException {
		FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		final MultiFPSet mfps = new MultiFPSet(conf);

		// put a random fp value into set
		try {
			mfps.put(Long.MIN_VALUE);
		} catch (ArrayIndexOutOfBoundsException e) {
			fail();
		}
	}

	/**
	 * Test method for {@link tlc2.tool.fp.MultiFPSet#put(long)}.
	 * @throws IOException Not supposed to happen
	 */
	@Test
	public void testPutZero() throws IOException {
		FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		final MultiFPSet mfps = new MultiFPSet(conf);

		// put a random fp value into set
		try {
			mfps.put(0);
		} catch (ArrayIndexOutOfBoundsException e) {
			fail();
		}
	}
	
	@Test
	public void testGetFPSet() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSet");
		
		final long a = (1L << 62) + 1; // 01...0
		printBinaryString("a01...1", a);
		final long b = 1L; // 0...1
		printBinaryString("b00...1", b);
		
		FPSet aFPSet = mfps.getFPSet(a);
		Assert.assertTrue(aFPSet == mfps.getFPSet(b));
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));

		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertTrue(aFPSet.contains(b));
		Assert.assertEquals(2, aFPSet.size());
		
		// Get the other FPSet
		FPSet[] fpSets = mfps.getFPSets();
		Set<FPSet> s = new HashSet<FPSet>();
		for (int i = 0; i < fpSets.length; i++) {
			s.add(fpSets[i]);
		}
		s.remove(aFPSet);
		FPSet bFPSet = (FPSet) s.toArray()[0];
		
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		Assert.assertEquals(0, bFPSet.size());
		
		Assert.assertTrue(mfps.checkInvariant());
	}

	@Test
	public void testGetFPSet0() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSet0");
		
		final long a = (1L << 63) + 1; // 10...1
		printBinaryString("a1...1", a);
		final long b = 1L;             // 00...1
		printBinaryString("b0...1", b);
		final long c = (1L << 62) + 1; // 01...1
		printBinaryString("c1...1", c);
		final long d = (3L << 62) + 1; // 11...1
		printBinaryString("d0...1", d);
		
		FPSet aFPSet = mfps.getFPSet(a);
		FPSet bFPSet = mfps.getFPSet(b);
		Assert.assertTrue(aFPSet != bFPSet);
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(c));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));
		
		Assert.assertFalse(mfps.put(d));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertTrue(mfps.contains(d));
		
		for (FPSet fpSet : mfps.getFPSets()) {
			Assert.assertEquals(2, fpSet.size());
			// Expect to have two buckets
			Assert.assertEquals(2, ((FPSetStatistic) fpSet).getTblLoad());
		}
		
		Assert.assertTrue(mfps.checkInvariant());
	}
	
	@Test
	public void testGetFPSet1() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, MSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(2);
		final MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSet1");
		
		final long a = 1L; // 00...1
		printBinaryString("a02", a);
		final long b = (1L << 62) + 1; // 01...1
		printBinaryString("b02", b);
		final long c = (1L << 63) + 1; // 10...1
		printBinaryString("c02", c);
		final long d = (3L << 62) + 1; // 11...1
		printBinaryString("d02", d);
		
		final Set<FPSet> s = new HashSet<FPSet>();
		final FPSet aFPSet = mfps.getFPSet(a);
		s.add(aFPSet);
		final FPSet bFPSet = mfps.getFPSet(b);
		s.add(bFPSet);
		final FPSet cFPSet = mfps.getFPSet(c);
		s.add(cFPSet);
		final FPSet dFPSet = mfps.getFPSet(d);
		s.add(dFPSet);
		Assert.assertEquals(4, s.size());
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(c));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(d));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertTrue(mfps.contains(d));
		
		for (FPSet fpSet : s) {
			Assert.assertEquals(1, fpSet.size());
			// Expect to have two buckets
			Assert.assertEquals(1, ((FPSetStatistic) fpSet).getTblLoad());
		}
		
		// a & c and b & d have collisions at the individual DiskFPSet level.
		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertFalse(aFPSet.contains(b));
		Assert.assertTrue(aFPSet.contains(c)); // expected collision
		Assert.assertFalse(aFPSet.contains(d));
		
		Assert.assertTrue(bFPSet.contains(b));
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(c));
		Assert.assertTrue(bFPSet.contains(d)); // expected collision

		Assert.assertTrue(cFPSet.contains(c));
		Assert.assertFalse(cFPSet.contains(b));
		Assert.assertTrue(cFPSet.contains(a)); // expected collision
		Assert.assertFalse(cFPSet.contains(d));

		Assert.assertTrue(dFPSet.contains(d));
		Assert.assertTrue(dFPSet.contains(b)); // expected collision
		Assert.assertFalse(dFPSet.contains(c));
		Assert.assertFalse(dFPSet.contains(a));

		Assert.assertTrue(mfps.checkInvariant());
	}

	@Test
	public void testGetFPSetL() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSetL");
		
		final long a = (1L << 62) + 1;
		printBinaryString("a01", a);
		final long b = 1L;
		printBinaryString("b01", b);
		
		FPSet aFPSet = mfps.getFPSet(a);
		Assert.assertTrue(aFPSet == mfps.getFPSet(b));
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));

		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertTrue(aFPSet.contains(b));
		Assert.assertEquals(2, aFPSet.size());
		
		// Get the other FPSet
		FPSet[] fpSets = mfps.getFPSets();
		Set<FPSet> s = new HashSet<FPSet>();
		for (int i = 0; i < fpSets.length; i++) {
			s.add(fpSets[i]);
		}
		s.remove(aFPSet);
		FPSet bFPSet = (FPSet) s.toArray()[0];
		
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		Assert.assertEquals(0, bFPSet.size());

		Assert.assertTrue(mfps.checkInvariant());
	}

	@Test
	public void testGetFPSet0L() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSet0L");
		
		final long a = (1L << 63) + 1;
		printBinaryString("a01", a);
		final long b = 1L;
		printBinaryString("b01", b);
		
		FPSet aFPSet = mfps.getFPSet(a);
		FPSet bFPSet = mfps.getFPSet(b);
		Assert.assertTrue(aFPSet != bFPSet);
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));

		Assert.assertTrue(mfps.checkInvariant());
	}
	
	@Test
	public void testGetFPSet1L() throws IOException {
		System.setProperty(FPSetFactory.IMPL_PROPERTY, LSBDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(2);
		final MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSet1L");
		
		final long a = 1L; // 00...1
		printBinaryString("a02", a);
		final long b = (1L << 62) + 1; // 01...1
		printBinaryString("b02", b);
		final long c = (1L << 63) + 1; // 10...1
		printBinaryString("c02", c);
		final long d = (3L << 62) + 1; // 11...1
		printBinaryString("d02", d);
		
		final Set<FPSet> s = new HashSet<FPSet>();
		final FPSet aFPSet = mfps.getFPSet(a);
		s.add(aFPSet);
		final FPSet bFPSet = mfps.getFPSet(b);
		s.add(bFPSet);
		final FPSet cFPSet = mfps.getFPSet(c);
		s.add(cFPSet);
		final FPSet dFPSet = mfps.getFPSet(d);
		s.add(dFPSet);
		Assert.assertEquals(4, s.size());
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(c));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(d));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertTrue(mfps.contains(d));
		
		for (FPSet fpSet : s) {
			Assert.assertEquals(1, fpSet.size());
		}
		
		// a & c and b & d have collisions at the individual DiskFPSet level.
		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertFalse(aFPSet.contains(b));
		Assert.assertTrue(aFPSet.contains(c)); // expected collision
		Assert.assertFalse(aFPSet.contains(d));
		
		Assert.assertTrue(bFPSet.contains(b));
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(c));
		Assert.assertTrue(bFPSet.contains(d)); // expected collision

		Assert.assertTrue(cFPSet.contains(c));
		Assert.assertFalse(cFPSet.contains(b));
		Assert.assertTrue(cFPSet.contains(a)); // expected collision
		Assert.assertFalse(cFPSet.contains(d));

		Assert.assertTrue(dFPSet.contains(d));
		Assert.assertTrue(dFPSet.contains(b)); // expected collision
		Assert.assertFalse(dFPSet.contains(c));
		Assert.assertFalse(dFPSet.contains(a));

		Assert.assertTrue(mfps.checkInvariant());
	}
	
	@Test
	public void testGetFPSetOffHeap() throws IOException {
		if (!System.getProperty("sun.arch.data.model").equals("64")) {
			// LongArray only works on 64bit architectures. See comment in
			// LongArray ctor.
			return;
		}
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSetOffHeap");
		
		final long a = (1L << 62) + 1; // 01...0
		printBinaryString("a01...1", a);
		final long b = 1L; // 0...1
		printBinaryString("b00...1", b);
		
		FPSet aFPSet = mfps.getFPSet(a);
		Assert.assertTrue(aFPSet == mfps.getFPSet(b));
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));

		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertTrue(aFPSet.contains(b));
		Assert.assertEquals(2, aFPSet.size());
		
		// Get the other FPSet
		FPSet[] fpSets = mfps.getFPSets();
		Set<FPSet> s = new HashSet<FPSet>();
		for (int i = 0; i < fpSets.length; i++) {
			s.add(fpSets[i]);
		}
		s.remove(aFPSet);
		FPSet bFPSet = (FPSet) s.toArray()[0];
		
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		Assert.assertEquals(0, bFPSet.size());
		
		Assert.assertTrue(mfps.checkInvariant());
	}

	@Test
	public void testGetFPSetOffHeap0() throws IOException {
		if (!System.getProperty("sun.arch.data.model").equals("64")) {
			// LongArray only works on 64bit architectures. See comment in
			// LongArray ctor.
			return;
		}
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(1);
		
		MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSetOffHeap0");
		
		final long a = (1L << 63) + 1; // 10...1
		printBinaryString("a1...1", a);
		final long b = 1L;             // 00...1
		printBinaryString("b0...1", b);
		final long c = (1L << 62) + 1; // 01...1
		printBinaryString("c1...1", c);
		final long d = (3L << 62) + 1; // 11...1
		printBinaryString("d0...1", d);
		
		FPSet aFPSet = mfps.getFPSet(a);
		FPSet bFPSet = mfps.getFPSet(b);
		Assert.assertTrue(aFPSet != bFPSet);
		
		// Initially neither a nor b are in the set.
		Assert.assertFalse(aFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(b));
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		// Add a to the set and verify it's in the
		// set and b isn't.
		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		// Add b to the set as well. Now both
		// are supposed to be set members.
		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(c));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));
		
		Assert.assertFalse(mfps.put(d));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertTrue(mfps.contains(d));
		
		for (FPSet fpSet : mfps.getFPSets()) {
			Assert.assertEquals(2, fpSet.size());
			// Expect to have two buckets
			Assert.assertEquals(2, ((FPSetStatistic) fpSet).getTblLoad());
		}
		
		Assert.assertTrue(mfps.checkInvariant());
	}
	
	@Test
	public void testGetFPSetOffHeap1() throws IOException {
		if (!System.getProperty("sun.arch.data.model").equals("64")) {
			// LongArray only works on 64bit architectures. See comment in
			// LongArray ctor.
			return;
		}
		System.setProperty(FPSetFactory.IMPL_PROPERTY, OffHeapDiskFPSet.class.getName());
		final FPSetConfiguration conf = new FPSetConfiguration();
		conf.setFpBits(2);
		final MultiFPSet mfps = new MultiFPSet(conf);
		mfps.init(1, tmpdir, "testGetFPSetOffHeap1");
		
		final long a = 1L; // 00...1
		printBinaryString("a02", a);
		final long b = (1L << 62) + 1; // 01...1
		printBinaryString("b02", b);
		final long c = (1L << 63) + 1; // 10...1
		printBinaryString("c02", c);
		final long d = (3L << 62) + 1; // 11...1
		printBinaryString("d02", d);
		
		final Set<FPSet> s = new HashSet<FPSet>();
		final FPSet aFPSet = mfps.getFPSet(a);
		s.add(aFPSet);
		final FPSet bFPSet = mfps.getFPSet(b);
		s.add(bFPSet);
		final FPSet cFPSet = mfps.getFPSet(c);
		s.add(cFPSet);
		final FPSet dFPSet = mfps.getFPSet(d);
		s.add(dFPSet);
		Assert.assertEquals(4, s.size());
		
		Assert.assertFalse(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(a));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertFalse(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(b));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertFalse(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(c));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertFalse(mfps.contains(d));

		Assert.assertFalse(mfps.put(d));
		Assert.assertTrue(mfps.contains(a));
		Assert.assertTrue(mfps.contains(b));
		Assert.assertTrue(mfps.contains(c));
		Assert.assertTrue(mfps.contains(d));
		
		for (FPSet fpSet : s) {
			Assert.assertEquals(1, fpSet.size());
			// Expect to have two buckets
			Assert.assertEquals(1, ((FPSetStatistic) fpSet).getTblLoad());
		}
		
		// a & c and b & d have collisions at the individual DiskFPSet level.
		Assert.assertTrue(aFPSet.contains(a));
		Assert.assertFalse(aFPSet.contains(b));
		Assert.assertTrue(aFPSet.contains(c)); // expected collision
		Assert.assertFalse(aFPSet.contains(d));
		
		Assert.assertTrue(bFPSet.contains(b));
		Assert.assertFalse(bFPSet.contains(a));
		Assert.assertFalse(bFPSet.contains(c));
		Assert.assertTrue(bFPSet.contains(d)); // expected collision

		Assert.assertTrue(cFPSet.contains(c));
		Assert.assertFalse(cFPSet.contains(b));
		Assert.assertTrue(cFPSet.contains(a)); // expected collision
		Assert.assertFalse(cFPSet.contains(d));

		Assert.assertTrue(dFPSet.contains(d));
		Assert.assertTrue(dFPSet.contains(b)); // expected collision
		Assert.assertFalse(dFPSet.contains(c));
		Assert.assertFalse(dFPSet.contains(a));

		Assert.assertTrue(mfps.checkInvariant());
	}

	private void printBinaryString(final String id, final long a) {
//		System.out.println(String.format(id + ":%64s", Long.toBinaryString(a)).replace(' ', '0'));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/ControlNavigationLocation.java<|end_filename|>
// Copyright (c) Dec 22, 2011 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationLocation;

/**
 * @author <NAME>
 */
public class ControlNavigationLocation implements INavigationLocation {

	private Control control;

	public ControlNavigationLocation(Control aControl) {
		Assert.isNotNull(aControl);
		control = aControl;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#dispose()
	 */
	public void dispose() {
		releaseState();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#releaseState()
	 */
	public void releaseState() {
		control = null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#saveState(org.eclipse.ui.IMemento)
	 */
	public void saveState(IMemento memento) {
		// no-op because we don't support persistent navigation history
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreState(org.eclipse.ui.IMemento)
	 */
	public void restoreState(IMemento memento) {
		// no-op because we don't support persistent navigation history
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreLocation()
	 */
	public void restoreLocation() {
		if(control != null) {
			control.setFocus();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#mergeInto(org.eclipse.ui.INavigationLocation)
	 */
	public boolean mergeInto(INavigationLocation currentLocation) {
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#getInput()
	 */
	public Object getInput() {
		return control;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#getText()
	 */
	public String getText() {
		// if null the navigation history just uses the part's name
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#setInput(java.lang.Object)
	 */
	public void setInput(Object input) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#update()
	 */
	public void update() {
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/pref/UnwantedPreferenceManager.java<|end_filename|>
package org.lamport.tla.toolbox.util.pref;

import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.PreferenceManager;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.ui.intro.ToolboxIntroPart;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * This class removes unwanted preference pages that are declared
 * by eclipse plug-ins, i.e. plug-ins outside of our control.
 * It is a ToolboxLifeCycleParticipant. The removing of the preference
 * pages occurs in the method initialize which is called by 
 * the ToolboxLifecycleParticipantManager at some point after
 * the toolbox starts up.
 * 
 * @author <NAME>
 *
 */
public class UnwantedPreferenceManager extends ToolboxLifecycleParticipant
{

    public UnwantedPreferenceManager()
    {
        // TODO Auto-generated constructor stub
    }

    public void initialize()
    {
        if (Activator.getDefault().getWorkbench() == null)
        {
            return;
        }
        PreferenceManager pm = Activator.getDefault().getWorkbench().getPreferenceManager();

        if (pm != null)
        {
            /*
             * Subpages need to be removed by calling the remove method
             * on their parent. Pages with no parent can be removed
             * by calling the remove method on the preference manager.
             * 
             * Getting the appropriate id of the page to remove can be done
             * using the code that is commented at the end of this method.
             * It will print out the name followed by the id of every preference page.
             */
            IPreferenceNode generalNode = pm.find("org.eclipse.ui.preferencePages.Workbench");
            if (generalNode != null)
            {
                // these are sub pages of general that we want removed
                generalNode.remove("org.eclipse.ui.preferencePages.Workspace");
                generalNode.remove("org.eclipse.ui.preferencePages.ContentTypes");
                // We no longer want to remove this node.
                // We only want to remove one of its sub nodes.
                // generalNode.remove("org.eclipse.ui.preferencePages.Views");
                // we only want to remove some subnodes of the Editors page
                IPreferenceNode editorsNode = generalNode.findSubNode("org.eclipse.ui.preferencePages.Editors");
                if (editorsNode != null)
                {
                    // remove File Associations page
                    editorsNode.remove("org.eclipse.ui.preferencePages.FileEditors");
                    // want to remove only some subnodes of the Text Editors page
                    IPreferenceNode textEditorsNode = editorsNode
                            .findSubNode("org.eclipse.ui.preferencePages.GeneralTextEditor");
                    if (textEditorsNode != null)
                    {
                        textEditorsNode.remove("org.eclipse.ui.editors.preferencePages.Spelling");
                        textEditorsNode.remove("org.eclipse.ui.editors.preferencePages.QuickDiff");
                        textEditorsNode.remove("org.eclipse.ui.editors.preferencePages.LinkedModePreferencePage");
                    }
                }
                generalNode.remove("org.eclipse.ui.preferencePages.Perspectives");
                generalNode.remove("org.eclipse.equinox.security.ui.category");
                IPreferenceNode appearanceNode = generalNode.findSubNode("org.eclipse.ui.preferencePages.Views");
                if (appearanceNode != null)
                {
                    // Removes the label decorators node that is a sub node of
                    // the appearance node.
                    // We want to keep the other sub node, colors and fonts
                    // because it allows for setting the font for
                    // the module editor.
                    appearanceNode.remove("org.eclipse.ui.preferencePages.Decorators");
                }
            }

            // remove Install/Update
            pm.remove("org.eclipse.equinox.internal.p2.ui.sdk.ProvisioningPreferencePage");

            // remove the sub node of help
            IPreferenceNode helpNode = pm.find("org.eclipse.help.ui.browsersPreferencePage");
            if (helpNode != null)
            {
                helpNode.remove("org.eclipse.help.ui.contentPreferencePage");
            }
        }
    }

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant#terminate()
	 */
	public void terminate() {
		if (!ToolboxHandle.getInstanceStore().getBoolean(ToolboxHandle.I_RESTORE_LAST_SPEC)) {
			UIHelper.getActivePage().closeAllEditors(true);
			UIHelper.switchPerspective(ToolboxIntroPart.PERSPECTIVE_ID);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/SwitchPerspectiveHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.menus.UIElement;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 Switches perspective
 *    <code>
 *      <command
 *           categoryId="toolbox.command.category.ui"
 *           description="Switches to the perspective"
 *           id="toolbox.command.switchperspective"
 *           name="Switches to the perspective">
 *        <commandParameter
 *              id="toolbox.switchperspective.id"
 *              name="name"
 *              optional="false">
 *        </commandParameter>
 *     </command>
 *     <menuContribution
 *           locationURI="menu:toolbox.window.menu?after=toolbox.window.tools.separator">
 *        <command
 *              commandId="toolbox.command.switchperspective"
 *              id="toolbox.menu.switchperspective-specLoaded"
 *              label="Specification"
 *              mode="FORCE_TEXT"
 *              style="radio">
 *           <parameter
 *                 name="toolbox.switchperspective.id"
 *                 value="org.lamport.tla.toolbox.ui.perspective.specLoaded">
 *           </parameter>
 *        </command>
 *     </menuContribution>
 * </code>
 * @author <NAME>
 * @version $Id$ 
 * @deprecated Simon says it is not used now.
 */
public class SwitchPerspectiveHandler extends AbstractHandler implements IHandler, IElementUpdater
{
    public static final String COMMAND_ID = "toolbox.command.switchperspective";
    public static final String PARAM_PERSPECTIVE_ID = "toolbox.switchperspective.id";

    public Object execute(final ExecutionEvent event) throws ExecutionException
    {
        final String perspectiveId = event.getParameter(PARAM_PERSPECTIVE_ID);
        if (perspectiveId == null)
        {
            return null;
        }

        // in theory, we're already in the correct state
        if (UIHelper.getActivePerspectiveId().equals(perspectiveId))
        {
            return null;
        }

        final ICommandService service = (ICommandService) HandlerUtil.getActiveWorkbenchWindowChecked(event).getService(
                ICommandService.class);

        /**
         * opens a perspective by name
         */
        UIHelper.runUIAsync(new Runnable() {
            public void run()
            {
                UIHelper.switchPerspective(perspectiveId);

                // update our radio button states ... get the service from
                // a place that's most appropriate
                // but do it in the same thread, and AFTER the UI has been updated
                service.refreshElements(event.getCommand().getId(), null);
            }
        });


        return null;
    }

    public void updateElement(UIElement element, Map parameters)
    {
        String parameter = (String) parameters.get(PARAM_PERSPECTIVE_ID);
        if (parameter != null)
        {
            if (UIHelper.getActivePerspectiveId().equals(parameter))
            {
                element.setChecked(true);
            } else
            {
                element.setChecked(false);
            }
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/PcalResourceFileReaderException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class PcalResourceFileReaderException extends UnrecoverableException
{

    /**
     * @param message
     */
    public PcalResourceFileReaderException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src-aj/tlc2/tool/distributed/RMIMethodMonitor.java<|end_filename|>
package tlc2.tool.distributed;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;

public class RMIMethodMonitor {

	/**
	 * Holder to count invocations per remote method
	 */
	private static final Map<String, Integer> invoctions = new HashMap<String, Integer>();
	
	/**
	 * @param joinPoint Counts the invocation for the given joinPoint
	 */
	public static synchronized void entering(JoinPoint joinPoint) {
		final Signature signature = joinPoint.getSignature();
		final String methodName = signature.toShortString();
		Integer invocedTimes = invoctions.get(methodName);
		
		if(invocedTimes == null) {
			invoctions.put(methodName, 1);
		} else {
			int i = invocedTimes.intValue();
			invoctions.put(methodName, ++i);
		}
	}

	public static synchronized Map<String, Integer> getInvocations() {
		return invoctions;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/nature/TLANature.java<|end_filename|>
package org.lamport.tla.toolbox.spec.nature;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.Activator;

/**
 * TLA Nature
 * @author <NAME>
 * @version $Id$
 */
public class TLANature implements IProjectNature
{
    
    private IProject project;
    public static final String ID = "toolbox.natures.TLANature";


    /**
     * add TLA nature
     */
    public void configure() throws CoreException
    {
        IProjectDescription desc = project.getDescription();
        ICommand[] commands = desc.getBuildSpec();

        boolean tlaBuilderFound = false;
        boolean pcalBuilderFound = false;
        int numberOfBuildersToInstall = 1;
        
        
        for (int i = 0; i < commands.length; ++i) {
            String builderName = commands[i].getBuilderName();
            if (builderName.equals(TLAParsingBuilder.BUILDER_ID)) 
            {
                tlaBuilderFound = true;
                numberOfBuildersToInstall--;
            }
            
            if (tlaBuilderFound && pcalBuilderFound) 
            {
                return;
            }
        }

        ICommand[] newCommands = new ICommand[commands.length + numberOfBuildersToInstall];
        System.arraycopy(commands, 0, newCommands, 0, commands.length);
        
        int position = commands.length;
        
        if (!tlaBuilderFound) 
        {
            ICommand command = desc.newCommand();
            command.setBuilderName(TLAParsingBuilder.BUILDER_ID);
            newCommands[position] = command;
            position++;
        }
        
        desc.setBuildSpec(newCommands);
        project.setDescription(desc, null);
        Activator.getDefault().logDebug("Nature added");
    }

    /**
     * remove TLA nature
     */
    public void deconfigure() throws CoreException
    {
        
        IProjectDescription description = getProject().getDescription();
        ICommand[] commands = description.getBuildSpec();
        for (int i = 0; i < commands.length; ++i) {
            String builderName = commands[i].getBuilderName();
            if (builderName.equals(TLAParsingBuilder.BUILDER_ID)) {
                ICommand[] newCommands = new ICommand[commands.length - 1];
                System.arraycopy(commands, 0, newCommands, 0, i);
                System.arraycopy(commands, i + 1, newCommands, i,
                        commands.length - i - 1);
                description.setBuildSpec(newCommands);
            } 
        }
        Activator.getDefault().logDebug("Nature removed");
    }
   
    public IProject getProject()
    {
        return this.project;
    }

    public void setProject(IProject project)
    {
        this.project = project;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/Bug242DiskFPSetTest.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.fail;

import java.io.IOException;
import java.rmi.RemoteException;

import org.junit.Test;

/**
 *
 */
public class Bug242DiskFPSetTest extends AbstractFPSetTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractFPSetTest#getFPSet(int)
	 */
	@Override
	protected FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws IOException {
		return new DummyDiskFPSet(fpSetConfig);
	}
	
	@SuppressWarnings("deprecation")
	private FPSet getFPSet(int mem) throws IOException {
		FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setMemory(mem);
		fpSetConfiguration.setRatio(1.0d);
		return getFPSet(fpSetConfiguration);
	}
	
	/**
	 * @see Bug #242 in general/bugzilla/index.html
	 */
	@Test
	public void testDiskFPSetWithHighMem() throws RemoteException {
		try {
			getFPSet(2097153638);
		} catch (OutOfMemoryError e) {
			// valid case
			return;
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
	@Test
	public void testDiskFPSetIntMaxValue() throws RemoteException {
		try {
			getFPSet(Integer.MAX_VALUE);
		} catch (OutOfMemoryError e) {
			// valid case
			return;
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
	@Test
	public void testDiskFPSetIntMinValue() throws RemoteException {
		try {
			getFPSet(Integer.MIN_VALUE);
		} catch (Exception e) {
			// expected to be invalid
			return;
		}
		fail();
	}
	@Test
	public void testDiskFPSetZero() throws RemoteException {
		try {
			getFPSet(0);
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
	@Test
	public void testDiskFPSetOne() throws RemoteException {
		try {
			getFPSet(1);
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/GotoNextUseHandler.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * @author lamport
 *
 */
public class GotoNextUseHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        Spec spec = ToolboxHandle.getCurrentSpec();
        if (spec == null)
        {
            // This should not happen.
            return null;
        }
        IMarker[] markers = spec.getMarkersToShow();
        if (markers == null)
        {
            // This should not happen.
            return null;
        }
        spec.setCurrentSelection((spec.getCurrentSelection() + 1) % markers.length);
        jumpToCurrentSelection(spec);

        return null;
    }

    public boolean isEnabled()
    {
        Spec spec = ToolboxHandle.getCurrentSpec();
        if (spec == null)
        {
            return false;
        }
        return spec.getMarkersToShow() != null;
    }

    /**
     * This method does the work of the Goto Next/Previous Use.  All the code in it was
     * copied from UIHelper.jumpToLocation.  This should be pulled out and made a 
     * method in UIHelper.  However, that's a nuisance because getting the offset and
     * length for the jump in jumpToLocation is performed deep inside that method. 
     *  
     * @param spec
     */
    public static void jumpToCurrentSelection(Spec spec)
    {
        IResource moduleResource = ResourceHelper.getResourceByModuleName(spec.getModuleToShow());
        if (moduleResource != null && moduleResource.exists())
        {
            /*
             * Now, retrieve a representation of the resource
             * as a document. To do this, we use a FileDocumentProvider.
             * 
             * We disconnect the document provider in the finally block
             * for the following try block in order to avoid a memory leak.
             */
            IDocument document = null;

            // since we know that the editor uses file based editor representation
            FileEditorInput fileEditorInput = new FileEditorInput((IFile) moduleResource);
            FileDocumentProvider fileDocumentProvider = new FileDocumentProvider();
            try
            {

                fileDocumentProvider.connect(fileEditorInput);

                document = fileDocumentProvider.getDocument(fileEditorInput);
                if (document != null)
                {
                    IMarker marker = spec.getMarkersToShow()[spec.getCurrentSelection()];
                    // The following gets the location information for the position at which
                    // the marker was created, not at its current position.  Is there any way
                    // to get the marker's current position?
                    // int offset = ((Integer) marker.getAttribute(IMarker.CHAR_START)).intValue();
                    // int length = ((Integer) marker.getAttribute(IMarker.CHAR_END)).intValue() - offset;
                    
                    // Yes.  Dan provided the following method and LL incorporated it into the
                    // code on 24 Jun 2010.
                    Position pos =EditorUtil.getMarkerPosition(marker);
                    int offset = pos.getOffset();
                    int length = pos.getLength();
                    
                    IEditorPart editor = UIHelper.openEditor(OpenSpecHandler.TLA_EDITOR_CURRENT, new FileEditorInput(
                            (IFile) moduleResource));

                    if (editor != null)
                    {
                        ITextEditor textEditor;

                        if (editor instanceof ITextEditor)
                        {
                            textEditor = (ITextEditor) editor;
                        } else
                        {

                            textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
                        }

                        if (textEditor == null && editor instanceof MultiPageEditorPart)
                        {

                            IEditorPart[] editors = ((MultiPageEditorPart) editor).findEditors(editor.getEditorInput());
                            for (int i = 0; i < editors.length; i++)
                            {
                                if (editors[i] instanceof ITextEditor)
                                {
                                    textEditor = (ITextEditor) editors[i];
                                }
                            }
                        }

                        if (textEditor != null)
                        {
                            // the text editor may not be active, so set it active
                            if (editor instanceof MultiPageEditorPart)
                            {
                                ((MultiPageEditorPart) editor).setActiveEditor(textEditor);
                            }
                            // getActivePage().activate(textEditor);
                            textEditor.selectAndReveal(offset, length);
                        }
                    }

                }
            } catch (CoreException e1)
            {
                Activator.getDefault().logDebug("Error going to a module location. This is a bug.");
            } finally
            {
                fileDocumentProvider.disconnect(fileEditorInput);
            }
        }

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/Github317aTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class Github317aTest extends ModelCheckerTestCase {

	public Github317aTest() {
		super("Github317a", new String[] { "-config", "Github317a.tla"}, EC.ExitStatus.ERROR);
	}

	@Override
	protected int getNumberOfThreads() {
		// Have multiple workers compete to report/print the error stack. Implies that
		// the actual error trace is non-deteministic and not asserted below.
		return Runtime.getRuntime().availableProcessors();
	}

	@Test
	public void testSpec() {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));

		// Assert there is a trace.
		assertFalse(recorder.getRecords(EC.TLC_STATE_PRINT2).isEmpty());

		// Assert the right error trace has been printed.
		assertTrue(recorder.recordedWithStringValues(EC.TLC_NESTED_EXPRESSION,
				"0. Line 138, column 41 to line 138, column 48 in Github317a\n"
				+ "1. Line 117, column 13 to line 133, column 54 in Github317a\n"
				+ "2. Line 118, column 15 to line 133, column 54 in Github317a\n"
				+ "3. Line 128, column 23 to line 133, column 54 in Github317a\n"
				+ "4. Line 128, column 26 to line 128, column 67 in Github317a\n"
				+ "5. Line 129, column 26 to line 132, column 50 in Github317a\n"
				+ "6. Line 129, column 29 to line 129, column 59 in Github317a\n"
				+ "7. Line 129, column 29 to line 129, column 42 in Github317a\n\n"));
		
		// Assert error stack has only been printed once by one of the workers.
		assertEquals(1, recorder.getRecords(EC.TLC_NESTED_EXPRESSION).size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/LongVec.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:33 PST by lamport
//      modified on Mon Dec  4 16:20:19 PST 2000 by yuanyu
package tlc2.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;

import util.FileUtil;

public class LongVec implements Cloneable, Serializable {
	private static final long serialVersionUID = 2406899362740899071L;
	protected long[] elementData;
	protected int elementCount;

	public LongVec() { this(10); }

	public LongVec(int initialCapacity) {
		this.elementCount = 0;
		this.elementData = new long[initialCapacity];
	}

	private LongVec(final LongVec other) {
		this.elementCount = other.elementCount;
		this.elementData = Arrays.copyOfRange(other.elementData, 0, other.elementCount);
	}

	public final void addElement(long x) {
		if (this.elementCount == this.elementData.length) {
			ensureCapacity(this.elementCount + 1);
		}
		this.elementData[this.elementCount++] = x;
	}

	public final long elementAt(int index) {
		rangeCheck(index);
		return this.elementData[index];
	}
	
	public final long lastElement() {
		return this.elementData[elementCount - 1];
	}

	public final void removeElement(int index) {
		rangeCheck(index);
		this.elementData[index] = this.elementData[this.elementCount - 1];
		this.elementCount--;
	}

	private void rangeCheck(int index) {
		if (index >= elementCount) {
			throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
		}
	}
	
    /**
     * Constructs an IndexOutOfBoundsException detail message.
     * Of the many possible refactorings of the error handling code,
     * this "outlining" performs best with both server and client VMs.
     */
	// Copied from java.util.ArrayList
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+elementCount;
    }

	public final boolean isEmpty() {
		return this.elementCount == 0;
	}

	public final int size() {
		return this.elementCount;
	}

	private final void ensureCapacity(int minCapacity) {
		if (elementData.length < minCapacity) {
			int newCapacity = elementData.length + elementData.length;
			if (newCapacity < minCapacity) {
				newCapacity = minCapacity;
			}
			long oldBuffer[] = this.elementData;
			this.elementData = new long[newCapacity];

			System.arraycopy(oldBuffer, 0, elementData, 0, elementCount);
		}
	}

	public final void reset() { this.elementCount = 0; }

	private void readObject(ObjectInputStream ois)
			  throws IOException, ClassNotFoundException {
		this.elementCount = ois.readInt();
		this.elementData = new long[this.elementCount];
		for (int i = 0; i < this.elementCount; i++) {
			this.elementData[i] = ois.readLong();
		}
	}

	private void writeObject(ObjectOutputStream oos) throws IOException {
		oos.writeInt(this.elementCount);
		for (int i = 0; i < this.elementCount; i++) {
			oos.writeLong(this.elementData[i]);
		}
	}

	public final String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("<");
		if (this.elementCount != 0) {
			sb.append(this.elementData[0]);
		}
		for (int i = 1; i < this.elementCount; i++) {
			sb.append(", ");
			sb.append(this.elementData[i]);
		}
		sb.append(">");
		return sb.toString();
	}

	public static void main(String args[]) throws Exception {
		LongVec vec = new LongVec(1000);
		vec.addElement(1);
		vec.addElement(3);
		vec.addElement(5);
		System.err.println(vec.size());
		ObjectOutputStream oos = FileUtil.newOBFOS("XXX");
		oos.writeObject(vec);

		ObjectInputStream ois = FileUtil.newOBFIS("XXX");
		LongVec vec1 = (LongVec) ois.readObject();
		System.err.println(vec1.size());
		System.err.println(vec1.elementAt(0));
		System.err.println(vec1.elementAt(1));
		System.err.println(vec1.elementAt(2));
	}

	private LongVec reverse0() {
		int left = 0;
		int right = elementData.length - 1;

		while (left < right) {
			long temp = elementData[left];
			elementData[left] = elementData[right];
			elementData[right] = temp;

			left++;
			right--;
		}
		return this;
	}
	
	public LongVec reverse() {
		try {
			return new LongVec(this).reverse0();
		} catch (Exception e) {
			throw e;
		}
	}

	/** 
	 * Remove *consecutive* duplicates:
	 * [1,2,2,1,1,3] -> [1,2,1,3]
	 */
	public LongVec pack() {
		// so far only used to while printing a liveness error trace and thus not
		// performance critical. Once performance matters, we should do it in-place.
		final LongVec filtered = new LongVec(size());
		for (int i = 0; i < elementCount; i++) {
			long x = elementData[i];
			if (filtered.elementCount == 0 || filtered.lastElement() != x) {
				filtered.addElement(x);
			}
		}
		this.elementCount = filtered.elementCount;
		this.elementData = filtered.elementData;
		return this;
	}

	public LongVec removeLastIf(long x) {
		if (this.elementCount > 0 && this.lastElement() == x) {
			this.elementCount = this.elementCount - 1;
		}
		return this;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/May09Test.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Ignore;
import org.junit.Test;

import tlc2.output.EC;

/**
 * May09Test and its counterpart May09dTest prove that the algorithm with
 * redundant arcs with different action predicate labels in the liveness graph
 * does not work even when liveness properties containing conjuncts over the
 * elements of the symmetry set are rewritten to a disjunct and out-arcs are
 * counted (compare to {@link April29Test} and {@link April29dTest}).
 * 
 * <pre>
 *	[]<>P(a) /\ []<>P(b) rewritten to: []<>P(a) \/ []<>P(b)
 * </pre>
 * 
 * (where P is either a State or Action predicate and a,b are all elements of
 * the symmetry set)
 * 
 * Trying to deduce []<>P(b) from the occurrence of []<>P(a) (or vice versa)
 * fails because the two specs (Spec & SpecD) under symmetry produce the same
 * state graph. Without symmetry, Spec does not satisfy []<>P(a) /\ []<>P(b),
 * only SpecD does. Under symmetry, a version of TLC that does not rewrite the
 * liveness property finds the bogus counterexample for SpecD.  
 * 
 * A yet unexplored research hypothesis is, that labeling all arcs with the
 * permutation that the to-state represents in the liveness graph. This information
 * would allow us to distinguish the graphs of May09 and May09d.
 */
public class May09Test extends ModelCheckerTestCase {

	public May09Test() {
		super("May09MC", "symmetry");
	}

	@Test
	@Ignore("Ignored for as long as symmetry is incorrectly handled by TLC with liveness checking.")
	public void testSpec() throws IOException {
		// Assert TLC has found a temporal violation and a counter example
		assertTrue(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
		assertTrue(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));

		// Assert the error trace
		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT2));
		final List<String> expectedTrace = new ArrayList<String>(2);
		expectedTrace.add("/\\ x = a\n/\\ y = 0");
		expectedTrace.add("/\\ x = a\n/\\ y = 1");
		expectedTrace.add("/\\ x = a\n/\\ y = 2");
		expectedTrace.add("/\\ x = a\n/\\ y = 3");
		expectedTrace.add("/\\ x = a\n/\\ y = 4");
		expectedTrace.add("/\\ x = a\n/\\ y = 5");
		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);

		assertBackToState(2, "<Action line 19, col 10 to line 21, col 18 of module May09>");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/BufferedRandomAccessFileTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

public class BufferedRandomAccessFileTest {

	@Test
	public void testWrite() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testWrite", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");
		for (long i = 0L; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
			raf.writeLong(i);
		}
		raf.close();
	}
	
	@Test
	public void testWriteSeek() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testWriteSeek", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");
		
		raf.setLength(BufferedRandomAccessFile.BuffSz + 1L);
		raf.seek(1);
		
		for (long i = 0L; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
			raf.writeLong(i);
		}
		raf.close();
	}
	
	@Test
	public void testWriteSeekNoLength() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testWriteSeekNoLength", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");

		// Do not set length, expect meaningful exception
		raf.seek(1);
		try {
			for (long i = 0L; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
				raf.writeLong(i);
			}
		} catch (IOException expected) {
			return;
		} catch (Exception e) {
			fail(e.getMessage());
		} finally {
			raf.close();
		}
	}
	
	@Test
	public void testRead() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testRead", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");
		for (long i = 0L; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
			raf.writeLong(i);
		}

		raf.seek(0);
		for (long i = 0l; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
			assertEquals(i, raf.readLong());
		}
		raf.close();
	}
	
	@Test
	public void testReadSeek() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testReadSeek", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");
		
		raf.setLength(BufferedRandomAccessFile.BuffSz + 1L);
		raf.seek(1);
		
		for (int i = 0; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
			assertEquals(0L, raf.readLong());
		}
		raf.close();
	}
	
	@Test
	public void testReadSeekNoLength() throws IOException {
		final File tmpFile = File.createTempFile("BufferedRandomAccessFileTest_testReadSeekNoLength", ".bin");
		tmpFile.deleteOnExit();
		final java.io.RandomAccessFile raf = new BufferedRandomAccessFile(tmpFile, "rw");

		// Do not set length, expect meaningful exception
		raf.seek(1);
		try {
			for (int i = 0; i < BufferedRandomAccessFile.BuffSz / 8; i++) {
				raf.readLong();
			}
		} catch (IOException expected) {
			return;
		} catch (Exception e) {
			fail(e.getMessage());
		} finally {
			raf.close();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/DiskIntStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:27 PST by lamport
//      modified on Thu Jan 10 18:33:42 PST 2002 by yuanyu

package tlc2.util;

import java.io.File;

import tlc2.output.EC;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;

/**
 * Alternative implementation. Currently not used
 * 
 * This implementation is likely to have never worked and should be regarded as
 * a sketch for a how a concurrent implementation could look like. For the
 * moment, {@link SynchronousDiskIntStack} does the job just fine. Albeit - as
 * the name suggests - in a synchronous fashion.
 * 
 */
public final class DiskIntStack implements IntStack {
  private final static int BufSize = 16384;

  private long size;
  private String filePrefix;
  private File poolFile;
  private int[] buf1, buf2, buf, rwbuf;
  private int index;
  private int hiPool;
  private boolean isIdle;
  private Reader reader;
  private Writer writer;
  
  public DiskIntStack(String diskdir, String name) {
    this.size = 0;
    this.buf1 = new int[BufSize];
    this.buf2 = new int[BufSize];
    this.rwbuf = new int[BufSize];
    this.buf = this.buf1;
    this.index = 0;
    this.hiPool = 0;
    this.isIdle = true;
    this.filePrefix = diskdir + FileUtil.separator + name;
    this.poolFile = null;
    this.reader = new Reader();
    this.writer = new Writer();
    this.reader.start();
    this.writer.start();
  }

  /* Return the number of items on the stack. */
  public final long size() { return this.size; }
  
  /* Push an integer onto the stack.  */
  public final synchronized void pushInt(int x) {
    if (this.index == BufSize && this.buf == this.buf2) {
      // need to flush buf1 to disk
      try {
	while (!this.isIdle) this.wait();
	this.buf = this.rwbuf;
	this.rwbuf = this.buf1;
	this.poolFile = new File(this.filePrefix + Integer.toString(this.hiPool++));
	this.isIdle = false;
	this.writer.notify();
	this.buf1 = this.buf2;
	this.buf2 = this.buf;
	this.index = 0;
      }
      catch (Exception e) {
          Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES, new String[]{"stack", e.getMessage()});          
      }
    }
    this.buf[this.index++] = x;
    this.size++;
  }
  
  /* Push a long integer onto the stack.  */
  public final synchronized void pushLong(long x) {
    this.pushInt((int)(x & 0xFFFFFFFFL));
    this.pushInt((int)(x >>> 32));
  }

  /* Pop the integer on top of the stack.  */
  public final synchronized int popInt() {
    if (this.buf == this.buf1 && this.index < BufSize/2 && this.hiPool != 0) {
      // need to fill buf1 from disk
      try {
	while (!this.isIdle) this.wait();
	this.buf = this.rwbuf;
	this.rwbuf = this.buf2;
	this.hiPool--;
	if (this.hiPool > 0) {
	  this.poolFile = new File(this.filePrefix + Integer.toString(this.hiPool-1));
	  this.isIdle = false;
	  this.reader.notify();
	}
	this.buf2 = this.buf1;
	this.buf1 = this.buf;
	this.buf = this.buf2;
      }
      catch (Exception e) {
          Assert.fail(EC.SYSTEM_ERROR_READING_STATES, new String[]{"stack", e.getMessage()});
      }
    }
    this.size--;
    return this.buf[--this.index];
  }

  /* Pop the long integer on top of the stack.  */
  public final synchronized long popLong() {
    long high = this.popInt();
    long low = this.popInt();
    return (high << 32) | (low & 0xFFFFFFFFL);
  }

  class Reader extends Thread {
    public void run() {
      try {
	synchronized(this) {
	  while (true) {
	    while (DiskIntStack.this.poolFile == null) {
	      this.wait();
	    }
	    BufferedDataInputStream bdis = FileUtil.newBdFIS(false, DiskIntStack.this.poolFile);
	    int len = DiskIntStack.this.rwbuf.length;
	    for (int i = 0; i < len; i++) {
	      DiskIntStack.this.rwbuf[i] = bdis.readInt();
	    }
	    bdis.close();
	    DiskIntStack.this.poolFile = null;
	    DiskIntStack.this.isIdle = true;
	    DiskIntStack.this.notify();	    
	  }
	}
      }
      catch (Exception e) 
      {
          Assert.fail(EC.SYSTEM_DISK_IO_ERROR_FOR_FILE, e);
      }
    }
  }

  class Writer extends Thread {
    public void run() {
      try {
	synchronized(this) {
	  while (true) {
	    while (DiskIntStack.this.poolFile == null) {
	      this.wait();
	    }
	    BufferedDataOutputStream bdos = FileUtil.newBdFOS(false, DiskIntStack.this.poolFile);
	    int len = DiskIntStack.this.buf.length;
	    for (int i = 0; i < len; i++) {
	      bdos.writeInt(DiskIntStack.this.buf[i]);
	    }
	    bdos.close();
	    DiskIntStack.this.poolFile = null;
	    DiskIntStack.this.isIdle = true;
	    DiskIntStack.this.notify();
	  }
	}
      }
      catch (Exception e) 
      {
          Assert.fail(EC.SYSTEM_DISK_IO_ERROR_FOR_FILE, e);
      }
    }
  }

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#reset()
	 */
	public void reset() {
		// TODO Auto-generated method stub
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/util/ElementStateAdapter.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.util;

import org.eclipse.ui.texteditor.IElementStateListener;

/**
 * A simple adapter of the Element state listener
 * @author <NAME>
 * @version $Id$
 */
public class ElementStateAdapter implements IElementStateListener
{

    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.IElementStateListener#elementContentAboutToBeReplaced(java.lang.Object)
     */
    public void elementContentAboutToBeReplaced(Object element)
    {

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.IElementStateListener#elementContentReplaced(java.lang.Object)
     */
    public void elementContentReplaced(Object element)
    {

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.IElementStateListener#elementDeleted(java.lang.Object)
     */
    public void elementDeleted(Object element)
    {

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.IElementStateListener#elementDirtyStateChanged(java.lang.Object, boolean)
     */
    public void elementDirtyStateChanged(Object element, boolean isDirty)
    {

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.IElementStateListener#elementMoved(java.lang.Object, java.lang.Object)
     */
    public void elementMoved(Object originalElement, Object movedElement)
    {

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PCalLocation.java<|end_filename|>
/**
 * A Location is a line, column pair of integers.  It represents 
 * a location in the .tla file.  The column is a Java position
 * (starting from 0); a line may be relative to some anchoring 
 * line.
 *
 */
package pcal;

import java.io.Serializable;

/**
 * @author lamport
 *
 */
public class PCalLocation implements Serializable {
	
    /**
	 * @see TLAtoPCalMapping#serialVersionUID
	 */
	private static final long serialVersionUID = 5224570720345403320L;

	private int line;
	
	private int column;
	
	public PCalLocation(int line, int column) {
		this.line = line;
		this.column = column;
	}

	public int getLine() {
		return line;
	}
	
	public void adjustLineBy(int l) {
		line -= l;
	}

	public int getColumn() {
		return column;
	}
	
	public int getOffset() {
		return line + column;
	}
	
	public String toString() {
//		return "[line |-> " + line + ", column |-> " + column + "]" ;
		return "(" + line + ", " + column +")" ;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + column;
		result = prime * result + line;
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PCalLocation other = (PCalLocation) obj;
		if (column != other.column)
			return false;
		if (line != other.line)
			return false;
		return true;
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/preference/TLA2TeXPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.preference;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.tool.tla2tex.TLA2TeXActivator;

/**
 * Preference page for TLA2TeX
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLA2TeXPreferencePage extends FieldEditorPreferencePage implements
		IWorkbenchPreferencePage {

	public TLA2TeXPreferencePage() {
		super(GRID);
		setPreferenceStore(TLA2TeXActivator.getDefault().getPreferenceStore());
		setDescription("PDF Viewer Preferences");
	}

	public TLA2TeXPreferencePage(int style) {
		super(style);
	}

	public TLA2TeXPreferencePage(String title, int style) {
		super(title, style);
	}

	public TLA2TeXPreferencePage(String title, ImageDescriptor image, int style) {
		super(title, image, style);
	}

	protected void createFieldEditors() {
		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			addField(new BooleanFieldEditor(
					ITLA2TeXPreferenceConstants.HAVE_OS_OPEN_PDF,
					"Have your OS open PDFs", getFieldEditorParent()));
		} else {
			addField(new BooleanFieldEditor(
					ITLA2TeXPreferenceConstants.EMBEDDED_VIEWER,
					"&Use built-in PDF viewer", getFieldEditorParent()));
		}
		
		// Preference to regenerate PDF upon spec save?
		addField(new BooleanFieldEditor(
				ITLA2TeXPreferenceConstants.AUTO_REGENERATE, "&Regenerate pretty-printed PDF on spec save (takes effect once spec re-opened).",
				getFieldEditorParent()));

		addField(new BooleanFieldEditor(
				ITLA2TeXPreferenceConstants.SHADE_COMMENTS, "&Shade comments",
				getFieldEditorParent()));
        addField(new BooleanFieldEditor(
                ITLA2TeXPreferenceConstants.NO_PCAL_SHADE, "&Do not shade PlusCal code",
                getFieldEditorParent()));
		addField(new BooleanFieldEditor(
				ITLA2TeXPreferenceConstants.NUMBER_LINES, "&Number lines",
				getFieldEditorParent()));
		addField(new StringFieldEditor(
				ITLA2TeXPreferenceConstants.DOT_COMMAND,
				"&Specify dot command", getFieldEditorParent()));
		addField(new StringFieldEditor(
				ITLA2TeXPreferenceConstants.LATEX_COMMAND,
				"&Specify pdflatex command", getFieldEditorParent()));
		addField(new DoubleFieldEditor(ITLA2TeXPreferenceConstants.GRAY_LEVEL,
				"&Specify gray level (between 0.0 and 1.0)",
				getFieldEditorParent(), 0, 1));
	}

	public void init(IWorkbench workbench) {
		// nop
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/DistributedTLCTestCase.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.distributed;

import java.security.Permission;
import java.util.concurrent.CountDownLatch;

import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;

import tlc2.TestMPRecorder;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.CommonTestCase;
import tlc2.tool.distributed.fp.DistributedFPSet;

public abstract class DistributedTLCTestCase extends CommonTestCase {
	
	protected final String[] arguments;
	protected final int fpSets;
	
	private SecurityManager securityManager;
	
	public DistributedTLCTestCase(String spec, String path) {
		this(spec, path, new String[] {});
	}
	
	public DistributedTLCTestCase(String spec, String path, String[] args) {
		this(spec, path, args, 0);
	}
	
	public DistributedTLCTestCase(String spec, String path, String[] args, int fpSets) {
		super(new FilteringTestMPRecorder());
		this.arguments = new String[args.length + 1];
		this.arguments[this.arguments.length - 1] = path + spec; // Add path to additional arguments
		System.arraycopy(args, 0, arguments, 0, args.length);
		
		this.fpSets = fpSets;
	}
    
	@Before
	public void setUp() {
		Assume.assumeTrue("DistributedTLCTestCase broken with OffHeapDiskFPSet.", false);
		// Remember the original security manager and have it replaced with this
		// custom one. Contrary to the original, this security manager
		// intercepts calls to System.exit(int) and throws an exception instead
		// of terminating the VM. This is done to prevent TLCWorker/TLCServer/...
		// from terminating the JUnit test itself. To allow the JUnit test to
		// later terminate the VM after test completion, we have to reinstate
		// the original security manager again (see tearDown).
		securityManager = System.getSecurityManager();
		System.setSecurityManager(new NoExitSecurityManager());

		MP.setRecorder(recorder);
		
		// Wait for all processes to terminate before the setup itself is done
		final CountDownLatch latch = new CountDownLatch(fpSets + 2);
		
		// Workers
		new Thread(new Runnable() {
			public void run() {
				try {
					TLCWorker.main(new String[] { "localhost" });
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					latch.countDown();
				}
			}
		}, "Worker").start();

		// master
		new Thread(new Runnable() {
			public void run() {
				try {
					System.setProperty(TLCServer.class.getName() + ".expectedFPSetCount", Integer.toString(fpSets));
					TLCServer.main(arguments);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					latch.countDown();
				}
			}
		}, "Master").start();

		// FPSet
		if (fpSets > 0) {
			new Thread(new Runnable() {
				public void run() {
					try {
						DistributedFPSet.main(new String[] { "localhost" });
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						latch.countDown();
					}
				}
			}, "FPSet").start();
		}

		try {
			latch.await();
		} catch (InterruptedException e) {
			Assert.fail();
		}
	}
	
	@After
	public void tearDown() {
		System.setSecurityManager(securityManager);
	}
	
	private static class NoExitSecurityManager extends SecurityManager {
		/* (non-Javadoc)
		 * @see java.lang.SecurityManager#checkPermission(java.security.Permission)
		 */
		public void checkPermission(Permission perm) {
			// allow anything.
		}

		/* (non-Javadoc)
		 * @see java.lang.SecurityManager#checkPermission(java.security.Permission, java.lang.Object)
		 */
		public void checkPermission(Permission perm, Object context) {
			// allow anything.
		}

		/* (non-Javadoc)
		 * @see java.lang.SecurityManager#checkExit(int)
		 */
		public void checkExit(int status) {
			super.checkExit(status);
			throw new NoExitException();
		}
	}
	
	@SuppressWarnings("serial")
	public static class NoExitException extends RuntimeException {
		// Want an easily distinguishable exception.
	}
	
	private static class FilteringTestMPRecorder extends TestMPRecorder {
		/* (non-Javadoc)
		 * @see tlc2.TestMPRecorder#record(int, java.lang.Object[])
		 */
		public void record(int code, Object... objects) {
			if (EC.GENERAL == code && objects instanceof String[]) {
				// GENERAL errors contain the exceptions thrown because of the
				// intercepted System.exit(int) calls. Remove them so that 
				// tests can check for real EC.GENERAL errors.
				final String msg = ((String[]) objects)[0];
				if (msg.contains(NoExitException.class.getName())) {
					return;
				}
			}
			super.record(code, objects);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/PartitionToolkit.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TypedRegion;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCRegion;
import org.lamport.tla.toolbox.tool.tlc.output.source.TagBasedTLCOutputTokenScanner;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * A toolkit with helper methods
 * @author <NAME>
 * @version $Id$
 */
public class PartitionToolkit
{
    /**
     * Merges an array of partitions of the same type to one partition of this type
     * @param regions array of partitions of the same type, which MUST be intervals of document following 
     * each other continuously ([i, i+k], [i+k, i+k+l], [i+k+l, i+k+l+n], etc)...    
     * @return one partition starting as the first element and ending as the last in the array, 
     * or <code>null</code> on any error
     */
    public static ITypedRegion mergePartitions(ITypedRegion[] regions)
    {
        Assert.isNotNull(regions);
        if (regions.length == 0)
        {
            return null;
        }
        String type = null;
        int offset = -1;
        int length = 0;
        int matcher = -1;

        for (int i = 0; i < regions.length; i++)
        {
            if (type == null)
            {
                type = regions[i].getType();
            } else
            {
                if (!type.equals(regions[i].getType()))
                {
                    return null;
                }
            }
            if (offset == -1)
            {
                offset = regions[i].getOffset();

            } else
            {
                if (regions[i].getOffset() != matcher)
                {
                    return null;
                }
            }

            matcher = regions[i].getOffset() + regions[i].getLength();
            length += regions[i].getLength();

        }
        return new TypedRegion(offset, length, type);
    }

    /**
     * Prints partition information
     * @param region
     * @param document
     */
    public static void printPartition(ITypedRegion region, IDocument document)
    {
        if (region == null)
        {
            return;
        }

        try
        {
            StringBuffer messageBuffer = new StringBuffer();
            String location = "[" + region.getOffset() + ":" + region.getLength() + "]";

            if (region instanceof TLCRegion)
            {
                TLCRegion tlcRegion = (TLCRegion) region;
                messageBuffer.append("TLC:" + tlcRegion.getMessageCode() + " " + tlcRegion.getSeverity() + " "
                        + location);
            } else
            {
                int offset = region.getOffset();
                int printLength = Math.min(region.getLength(), 255);

                String type = region.getType();
                Assert.isTrue(type.equals(TagBasedTLCOutputTokenScanner.DEFAULT_CONTENT_TYPE));

                String head = document.get(offset, printLength);
                messageBuffer.append("OUTPUT:" + location + ": >" + head + "< ...");
            }

            TLCUIActivator.getDefault().logDebug(messageBuffer.toString());

        } catch (BadLocationException e)
        {
            TLCUIActivator.getDefault().logError("Error printing partition", e);
        }

    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MemFPSet1.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:15:06 PST by lamport
//      modified on Tue May 15 23:11:51 PDT 2001 by yuanyu

package tlc2.tool.fp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.RemoteException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCTrace;
import tlc2.util.SetOfLong;
import util.Assert;
import util.FileUtil;

/**
 * Alternative implementation
 * @deprecated not used currently
 * @version $Id$
 */
public final class MemFPSet1 extends FPSet {
  private String metadir;
  private String filename;
  private SetOfLong set;

  public MemFPSet1(final FPSetConfiguration fpSetConfig) throws RemoteException {
    super(fpSetConfig);
    this.set = new SetOfLong(10001, 0.75f);
  }

  public final FPSet init(int numThreads, String metadir, String filename) {
    this.metadir = metadir;
    this.filename = filename;
	return this;
  }

  public final long size() { return this.set.size(); }

  public final long sizeof() { return 8 + this.set.sizeof(); }

  public synchronized final boolean put(long fp) {
    return this.set.put(fp);
  }

  public synchronized final boolean contains(long fp) {
    return this.set.contains(fp);
  }

  public final void exit(boolean cleanup) throws IOException {
    super.exit(cleanup);
    if (cleanup) {
      // Delete the metadata directory:
      File file = new File(this.metadir);
      FileUtil.deleteDir(file, true);
    }
    String hostname = InetAddress.getLocalHost().getHostName();    
    MP.printMessage(EC.TLC_FP_COMPLETED, hostname);
    System.exit(0);    
  }

  public final long checkFPs() { return this.set.checkFPs(); }

  /* Checkpoint. */
  public final void beginChkpt(String fname) throws IOException {
    DataOutputStream dos = FileUtil.newDFOS(this.chkptName(fname, "tmp"));
    this.set.beginChkpt(dos);
    dos.close();
  }
  
  public final void commitChkpt(String fname) throws IOException {
    File oldChkpt = new File(this.chkptName(fname, "chkpt"));
    File newChkpt = new File(this.chkptName(fname, "tmp"));
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemFPSet1.commitChkpt: cannot delete " + oldChkpt);
    }
  } 

  public final void recover(String fname) throws IOException {
    
    DataInputStream dis = FileUtil.newDFIS(this.chkptName(fname, "chkpt"));
    this.set.recover(dis);
    dis.close();
    
  }

  public final void beginChkpt() throws IOException {
    this.beginChkpt(this.filename);
  }

  public final void commitChkpt() throws IOException {
    this.commitChkpt(this.filename);
  }
  
  public final void recover(TLCTrace trace) throws IOException {
    this.recover(this.filename);
  }

  public final void recoverFP(long fp) throws IOException {
    Assert.check(!this.set.put(fp), EC.TLC_FP_NOT_IN_SET);
  }
  
  private final String chkptName(String fname, String ext) {
    return this.metadir + FileUtil.separator + fname + ".fp." + ext;
  }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/Assert.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.utilities;

/**
 * Implementation of assertion for SANY. 
 * 
 * @author <NAME>
 * @version $Id$
 * 
 * @deprecated Use {@linkplain util.Assert} instead of this class
 */
public class Assert
{

    // SZ Jul 13, 2009: fishy way to exit the program
    /**
     * @deprecated Use {@linkplain util.Assert#check(boolean, int, String[])} instead of this method
     */
    public final static void assertion(boolean b)
    {
        // if (!b) {
        // ToolIO.err.println("assertion failed:");
        // System.exit(1);
        // }
    }

    // SZ Jul 13, 2009: method not used
    /**
     * @deprecated Use {@linkplain util.Assert#fail(int, String[])} instead of this method
     */
    public final static void fail(String msg)
    {
        // ToolIO.err.println("Error: " + msg);
        // System.exit(1);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Symbol.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Symbol                                                             *
*                                                                          *
* A Symbol object describes a built-in symbol of TLA.  It is essentially   *
* a record, with its fields made public.  It contains the following        *
* fields:                                                                  *
*                                                                          *
*    TLAString     : How the symbol appears in the input file.             *
*                                                                          *
*    TeXString     : The LaTeX input to print the symbol.                  *
*                                                                          *
*    symbolType    : A classification.                                     *
*                                                                          *
*    alignmentType : Two symbols are candidates for alignment iff          *
*                    they have the same non-zero alignmentType.            *
***************************************************************************/
package tla2tex;

public class Symbol
  { public String TLAString;
      /*********************************************************************
      * The TLA representation of the symbol.  There is a different        *
      * Symbol object for each way of writing the same symbol--for         *
      * example, there are separate symbol objects for "#" and "/=".       *
      *********************************************************************/

    public String TeXString;
      /*********************************************************************
      * The TeX input that prints the symbol.                              *
      *********************************************************************/
      
    public int symbolType ;
      /*********************************************************************
      * The type of symbol it is.  Here are the possibilities:             *
      *********************************************************************/
                                                 /* Examples              */
                                                 /* ~~~~~~~~              */
      public static final int INFIX        =  1 ;  /* "+"  ":"  "-"       */
      public static final int PREFIX       =  2 ;  /*"\A" "ENABLED"       */
      public static final int POSTFIX      =  3 ;  /* "^#" "'"            */
      public static final int LEFT_PAREN   =  4 ;  /* "("  "<<"           */
      public static final int RIGHT_PAREN  =  5 ;  /* ")"  ">>"           */
      public static final int SUBSCRIPTED  =  6 ;  /* "WF_" "]_"          */
      public static final int KEYWORD      =  7 ;  /* "THEOREM"           */
      public static final int PUNCTUATION  =  8 ;  /* ","                 */
      public static final int MISC         =  9 ;  /* "-."                */
      public static final int NOT_A_SYMBOL = 10 ;  
        /*******************************************************************
        * For convenience, we define a value that's not a symbol type.     *
        *******************************************************************/
      
    public boolean pcal = false ;  
      // True iff this is a PlusCal symbol.
    
    public int alignmentType ;
      /*********************************************************************
      * Two symbols can be inner-aligned iff they have the same alignment  *
      * type.  However, an alignment type of 0 means that the symbol       *
      * cannot be inner-aligned.  See the FindAlignments class for an      *
      * explanation of inner-alignment.                                    *
      *********************************************************************/
 
    public Symbol(String tla, String tex, int stype, int atype)
      /*********************************************************************
      * The constructor for a non-PlusCal Symbol object.                   *
      *********************************************************************/
      { TLAString     = tla   ;
        TeXString     = tex   ;
        symbolType    = stype ;
        alignmentType = atype ;
        pcal          = false ;
      };

    public Symbol(String tla, String tex, int stype, int atype, boolean plusCal)
      /*********************************************************************
      * The constructor used for a PlusCal Symbol object.                  *
      *********************************************************************/
      { TLAString     = tla   ;
        TeXString     = tex   ;
        symbolType    = stype ;
        alignmentType = atype ;
        pcal          = plusCal ;
      };

      public String toString() 
      /*********************************************************************
      * To print a Symbol object for debugging.                            *
      *********************************************************************/
      { return "[TLAString |-> " + TLAString     
                 + ", TeXString |-> " + TeXString
                 + ", symbolType |-> " + symbolType
                 + ", alignmentType |-> " + alignmentType + "]";
      };  

  }

/* Last modified on Tue 18 Sep 2007 at  6:51:56 PST by lamport */

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/drivers/InitException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.drivers;

public class InitException extends Exception {}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/RenameSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IWorkbenchPage;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Handler for renaming the specifications
 */
public class RenameSpecHandler extends AbstractHandler implements IHandler {

	private boolean reopenEditorAfterRename;

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
	 */
	public Object execute(ExecutionEvent event) throws ExecutionException {
		/*
		 * No parameter try to get it from active navigator if any
		 */
		final IWorkbenchPage activePage = UIHelper.getActivePage();
		if (activePage != null) {
			final ISelection selection = activePage.getSelection(ToolboxExplorer.VIEW_ID);
			if (selection != null && selection instanceof IStructuredSelection) {
				// handler is set up to only allow single selection in
				// plugin.xml -> no need to handle multi selection
				final Spec spec = (Spec) ((IStructuredSelection) selection).getFirstElement();

				// name proposal
				String specName = spec.getName() + "_Copy";

				// dialog that prompts the user for the new spec name (no need
				// to join UI thread, this is the UI thread)
				final InputDialog dialog = new InputDialog(UIHelper.getShell(), "New specification name",
						"Please input the new name of the specification", specName, new SpecNameValidator());
				dialog.setBlockOnOpen(true);
				if (dialog.open() == Window.OK) {
					final WorkspaceSpecManager specManager = Activator.getSpecManager();
					
					// close open spec before it gets renamed
					reopenEditorAfterRename = false;
					if (specManager.isSpecLoaded(spec)) {
						UIHelper.runCommand(CloseSpecHandler.COMMAND_ID, new HashMap<String, String>());
						reopenEditorAfterRename = true;
					}
					
					// use confirmed rename -> rename
					final Job j = new ToolboxJob("Renaming spec...") {
						protected IStatus run(final IProgressMonitor monitor) {
							// do the actual rename
							specManager.renameSpec(spec, dialog.getValue(), monitor);
							
							// reopen editor again (has to happen in UI thread)
							UIHelper.runUIAsync(new Runnable() {
								/* (non-Javadoc)
								 * @see java.lang.Runnable#run()
								 */
								public void run() {
									if (reopenEditorAfterRename) {
										Map<String, String> parameters = new HashMap<String, String>();
										parameters.put(OpenSpecHandler.PARAM_SPEC, dialog.getValue());
										UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
									}
								}
							});
							return Status.OK_STATUS;
						}
					};
					j.schedule();
				}
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActivePage() == null) {
			return false;
		}
		return super.isEnabled();
	}

	class SpecNameValidator implements IInputValidator {

		/* (non-Javadoc)
		 * @see org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String)
		 */
		public String isValid(String name) {
			// null, empty, just whitespaces
			if (name == null || name.length() == 0 || name.trim().length() == 0) {
				return "The specification name must not be empty";
			}
			final Spec[] specs = Activator.getSpecManager().getRecentlyOpened();
			for (int i = 0; i < specs.length; i++) {
				if (name.equals(specs[i].getName())) {
					return "The specification with this name already exists";
				}
				if (name.equalsIgnoreCase(specs[i].getName())) {
					return "A specification exists with the same name but a different case. This is not allowed.";
				}
			}
			return null;
		}

	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex.uitest/src/org/lamport/tla/toolbox/tool/tla2tex/PDFHandlerThreadingTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex;

import java.io.File;

import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.lamport.tla.toolbox.test.RCPTestSetupHelper;
import org.lamport.tla.toolbox.test.threading.MonitorAdaptor;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;

@RunWith(SWTBotJunit4ClassRunner.class)
public class PDFHandlerThreadingTest {
	
	private static SWTWorkbenchBot bot;

	private static final String specA = System.getProperty("org.lamport.tla.toolbox.tool.tlc.ui.test.PathToSpecA",
			RCPTestSetupHelper.getAbsolutePath("org.lamport.tla.toolbox.uitest",
					"farsite/DistributedSystemModule.tla"));
	private static final String specB = System.getProperty("org.lamport.tla.toolbox.tool.tlc.ui.test.PathToSpecB",
			RCPTestSetupHelper.getAbsolutePath("org.lamport.tla.toolbox.uitest", "DieHard/DieHard.tla"));
	
	@BeforeClass
	public static void beforeClass() throws Exception {
		
		// If this assert fails see http://wiki.eclipse.org/JDT_weaving_features
		final String osgiFrameworkExtensions = System.getProperty("osgi.framework.extensions");
		Assert.assertNotNull(
				"Test requires Aspectj weaving hook property to be present as an indicator for active weaving support",
				osgiFrameworkExtensions);
		
		// Reset the workbench
		RCPTestSetupHelper.beforeClass();
		
		// check to make sure the given spec files exist
		Assert.assertTrue("Given spec file does not exist: " + specA, new File(
				specA).exists());
		Assert.assertTrue("Given spec file does not exist: " + specA, new File(
				specB).exists());
		
		bot = new SWTWorkbenchBot();
	}
	
	@Test @Ignore("not ready yet")
	public void producePDFInNonUIThread() throws InterruptedException {
		
		// Open specA 
		SWTBotMenu fileMenu = bot.menu("File");
		SWTBotMenu openSpecMenu = fileMenu.menu("Open Spec");
		SWTBotMenu addNewSpecMenu = openSpecMenu.menu("Add New Spec...");
		addNewSpecMenu.click();

		bot.textWithLabel("Root-module file:").setText(specA);
		bot.button("Finish").click();
		
		// generate PDF
		SWTBotMenu pdfMenu = fileMenu.menu("Produce PDF Version");
		pdfMenu.click();
		
		// wait for the browser to show up with the generated PDF
		SWTBotEditor swtBotEditor = bot.editorById(OpenSpecHandler.TLA_EDITOR);
		Assert.assertNotNull(swtBotEditor);
		
		assertNoBackendCodeInUIThread();
	}

	/**
	 * Checks how many invocations of backend code have happend inside the UI thread
	 */
	private void assertNoBackendCodeInUIThread() {
		
		// Check if MonitorAspect has been enabled
		Assert.assertTrue("Test requires active MonitorAspect aspect!", MonitorAdaptor.aspectIsActive());

		Assert.assertFalse(
				"Backend code (e.g. parsing must not be executed in UI thread) times executed: "
						+ MonitorAdaptor.getTriggeredJoinPoints().size(),
				MonitorAdaptor.hasTriggeredBackendCode());
		// Resets the counting adapter for UI thread backend invocations
		MonitorAdaptor.reset();
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TLAHyperlinkDetector.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import java.io.File;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorAndPDFViewer;
import org.lamport.tla.toolbox.editor.basic.TLAEditorReadOnly;
import org.lamport.tla.toolbox.editor.basic.actions.OpenDeclarationAction;
import org.lamport.tla.toolbox.editor.basic.actions.OpenDeclarationInCurrentAction;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.ThmOrAssumpDefNode;
import tla2sany.st.SyntaxTreeConstants;
import util.FilenameToStream;

/**
 * Detects hyperlinks in TLA+ code
 * 
 * The hyperlinks in a module editor are the identifiers whose 
 * definitions or declarations are in the root module--meaning they are
 * in the root module, in EXTENDed modules, or are imported with an INSTANCE
 * statement.  The detectHyperlinks method returns an array of at most one
 * object, which is an OpenDeclarationAction object.  See the comments
 * in TLAEditor.java for the OpenDeclarationHandler nested class.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLAHyperlinkDetector extends AbstractHyperlinkDetector
{

    /**
     * This method first sets label to the token at the position indicated by the
     * region.  If the module is parsed and unmodified, it uses EditorUtil.getTokenAt
     * to do that from the syntax tree.  Otherwise, it uses DocumentHelper.getRegionExpandedBoth
     * to try to do it from the actual text in the buffer.  This method, written by Simon,
     * works only if the region actually indicates the entire token, if it is inside
     * an Identifier, or in certain other cases if it is lucky.
     * 
     * It then currently tries to look up label in the module's symbol table.  It thus finds
     * only globally defined symbols.  It should be modified so that, if that fails and 
     * the module is parsed and unmodified, then it goes down the semantic tree trying to 
     * find a local definition for the label. 
     * 
     * It also needs to be modified to look up the symbol in the module whose editor
     * has the focus, instead of in the root module--at least, if the spec
     * is parsed and that module in the spec.
     * 
     * This was modified by LL on 12 June 2010 so that, for identifiers like Foo!bar!X, 
     * it produces a hyperlink to the definition of X in the source module.
     * 
     * It was completely modified again by LL in Sep 2010 to use TokenSpec.findTokenSpecs,
     * so it handles approximately all symbol occurrences using only the text and the last 
     * module parse.
     * 
     * Note: This method is called by the Eclipse infrastructure to show hyperlinks 
     * when the user holds down the Control key and moves the mouse.  It is called
     * by TLAEditor$OpenDeclarationHandler.execute to implement the Open Declaration
     * command.
     */
    public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks)
    {
        if (ToolboxHandle.getSpecObj() == null)
        {
            // no spec
            return null;
        }

        // set currentTokenSpec to the TokenSpec object specifying the
        // currently selected symbol and its resolution.
        TokenSpec currentTokenSpec = TokenSpec.findCurrentTokenSpec(region);
        if (currentTokenSpec == null)
        {
            return null;
        }
        

        // Set region to the Region of the document described by currentTokenSpec
        // (this ugly re-use of a parameter name is kept from Simon's original
        // code), set label to the found symbol name, and set resolvedSymbol to
        // the SymbolNode.
        region = new Region(currentTokenSpec.leftPos, currentTokenSpec.rightPos - currentTokenSpec.leftPos);
        String label = currentTokenSpec.token;
        SymbolNode resolvedSymbol = currentTokenSpec.resolvedSymbol;
        try
        {
            // If it didn't find the symbol, check if this is a module name and, if
            // so, set resolvedSymbol to the module node.
            if (resolvedSymbol == null /* && label != null */)
            {
                resolvedSymbol = ResourceHelper.getModuleNode(label);
            }

            // try symbols (does not work for module nodes)
            if (resolvedSymbol != null)
            {
                // If this symbol was imported by instantiation from
                // another module, we set resolvedSymbol to its
                // definition in that module.
                // LL Sep 2010: The comment above doesn't make sense since we're
                // not setting resolvedSymbol. I suppose the code was changed
                // at some point without changing the comment.
                SyntaxTreeNode csNode = (SyntaxTreeNode) resolvedSymbol.getTreeNode();

                // If this is a module, we want csNode to be the SyntaxTreeNode of just the name.
                // However, for some reason, that node doesn't have a file name. So we set
                // csNode to be the node representing the whole "---- MODULE foo -----",
                // which works and is perhaps even better.
                if (resolvedSymbol instanceof ModuleNode)
                {
                    csNode = (SyntaxTreeNode) resolvedSymbol.stn.heirs()[0]; // .heirs()[1];
                }
                
                // Before using the default TLA+ editor below, try to identify and reuse the current
                // editor if it shows the same module already.
                final TLAEditor tlaEditor = EditorUtil.getTLAEditorWithFocus();
				if (tlaEditor != null && csNode.getLocation().source().equals(tlaEditor.getModuleName())) {
					final IDocument document = tlaEditor.getDocumentProvider().getDocument(tlaEditor.getEditorInput());
					final int[] region2 = getRegion(getCS(resolvedSymbol, csNode), document);
					return new IHyperlink[] { new OpenDeclarationInCurrentAction(tlaEditor,
							new Region(region2[0], region2[1] - region2[0]), label, region) };
				}
                
				IDocumentProvider documentProvider = null;
				IEditorInput editorInput = null;
				String editorId = "";
				//
				final FilenameToStream resolver = ToolboxHandle.getSpecObj().getResolver();
				if (ToolboxHandle.isUserModule(ResourceHelper.getModuleFileName(csNode.getFilename()))) {
					editorId = TLAEditorAndPDFViewer.ID;
					editorInput = new FileEditorInput(
							(IFile) ResourceHelper.getResourceByModuleName(csNode.getFilename()));
					documentProvider = new FileDocumentProvider();
				} else if (resolver.isStandardModule(csNode.getFilename())) {
					// No point editing standard modules.
					editorId = TLAEditorReadOnly.ID;

					// Resolve the file via the FilenameToStream resolver in case a user has
					// provided its own standard module definition.
					final File resolved = resolver.resolve(csNode.getFilename(), true);

					// Standard modules live outside the workspace which is why they have to be
					// opened with EFS and read with a TextFileDocumentProvider.
					final IFileStore fileStore = EFS.getLocalFileSystem()
							.getStore(new Path(resolved.getAbsolutePath()));
					editorInput = new FileStoreEditorInput(fileStore);
					documentProvider = new TextFileDocumentProvider();
				} else {
					// A TLA+ built-in module.
					return null;
				}

                final int[] region2 = getDocumentAndRegion(getCS(resolvedSymbol, csNode), documentProvider, editorInput);
				return new IHyperlink[] { new OpenDeclarationAction(editorId, editorInput,
						new Region(region2[0], region2[1] - region2[0]), label, region) };
	           }
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

	private int[] getDocumentAndRegion(SyntaxTreeNode csNode, IDocumentProvider documentProvider, IEditorInput editorInput)
			throws CoreException {
		IDocument document;
		// connect to the resource
		try {
			documentProvider.connect(editorInput);
			document = documentProvider.getDocument(editorInput);
		} finally {
			/*
			 * Once the document has been retrieved, the document provider is not needed.
			 * Always disconnect it to avoid a memory leak.
			 * 
			 * Keeping it connected only seems to provide synchronization of the document
			 * with file changes. That is not necessary in this context.
			 */
			documentProvider.disconnect(editorInput);
		}

		return getRegion(csNode, document);
	}

	private int[] getRegion(SyntaxTreeNode csNode, IDocument document) {
		try {
			IRegion startLineRegion = document.getLineInformation(csNode.getLocation().beginLine() - 1);
			IRegion endLineRegion = document.getLineInformation(csNode.getLocation().endLine() - 1);

			// offsets
			int startOffset = startLineRegion.getOffset() + csNode.getLocation().beginColumn() - 1;
			int endOffset = endLineRegion.getOffset() + csNode.getLocation().endColumn();

			return new int[] { startOffset, endOffset };
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
		return new int[] { 0, 0 };
	}

	private SyntaxTreeNode getCS(SymbolNode resolvedSymbol, SyntaxTreeNode csNode) {
		// Get the location to highlight. If it's an OpDefNode, want
		// to get just the symbol from the left-hand side. (Otherwise,
		// the user can't execute Goto Declaration immediately followed
		// by Show Uses.)
		if (resolvedSymbol instanceof OpDefNode && csNode.getHeirs().length >= 1) {
			// Need to pick out the symbol from the left-hand side of
			// the definition.
			csNode = csNode.getHeirs()[0];
			if (csNode.getKind() == SyntaxTreeConstants.N_IdentLHS) {
				csNode = csNode.getHeirs()[0];
			} else {
				if ((csNode.getKind() == SyntaxTreeConstants.N_InfixLHS)
						|| (csNode.getKind() == SyntaxTreeConstants.N_PostfixLHS)) {
					csNode = csNode.getHeirs()[1];
				}
			}
		} else if ((resolvedSymbol instanceof ThmOrAssumpDefNode && csNode.getHeirs().length >= 2)
				&& ((csNode.getKind() == SyntaxTreeConstants.N_Theorem)
						|| (csNode.getKind() == SyntaxTreeConstants.N_Assumption))) {
			csNode = csNode.getHeirs()[1];
		}
		return csNode;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/TLCSpecFactory.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.model;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IAdapterFactory;
import org.lamport.tla.toolbox.spec.Spec;

public class TLCSpecFactory implements IAdapterFactory {
	
	private final Map<Spec, TLCSpec> spec2tclSpec = new HashMap<Spec, TLCSpec>();

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
	 */
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
		if (TLCSpec.class.equals(adapterType) && adaptableObject instanceof Spec) {
			if (!spec2tclSpec.containsKey(adaptableObject)) {
				final Spec spec = (Spec) adaptableObject;
				spec2tclSpec.put(spec, new TLCSpec(spec));
			}
			return (T) spec2tclSpec.get(adaptableObject);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
	 */
	public Class<?>[] getAdapterList() {
		return new Class[] {Spec.class};
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/wizard/LabeledListComposite.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.wizard;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * @author <NAME>
 * @version $Id$
 */
public class LabeledListComposite
{
    Text[] fields;
    String[] values;
    Composite self;

    public LabeledListComposite(Composite parent, String label, String[] values)
    {
        this.values = values;
        this.fields = new Text[values.length];
        initContent(parent, label);
    }

    /**
     * Returns true iff no parameters are used
     * @return
     */
    public boolean hasParameters()
    {
        return this.values.length > 0;
    }

    /**
     * @param i 
     * @param parent 
     * 
     */
    private void initContent(Composite parent, String label)
    {
        self = new Composite(parent, SWT.NONE);
        self.setLayout(new RowLayout(SWT.HORIZONTAL));
        RowData rd;

        Label l;
        l = new Label(self, SWT.NULL);
        l.setText(label);

        if (hasParameters())
        {
            l = new Label(self, SWT.NULL);
            l.setText("(");
        }

        for (int i = 0; i < fields.length; i++)
        {
            fields[i] = new Text(self, SWT.BORDER | SWT.SINGLE);
            fields[i].setText(values[i]);
            rd = new RowData();
            rd.width = 50;
            rd.height = 12;
            fields[i].setLayoutData(rd);

            if (i != fields.length - 1)
            {
                l = new Label(self, SWT.NULL);
                l.setText(", ");
            }
        }

        if (hasParameters())
        {
            l = new Label(self, SWT.NULL);
            l.setText(")");
        }

        l = new Label(self, SWT.NULL);
        l.setText(" <- ");

    }

    public String[] getValues()
    {
        String[] result = new String[fields.length];

        for (int i = 0; i < fields.length; i++)
        {
            result[i] = fields[i].getText();
        }

        return result;
    }

    /**
     * @param gd
     */
    public void setLayoutData(Object layoutData)
    {
        self.setLayoutData(layoutData);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/IValueOutputStream.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value;

import java.io.IOException;

import util.IDataOutputStream;

public interface IValueOutputStream {

	void writeShort(short x) throws IOException;

	void writeInt(int x) throws IOException;

	void writeLong(long x) throws IOException;

	void close() throws IOException;

	/* Precondition: x is a non-negative short. */
	void writeShortNat(short x) throws IOException;

	/* Precondition: x is a non-negative int. */
	void writeNat(int x) throws IOException;

	/* Precondition: x is a non-negative long. */
	void writeLongNat(long x) throws IOException;

	void writeByte(byte b) throws IOException;

	void writeBoolean(boolean b) throws IOException;

	IDataOutputStream getOutputStream();

	/**
	 * Check if another TLCState - which is currently also being serialized to the
	 * same storage (i.e. disk file) - has/contains an identical Value. If yes, do
	 * not serialize the Value instance again but make this TLCState point to the
	 * Value instance previously serialized for the other TLCState. In other words,
	 * this is a custom-tailored compression/de-duplication mechanism for Value
	 * instances.
	 * <p>
	 * This approach only works because both TLCStates are serialized to the same
	 * storage and thus de-serialized as part of the same operation (same
	 * Value*Stream instance).
	 * <p>
	 * The purpose of this approach appears to be:
	 * <ul>
	 * <li>Reduce serialization efforts and storage size</li>
	 * <li>Reduce the number of Value instances created during de-serialization</li>
	 * <li>Allow identity comparison on Value instances (AFAICT not used by Value
	 * explicitly, just UniqueString) to speed up check. Value#equals internally
	 * likely uses identity comparison as first check.</li>
	 * </ul>
	 * <p>
	 * A disadvantage is the cost of maintaining the internal HandleTable which can
	 * grow to thousands of elements during serialization/de-serialization (in
	 * ValueInputStream). Since serialization suspends the DiskStateQueue and thus
	 * blocks tlc2.tool.Workers from exploring the state space, this might has
	 * adverse effects.
	 */
	int put(Object obj);

}

<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/actions/ProofFoldAction.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.actions;

import java.util.ResourceBundle;

import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.CaretListener;
import org.eclipse.ui.texteditor.ResourceAction;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;

/**
 * Action for collapsing and expanding proofs in TLA modules.
 * 
 * @author <NAME>
 *
 */
public class ProofFoldAction extends TextEditorAction implements CaretListener, ISelectionChangedListener
{

    /**
     * Creates and initializes the action for the given text editor. The action
     * configures its visual representation from the given resource bundle.
     *
     * @param bundle the resource bundle
     * @param prefix a prefix to be prepended to the various resource keys
     *   (described in <code>ResourceAction</code> constructor), or
     *   <code>null</code> if none
     * @param editor the text editor
     * @see ResourceAction#ResourceAction(ResourceBundle, String, int)
     */
    public ProofFoldAction(ResourceBundle bundle, String prefix, TLAEditor editor)
    {
        super(bundle, prefix, editor);
        editor.getViewer().getTextWidget().addCaretListener(this);
        editor.getSelectionProvider().addSelectionChangedListener(this);
    }

    /**
     * If the caret is located within a proof, collapses and
     * expands the appropriate proofs.
     */
    public void run()
    {
        if (getTextEditor() instanceof TLAEditor)
        {
            TLAEditor editor = (TLAEditor) getTextEditor();
            editor.runFoldOperation(getActionDefinitionId());
        }
    }

    public void update()
    {
        if (getTextEditor() instanceof TLAEditor)
        {
            TLAEditor editor = (TLAEditor) getTextEditor();
            if (editor.getProofStructureProvider() != null)
            {
                setEnabled(editor.getProofStructureProvider().canRunFoldOperation(getActionDefinitionId(),
                        (ITextSelection) editor.getSelectionProvider().getSelection()));
            }
        }
    }

    public void caretMoved(CaretEvent event)
    {
        update();
    }

    public void selectionChanged(SelectionChangedEvent event)
    {
        if (getTextEditor() instanceof TLAEditor)
        {
            TLAEditor editor = (TLAEditor) getTextEditor();
            if (editor.getProofStructureProvider() != null)
            {
                setEnabled(editor.getProofStructureProvider().canRunFoldOperation(getActionDefinitionId(),
                        (ITextSelection) event.getSelection()));
            }
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/job/DistributedTLCJob.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.job;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tlc2.tool.distributed.TLCServer;

/**
 * Starts the distributed TLCServer inside the Toolbox 
 */
public class DistributedTLCJob extends TLCProcessJob {

	private static final List<String> WHITELIST = new ArrayList<String>();
	private static final List<String> WHITELIST_WITH_ARG = new ArrayList<String>();
	// take from tlc2.tool.distributed.TLCApp.create(String[])
	static {
		WHITELIST.add("-deadlock");
		WHITELIST.add("-terse");
		WHITELIST.add("-nowarning");
		
		WHITELIST_WITH_ARG.add("-checkpoint");
// Temporarily removed due to Bug #212 in general/bugzilla/index.html
//		WHITELIST_WITH_ARG.add("-coverage");
		WHITELIST_WITH_ARG.add("-fp");
		WHITELIST_WITH_ARG.add("-recover");
		WHITELIST_WITH_ARG.add("-metadir");
	}
	
	public DistributedTLCJob(String specName, String modelName, ILaunch launch, int numberOfWorkers) {
		super(specName, modelName, launch, numberOfWorkers);
	}
	
    /**
     * Removes non matching arguments from super class
     * @throws CoreException 
     */
	protected String[] constructProgramArguments() throws CoreException {
		final List<String> arguments = new ArrayList<String>();
		
		// filter super args to what is accepted by TLCServer/TLCApp
		final List<String> superArguments = Arrays.asList(super.constructProgramArguments());
		for (int i = 0; i < superArguments.size(); i++) {
			final String arg = superArguments.get(i);
			if(WHITELIST.contains(arg)) {
				arguments.add(arg);
			} else if(WHITELIST_WITH_ARG.contains(arg)) {
				arguments.add(arg);
				arguments.add(superArguments.get(++i));
			}
		}
		
		// local args
		final String userDir = launchDir.getLocation().toOSString();
		final String specFile = ResourceHelper.getModuleName(rootModule);
        
		arguments.add(userDir + File.separator + specFile);
		arguments.add("-tool");
        return arguments.toArray(new String[arguments.size()]);
	}
	
	protected List<String> getAdditionalVMArgs() throws CoreException {
		final List<String> additionalVMArgs = super.getAdditionalVMArgs();
		
		// distributed FPSet count
		final ILaunchConfiguration launchConfig = launch.getLaunchConfiguration();
		final int distributedFPSetCount = launchConfig.getAttribute(LAUNCH_DISTRIBUTED_FPSET_COUNT, 0);
		if (distributedFPSetCount > 0) {
			additionalVMArgs.add("-Dtlc2.tool.distributed.TLCServer.expectedFPSetCount=" + distributedFPSetCount);
		}
		
		// Inet Address to listen on
		final String iface = launchConfig.getAttribute(LAUNCH_DISTRIBUTED_INTERFACE, "");
		if (!"".equals(iface)) {
			additionalVMArgs.add("-Djava.rmi.server.hostname=" + iface);
		}
		
		return additionalVMArgs;
	}


	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.job.TLCProcessJob#getMainClass()
	 */
	protected Class getMainClass() {
		return TLCServer.class;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/ParseErrors.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;

import java.util.Vector;

public final class ParseErrors implements tla2sany.st.ParseErrors {
  private Vector loe;

  ParseErrors() { loe = new Vector(); };
  final boolean empty() { return loe.isEmpty(); }

  final void push( ParseError pe ) {
    loe.addElement( pe );
  }

  public final tla2sany.st.ParseError[] errors() {
    tla2sany.st.ParseError[] pes = new tla2sany.st.ParseError[ loe.size() ];
    for (int lvi = 0; lvi < pes.length; lvi++ )
      pes[ lvi ] = (ParseError)loe.elementAt( lvi );
    return pes;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/IModelOperationContainer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

/**
 * Interface for basic model operations
 * @author <NAME>
 * @version $Id$
 */
public interface IModelOperationContainer
{

    /**
     * Command for running the model checking 
     * @param mode
     */
    public void doRun();

    /**
     * Command for running the model checking in debug mode
     */
    // public void doDebug();

    /**
     * Command for running the model generation only
     * @param mode
     */
    public void doGenerate();

}

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/LongArraysTest.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static tlc2.tool.fp.OffHeapDiskFPSet.EMPTY;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import tlc2.tool.fp.LongArrays.LongComparator;
import tlc2.tool.fp.OffHeapDiskFPSet.Indexer;

public class LongArraysTest {
	
	@Before
	public void setup() {
		Assume.assumeTrue(LongArray.isSupported());
	}
	
	@Test
	public void testEmpty1() {
		doTest(new ArrayList<Long>(0), 1L, 0, new OffHeapDiskFPSet.Indexer(0, 1));
	}
	
	@Test
	public void testEmpty2() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);

		doTest(expected, 1L, 2, new OffHeapDiskFPSet.Indexer(expected.size(), 1));
	}
	
	@Test
	public void testBasic1() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(5L);
		expected.add(8L);
		expected.add(1L);
		expected.add(7L);
		expected.add(0L);
		expected.add(3L);
		final LongArray array = new LongArray(expected);
		LongArrays.sort(array);
		
		// This amounts to a regular/basic insertion sort because there are no
		// sentinels in the array. doTest fails for this array, because the
		// indices calculated by the indexer are invalid.
		for (int i = 1; i < array.size(); i++) {
			assertTrue(array.get(i - 1L) < array.get(i));
		}
	}

	@Test
	public void testBasic2() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(74236458333421747L);
		expected.add(9185197375878056627L);
		expected.add(9017810141411942826L);
		expected.add(481170446028802552L);
		expected.add(587723185270146839L);
		expected.add(764880467681476738L);
		expected.add(1028380228728529428L);
		expected.add(1246117495100367611L);
		expected.add(1353681884824400499L);
		expected.add(1963327988900916594L);
		expected.add(2157942654452711468L);
		expected.add(2211701751588391467L);
		expected.add(2197266581704230150L);
		expected.add(2391118405386569995L);
		expected.add(2754416910109403115L);
		expected.add(3528296600587602855L);
		expected.add(3766154305485605955L);
		expected.add(4172091881329434331L);
		expected.add(4273360576593753745L);
		expected.add(4338054185482857322L);
		expected.add(4487790251341705673L);
		expected.add(4760603841378765728L);
		expected.add(4897534821030901381L);
		expected.add(5057347369431494228L);
		expected.add(5185984701076703188L);
		expected.add(5255556356599253415L);
		expected.add(4911921657882287345L);
		expected.add(5512811886280168498L);
		expected.add(5627022814159167180L);
		expected.add(5630009759945037387L);
		expected.add(5592096823142754761L);
		expected.add(5880489878946290534L);
		expected.add(6796173646113527960L);
		expected.add(6887096685265647763L);
		expected.add(6946033094922439935L);
		expected.add(7100083311060830826L);
		expected.add(7575172208974668528L);
		expected.add(8240485391672917634L);
		expected.add(8572429495433200993L);
		expected.add(8804495173596718076L);
		expected.add(8771524479740786626L);
		expected.add(8986659781390119011L);
		expected.add(9136953010061430590L);
		expected.add(9195197379878056627L);		
		final LongArray array = new LongArray(expected);
		LongArrays.sort(array);
		
		// This amounts to a regular/basic insertion sort because there are no
		// sentinels in the array. doTest fails for this array, because the
		// indices calculated by the indexer are invalid.
		for (int i = 1; i < array.size(); i++) {
			assertTrue(array.get(i - 1L) < array.get(i));
		}
	}

	@Test
	public void test0() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(22102288204167208L);
		expected.add(225160948165161873L);
		expected.add(0L);
		expected.add(1638602644344629957L);
		expected.add(1644442600000000000L);
		expected.add(0L);

		doTest(expected, 1L, 3, new OffHeapDiskFPSet.Indexer(expected.size(), 1));
	}
	
	@Test
	public void test1() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(22102288204167208L);
		expected.add(225160948165161873L);
		expected.add(0L);
		expected.add(0L);
		expected.add(810435887525385357L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1638602644344629957L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2068351286375637679L);
		expected.add(0L);
		expected.add(2528370576879701538L);
		expected.add(2453870502940122045L);
		expected.add(0L);
		expected.add(3145830401686811393L);
		expected.add(3192897355035876677L);
		expected.add(3527505876050247287L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(4563398963865761585L);
		expected.add(0L);
		expected.add(4858869653769863593L);
		expected.add(5180223017321191209L);
		expected.add(0L);
		expected.add(0L);
		expected.add(5635076245116608576L);
		expected.add(5649139415351271641L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6703691584433488410L);
		expected.add(0L);
		expected.add(7143040549630863225L);
		expected.add(7205281130519852628L);
		expected.add(7012967342342885117L);
		expected.add(7709106021212022085L);
		expected.add(7908712604546919197L);
		expected.add(7246110956693059329L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8781691546738212390L);
		expected.add(8897195185152846807L);
		expected.add(0L);

		doTest(expected);
	}

	@Test
	public void test2() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(0L);
		expected.add(0L);
		expected.add(22102288204167208L);
		expected.add(225160948165161873L);
		expected.add(810435887525385357L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1638602644344629957L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2068351286375637679L);
		expected.add(0L);
		expected.add(2528370576879701538L);
		expected.add(2453870502940122045L);
		expected.add(0L);
		expected.add(3145830401686811393L);
		expected.add(3192897355035876677L);
		expected.add(3527505876050247287L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(4563398963865761585L);
		expected.add(0L);
		expected.add(4858869653769863593L);
		expected.add(5180223017321191209L);
		expected.add(0L);
		expected.add(0L);
		expected.add(5635076245116608576L);
		expected.add(5649139415351271641L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6703691584433488410L);
		expected.add(0L);
		expected.add(7143040549630863225L);
		expected.add(7205281130519852628L);
		expected.add(7012967342342885117L);
		expected.add(7709106021212022085L);
		expected.add(7908712604546919197L);
		expected.add(7246110956693059329L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8781691546738212390L);
		expected.add(8897195185152846807L);
		expected.add(0L);

		doTest(expected);
	}

	@Test
	public void test3() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(9183932681676589496L);
		expected.add(0L);
		expected.add(0L);
		expected.add(329728050397015749L);
		expected.add(436139026681109109L);
		expected.add(556905678415593173L);
		expected.add(0L);
		expected.add(796460649423573389L);
		expected.add(797798112015065380L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1632374027957690827L);
		expected.add(1756811852021281877L);
		expected.add(0L);
		expected.add(1881448932687659007L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2342821865031748924L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2736147834640710575L);
		expected.add(2864022862265935958L);
		expected.add(2773542629236699928L);
		expected.add(2957298868366608281L);
		expected.add(0L);
		expected.add(3330257111892751888L);
		expected.add(3295675356431597478L);
		expected.add(3395836867027940583L);
		expected.add(3681469222400184316L);
		expected.add(3754947896063147473L);
		expected.add(3698681814958844261L);
		expected.add(3951382885893085878L);
		expected.add(0L);
		expected.add(4188454649677385650L);
		expected.add(4129247165607948084L);
		expected.add(4365409305525871332L);
		expected.add(4526757821913904014L);
		expected.add(4254202026550171921L);
		expected.add(4557871951994955815L);
		expected.add(4806497834029622101L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(5236202638577037427L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(5936146187640212534L);
		expected.add(0L);
		expected.add(6127434886073515781L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6547025209145878563L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6931928829149329960L);
		expected.add(0L);
		expected.add(0L);
		expected.add(7244186580741581738L);
		expected.add(0L);
		expected.add(0L);
		expected.add(7634041392899269082L);
		expected.add(7590982629575593986L);
		expected.add(0L);
		expected.add(7954723745221262664L);
		expected.add(0L);
		expected.add(8156105620374757718L);
		expected.add(8305398393196381769L);
		expected.add(8318253237689249492L);
		expected.add(8487954051864981042L);
		expected.add(8411933954485687818L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(9175849669163144218L);
		
		doTest(expected);
	}
	
	@Test
	public void test4() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(9136953010061430590L);
		expected.add(74236458333421747L);
		expected.add(0L);
		expected.add(0L);
		expected.add(481170446028802552L);
		expected.add(587723185270146839L);
		expected.add(0L);
		expected.add(764880467681476738L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1028380228728529428L);
		expected.add(0L);
		expected.add(1246117495100367611L);
		expected.add(1353681884824400499L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1963327988900916594L);
		expected.add(0L);
		expected.add(2157942654452711468L);
		expected.add(2211701751588391467L);
		expected.add(2197266581704230150L);
		expected.add(2391118405386569995L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2754416910109403115L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(3528296600587602855L);
		expected.add(0L);
		expected.add(3766154305485605955L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(4172091881329434331L);
		expected.add(4273360576593753745L);
		expected.add(4338054185482857322L);
		expected.add(4487790251341705673L);
		expected.add(0L);
		expected.add(4760603841378765728L);
		expected.add(0L);
		expected.add(4897534821030901381L);
		expected.add(5057347369431494228L);
		expected.add(5185984701076703188L);
		expected.add(5255556356599253415L);
		expected.add(4911921657882287345L);
		expected.add(5512811886280168498L);
		expected.add(5627022814159167180L);
		expected.add(5630009759945037387L);
		expected.add(5592096823142754761L);
		expected.add(5880489878946290534L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6796173646113527960L);
		expected.add(6887096685265647763L);
		expected.add(6946033094922439935L);
		expected.add(7100083311060830826L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(7575172208974668528L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8240485391672917634L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8572429495433200993L);
		expected.add(0L);
		expected.add(8804495173596718076L);
		expected.add(8771524479740786626L);
		expected.add(8986659781390119011L);
		expected.add(9017810141411942826L);
		expected.add(9195197379878056627L);		
		
		doTest(expected);
	}

	@Test
	public void test5() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(9185197375878056627L);
		expected.add(74236458333421747L);
		expected.add(9017810141411942826L);
		expected.add(0L);
		expected.add(481170446028802552L);
		expected.add(587723185270146839L);
		expected.add(0L);
		expected.add(764880467681476738L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1028380228728529428L);
		expected.add(0L);
		expected.add(1246117495100367611L);
		expected.add(1353681884824400499L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1963327988900916594L);
		expected.add(0L);
		expected.add(2157942654452711468L);
		expected.add(2211701751588391467L);
		expected.add(2197266581704230150L);
		expected.add(2391118405386569995L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2754416910109403115L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(3528296600587602855L);
		expected.add(0L);
		expected.add(3766154305485605955L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(4172091881329434331L);
		expected.add(4273360576593753745L);
		expected.add(4338054185482857322L);
		expected.add(4487790251341705673L);
		expected.add(0L);
		expected.add(4760603841378765728L);
		expected.add(0L);
		expected.add(4897534821030901381L);
		expected.add(5057347369431494228L);
		expected.add(5185984701076703188L);
		expected.add(5255556356599253415L);
		expected.add(4911921657882287345L);
		expected.add(5512811886280168498L);
		expected.add(5627022814159167180L);
		expected.add(5630009759945037387L);
		expected.add(5592096823142754761L);
		expected.add(5880489878946290534L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6796173646113527960L);
		expected.add(6887096685265647763L);
		expected.add(6946033094922439935L);
		expected.add(7100083311060830826L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(7575172208974668528L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8240485391672917634L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8572429495433200993L);
		expected.add(0L);
		expected.add(8804495173596718076L);
		expected.add(8771524479740786626L);
		expected.add(8986659781390119011L);
		expected.add(9136953010061430590L);
		expected.add(9195197379878056627L);		
		
		doTest(expected);
	}
	
	@Test
	public void test6() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(1L);
		expected.add(9185197375878056627L);
		expected.add(9017810141411942826L);
		expected.add(0L);
		expected.add(481170446028802552L);
		expected.add(587723185270146839L);
		expected.add(0L);
		expected.add(764880467681476738L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1028380228728529428L);
		expected.add(0L);
		expected.add(1246117495100367611L);
		expected.add(1353681884824400499L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(1963327988900916594L);
		expected.add(0L);
		expected.add(2157942654452711468L);
		expected.add(2211701751588391467L);
		expected.add(2197266581704230150L);
		expected.add(2391118405386569995L);
		expected.add(0L);
		expected.add(0L);
		expected.add(2754416910109403115L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(3528296600587602855L);
		expected.add(0L);
		expected.add(3766154305485605955L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(4172091881329434331L);
		expected.add(4273360576593753745L);
		expected.add(4338054185482857322L);
		expected.add(4487790251341705673L);
		expected.add(0L);
		expected.add(4760603841378765728L);
		expected.add(0L);
		expected.add(4897534821030901381L);
		expected.add(5057347369431494228L);
		expected.add(5185984701076703188L);
		expected.add(5255556356599253415L);
		expected.add(4911921657882287345L);
		expected.add(5512811886280168498L);
		expected.add(5627022814159167180L);
		expected.add(5630009759945037387L);
		expected.add(5592096823142754761L);
		expected.add(5880489878946290534L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(6796173646113527960L);
		expected.add(6887096685265647763L);
		expected.add(6946033094922439935L);
		expected.add(7100083311060830826L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(7575172208974668528L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8240485391672917634L);
		expected.add(0L);
		expected.add(0L);
		expected.add(8572429495433200993L);
		expected.add(0L);
		expected.add(8804495173596718076L);
		expected.add(8771524479740786626L);
		expected.add(8986659781390119011L);
		expected.add(9136953010061430590L);
		expected.add(9195197379878056627L);		
		
		doTest(expected);
	}
	
	@Test
	public void test7() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(1L);
		expected.add(0L);
		expected.add(4L);
		expected.add(0L);
		expected.add(6L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(13L);
		
		doTest(expected, 1, 0, new OffHeapDiskFPSet.Indexer(expected.size(), 1, 13));
	}
	
	@Test
	public void test8() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(1L);
		expected.add(11L);
		expected.add(3L);
		expected.add(4L);
		expected.add(5L);
		expected.add(6L);
		expected.add(7L);
		expected.add(8L);
		expected.add(9L);
		expected.add(10L);
		expected.add(12L);
		
		final OffHeapDiskFPSet.Indexer indexer = new OffHeapDiskFPSet.Indexer(expected.size(), 1, 12);
		final LongArray array = new LongArray(expected);
		final LongComparator comparator = getComparator(indexer);
		LongArrays.sort(array, 0, array.size() - 1L + 3, comparator);
		verify(expected, 3, indexer, array);

	}
	
	@Test
	public void test9a() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(12L);
		expected.add(1L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(11L);
		
		doTest(expected, 1, 2, new OffHeapDiskFPSet.Indexer(expected.size(), 1, 13));
	}
	
	@Test
	public void test9b() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(11L);
		expected.add(1L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(12L);
		
		doTest(expected, 1, 2, new OffHeapDiskFPSet.Indexer(expected.size(), 1, 13));
	}
	
	@Test
	public void test9c() {
		final List<Long> expected = new ArrayList<Long>();
		expected.add(1L);
		expected.add(12L);
		expected.add(0L);
		expected.add(0L);
		expected.add(0L);
		expected.add(11L);
		
		doTest(expected, 1, 3, new OffHeapDiskFPSet.Indexer(expected.size(), 1, 13));
	}
	
	private void doTest(final List<Long> expected) {
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(expected.size(), 1);
		for (int i = 1; i < (expected.size() / 2); i++) {
			doTest(expected, i, 2, indexer);
		}
	}
	
	private void doTest(final  List<Long>  expected, final long partitions, final int reprobe, final Indexer indexer) {
		final LongArray array = new LongArray(expected);
		final LongComparator comparator = getComparator(indexer);
		final long length = expected.size() / partitions;
		
		// Sort each disjunct partition.
		for (long i = 0; i < partitions; i++) {
			final long start = i * length;
			final long end = i + 1L == partitions ? array.size() - 1L: start + length;
			LongArrays.sort(array, start, end, comparator);
		}
		// Stitch the disjunct partitions together. Only need if more than one
		// partition, but done with one partition anyway to see that it causes
		// no harm.
		for (long i = 0; i < partitions; i++) {
			final long end = getEnd(partitions, array, length, i);
			LongArrays.sort(array, end - reprobe, end + reprobe, comparator);
		}
		
		verify(expected, reprobe, indexer, array);
	}

	private long getEnd(final long partitions, final LongArray array, final long length, long idx) {
		return idx + 1L == partitions ? array.size() - 1L: (idx + 1L) * length;
	}

	private static LongComparator getComparator(final Indexer indexer) {
		return new LongComparator() {
			public int compare(final long fpA, final long posA, final long fpB, final long posB) {
				// Elements not in Nat \ {0} remain at their current
				// position.
				if (fpA <= EMPTY || fpB <= EMPTY) {
					return 0;
				}
				
				final boolean wrappedA = indexer.getIdx(fpA) > posA;
				final boolean wrappedB = indexer.getIdx(fpB) > posB;
				
				if (wrappedA == wrappedB && posA > posB) {
					return fpA < fpB ? -1 : 1;
				} else if ((wrappedA ^ wrappedB)) {
					if (posA < posB && fpA < fpB) {
						// Swap fpB, which is at the end of array a, with fpA.
						// fpA is less than fpB. fpB was inserted into array a
						// before fpA.
						return -1;
					}
					if (posA > posB && fpA > fpB) {
						return -1;
					}
				}
				return 0;
			}
		};
	}

	private void verify(final List<Long> expected, final int reprobe, final Indexer indexer, final LongArray array) {
		// Verify that negative and EMPTY elements remain at their position.
		// Lets call them sentinels.
		int sentinel = 0;
		OUTER: for (int j = 0; j < expected.size(); j++) {
			final long l = expected.get(j);
			if (l == EMPTY) {
				// EMPTY remain at their original positions.
				assertEquals(EMPTY, array.get(j));
				sentinel++;
			} else if (l < EMPTY) {
				// Negative remain at their original positions.
				assertEquals(l, array.get(j));
				sentinel++;
			} else {
				// Verify that all non-sentinels are still
				// array members.
				for (int k = 0; k < array.size(); k++) {
					if (array.get(k) == l) {
						continue OUTER;
					}
				}
				fail(String.format("long %s not found.", l));
			}
		}
		
		// Verify elements stayed within their lookup range.
		for (int pos = 0; pos < array.size(); pos++) {
			final long l = array.get(pos);
			if (l <= EMPTY) {
				continue;
			}
			final long idx = indexer.getIdx(l);
			assertTrue(String.format("%s, pos: %s, idx: %s, r: %s (was at: %s)", l, pos, idx, reprobe,
					expected.indexOf(l)), isInRange(idx, reprobe, pos, array.size()));
		}
		
		// Verify that non-sentinels are sorted is ascending order. Take
		// care of wrapped elements too. A) First find the first non-sentinel,
		// non-wrapped element.
		long pos = 0;
		final List<Long> seen = new ArrayList<Long>(expected.size());
		while (pos < array.size()) {
			long e = array.get(pos);
			if (e <= EMPTY || indexer.getIdx(e) > pos) {
				// Either sentinel or wrapped.
				pos++;
				continue;
			}
			seen.add(e);
			pos++;
			break;
		}
		// B) Collect all elements into seen but skip those at the beginning that
		// wrapped, and those that didn't wrap at the end (array.size + reprobe).
		for (; pos < array.size() + reprobe; pos++) {
			long actual = array.get(pos % array.size());
			if (actual <= EMPTY) {
				continue;
			}
			final long idx = indexer.getIdx(actual);
			if (pos < array.size() && idx > pos) {
				// When not wrapped, ignore elements belonging to the end that wrapped.
				continue;
			}
			if (pos > array.size() - 1L && idx + reprobe < pos) {
				// When wrapped, ignore elements at beginning which do not
				// belong to the end.
				continue;
			}
			seen.add(actual);
		}
		// C) Verify that all elements are sorted.
		for (int i = 1; i < seen.size(); i++) {
			final long lo = seen.get(i - 1);
			final long hi = seen.get(i);
			assertTrue(String.format("%s > %s", lo, hi), lo < hi);
		}
		// D) Verify we saw all expected elements.
		assertEquals(expected.size() - sentinel, seen.size());
	}
	
	@Test
	public void testIsInRange() {
		assertTrue(isInRange(0, 0, 0, 4));

		assertFalse(isInRange(0, 0, 1, 4));
		assertFalse(isInRange(0, 0, 2, 4));
		assertFalse(isInRange(0, 0, 3, 4));
		assertFalse(isInRange(0, 0, 4, 4));

		assertTrue(isInRange(0, 1, 1, 4));
		assertFalse(isInRange(0, 1, 2, 4));
		assertTrue(isInRange(0, 2, 2, 4));
		assertFalse(isInRange(0, 2, 3, 4));
		assertTrue(isInRange(0, 3, 3, 4));
		assertFalse(isInRange(0, 3, 4, 4));
		
		assertTrue(isInRange(3, 0, 3, 4));
		assertTrue(isInRange(3, 1, 0, 4));
		assertTrue(isInRange(3, 2, 1, 4));
		assertFalse(isInRange(3, 2, 2, 4));
	}

	private static boolean isInRange(long idx, int reprobe, int pos, long size) {
		if (idx + reprobe >= size && pos < idx) {
			return pos <= (idx + reprobe) % size;
		} else {
			return idx <= pos && pos <= idx + reprobe;
		}
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SemanticsException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

// This class is not used in the current code

public class SemanticsException extends Exception {

  int    severity;      // 0 == warning; 1 == error; 2 == abort
  String message;       // human-readable error message

  public SemanticsException( int s, String m) { 
    severity = s;
    message = m; 
  }

  public int    getSeverity() { return severity; }
  public String getMessage()  { return message; }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ReturnFromOpenDeclarationHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.Spec.Pair;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.UIHelper;

public class ReturnFromOpenDeclarationHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        final Spec spec = ToolboxHandle.getCurrentSpec();
        final Pair p = spec.getOpenDeclModuleName();
		if (p != null) {
			UIHelper.jumpToSelection(p.editor, p.selection);
			//TODO Bring the editor back to top in its editor stack.
		}
        return null;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/ToolboxJob.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import org.eclipse.core.runtime.jobs.Job;

public abstract class ToolboxJob extends Job {

	/**
	 * Jobs marked by this family will be disposed by the TLCLifeCycleParticipant 
	 * in bundle org.lamport.tla.toolbox.tlc
	 */
	//TODO refactor lifecycleparticipant to live in .toolbox instead of .tlc
	public static final String FAMILY = ToolboxJob.class.getName() + ".TOOLBOX_JOBS_FAMILY";

	public ToolboxJob(String name) {
		super(name);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
	 */
	@Override
	public boolean belongsTo(Object aFamily) {
		if(FAMILY.equals(aFamily)) {
			return true;
		}
		return super.belongsTo(aFamily);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/HelpButton.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.io.File;
import java.io.IOException;
import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;

/**
 * This class implements a help button that takes the user to a specified location
 * in the help system's html files.  The only part of this class that is used
 * externally is the helpButton command.
 * 
 * Implemented by <NAME>
 */

/*
 * Sometimes the Eclipse default internal web browser will not work in your
 * Ubuntu environment.  Is that the case, you need to install webkit
 * library for Ubuntu.  In order to install webkit libraries go to your
 * terminal and run this command.
 *
 *   sudo apt-get install libwebkitgtk-1.0-0
 */

/**
 * The constructor adds a help button to a specified Composite that links
 * to the help page specified by its String argument.
 */
public class HelpButton {
    /**
     * 
     * @param parent    Where the button should be added.
     * @param helpFile  The suffix of the URL of the help page, which follows
     *                  .../org.lamport.tla.toolbox.doc/html/ -- for example,
     *                  "model/overview-page.html#what-to-check" .             
     * @return A Button that has been added to the Composite that, when clicked
     *         raises a browser window on the specified help page URL.
     */
    public static Button helpButton(final Composite parent, final String helpFile) {
    	final Button button = new Button(parent, SWT.NONE);
    	final HelpButtonListener listener = new HelpButtonListener(parent, helpFile);
        button.addSelectionListener(listener);
        button.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_LCL_LINKTO_HELP));
        final GridData gridData = new GridData();
        gridData.verticalAlignment = SWT.TOP;
        button.setLayoutData(gridData);
        button.setEnabled(true);
        return button;
    }

    
	private static class HelpButtonListener extends SelectionAdapter implements SelectionListener {
        private final String url;
        
        private Browser browser = null;
        private Shell helpShell = null;
        private Point location = null ;
        private Point size = null ;

        HelpButtonListener(final Composite parent, final String helpFile) {
            final String file = helpFile;
            /*
             * For a helpFile like "foo.html#section", set fileName to
             * "foo.html" and suffix to "#section".  If there is no
             * such suffix, then set fileName to file and suffix to "".
             */
            String fileName = file;
            String suffix = "" ;
            final int idx = fileName.indexOf("#") ;
            if (idx != -1) {
                suffix = fileName.substring(idx) ;
                fileName = fileName.substring(0, idx) ;
            }
            final Bundle bundle = Platform.getBundle("org.lamport.tla.toolbox.doc");
            /* 
             * The bundle .tla.toolbox does not explicitly depend on .toolbox.doc.
             * Thus, it's possible that the application is running without documentation
             * which results in the variable bundle being null.
             */
            String urlString = null;
            if (bundle == null) {
                urlString = "http://tla.msr-inria.inria.fr/tlatoolbox/doc/" + file ;
                System.out.println("Could not find local copy of help file.");
            } else {
            	final URL fileURL = bundle.getEntry("html/" + fileName);
            	File theFile = null;
            	try {
            		theFile = new File(FileLocator.resolve(fileURL).getFile());
            	} catch (IOException e1) {
            		e1.printStackTrace();
            	}
            	if (theFile != null) {
            		urlString = theFile.getPath() + suffix;
            	}
            	if ((theFile == null) || (urlString == null)) {
            		urlString = "http://tla.msr-inria.inria.fr/tlatoolbox/doc/" + file ;
            		System.out.println("Could not find local copy of help file.");
            	}
            }
            
            url = urlString;
        }
        
        /**
         * This method is called when the `?' button is clicked. It opens the
         * page in the current help window if there is one, otherwise it raises
         * a new window at the position and with the size of the window the last
         * time it was closed in the current execution of the Toolbox.
         */
        @Override
        public void widgetSelected(final SelectionEvent e) {
            boolean setSize = false;

            /*
             * If the window doesn't already exist, create it and add the
             * browser.
             */
            if (helpShell == null) {
                setSize = true;

                /*
                 * Raise the window without a minimize button because minimizing
                 * puts it as a small window in a corner of the screen, not on
                 * the task bar.
                 */
				helpShell = new Shell(SWT.CLOSE | SWT.TITLE | SWT.RESIZE);
                helpShell.setText("Toolbox Help");
                helpShell.addDisposeListener((event) -> {
                    location = helpShell.getLocation();
                    size = helpShell.getSize();
                    helpShell = null;
                });
                browser = null;
                helpShell.setLayout(new FillLayout());
                final Composite comp = new Composite(helpShell, SWT.NONE);
                comp.setLayout(new GridLayout(1, false));

                /*
                 * Add the "back" and "forward" buttons.
                 */
                final ToolBar navBar = new ToolBar(comp, SWT.NONE);
				navBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_END));
                final ToolItem back = new ToolItem(navBar, SWT.PUSH);
                back.setText("<-    Back    ");
                back.setEnabled(false);
                final ToolItem forward = new ToolItem(navBar, SWT.PUSH);
                forward.setText(" Forward  ->");
                forward.setEnabled(false);

                /*
                 * Add an html browser.
                 */
                try {
                    browser = new Browser(comp, SWT.NONE);
                } catch (SWTError e1) {
                    System.out.println("Could not instantiate Browser: " + e1.getMessage());
                    helpShell.dispose();
                    return;
                }

                final GridData data = new GridData(GridData.FILL_BOTH);
                browser.setLayoutData(data);

                /*
                 * Add the listeners for the "back" and "forward" buttons.
                 */
                back.addListener(SWT.Selection, (event) -> {
                    browser.back();
                });
                forward.addListener(SWT.Selection, (event) -> {
                    browser.forward();
                });
                final LocationListener locationListener = new LocationListener() {
                    public void changed(LocationEvent event) {
                    	final Browser browser = (Browser) event.widget;
                        back.setEnabled(browser.isBackEnabled());
                        forward.setEnabled(browser.isForwardEnabled());
                    }

                    public void changing(LocationEvent event) {
                    }
                };
                browser.addLocationListener(locationListener);
            }

            /*
             * Load the page into the browser.
             */
            browser.setUrl(url);

            /*
             * If a new window is being created, set its size to what it was the
             * when the previous window was closed.
             */
            if (setSize) {
                if (location != null) {
                    helpShell.setLocation(location);
                }
                if (size != null) {
                    helpShell.setSize(size);
                }
            }
            helpShell.open();
            helpShell.forceFocus();
        }

        @Override
        public void widgetDefaultSelected(final SelectionEvent e) {
            widgetSelected(e);
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/OpDefOrLabelNode.java<|end_filename|>
// Last modified on Sat 28 Apr 2007 at 14:37:16 PST by lamport

/***************************************************************************
* This interface is implemented by LabelNode, OpDefNode, and               *
* ThmOrAssumpDefNode.  It contains methods for accessing the set of        *
* LabelNode objects for labels that occur immediately within this          *
* node--that is, with no intervening LabelNode or OpDefNode in the         *
* semantic tree.  This set is represented by a Hashtable, and by the null  *
* object if the set is empty.  The Hashtable key of a LabelNode ln is      *
* ln.getName(), which is a UniqueString.                                   *
*                                                                          *
* WARNING: If an OpDefNode odn represents an operator obtained by          *
* instanting a module M, then each LabelNode object lab returned by        *
* getLabel() and getLabels() is the same one as in the OpDefNode           *
* from module M. Therefore, lab.body is an expression in module M, not in  *
* the current module.  The meaning of this label must be interpreted as    *
* lab.body under the substitutions of the instantiation.  This             *
* substitution is described by the SubstInNode odn.body.  Hence, to        *
* interpret a label in the label set of an OpDefNode odn, one must check   *
* if odn.body is a SubstInNode, in which case that substitution must be    *
* applied to the body of the label.  In general, odn is the result of a    *
* series of k instantiations iff odn.body.body. ... .body is a SubstIn     *
* node, for up to k ".body"s.                                              *
*                                                                          *
* A similar warning applies to ThmOrAssumpDefNode objects, except they     *
* use APSubstInNode objects instead of SubstInNode objects for the         *
* instantiation.                                                           *
***************************************************************************/

package tla2sany.semantic;

import java.util.Hashtable;

import util.UniqueString;

interface OpDefOrLabelNode {

public abstract void setLabels(Hashtable<UniqueString, LabelNode> ht) ;
  /*************************************************************************
  * Set the set of labels to ht.                                           *
  *************************************************************************/
  
public abstract LabelNode getLabel(UniqueString us) ;
  /*************************************************************************
  * If the set contains an OpDefNode with name `us', then that OpDefNode   *
  * is returned; otherwise null is returned.                               *
  *************************************************************************/

public abstract boolean addLabel(LabelNode odn) ;
  /*************************************************************************
  * If the set contains no LabelNode with the same name as odn, then odn   *
  * is added to the set and true is return; else the set is unchanged and  *
  * false is returned.                                                     *
  *************************************************************************/
  
public abstract LabelNode[] getLabels() ;
  /*************************************************************************
  * Returns an array containing the Label objects in the set.              *
  *************************************************************************/
  
public abstract int getArity();
  /*************************************************************************
  * Returns the arity of the label or operator.                            *
  *************************************************************************/
  
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/MemObjectStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:34 PST by lamport
//      modified on Wed Oct 24 11:56:57 PDT 2001 by yuanyu

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import tlc2.output.EC;
import util.Assert;
import util.FileUtil;

/**
 * 
 * @version $Id$
 */
public final class MemObjectStack extends ObjectStack {
  private final static int InitialSize = 4096;
  private final static int GrowthFactor = 2;

  /* Fields  */
  private Object[] states;
  private String filename;
    
  public MemObjectStack(String metadir, String name) {
    this.states = new Object[InitialSize];
    this.filename = metadir +  FileUtil.separator + name;
  }
    
  final void enqueueInner(Object state) {
    if (this.len == this.states.length) {
      // grow the array
      int newLen = Math.max(1, this.len * GrowthFactor);
      Object[] newStates = new Object[newLen];
      System.arraycopy(this.states, 0, newStates, 0, this.len);
      this.states = newStates;
    }
    this.states[this.len] = state;
  }
    
  final Object dequeueInner() {
    int head = this.len - 1;
    Object res = this.states[head];
    this.states[head] = null;
    return res;
  }

  // Checkpoint.
  public final void beginChkpt() throws IOException {
    String tmpfile = this.filename + ".tmp";
    
    ObjectOutputStream oos = FileUtil.newOBFOS(tmpfile);
    oos.writeInt(this.len);
    for (int i = 0; i < this.len; i++) {
      oos.writeObject(this.states[i++]);
    }
    oos.close();
    
  }

  public final void commitChkpt() throws IOException {
    String oldName = this.filename + ".chkpt";
    File oldChkpt = new File(oldName);
    String newName = this.filename + ".tmp";
    File newChkpt = new File(newName);
    if (!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemObjectStack.commitChkpt: cannot delete " + oldChkpt);
    }
  }
  
  public final void recover() throws IOException {
    String chkptfile = this.filename + ".chkpt";
    ObjectInputStream ois = FileUtil.newOBFIS(chkptfile);
    this.len = ois.readInt();
    try {
      for (int i = 0; i < this.len; i++) {
	this.states[i] = ois.readObject();
      }
    }
    catch (ClassNotFoundException e) {
      Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e.getMessage());
    }
    finally {
      ois.close();
    }
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/NoopFPSet.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import java.io.IOException;
import java.rmi.RemoteException;

import tlc2.tool.TLCTrace;

/**
 * An FPSet whose methods are all no-ops.
 */
@SuppressWarnings("serial")
public class NoopFPSet extends FPSet {

	protected NoopFPSet(FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#init(int, java.lang.String, java.lang.String)
	 */
	@Override
	public FPSet init(int numThreads, String metadir, String filename) throws IOException {
		return this;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#size()
	 */
	@Override
	public long size() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#put(long)
	 */
	@Override
	public boolean put(long fp) throws IOException {
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#contains(long)
	 */
	@Override
	public boolean contains(long fp) throws IOException {
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#checkFPs()
	 */
	@Override
	public long checkFPs() throws IOException {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#beginChkpt()
	 */
	@Override
	public void beginChkpt() throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#commitChkpt()
	 */
	@Override
	public void commitChkpt() throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recover()
	 */
	@Override
	public void recover(TLCTrace trace) throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recoverFP(long)
	 */
	@Override
	public void recoverFP(long fp) throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#beginChkpt(java.lang.String)
	 */
	@Override
	public void beginChkpt(String filename) throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#commitChkpt(java.lang.String)
	 */
	@Override
	public void commitChkpt(String filename) throws IOException {
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSet#recover(java.lang.String)
	 */
	@Override
	public void recover(String filename) throws IOException {
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SymbolMatcher.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tla2sany.semantic;

import java.util.HashSet;
import java.util.Set;

public interface SymbolMatcher {
	
	/**
	 * @return true if the given {@link SymbolNode} matches this predicate.
	 */
	boolean matches(final SymbolNode aSymbol);

	public static class NameAndTypeMatcher implements SymbolMatcher {
	
		private String prefix;
		
		//** Invoked by clients of ModuleNode#getSymbols **//
		
		public NameAndTypeMatcher setPrefix(final String aPrefix) {
			this.prefix = aPrefix;
			return this;
		}
		
		//** Invoked by ModuleNode, overridden by clients **//
		
		/* (non-Javadoc)
		 * @see tla2sany.semantic.SymbolMatcher#matches(tla2sany.semantic.SymbolNode)
		 */
		@Override
		public boolean matches(final SymbolNode aSymbol) {
			if (!matchesAnyType() && !matchTypes().contains(aSymbol.getClass())) {
				// TODO Better test for isAssignableFrom(aSymbol.getClass()), but would require
				// looping over matchTypes.
				return false;
			}
			if (aSymbol.getKind() == ASTConstants.BuiltInKind && aSymbol.getName().toString().startsWith("$")) {
				// Do not match internal built-in operators.
				return false;
			}

			final String symbolName = aSymbol.getName().toString();
			if (matchCaseSensitive() && !symbolName.startsWith(getPrefix())) {
				return false;
			} else if (!symbolName.toLowerCase().startsWith(getPrefix().toLowerCase())){
				return false;
			}
			
			return true;
		}
		
		//** Invoked by matches, subclasses may override **//
		
		/**
		 * @return A Set of SymbolNodes to match.
		 */
		protected Set<Class<? extends SymbolNode>> matchTypes() {
			return new HashSet<>();
		}
		
		protected boolean matchesAnyType() {
			return matchTypes().isEmpty();
		}
		
		protected boolean matchCaseSensitive() {
			return false;
		}
	
		protected String getPrefix() {
			return prefix;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/handler/AbstractProverHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.tool.prover.ui.util.TLAPMExecutableLocator;

/**
 * All of our prover handlers have the same {@link #setEnabled(Object)} logic, so we abstract it out here.
 */
public abstract class AbstractProverHandler extends AbstractHandler {
	/**
	 * The handler is enabled if there is a TLA editor with focus, a TLAPM executable exists, and the spec
	 * 	has been parsed successfully.
	 */
	public void setEnabled(Object context) {
		final TLAPMExecutableLocator locator = TLAPMExecutableLocator.INSTANCE;
		final Spec spec = Activator.getSpecManager().getSpecLoaded();

		setBaseEnabled((EditorUtil.getTLAEditorWithFocus() != null) && locator.tlapmDoesExist()
				&& (spec.getStatus() == IParseConstants.PARSED));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/RemoveNameConflictsException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class RemoveNameConflictsException extends UnrecoverablePositionedException
{

    /**
     * @param message
     */
    public RemoveNameConflictsException(String message)
    {
        super(message);
    }

    /**
     * @param e2
     */
    public RemoveNameConflictsException(UnrecoverablePositionedException e2)
    {
        super(e2.getMessage(), e2.getPosition());
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/SimpUtil.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:39 PST by lamport
//      modified on Mon Jun 28 14:52:12 PDT 1999 by yuanyu

package tlc2.util;

import java.util.Hashtable;

import tlc2.tool.ToolGlobals;
import util.UniqueString;

public class SimpUtil implements ToolGlobals {

  public static Sx store = Sx.Atom("store");
  public static Sx select = Sx.Atom("select");
  public static Sx t = Sx.Atom("|@true|");
  public static Sx f = Sx.Atom("|@false|");
  public static Sx forall = Sx.Atom("FORALL");
  public static Sx exists = Sx.Atom("EXISTS");
  public static Sx f_eq = Sx.Atom("F_EQ");
  public static Sx implies = Sx.Atom("IMPLIES");
  public static Sx f_implies = Sx.Atom("F_IMPLIES");  
  public static Sx and = Sx.Atom("AND");
  public static Sx f_and = Sx.Atom("F_AND");  
  public static Sx or = Sx.Atom("OR");
  public static Sx f_or = Sx.Atom("F_OR");
  public static Sx iff = Sx.Atom("IFF");  
  public static Sx eq = Sx.Atom("EQ");
  public static Sx in = Sx.Atom("in");
  public static Sx empty = Sx.Atom("EMPTY");
  public static Sx mkdom = Sx.Atom("mkdom");
  public static Sx intv = Sx.Atom("intv");
  public static Sx cond = Sx.Atom("cond");
  public static Sx cross2 = Sx.Atom("cross2");
  public static Sx bgPush = Sx.Atom("BG_PUSH");
  public static Sx pats = Sx.Atom("PATS");  
  
  protected static Hashtable trop;
  public static Hashtable defns; // Maps operator name to translated defintions.

  // The following list contains the Sx translations of the TLA expressions in
  // the input module.
  public static Sx opDefns = Sx.nil;
  public static Sx fcnDefns = Sx.nil;
  public static Sx thms = Sx.nil;

  static {
    trop = new Hashtable();
    trop.put(OP_lnot, "F_NOT");
    trop.put(OP_eq, "F_EQ");
    trop.put(OP_noteq, "F_NEQ");
    trop.put(OP_implies, "F_IMPLIES");
    trop.put(OP_land, "F_AND");
    trop.put(OP_lor, "F_OR");
    trop.put(OP_in, "in");
    trop.put(OP_dotdot, "intv");
    trop.put(OP_leq, "F_LE");
    trop.put(OP_geq, "F_GE");
    trop.put(OP_gt, "F_GT");    
    trop.put(OP_cp, "cross2");

    defns = new Hashtable();
  }

  public static UniqueString transOp(UniqueString name) {
    UniqueString op = (UniqueString)trop.get(name);
    return (op == null) ? name : op;
  }

  public static Sx mkForall(Sx vars, Sx body) {
    return Sx.List(forall, vars, body);
  }

  public static Sx mkForall(Sx vars, Sx pats, Sx body) {
    return Sx.List(forall, vars, pats, body);
  }

  public static Sx mkImplies(Sx p, Sx q) {
    return Sx.List(f_implies, p, q);
  }

  public static Sx mkAnd(Sx p, Sx q) {
    return Sx.List(f_and, p, q);
  }

  public static Sx mkEquality(Sx p, Sx q) {
    return Sx.List(eq, p, q);
  }

  public static Sx mkInterval(Sx i, Sx j) {
    return Sx.List(intv, i, j);
  }

  public static Sx mkIn(Sx x, Sx s) {
    return Sx.List(in, x, s);
  }

  public static Sx mkIff(Sx x, Sx s) {
    return Sx.List(iff, x, s);
  }
  
  public static Sx mkBgPush(Sx x) {
    return Sx.List(bgPush, x);
  }  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SymbolNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.st.TreeNode;
import util.UniqueString;

/**
 * Abstract class extended by classes that represent the meaning of an
 * identifier, including generalized IDs.
 *
 * Extended by OpDefOrDeclNode (and its subclasses OpDefNode, OpDeclNode),
 * FormalParamNode, and ModuleNode
 */

/***************************************************************************
* Also extended by NewSymbNode and ThmOrAssumpDefNode.                     *
***************************************************************************/

/***************************************************************************
* An object of superclass SymbolNode seems to represent something that     *
* defines or declares a symbol, and hence might appear in a SymbolTable.   *
* The constructors for these objects take a SymbolTable st as an argument  *
* and, if st is non-null, call st.addSymbol to put the symbol in the       *
* SymbolTable st.                                                          *
***************************************************************************/
public abstract class SymbolNode extends LevelNode {

  protected final UniqueString name;    // the name of this symbol

  protected SymbolNode(int kind, TreeNode stn, UniqueString name) {
    super(kind, stn);
    this.name = name;
  }

  /**
   * This method returns the UniqueString for the printable name of
   * the symbol being declared or defined. For example, if this node
   * is an operator definition:
   *
   *   Foo(a, b) == a*b
   *
   * getName() is the UniqueString for "Foo".
   */
  public final UniqueString getName() { return this.name; }

  /* Returns the arity of the operator named by the symbol.  */
  public abstract int getArity();

  /**
   * Returns true iff the symbol is local to its module; does not
   * apply to FormalParamNodes or ModuleNodes.
   */
  public abstract boolean isLocal();

  /**
   * Returns true iff the OpApplNode test has the proper types of
   * arguments for the operator as declared in module mn.
   */
  public abstract boolean match(OpApplNode test, ModuleNode mn) throws AbortException ;

  public final boolean occur(SymbolNode[] params) {
    for (int i = 0; i < params.length; i++) {
      if (this == params[i]) return true;
    }
    return false;
  }

  public final boolean isParam() {
    return (this instanceof OpDeclNode ||
	    this instanceof FormalParamNode);
  }
  
  public String getSignature() {
	  return getName().toString();
  }

  /**
   * Returns true iff this node and otherNode are both OpDefOrDeclNode objects or
   * both ThmOrAssumpDefNode objects and have the same originallyDefinedInModule
   * field.  Added by LL on 31 Oct 2012.
   *
   * Corrected by LL on 1 Nov 2012 by (a) using the originallyDefinedInModule for
   * the source definitions (returned by getSource()), and by adding requirement
   * that their module of origin has no parameters.
   *
   * This method is used to check that two instantiations of a definition
   * are the same.  They may not be if the two instantiations of their module have different
   * substitutions for parameters.  To check that the substitutions are the same
   * would be difficult, so we require that the module has no parameters.  This covers
   * the common case when the definitions come from a standard module.
   *
   * @param otherNode
   * @return
   */
  public final boolean sameOriginallyDefinedInModule(SymbolNode otherNode) {
      if (this.getClass() == otherNode.getClass()) {
          ModuleNode thisModule = null ;
          if (this instanceof OpDefNode) {
              OpDefNode thisSrc = ((OpDefNode) this).getSource() ;
              if (thisSrc != ((OpDefNode) otherNode).getSource()) {
                  return false;
              }
              thisModule  = ((OpDefNode) thisSrc).getOriginallyDefinedInModuleNode();
          }
          else if (this instanceof ThmOrAssumpDefNode) {
              ThmOrAssumpDefNode thisSrc = ((ThmOrAssumpDefNode) this).getSource() ;
              if (thisSrc != ((ThmOrAssumpDefNode) otherNode).getSource()) {
                  return false;
              }
              thisModule  = ((ThmOrAssumpDefNode) thisSrc).getOriginallyDefinedInModuleNode();
          }
          else {
              return false;
          }

          return   (thisModule == null)
                || (   (thisModule.getConstantDecls().length == 0)
                    && (thisModule.getVariableDecls().length == 0)) ;
      }
      return false ; // The compiler doesn't realize this is unreachable.
  }


  /** TL
   * Symbol nodes are exported using their names only. Within a context element,
   * we want to expand their whole definitions and are using this method
   * we need to add location and level information here.
   */
  public Element exportDefinition(Document doc, tla2sany.xml.SymbolContext context) {
    if (!context.isTop_level_entry())
      throw new IllegalArgumentException("Exporting definition "+getName()+" ref "+getNodeRef()+" twice!");
    context.resetTop_level_entry();
    try {
      Element e = getSymbolElement(doc, context);
      // level
      try {
        Element l = appendText(doc,"level",Integer.toString(getLevel()));
        e.insertBefore(l,e.getFirstChild());
      } catch (RuntimeException ee) {
        // not sure it is legal for a LevelNode not to have level, debug it!
      }
      //location
      try {
        Element loc = getLocationElement(doc);
        e.insertBefore(loc,e.getFirstChild());
      } catch (RuntimeException ee) {
        // do nothing if no location
      }
      return e;
    } catch (RuntimeException ee) {
      System.err.println("failed for node.toString(): " + toString() + "\n with error ");
      ee.printStackTrace();
      throw ee;
    }
  }

  protected abstract Element getSymbolElement(Document doc, tla2sany.xml.SymbolContext context);
  protected abstract String getNodeRef();

  /** TL
   * we also override getLevelElement as it should never be called
   */
  protected Element getLevelElement(Document doc, tla2sany.xml.SymbolContext context) {
    throw new UnsupportedOperationException("implementation Error: A symbol node may not be called for its level element.");
  }

  /** TL
   * We override export in order not to export location and level.
   * We only export names.
   */
  public Element export(Document doc, tla2sany.xml.SymbolContext context) {
    // first add symbol to context
    context.put(this, doc);
    Element e = doc.createElement(getNodeRef());
    e.appendChild(appendText(doc,"UID",Integer.toString(myUID)));
    return e;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/TLCTranslationException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class TLCTranslationException extends UnrecoverableException
{
    public TLCTranslationException(String message)
    {
        super(message);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/REPL.java<|end_filename|>
package tlc2;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;

import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.reader.impl.DefaultParser;
import org.jline.reader.impl.history.DefaultHistory;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpDefNode;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.EvalException;
import tlc2.tool.impl.FastTool;
import tlc2.tool.impl.Tool;
import tlc2.value.impl.Value;
import util.Assert;
import util.SimpleFilenameToStream;
import util.TLAConstants;
import util.ToolIO;


/**
 * A TLA+ REPL which provides an interactive mode of evaluating expressions and specifications.
 */
public class REPL {
	
	private static final String HISTORY_PATH = System.getProperty("user.home", "") + File.separator + ".tlaplus" + File.separator + "history.repl";

    // The spec file to use in the REPL context, if any.
    private File specFile = null;

    // The naming prefix of the temporary directory.
    static final String TEMP_DIR_PREFIX = "tlarepl";

    // The name of the spec used for evaluating expressions.
    final String REPL_SPEC_NAME = "tlarepl";
    
    private static final String prompt = "(tla+) ";

    private final Writer replWriter = new PrintWriter(System.out);
    
    // A temporary directory to place auxiliary files needed for REPL evaluation.
    Path replTempDir;

    public REPL(Path tempDir) {
        replTempDir = tempDir;
    }

    public void setSpecFile(final File pSpecFile) {
        specFile = pSpecFile;
    }

    /**
     * Evaluate the given string input as a TLA+ expression.
     *
     * @return the pretty printed result of the evaluation or an empty string if there was an error.
     */
    public String processInput(String evalExpr) {

        // The modules we will extend in the REPL environment.
        String moduleExtends = "Reals,Sequences,Bags,FiniteSets,TLC,Randomization";
        try {
			// Try loading the "index" class of the Community Modules that define
			// popular modulesl that should be loaded by default. If the Community Modules
			// are not present, silently fail.
        	final Class<?> clazz = Class.forName("tlc2.overrides.CommunityModules");
        	final Method m = clazz.getDeclaredMethod("popularModules");
        	moduleExtends += String.format(",%s", m.invoke(null));
		} catch (Exception | NoClassDefFoundError ignore) {
		}
        
        if (specFile != null) {
            String mainModuleName = specFile.getName().replaceFirst(TLAConstants.Files.TLA_EXTENSION + "$", "");
            moduleExtends += ("," + mainModuleName);
        }

        File tempFile, configFile;
        try {

            // We want to place the spec files used by REPL evaluation into the temporary directory.
            tempFile = new File(replTempDir.toString(), REPL_SPEC_NAME + TLAConstants.Files.TLA_EXTENSION);
            configFile = new File(replTempDir.toString(), REPL_SPEC_NAME + TLAConstants.Files.CONFIG_EXTENSION);

            // Create the config file.
            BufferedWriter cfgWriter = new BufferedWriter(new FileWriter(configFile.getAbsolutePath(), false));
            cfgWriter.append("INIT replinit");
            cfgWriter.newLine();
            cfgWriter.append("NEXT replnext");
            cfgWriter.newLine();
            cfgWriter.close();

            // Create the spec file lines.
            ArrayList<String> lines = new ArrayList<String>();
            String replValueVarName = "replvalue";
            lines.add("---- MODULE tlarepl ----");
            lines.add("EXTENDS " + moduleExtends);
            lines.add("VARIABLE replvar");
            // Dummy Init and Next predicates.
            lines.add("replinit == replvar = 0");
            lines.add("replnext == replvar' = 0");
            // The expression to evaluate.
            lines.add(replValueVarName + " == " + evalExpr);
            lines.add("====");

            // Write out the spec file.
            BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile.getAbsolutePath(), false));
            for (String line : lines) {
                writer.append(line);
                writer.newLine();
            }
            writer.close();

            // Avoid sending log messages to stdout and reset the messages recording.
            ToolIO.setMode(ToolIO.TOOL);
            ToolIO.reset();

            try {
                // We placed the REPL spec files into a temporary directory, so, we add this temp directory
                // path to the filename resolver used by the Tool.
                SimpleFilenameToStream resolver = new SimpleFilenameToStream(replTempDir.toAbsolutePath().toString());
                Tool tool = new FastTool(REPL_SPEC_NAME, REPL_SPEC_NAME, resolver);
                ModuleNode module = tool.getSpecProcessor().getRootModule();
                OpDefNode valueNode = module.getOpDef(replValueVarName);
                
				// Make output of TLC!Print and TLC!PrintT appear in the REPL. Set here
				// and unset in finally below to suppress output of FastTool instantiation
				// above.
				tlc2.module.TLC.OUTPUT = replWriter;
				final Value exprVal = (Value) tool.eval(valueNode.getBody());
				return exprVal.toString();
            } catch (EvalException exc) {
                // TODO: Improve error messages with more specific detail.
            	System.out.printf("Error evaluating expression: '%s'%n%s%n", evalExpr, exc);
            } catch (Assert.TLCRuntimeException exc) {
            	if (exc.parameters != null && exc.parameters.length > 0) {
					// 0..1 \X 0..1 has non-null params of length zero. Actual error message is
					// "Parsing or semantic analysis failed.".
					System.out.printf("Error evaluating expression: '%s'%n%s%n", evalExpr,
							Arrays.toString(exc.parameters));
            	} else if (exc.getMessage() != null) {
            		// Examples of what ends up here:
            		// 23 = TRUE
            		// Attempted to evaluate an expression of form P \/ Q when P was an integer.
            		// 23 \/ TRUE
            		// Attempted to check equality of integer 23 with non-integer: TRUE
            		// CHOOSE x \in Nat : x = 4
            		// Attempted to compute the value of an expression of form CHOOSE x \in S: P, but S was not enumerable.
					String msg = exc.getMessage().trim();
					// Strip meaningless location from error message.
					msg = msg.replaceFirst("\\nline [0-9]+, col [0-9]+ to line [0-9]+, col [0-9]+ of module tlarepl$", "");
					// Replace any newlines with whitespaces.
					msg = msg.replaceAll("\\n", " ").trim();
					System.out.printf("Error evaluating expression: '%s'%n%s%n", evalExpr, msg);
            	} else {
            		System.out.printf("Error evaluating expression: '%s'%n", evalExpr);
            	}
            } finally {
                replWriter.flush();
        		tlc2.module.TLC.OUTPUT = null;
            }
        } catch (IOException pe) {
            pe.printStackTrace();
        }
        return "";
    }

    /**
     * Runs the main REPL loop continuously until there is a fatal error or a user interrupt.
     */
    public void runREPL(final LineReader reader) throws IOException {
        // Run the loop.
    	String expr;
        while (true) {
            try {
                expr = reader.readLine(prompt);
                String res = processInput(expr);
                if (res.equals("")) {
                    continue;
                }
                System.out.println(res);
            } catch (UserInterruptException e) {
                return;
            } catch (EndOfFileException e) {
                e.printStackTrace();
                return;
            } finally {
				// Persistent file and directory will be create on demand.
            	reader.getHistory().save();
            }
        }
    }

    public static void main(String[] args) {
        try {
            final Path tempDir = Files.createTempDirectory(TEMP_DIR_PREFIX);
            final REPL repl = new REPL(tempDir);
            // TODO: Allow external spec file to be loaded into REPL context.
 
            if(args.length == 1) {
                String res = repl.processInput(args[0]);
                if (!res.equals("")) {
                	System.out.println(res);
                }
                //TODO Return actual exit value if parsing/evaluation fails.
                System.exit(0);
            }

            // For TLA+ we don't want to treat backslashes as escape chars e.g. for LaTeX like operators.
			final DefaultParser parser = new DefaultParser();
			parser.setEscapeChars(null);
			final Terminal terminal = TerminalBuilder.builder().build();
			final LineReader reader = LineReaderBuilder.builder().parser(parser).terminal(terminal)
					.history(new DefaultHistory()).build();
			reader.setVariable(LineReader.HISTORY_FILE, HISTORY_PATH);

			System.out.println("Welcome to the TLA+ REPL!");
            MP.printMessage(EC.TLC_VERSION, TLCGlobals.versionOfTLC);
        	System.out.println("Enter a constant-level TLA+ expression.");

            repl.runREPL(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/queue/MemStateQueue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:15:31 PST by lamport
//      modified on Mon Dec 18 22:56:08 PST 2000 by yuanyu

package tlc2.tool.queue;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import tlc2.output.EC;
import tlc2.tool.TLCState;
import tlc2.value.ValueInputStream;
import tlc2.value.ValueOutputStream;
import util.Assert;
import util.FileUtil;

public final class MemStateQueue extends StateQueue {
  private final static int InitialSize = 4096;

  /* Fields  */
  private TLCState[] states;
  private int start = 0;
  private String diskdir;
    
  /**
   * TESTING ONLY!
   */
  MemStateQueue() throws IOException {
	  this(Files.createTempDirectory("MemStateQueue").toFile().toString());
  }
  
  public MemStateQueue(String metadir) {
    this.states = new TLCState[InitialSize];
    this.start = 0;
    this.diskdir = metadir;
  }
    
  final void enqueueInner(TLCState state) {
	if (this.len > Integer.MAX_VALUE) {
        Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES, new String[]{"queue", "Amount of states exceeds internal storage"});
	}
    if (this.len == this.states.length) {
      // grow the array
      TLCState[] newStates = new TLCState[getNewLength(this.len)];
      int copyLen = this.states.length - this.start;
      System.arraycopy(this.states, this.start, newStates, 0, copyLen);
      System.arraycopy(this.states, 0, newStates, copyLen, this.start);
      this.states = newStates;
      this.start = 0;
    }
    int last = (this.start + (int) this.len) % this.states.length;
    this.states[last] = state;
  }
    
  /**
   * @param oldLength
   * @return The new capacity softly increased
   */
  private int getNewLength(final long oldLength) {
      return (int) Math.max(1, ((oldLength * 4) / 3 + 1));
  }

  final TLCState dequeueInner() {
    TLCState res = this.states[this.start];
    this.states[this.start] = null;
    this.start = (this.start + 1) % this.states.length;
    return res;
  }
  
  /* (non-Javadoc)
   * @see tlc2.tool.queue.StateQueue#peekInner()
   */
  final TLCState peekInner() {
	return this.states[this.start];
  }

  // Checkpoint.
  public final void beginChkpt() throws IOException {
    String filename = this.diskdir + FileUtil.separator + "queue.tmp";
    ValueOutputStream vos = new ValueOutputStream(filename);
    vos.writeInt((int)this.len);
    int index = this.start;
    for (int i = 0; i < this.len; i++) {
      this.states[index++].write(vos);
      if (index == this.states.length) index = 0;
    }
    vos.close();
  }

  public final void commitChkpt() throws IOException {
    String oldName = this.diskdir + FileUtil.separator + "queue.chkpt";
    File oldChkpt = new File(oldName);
    String newName = this.diskdir + FileUtil.separator + "queue.tmp";
    File newChkpt = new File(newName);
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemStateQueue.commitChkpt: cannot delete " + oldChkpt);
    }
  }
  
  public final void recover() throws IOException {
    String filename = this.diskdir + FileUtil.separator + "queue.chkpt";
    ValueInputStream vis = new ValueInputStream(filename);
    this.len = vis.readInt();
    for (int i = 0; i < this.len; i++) {
      this.states[i] = TLCState.Empty.createEmpty();
      this.states[i].read(vis);
    }
    vis.close();
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/FingerprintExceptionNextCallstackTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial design and implementation
 ******************************************************************************/

package tlc2.tool;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class FingerprintExceptionNextCallstackTest extends ModelCheckerTestCase {

	public FingerprintExceptionNextCallstackTest() {
		super("FingerprintExceptionNextCallstack", new String[] { "-config", "FingerprintExceptionNext.cfg" },
				ExitStatus.FAILURE_SPEC_EVAL);
	}

	@Test
	public void testSpec() {
		// ModelChecker has finished with a general exception, a fingerprint exception and underlying overflow exception
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "1", "1", "0"));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_INIT_GENERATED1, "1"));
		assertTrue(recorder.recorded(EC.GENERAL));
		String arg1 = "0. Line 9, column 9 to line 9, column 19 in FingerprintExceptionNextCallstack\n"
				+ "1. Line 9, column 14 to line 9, column 19 in FingerprintExceptionNextCallstack\n"
				+ "2. Line 7, column 10 to line 7, column 49 in FingerprintExceptionNextCallstack\n"
				+ "3. Line 7, column 43 to line 7, column 49 in FingerprintExceptionNextCallstack\n"
				+ "4. Line 7, column 25 to line 7, column 32 in FingerprintExceptionNextCallstack\n\n";
		String arg2 = "Attempted to check if the non-enumerable value\n"
				+ "42\n"
				+ "is element of\n"
				+ "SUBSET 42";
		assertTrue(recorder.recordedWithStringValues(EC.TLC_FINGERPRINT_EXCEPTION, arg1, arg2));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/OpenModelHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.launch.IConfigurationConstants;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Opens a model configuration in the editor
 * 
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class OpenModelHandler extends AbstractHandler implements IConfigurationConstants {
	public static final String COMMAND_ID = "toolbox.tool.tlc.commands.model.open";
	public static final String PARAM_MODEL_NAME = "toolbox.tool.tlc.commands.model.open.param";
	public static final String PARAM_EXPAND_SECTIONS = "toolbox.tool.tlc.commands.model.open.param.expand.properties";
	public static final String PARAM_EXPAND_SECTIONS_DELIM = ",";
	
	public static final String EDITOR_ID = "org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor";

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
	 */
	public Object execute(final ExecutionEvent event) throws ExecutionException {
		// The non-qualified model name (no spec prefix)
		// The ModelHelper associates it implicitly with the current spec
		final String modelName = event.getParameter(PARAM_MODEL_NAME);

		final Model model = ToolboxHandle.getCurrentSpec().getAdapter(TLCSpec.class).getModel(modelName);
		final IFile launchFile = model.getLaunchConfiguration().getFile();

		if (!launchFile.exists()) {
			throw new ExecutionException("Model file " + launchFile.getFullPath().toOSString()
					+ " does not exist. Try restarting the Toolbox and if that does not help, delete the model from the Spec Explorer.");
		}
		
		final ModelEditor modelEditor = (ModelEditor) UIHelper.openEditor(EDITOR_ID, launchFile);
		final String expand = event.getParameter(PARAM_EXPAND_SECTIONS);
		if (expand != null) {
			modelEditor.expandSections(expand.split(PARAM_EXPAND_SECTIONS_DELIM));
		}
		
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TagBasedTLCAnalyzer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.Stack;
import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TypedRegion;
import org.lamport.tla.toolbox.tool.tlc.output.PartitionToolkit;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * Message processor, detects message code, severity and the message body from the TLC tags
 * <br>Currently, only one level tags are supported (container tag with one user input tag contained)
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TagBasedTLCAnalyzer
{

    // @!@!@STARTMSG 2219:0 @!@!@
    public static final int OPEN_TAG_LENGTH = 27;
    // @!@!@ENDMSG 2219 @!@!@
    public static final int CLOSE_TAG_LENGTH = 24;

    private static final int START = 1;
    private static final int END = 2;

    private TLCRegion taggedRegion = null;

    private final IDocument document;
    private Stack<ITypedRegion> stack;
    private Vector<ITypedRegion> userOutput;

    /**
     * Constructs the analyzer
     * @param failOnError a flag indicating that the analyzer will fail if the start and end 
     * are not set in the interleaving manner. 
     */
    public TagBasedTLCAnalyzer(IDocument document)
    {
        this.document = document;
        stack = new Stack<ITypedRegion>();
        resetUserPartitions();
    }

    /**
     * Add start of coverage
     * @param start
     */
    public void addTagStart(ITypedRegion start)
    {
        // Assert.isTrue(inTag() && !inTag() == !hasUserPartitions(),
        // "Found user partitions which have not been removed. This is a bug.");

        ITypedRegion userRegion = getUserRegion();
        if (userRegion != null)
        {
            stack.push(userRegion);
        }
        TLCRegion startRegion = new TLCRegion(start.getOffset(), start.getLength(), start.getType());
        startRegion.setMessageCode(getMessageCode(start, START));
        startRegion.setSeverity(getSeverity(start));
        // add start to stack
        stack.push(startRegion);
    }

    /**
     * Add the end of coverage
     * @param end
     */
    public void addTagEnd(ITypedRegion end)
    {
        ITypedRegion userRegion = getUserRegion();
        if (userRegion != null)
        {
            stack.push(userRegion);
        }
        processTag(end);
        
    }

    /**
     * 
     * @param iTypedRegion
     */
    public void addUserRegion(ITypedRegion userRegion)
    {
        userOutput.add(userRegion);
    }

    /**
     * Retrieves if user partitions are present 
     */
    public boolean hasUserPartitions()
    {
        return !userOutput.isEmpty();
    }

    /**
     * True iff the stack of start and end
     * tags is not empty.
     * 
     * @return
     */
    public boolean inTag()
    {
        return !stack.isEmpty();
    }
    
    Stack<ITypedRegion> getStack() {
    	return stack;
    }

    /**
     * 
     */
    public void resetUserPartitions()
    {
        userOutput = new Vector<ITypedRegion>();
    }

    /**
     * Process the calculation of the coverage region
     * 
     * The task of this method is to produce TLCRegion or TLCRegionContainer 
     * instances based on the regions stored on the stack. 
     * 
     */
    private void processTag(ITypedRegion end)
    {
        // read the message code of the end tag
        int messageCode = getMessageCode(end, END);

        // find content until matching start tag on the stack
        // it is assumed that it is:
        // User, TLC-Tag, Start
        // User, Start
        // TLC-Tag, Start
        // TLC-Tag, User, Start
        // currently only this patterns are supported!
        // the Start tag is always the last
        // if there is a TLCTag on the stack, the content is already captured by it...
        ITypedRegion[] stackContent = getFindStart(messageCode);

        TLCRegion start = (TLCRegion) stackContent[stackContent.length - 1];

        int length = end.getOffset() - start.getLength() - start.getOffset();
        int offset = start.getOffset() + start.getLength();

        TLCRegion region;
        if (stackContent.length > 1)
        {
            region = new TLCRegionContainer(offset, length - 1);
            Vector<ITypedRegion> regions = new Vector<ITypedRegion>();
            for (int i = 0; i < stackContent.length - 1; i++)
            {
                regions.add(stackContent[i]);
                if (stackContent[i] instanceof TLCRegion)
                {
                    if (offset == stackContent[i].getOffset() - OPEN_TAG_LENGTH)
                    {
                        // the current tag and the child tag starts with the same offset
                        // it is either TLC-TAG, USer, Start case
                        // or TLC-TAG, Start case
                        if (length - CLOSE_TAG_LENGTH == stackContent[i].getLength())
                        {
                            // the child tag covers the same region as the current tag
                            // current tag is a container without a message
                            length = -1;
                            offset = -1;
                        } else
                        {
                            int shift = OPEN_TAG_LENGTH + stackContent[i].getLength();
                            offset = offset + shift;
                            length = length - shift;
                        }
                    } else if (offset + length - CLOSE_TAG_LENGTH == stackContent[i].getOffset()
                            + stackContent[i].getLength())
                    {
                        int shift = stackContent[i].getLength();
                        length = length - shift;
                    } else
                    {
                        // NOT SUPPORTED
                        throw new IllegalArgumentException("Bug parsing the regions");
                    }
                }
            }
            ((TLCRegionContainer) region).setSubRegions(regions);
        } else
        {
            region = new TLCRegion(offset, length - 1);
        }
        region.setMessageCode(start.getMessageCode());
        region.setSeverity(start.getSeverity());

        if (inTag())
        {
            stack.push(region);
        } else
        {
            this.taggedRegion = region;
        }
    }

    /**
     * Returns array of elements from top of the stack with start as the last element (call pop until the start is found) 
     * @param code
     * @return
     */
    private ITypedRegion[] getFindStart(int code)
    {
        Assert.isTrue(!stack.isEmpty(), "Bug. Empty stack, start tag expected");

        Vector<ITypedRegion> elements = new Vector<ITypedRegion>();
        while (!stack.isEmpty())
        {
            ITypedRegion region = (ITypedRegion) stack.pop();
            elements.add(region);
            if (TagBasedTLCOutputTokenScanner.TAG_OPEN.equals(region.getType()))
            {
                TLCRegion startRegion = (TLCRegion) region;
                Assert.isTrue(startRegion.getMessageCode() == code, "Found a non-matching start. This is a bug.");
                // found a match
                break;
            } else
            {
                // not a start tag
                // but something else, e.G. user partition

            }
        }

        return (ITypedRegion[]) elements.toArray(new ITypedRegion[elements.size()]);
    }

    /**
     * @return
     */
    public ITypedRegion getUserRegion()
    {
        if (hasUserPartitions())
        {
            ITypedRegion region = PartitionToolkit.mergePartitions((ITypedRegion[]) userOutput
                    .toArray(new TypedRegion[userOutput.size()]));
            // re-initialize the user partitions
            resetUserPartitions();
            return region;
        } else
        {
            return null;
        }
    }

    /**
     * Retrieves last detected coverage region, or null if no coverage information were available
     * @return
     */
    public TLCRegion getTaggedRegion()
    {
        return this.taggedRegion;
    }

    /**
     * Retrieves the message type
     * @param region
     * @return
     */
    private int getMessageCode(ITypedRegion region, int type)
    {
        try
        {
            String text = document.get(region.getOffset(), region.getLength());
            int index;
            String number;
            switch (type) {
            case START:
                index = text.indexOf(":");
                break;
            case END:
                index = text.lastIndexOf(" @!@!@");
                break;
            default:
                // make compiler happy
                index = -1;
                break;
            }
            if (index == -1)
            {
                Assert.isTrue(index != -1, "Could not read message code");
            }

            number = text.substring(text.indexOf(" ") + 1, index);
            return Integer.parseInt(number);
        } catch (BadLocationException e)
        {
            TLCUIActivator.getDefault().logError("Error retrieving the TLC message code", e);
        } catch (NumberFormatException e) {
            TLCUIActivator.getDefault().logError("Error retrieving the TLC message code", e);
        }
        return -1;
    }

    /**
     * Retrieves the message severity
     * @param region
     * @return
     */
    private int getSeverity(ITypedRegion region)
    {
        try
        {
            String text = document.get(region.getOffset(), region.getLength());
            int index = text.indexOf(":");
            String number = text.substring(index + 1, text.indexOf(" ", index));
            return Integer.parseInt(number);
        } catch (BadLocationException e)
        {
            TLCUIActivator.getDefault().logError("Error retrieving the TLC message severity", e);
        }
        return -1;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/LongVecTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.Test;

public class LongVecTest {

	protected LongVec getLongVec() {
		// default capacity
		return new LongVec();
	}
	
	@Test
	public void testReadBeyondCapacity() {
		final LongVec vec = getLongVec();
		try {
			vec.elementAt(0);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Read beyond capacity");
	}

	@Test
	public void testAddAndReadBeyondCapacity() {
		final LongVec vec = getLongVec();
		vec.addElement(1L);
		assertEquals(1L, vec.elementAt(0));
		try {
			vec.elementAt(1);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Read beyond capacity");
	}

	@Test
	public void testRemoveBeyondCapacity() {
		final LongVec vec = new LongVec(10);
		for (int i = -1; i <= 10; i++) {
			try {
				vec.removeElement(0);
			} catch (IndexOutOfBoundsException e) {
				continue;
			}
			fail("Read beyond capacity");
		}
	}

	@Test
	public void testAddRemoveBeyondCapacity() {
		final LongVec vec = new LongVec(10);
		vec.addElement(1L);
		vec.removeElement(0);
		try {
			vec.removeElement(1);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Read beyond capacity");
	}
	
	@Test
	public void testRemoveAndGet() {
		final LongVec vec = getLongVec();
		vec.addElement(1L);
		vec.addElement(2L);
		vec.addElement(3L);
		
		assertEquals(1L, vec.elementAt(0));
		assertEquals(2L, vec.elementAt(1));
		assertEquals(3L, vec.elementAt(2));
		
		vec.removeElement(1);
		assertEquals(1L, vec.elementAt(0));
		assertEquals(3L, vec.elementAt(1));
		// There must not be an element at idx 2 anymore!
		try {
			vec.elementAt(2);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("A new elements magically appeared in LongVec");
	}
	
	@Test
	public void testRemoveWrongOrder() {
		final LongVec vec = getLongVec();
		vec.addElement(1L);
		vec.addElement(2L);
		
		assertEquals(1L, vec.elementAt(0));
		assertEquals(2L, vec.elementAt(1));
		
		vec.removeElement(0);
		try {
			vec.removeElement(1);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Removed non-existing element");
	}

	@Test
	public void testGetNegative() {
		final LongVec vec = getLongVec();
		try {
			vec.elementAt(-1);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Read negative");
	}

	@Test
	public void testRemoveNegative() {
		final LongVec vec = getLongVec();
		try {
			vec.removeElement(-1);
		} catch (IndexOutOfBoundsException e) {
			return;
		}
		fail("Removed negative");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/TLAClass.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:28 PST by lamport
//      modified on Mon Jan 29 16:21:11 PST 2001 by yuanyu

package tlc2.tool.impl;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

import tlc2.output.EC;
import util.Assert;
import util.FilenameToStream;

/**
 * 
 * @author <NAME>, <NAME>
 * @version $Id$
 */
public class TLAClass
{
    /* Load a class from a file. */
    private final String pkg;
	private final FilenameToStream resolver;

    public TLAClass(String pkg, FilenameToStream resolver)
    {
        this.resolver = resolver;
		if (pkg.length() != 0 && pkg.charAt(pkg.length() - 1) != '.')
        {
            this.pkg = pkg + '.';
        } else
        {
            this.pkg = pkg;
        }
    }

	/**
	 * This method attempts to load the java class with the given name.
	 * 
	 * Loading classes is done in three steps:
	 * 
	 * <ul>
	 * <li>1) TLC's {@link FilenameToStream} resolver is used to locate a class
	 * file in the resolver's lookup path. Check {@link FilenameToStream}'s
	 * documentation on the lookup order. If a class file with name "name.class"
	 * can be found, it is loaded.</li>
	 * <li>2) With the unqualified name, we try to lookup the class in the
	 * regular VM's CLASSPATH.</li>
	 * <li>3) As a last resort, we try to load a class fully qualified with the
	 * package name given in {@link TLAClass#pkg}.</li>
	 * </ul>
	 * <p>
	 * If no class could be loaded, <code>null</code> is returned.
	 **/
    public synchronized Class loadClass(String name)
    {
        Class cl = null;
        try
        {
        	try {
        		if (resolver != null) {
        			final File module = resolver.resolve(name + ".class", false);
        			if (module != null && module.getAbsoluteFile() != null) {
        				final URL url = module.getAbsoluteFile().getParentFile().toURI().toURL();
        				cl = new URLClassLoader(new URL[] {url}).loadClass(name);
        			}
        		}
        	} catch (Exception ignored1) {
        		/*SKIP*/
        	} finally {
        		if (cl == null) {
        			try
        			{
        				cl = Class.forName(name);
        			} catch (Exception e)
        			{ /*SKIP*/
        			}
        		}
        	}
            if (cl == null)
            {
                try
                {
                    cl = Class.forName(this.pkg + name);
                } catch (Exception e)
                { /*SKIP*/
                }
            }
        } catch (Throwable e)
        {
            Assert.fail(EC.TLC_ERROR_REPLACING_MODULES, new String[] { name, 
                       (e.getMessage()==null)?e.toString():e.getMessage() });
        }
        return cl;
    }
    
//
//    public static void main(String argv[])
//    {
//        TLAClass tc = new TLAClass("tlc2.module");
//        Class c = tc.loadClass("Strings"); // must set CLASSPATH correctly
//        System.err.println("c = " + c);
//        // Class c1 = tc.loadClass("Class");
//        // System.err.println("c1 = " + c1);
//    }
//
}


<|start_filename|>tlatools/org.lamport.tlatools/test/util/ExecutionStatisticsCollectorTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import org.junit.Test;

public class ExecutionStatisticsCollectorTest {

	// Opt-out

	@Test
	public void testOptOutNoFile() throws IOException {
		final String tmpdir = System.getProperty("java.io.tmpdir");
		final File tempFile = new File(tmpdir + File.separator + "esc" + System.currentTimeMillis() + ".txt");
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		final String identifierA = esc.getIdentifier();
		assertNotNull(identifierA);
		assertNotNull(esc.getIdentifier());
		assertEquals(identifierA, esc.getIdentifier());
	}

	@Test
	public void testOptOutUnreadableFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		tempFile.setReadable(false);
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		assertNull(esc.getIdentifier());
	}

	@Test
	public void testOptOutEmptyFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		assertNull(esc.getIdentifier());
	}

	@Test
	public void testOptOutNoESCFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), ("   " + ExecutionStatisticsCollector.Selection.NO_ESC.toString() + "   ").getBytes());
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		assertNull(esc.getIdentifier());
	}

	@Test
	public void testOptOutRandomIdFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), ("   " + ExecutionStatisticsCollector.Selection.RANDOM_IDENTIFIER.toString() + "   ").getBytes());
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		final String identifierA = esc.getIdentifier();
		assertNotNull(identifierA);
		final String identifierB = esc.getIdentifier();
		assertNotNull(identifierB);
		assertNotEquals(identifierA, identifierB);
	}

	@Test
	public void testOptOutUserDefinedIdFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), "   123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ   ".getBytes());
		tempFile.deleteOnExit();
		
		final ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(true, tempFile.getAbsolutePath());
		
		assertEquals("123456789ABCDEFGHIJKLMNOPQRSTUVW", esc.getIdentifier());
	}
	
	// Opt-In

	@Test
	public void testNoFile() {
		assertNull(new ExecutionStatisticsCollector("/path/does/not/exist").getIdentifier());
	}

	@Test
	public void testUnreadableFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		tempFile.setReadable(false);
		tempFile.deleteOnExit();
		
		assertNull(new ExecutionStatisticsCollector(tempFile.getAbsolutePath()).getIdentifier());
	}

	@Test
	public void testEmptyFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		tempFile.deleteOnExit();
		
		assertNull(new ExecutionStatisticsCollector(tempFile.getAbsolutePath()).getIdentifier());
	}

	@Test
	public void testNoESCFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), ("   " + ExecutionStatisticsCollector.Selection.NO_ESC.toString() + "   ").getBytes());
		tempFile.deleteOnExit();
		
		assertNull(new ExecutionStatisticsCollector(tempFile.getAbsolutePath()).getIdentifier());
	}

	@Test
	public void testRandomIdFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), ("   " + ExecutionStatisticsCollector.Selection.RANDOM_IDENTIFIER.toString() + "   ").getBytes());
		tempFile.deleteOnExit();
		
		ExecutionStatisticsCollector esc = new ExecutionStatisticsCollector(tempFile.getAbsolutePath());
		
		final String identifierA = esc.getIdentifier();
		assertNotNull(identifierA);
		final String identifierB = esc.getIdentifier();
		assertNotNull(identifierB);
		assertNotEquals(identifierA, identifierB);
	}

	@Test
	public void testUserDefinedIdFile() throws IOException {
		File tempFile = File.createTempFile("esc", "txt");
		Files.write(tempFile.toPath(), "   123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ   ".getBytes());
		tempFile.deleteOnExit();
		
		assertEquals("123456789ABCDEFGHIJKLMNOPQRSTUVW", new ExecutionStatisticsCollector(tempFile.getAbsolutePath()).getIdentifier());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/UniqueString.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Wed Oct 17 15:25:39 PDT 2001 by yuanyu
package util;

import java.io.IOException;
import java.io.Serializable;
import java.util.Map;

import tlc2.tool.Defns;
import tlc2.tool.TLCState;
import tlc2.tool.distributed.InternRMI;
import tlc2.util.FP64;

/**
 * For any string (state variable, operator definition) the strings are stored 
 * only once for the entire run. This leads to a major speed-up in string comparison.<br>  
 * 
 * This class serves multiple purposes. 
 * <br><br>
 * 
 * The primary purpose is to use instances of this class as a wrapper or
 * data holder inside of the {@link InternTable}. The latter is organized that way, that it holds an
 * array of UniqueStrings. Each UniqueString that is created is put at most once into the table, and holds 
 * the information of its location in the table. The member variable {@link UniqueString#s} is used to represent 
 * the content, the member variable {@link UniqueString#tok} holds the position inside of the {@link InternTable}.
 * The following methods are responsible for access to content and position:
 * <ul>
 *  <li>{@link UniqueString#compareTo(UniqueString)}</li>
 *  <li>{@link UniqueString#concat(UniqueString)}</li>
 *  <li>{@link UniqueString#equals(UniqueString)}</li>
 *  <li>{@link UniqueString#equals(String)}</li>
 *  <li>{@link UniqueString#getTok()}</li>
 *  <li>{@link UniqueString#hashCode()}</li>
 *  <li>{@link UniqueString#length()}</li>
 *  <li>{@link UniqueString#toString()}</li>
 * </ul>
 * <br>
 * In addition, there exist two types of externally stored tables: the array of values of state variables 
 * in subclasses of {@link TLCState}, and array of operator definitions in {@link Defns}. The main scheme 
 * behind the storage of the objects in these arrays is that the value of a variable / operation 
 * definition with name, identified by a UniqueString <code>foo</code> is stored at position, in the array, that is 
 * stored inside of <code>foo</code>, using the instance member {@link UniqueString#loc}. Note, that multiple instances 
 * of TLCState store values of variables on the same position in their arrays and only one Defn instance 
 * exist. This is OK, because the state variable are global.
 * <br>
 * In order to distinguish between the index in the state variable array and index of operator definition array, 
 * the number of state variables defined in the specification is maintained in the static member {@link UniqueString#varCount}. 
 * The methods that are responsible for this feature are:
 * <ul>
 *   <li>{@link UniqueString#getDefnLoc()}</li>
 *   <li>{@link UniqueString#getVarLoc()}</li>
 *   <li>{@link UniqueString#setLoc(int)}</li>
 *   <li>{@link UniqueString#setVariableCount(int)}</li>
 * </ul>
 * <br>
 * Finally, there are two methods responsible for marshaling/un-marshaling and convenience methods to put and get unique 
 * string into and out of the InternTable
 *  
 * @author <NAME>, <NAME>
 */
public final class UniqueString implements Serializable
{
    
    /** 
     * Maps from strings to variables. 
     */
    public static InternTable internTbl = null;
    /**
     * The string content
     */
    private String s;

    /** 
     * The unique integer assigned to the string.
     */
    private int tok;

    /**
     * If this unique string is a state variable, this is the location of this
     * variable in {@link TLCState}.  If this string is the name of an operator
     * definition, this is the location of this definition in {@link Defns}.
     */
    private int loc = -1;

    // SZ 10.04.2009: removed the getter method
    // since it is only needed in Spec#processSpec and the setter is called from there
    private static int varCount;

    
    /**
     * Call static constructor method for call not out of TLC
     */
    static 
    {
        UniqueString.initialize();
    }

    /**
     * Static constructor method
     */
    public static void initialize()
    {
        internTbl = new InternTable(1024);
        varCount = 0;
    }

    /**
     * Protected constructor, used from utility methods
     * @param str a string to be saved 
     * @param tok the unique integer for this string (position in the InternalTable)
     */
    protected UniqueString(String str, int tok)
    {
        this.s = str;
        this.tok = tok;
    }

    /**
     * Private constructor, used on marshaling/un-marshaling
     * @param str a string to be saved 
     * @param tok the unique integer for this string (position in the InternalTable)
     * @param loc location inside of the state/definition table
     */
    private UniqueString(String str, int tok, int loc)
    {
        this(str, tok);
        this.loc = loc;
    }

    /**
     * Sets the number of variables in the spec
     * @param varCount number of variables defined
     */
    public static void setVariableCount(int varCount)
    {
        UniqueString.varCount = varCount;
        // SZ 10.04.2009: changed the method signature from setVariables(UniqueString[])
        // to setVariableCount(int), since the method is effectively only responsible
        // for storing this information in the static field of this class.

        // SZ 10.04.2009: removed the loop that runs through the variable names
        // and sets the Loc field of each variable name to it's order in the list
        // moved it to the place where the variables are initialized
    }

    /**
     * Returns the location of this variable in a state, if the name is a
     * variable.  Otherwise, returns -1.
     */
    public int getVarLoc()
    {
        return (this.loc < varCount) ? this.loc : -1;
    }

    /**
     * Returns the location of this operator in defns, if it is the name
     * of an operator.  Otherwise, returns -1.
     */
    public int getDefnLoc()
    {
        return (this.loc < varCount) ? -1 : this.loc;
    }

    /**
     * Set this string's location in either the state or the defns.
     * This is fishy to store location outside of the storage
     * 
     * @see {@link TLCState}
     * @see {@link Defns}
     */
    public void setLoc(int loc)
    {
        this.loc = loc;
    }

    /**
     * Retrieves the unique number associated with this string
     * @return
     */
    public int getTok()
    {
        return this.tok;
    }

    /**
     * Concatenates two unique strings
     */
    public UniqueString concat(UniqueString uniqueString)
    {
        return uniqueStringOf(this.toString() + uniqueString.toString());
    }
    
    public UniqueString concat(String string)
    {
        return uniqueStringOf(this.toString() + string);
    }

    /**
     * Delivers the stored string 
     */
    public String toString()
    {
        return this.s;
    }

    /**
     * @see {@link String#hashCode()} 
     */
    public int hashCode()
    {
        return this.s.hashCode();
    }

    /**
     * @see {@link String#length()} 
     */
    public int length()
    {
        return this.s.length();
    }
    /**
     * Not a compare method as usual for objects
     * Delivers the difference in positions inside of the table, the unique strings are stored in 
     * @param uniqueString
     * @return
     */
    public int compareTo(UniqueString uniqueString)
    {
        // SZ 10.04.2009: very strange way to compare strings
        // return this.s.compareTo(t.s);
        return this.tok - uniqueString.tok;
    }

    /**
     * Since uniqueness is guaranteed, the equals is a high performance reference comparison 
     */
    public boolean equals(UniqueString t)
    {
        return this.tok == t.tok;
    }

    /**
     * There is no performance gain to compare with a string.
     */
    public boolean equals(String t)
    {
        return this.s.equals(t);
    }

    
    public long fingerPrint(long fp)
    {
        return FP64.Extend(fp, this.tok);
    }

    /**
     * Returns a unique object associated with string str.  That is,
     * the first time uniqueStringOf("foo") is called, it returns a
     * new object o.  Subsequent invocations of uniqueStringOf("foo")
     * return the same object o.
     * 
     * This is a convenience method for a table put.
     */
    public static UniqueString uniqueStringOf(String str)
    {
        return internTbl.put(str);
    }

	public static UniqueString of(String str) {
		return uniqueStringOf(str);
	}

	public static UniqueString join(String delim, UniqueString... us) {
		return join(delim, us.length, us);
	}

	public static UniqueString join(String delim, int n, UniqueString... us) {
		assert 0 < n && n <= us.length;
		UniqueString out = null;
		for (int i = 0; i < n; i++) {
			if (out == null) {
				out = us[i];
			} else {
				out = out.concat("!");
				out = out.concat(us[i]);
			}
		}
		return out;
	}
	
    /**
     * If there exists a UniqueString object obj such that obj.getTok()
     * equals tok, then uidToUniqueString(i) returns obj; otherwise,    
     * it returns null.
     * 
     * This is a convenience method for a table lookup. 
     */
    public static UniqueString uidToUniqueString(int tok)
    {
        return internTbl.get(tok);
    }


    /**
     * Writes current unique string to the stream
     * @param dos
     * @return
     * @throws IOException
     */
    public final void write(IDataOutputStream dos) throws IOException
    {
        dos.writeInt(this.tok);
        dos.writeInt(this. getVarLoc()); 
         // Above changed from dos.writeInt(this.loc); by <NAME> on 17 Mar 2010
        dos.writeInt(this.s.length());
        dos.writeString(this.s);
    }

    /**
     * Utility method for reading a unique string from the stream
     * @param dis
     * @return
     * @throws IOException
     * 
     * The method does not change member/class variables
     */
    public static UniqueString read(IDataInputStream dis) throws IOException
    {
        int tok1 = dis.readInt();
        int loc1 = dis.readInt();
        int slen = dis.readInt();
        String str = dis.readString(slen);
        return new UniqueString(str, tok1, loc1);
    }
    
    public static UniqueString read(IDataInputStream dis, final Map<String, UniqueString> tbl) throws IOException
    {
        dis.readInt(); // skip, because invalid for the given internTbl
        dis.readInt(); // skip, because invalid for the given internTbl
        final int slen = dis.readInt();
        final String str = dis.readString(slen);
        return tbl.get(str);
    }


    /**
     * Sets the source 
     * @param source
     */
    public static void setSource(InternRMI source)
    {
        internTbl.setSource(source);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/ExecutionStatisticsCollector.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class ExecutionStatisticsCollector {

	static final String RND_ID_STR = "RANDOM_IDENTIFIER";
	static final String NO_ESC_STR = "NO_STATISTICS";
	
	public enum Selection {
		ON, RANDOM_IDENTIFIER, NO_ESC;

		@Override
		public String toString() {
			if (this == ON) {
				return getRandomIdentifier();
			} else if (this == RANDOM_IDENTIFIER) {
				return RND_ID_STR;
			} else {
				return NO_ESC_STR;
			}
		}
	}
	
	private static final String PATH = System.getProperty("user.home", "") + File.separator + ".tlaplus" + File.separator + "esc.txt";

	public static final String PROP = ExecutionStatisticsCollector.class.getName() + ".id";
	
	private final boolean isOptOut;
	private final String pathname;

	public ExecutionStatisticsCollector() {
		this(isOptOut(), PATH);
	}
	
	ExecutionStatisticsCollector(String path) {
		this(false, path);
	}
	
	ExecutionStatisticsCollector(final boolean optOut, final String path) {
		this.isOptOut = optOut;
		this.pathname = path;
	}
	
	public void collect(final Map<String, String> parameters) {
		collect(parameters, true);
	}

	private void collect(final Map<String, String> parameters, final boolean dontWaitForCompletion) {
		// Do not block TLC startup but send this to the background immediately. If
		// dontWaitForCompletion is true, the VM will terminate this thread regardless
		// of its state if the VM decides to shutdown (e.g. because TLC is done).
		final Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				if (isEnabled()) {
					// Include identifier to track individual installations (not users!).
					parameters.put("id", getIdentifier());
					submit(parameters, dontWaitForCompletion);
				}
			}
		}, "TLC Execution Statistics Collector");
		thread.setDaemon(dontWaitForCompletion);
		thread.start();
	}
	
	/*
	 * file == ~/.tlaplus/esc.txt
	 * fl == first line of file interpreted as a string without terminal chars
	 * in/out == opt-in & opt-out
	 * y/r/n == data collected with constant id/data collected with random id/data not collected
	 * 
	 *       | No file | fl unreadable | fl empty | fl = "NO_UDC" | fl = "RANDOM_IDENTIFIER" | fl any other string
	 * ==========================================================================================================
	 * | out |   y     |       n       |    n     |       n       |            r             |         y         |
	 * ----------------------------------------------------------------------------------------------------------
	 * | in  |   n     |       n       |    n     |       n       |            r             |         y         |
	 * ----------------------------------------------------------------------------------------------------------
	 */
	public String getIdentifier() {
		if (System.getProperty(PROP) != null) {
			return System.getProperty(PROP);
		}
		String identifier;

		final File udcFile = new File(pathname);
		if (!udcFile.exists() && isOptOut) {
			try (BufferedWriter br = new BufferedWriter(new FileWriter(udcFile))) {
				br.write(getRandomIdentifier());
			} catch (Exception e) {
				// Something went wrong writing to file ~/.tlaplus/esc.txt. Consider ESC failed.
				return null;
			}
		}
		if (!udcFile.exists()) {
			// No file ~/.tlaplus/esc.txt.
			return null;
		}
		try (BufferedReader br = new BufferedReader(new FileReader(udcFile))) {
			identifier = br.readLine();
		} catch (Exception e) {
			// Something went wrong reading file ~/.tlaplus/esc.txt
			return null;
		}
		if (identifier == null || NO_ESC_STR.equals(identifier.trim())) {
			// File is empty or its first line is "NO_STATISTICS".
			return null;
		} else if (identifier == null || RND_ID_STR.equals(identifier.trim())) {
			identifier = getRandomIdentifier();
		}
		
		// truncate the identifier no matter what, but first remove leading and trailing whitespaces.
		final String trimmed = identifier.trim();
		return trimmed.substring(0, Math.min(trimmed.length(), 32));
	}

	private boolean escFileExists() {
		return new File(pathname).exists();
	}

	public boolean isEnabled() {
		return getIdentifier() != null;
	}

	public void set(final Selection c) throws IOException {
		final File udcFile = new File(PATH);
		// Create ~/.tlaplus/ parent directory if it doesn't exist. This will probably
		// only ever be the case on a development machine where the Toolbox runs from
		// inside Eclipse with a workspace location ("-data") other than ~/.tlaplus/ .
		udcFile.getParentFile().mkdirs();
		udcFile.createNewFile();
		
		try (BufferedWriter br = new BufferedWriter(new FileWriter(udcFile))) {
			br.write(c.toString() + "\n");
		} catch (IOException e) {
			throw e;
		}
	}
	
	public Selection get() {
		if (isEnabled()) {
			try (BufferedReader br = new BufferedReader(new FileReader(new File(pathname)))) {
				String line = br.readLine();
				if (RND_ID_STR.equals(line)) {
					return Selection.RANDOM_IDENTIFIER;
				} else {
					return Selection.ON;
				}
			} catch (Exception e) {
			}
		}
		return Selection.NO_ESC;
	}
	
	public static boolean promptUser() {
		return !(new ExecutionStatisticsCollector().escFileExists());
	}

	private static String getRandomIdentifier() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	private static boolean isOptOut() {
		return false; // Nobody is opt-out right now
		
		// Below is a way how we could detect Microsoft corpnet machines: This check is
		// conservative because we don't identify Microsoft employees but corporate
		// Microsoft computers. We don't set ESC to opt-out for Microsoft machines yet
		// but might in the future.
//		final String userDNSDomain = System.getenv("USERDNSDOMAIN");
//		return userDNSDomain != null && userDNSDomain.toUpperCase().endsWith(".CORP.MICROSOFT.COM");
	}

	// Send the request.
	private static void submit(final Map<String, String> parameters, final boolean dontWaitForCompletion) {
		// Include a timestamp to cause HEAD to be un-cachable.
		parameters.put("ts", Long.toString(System.currentTimeMillis()));
		parameters.put("optout", Boolean.toString(isOptOut()));
		
		try {
			// Opt-out data doesn't report to the opt-in endpoint. The opt-in endpoint is
			// public data, the opt-out endpoint doesn't get shared with the public.
			final URL url = new URL(
					"https://" + (isOptOut() ? "esc02" : "esc01") + ".tlapl.us/?" + encode(parameters));

			final HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("HEAD");
			con.getResponseMessage();
			con.disconnect();
		} catch (Exception ignoreCompletely) {
			// A TLC user doesn't care if execution statistics collection doesn't work.
		}
	}	
	
	private static String encode(final Map<String, String> parameters) throws UnsupportedEncodingException {
		final StringBuffer buf = new StringBuffer();

		for (String key : parameters.keySet()) {
			String value = parameters.get(key);
			buf.append(URLEncoder.encode(key, "UTF-8"));
			buf.append("=");
			buf.append(URLEncoder.encode(value, "UTF-8"));
			buf.append(",");
		}
		
		return buf.toString().replaceFirst(",$", "");
	}

	// for manual testing //
	
	public static void main(String[] args) {
		new ExecutionStatisticsCollector().collect(new HashMap<>(), false);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ProverToolboxLifecycleParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover;

import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;

/**
 * This class gets notified when the toolbox starts up and shuts down.
 * When it shuts down, it cancels all running prover jobs.
 * 
 * @author <NAME>
 *
 */
public class ProverToolboxLifecycleParticipant extends ToolboxLifecycleParticipant
{

    public ProverToolboxLifecycleParticipant()
    {
        // TODO Auto-generated constructor stub
    }

    /**
     * Is called during termination of the toolbox. 
     * This implementation cancels all running prover jobs.
     */
    public void terminate()
    {

        ProverHelper.cancelProverJobs(true);

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/DistributedFPSet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp;

import java.io.File;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.rmi.ConnectException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.TLCServerRMI;
import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.FPSetConfiguration;
import tlc2.tool.fp.FPSetFactory;
import tlc2.tool.fp.MultiFPSet;
import util.ToolIO;

public class DistributedFPSet  {

	private static volatile boolean running = true;

	public static void main(String[] args) {
		ToolIO.out.println("TLC Distributed FP Server " + TLCGlobals.versionOfTLC);

        // Must have exactly one arg: a hostname (spec is read from the server
		// connecting to).
		if(args.length != 1) {
			printErrorMsg("Error: Missing hostname of the TLC server to be contacted.");
			return;
		}
		final String serverName = args[0];

		 //TODO read parameter fpbits?
		final int prefixBits = 0;

		try {
			// Lookup FPSetManager
			TLCServerRMI tlcServer = lookupTLCServer(serverName);
			
			// Create metadata directory
			final String metadir = System.getProperty("java.io.tmpdir") + File.separator + "FPSet"
					+ System.currentTimeMillis();
			final File filedir = new File(metadir);
			if (!filedir.exists()) {
				filedir.mkdirs();
			}
			
			// Initialize this FPSet with n-prefix bits and m mask bits
			final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration(1.0d);
			fpSetConfiguration.setFpBits(1 + prefixBits);
			final FPSet fpSet = FPSetFactory.getFPSet(fpSetConfiguration);
			final String filename = "FPSet" + System.currentTimeMillis();
			fpSet.init(1,metadir,filename);
			
			// Print out fpset type and nested FPSets when MultiFPSet
			System.err.println("FPSet instance type is: " + fpSet.getClass().getName());
			if (fpSet instanceof MultiFPSet) {
				final MultiFPSet multiFPSet = (MultiFPSet) fpSet;
				final FPSet[] fpSets = multiFPSet.getFPSets();
				for (int i = 0; i < fpSets.length; i++) {
					System.err.println("...with nested instance type: " + fpSets[i].getClass().getName());
				}
			}

			// Register this with the FPSetManager
			final String hostname = InetAddress.getLocalHost().getHostName();
			try {
				tlcServer.registerFPSet(fpSet, hostname);
			} catch (FPSetManagerException e) {
				// Registration as an FPSet has failed, un-export local FPSet and
				// exit main thread. Do not System.exit(int) as worker thread might 
				// run in this VM instance.
				fpSet.unexportObject(false);
				ToolIO.out.println(e.getMessage());
				return;
			}

			// Show FPset is ready accepting fingerprints
            System.out.println("Fingerprint set server at " + hostname + " is ready.");
			
			// Periodically report status (every 5 minutes)
			synchronized (fpSet) {
				while (running) {
					ToolIO.out.println("Progress: The number of fingerprints stored at " + hostname + " is "
							+ fpSet.size() + ".");
					fpSet.wait(300000);
				}
				
				// exit if signal received
				fpSet.unexportObject(false);
				ToolIO.out.println("Exiting TLC Distributed FP Server");
			}
		} catch (Throwable e) {
			// Assert.printStack(e);
			MP.printError(EC.GENERAL, e);
			ToolIO.out.println("Error: Failed to start FPSet "
					+ " for server " + serverName + ".\n" + e.getMessage());
		}
	
		ToolIO.out.flush();
	}

	/**
	 * Signal the {@link DistributedFPSet} to shutdown which results in a RMI
	 * de-registration by un-exporting the nested {@link FPSet}.
	 */
	public static void shutdown() {
		running = false;
	}
	
	private static TLCServerRMI lookupTLCServer(final String serverName) throws MalformedURLException, RemoteException, NotBoundException, InterruptedException {
		String url = "//" + serverName + ":" + TLCServer.Port
				+ "/" + TLCServer.SERVER_NAME;

		// try to repeatedly connect to the server until it becomes available.
		// see similar while loop in
		// tlc2.tool.distributed.TLCWorker.main(String[]) for more comments.
		int i = 1;
		while(true) {
			try {
				return (TLCServerRMI) Naming.lookup(url);
			} catch (ConnectException e) {
				// if the cause if a java.NET.ConnectException the server is
				// simply not ready yet
				final Throwable cause = e.getCause();
				if(cause instanceof java.net.ConnectException) {
					long sleep = (long) Math.sqrt(i);
					ToolIO.out.println("Server " + serverName
							+ " unreachable, sleeping " + sleep
							+ "s for server to come online...");
					Thread.sleep(sleep * 1000);
					i *= 2;
				} else {
					// some other exception occurred which we do not know
					// how to handle
					throw e;
				}
			} catch (NotBoundException e) {
				// Registry is available but no object by "TLCServer". This
				// happens when TLCServer makes it registry available but
				// has't registered itself yet.
				long sleep = (long) Math.sqrt(i);
				ToolIO.out.println("Server " + serverName + " reachable but not ready yet, sleeping " + sleep
						+ "s for server to come online...");
				Thread.sleep(sleep * 1000);
				i *= 2;
			}
		}
	}
	
	private static void printErrorMsg(String msg) {
		ToolIO.out.println(msg);
		ToolIO.out
				.println("Usage: java " + DistributedFPSet.class.getName() + " host");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools.consumer.distributed/src/org/lamport/tla/distributed/consumer/TLCWorkerConsumer.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.distributed.consumer;

import java.net.URI;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.packageadmin.PackageAdmin;

import tlc2.ITLCWorker;

/**
 * @author <NAME>
 * 
 * <p> If DS does not pass an ITLCWorker, make sure that: 
 *  <ul>
 *   <li>The DS framework (org.eclipse.equinox.ds) is installed in active</li>
 *   <li>org.lamport.tlatools.impl.distributed is installed and active</li>
 *  </ul>
 * </p>
 */
@SuppressWarnings("deprecation")
public class TLCWorkerConsumer {

	/**
	 * TLCServer address to connect to.
	 * 
	 * //TODO refactor to read/obtain URI from ECF discovery
	 * //TODO port number currently hard coded in TLCServer/TLCWorker 
	 */
	private final URI uri = URI
			.create(System.getProperty(TLCWorkerConsumer.class.getName()
					+ ".uri", "rmi://localhost:10997"));
	
	private PackageAdmin pa;

	public void setPackageAdmin(PackageAdmin pa) {
		this.pa = pa;
	}
	
	/**
	 * @see OSGi-INF/component.xml
	 * @param anITLCWorker
	 *            passed by OSGi Declarative Services
	 */
	public void setITLCWorker(final ITLCWorker anITLCWorker) {
		final ExecutorService executor = Executors.newSingleThreadExecutor();
		executor.submit(new Callable<Void>() {

			public Void call() throws Exception {
				try {
					// a) Connect and wait for some states to be calculated
					System.out.println(String.format("Connecting new TLCWorker %s to url %s", anITLCWorker, uri));
					anITLCWorker.connect(uri);
					
					// b) Wait for this model checker run to be done
					anITLCWorker.awaitTermination();
				} finally {
					// c) Refresh the OSGi bundle
					System.out.println("Disposing old tlatools bundle...");
					BundleContext bundleContext = FrameworkUtil.getBundle(
							TLCWorkerConsumer.class).getBundleContext();

					final Bundle bundle = getTlaToolsBundle();
					final String location = bundle.getLocation();
					bundle.stop();
					bundle.uninstall();
					Bundle newBundleInstance = bundleContext
							.installBundle(location);
					newBundleInstance.start();
					pa.refreshPackages(new Bundle[] { bundle });
				}
				return null;
			}
		});
	}
	
	private Bundle getTlaToolsBundle() {
		BundleContext ctx = FrameworkUtil.getBundle(
				TLCWorkerConsumer.class).getBundleContext();
		final Bundle[] bundles = ctx.getBundles();
		for (Bundle bundle : bundles) {
			if ("org.lamport.tlatools".equals(bundle.getSymbolicName())) {
				return bundle;
			}
		}
		// Getting here is very bad and means my assumptions about the
		// environment are incorrect, sorry :-(
		return null;
	}

	/**
	 * @see OSGi-INF/component.xml
	 * @param anITLCWorker passed by OSGi Declarative Services
	 */
	public void unsetITLCWorker(final ITLCWorker anITLCWorker) {
		anITLCWorker.disconnect();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/ILiveChecker.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import java.io.IOException;

import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.util.BitVector;
import tlc2.util.SetOfStates;

public interface ILiveChecker {

	/**
	 * This method records that state is an initial state in the behavior graph.
	 * It is called when a new initial state is generated.
	 */
	void addInitState(ITool tool, TLCState state, long stateFP);

	/**
	 * This method adds new nodes into the behavior graph induced by s0. It is
	 * called after the successors of s0 are computed.
	 */
	void addNextState(ITool tool, TLCState s0, long fp0, SetOfStates nextStates,
			BitVector checkActionResults, boolean[] checkStateResults) throws IOException;

	AbstractDiskGraph getDiskGraph();

	OrderOfSolution getSolution();

	void close() throws IOException;

}

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/ValueInputOutputStreamTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

import tlc2.TLCGlobals;

public class ValueInputOutputStreamTest {

	@Test
	public void testWriteShort() throws IOException {
		final File tempFile = File.createTempFile("ValueOutputStreamTest-testWriteShort", ".vos");
		tempFile.deleteOnExit();
		
		final ValueOutputStream out = new ValueOutputStream(tempFile);
		out.writeShort(Short.MAX_VALUE);
		out.writeShort(Short.MIN_VALUE);
		out.writeShort((short) 0);
		out.close();
		
		final ValueInputStream in = new ValueInputStream(tempFile);
		assertEquals(Short.MAX_VALUE, in.readShort());
		assertEquals(Short.MIN_VALUE, in.readShort());
		assertEquals((short) 0, in.readShort());
		in.close();
	}

	@Test
	public void testWriteInt() throws IOException {
		final File tempFile = File.createTempFile("ValueOutputStreamTest-testWriteInt", ".vos");
		tempFile.deleteOnExit();
		
		final ValueOutputStream out = new ValueOutputStream(tempFile);
		out.writeInt(Integer.MAX_VALUE);
		out.writeInt(Integer.MIN_VALUE);
		out.writeInt(0);
		out.close();
		
		final ValueInputStream in = new ValueInputStream(tempFile);
		assertEquals(Integer.MAX_VALUE, in.readInt());
		assertEquals(Integer.MIN_VALUE, in.readInt());
		assertEquals(0, in.readInt());
		in.close();
	}

	@Test
	public void testWriteShortNat() throws IOException {
		final File tempFile = File.createTempFile("ValueOutputStreamTest-testWriteShortNat", ".vos");
		tempFile.deleteOnExit();
		
		TLCGlobals.useGZIP = true;
		final ValueOutputStream out = new ValueOutputStream(tempFile);
		out.writeShortNat(Short.MAX_VALUE);
		out.writeShortNat((short) 0);
		out.close();
		
		// 20 byte header
		// 2 byte Short.MAX_VALUE
		// 1 byte 0
		assertEquals(20 + 2 + 1, tempFile.length());
		
		final ValueInputStream in = new ValueInputStream(tempFile);
		assertEquals(Short.MAX_VALUE, in.readShortNat());
		assertEquals(0, in.readShortNat());
		in.close();
	}

	@Test
	public void testWriteNat() throws IOException {
		final File tempFile = File.createTempFile("ValueOutputStreamTest-testWriteNat", ".vos");
		tempFile.deleteOnExit();
		
		TLCGlobals.useGZIP = true;
		final ValueOutputStream out = new ValueOutputStream(tempFile);
		out.writeNat(Integer.MAX_VALUE);
		out.writeNat(0);
		out.close();
		
		// 20 byte header
		// 4 byte Integer.MAX_VALUE
		// 2 byte 0
		assertEquals(20 + 4 + 2, tempFile.length());
		
		final ValueInputStream in = new ValueInputStream(tempFile);
		assertEquals(Integer.MAX_VALUE, in.readNat());
		assertEquals(0, in.readNat());
		in.close();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/ProblemViewResourceListener.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.view;

import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;
import org.lamport.tla.toolbox.util.TLAMarkerHelper;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/*
 * Use an inner class because instantiation of ProblemView itself should be
 * left to the Eclipse foundation and not be triggered directly via new.
 */
public class ProblemViewResourceListener extends ToolboxLifecycleParticipant implements IResourceChangeListener {

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant#postWorkbenchWindowOpen()
	 */
	public void postWorkbenchWindowOpen() {
		// Check if there have been any markers set already
		showOrHideProblemView();
		
		// ...and listen for new markers
		final IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_BUILD);
	}

	private void showOrHideProblemView() {
        boolean showProblems = PreferenceStoreHelper.getInstancePreferenceStore().getBoolean(
                IPreferenceConstants.I_PARSER_POPUP_ERRORS);
		if (showProblems) {
			if (TLAMarkerHelper.currentSpecHasProblems()) {
				// This used to be in Activator. However,
				// at startup there might not be an
				// activePage which results in a
				// NullPointerException. Thus, have the
				// ProblemView check the parse status when
				// UI startup complete.
				ProblemView view = (ProblemView) UIHelper.getActivePage().findView(ProblemView.ID);
				// show
				if (view != null) {
					// already shown, hide
					UIHelper.hideView(ProblemView.ID);
				}

				// not shown, show
				UIHelper.openViewNoFocus(ProblemView.ID);
			} else {
				// hide
				UIHelper.hideView(ProblemView.ID);
			}
		}
	}

	private boolean hasMarkerDelta(IResourceChangeEvent event) {
		IMarkerDelta[] deltas = event.findMarkerDeltas(TLAMarkerHelper.TOOLBOX_MARKERS_ALL_MARKER_ID, true);
		if (deltas.length > 0) {
			return true;
		}
		return false;
	}

	public void resourceChanged(IResourceChangeEvent event) {
		// no marker update
		if (!hasMarkerDelta(event)) {
			return;
		} else {
			UIHelper.runUIAsync(new Runnable() {
				public void run() {
					showOrHideProblemView();
				}
			});
		}
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/LetsCreateAHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;

/**
 * TODO LL says he deletes this file as soon as he does not need it anymore
 * @author <NAME>
 *
 */
public class LetsCreateAHandler extends AbstractHandler
{

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        return null;
    }
    
// I thought the following should make the menu item invisible, but 
// it at first seemed to be random.  Sometimes it did nothing, and then when
// I select another view it grayed it out.  Sometimes the menu item
// was invisible when I open the toolbox.  It seems now to have stabilized
// to the latter behavior.
//    
    public boolean isEnabled() {
        return false;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/PCalTranslateModuleHandler.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME> - Refactoring
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorAndPDFViewer;
import org.lamport.tla.toolbox.editor.basic.pcal.PCalTranslator;
import org.lamport.tla.toolbox.ui.handler.SaveDirtyEditorAbstractHandler;

/**
 * Triggers the PCal translation of the module
 * 
 * @author <NAME>
 */
public class PCalTranslateModuleHandler extends SaveDirtyEditorAbstractHandler {

	public Object execute(final ExecutionEvent event) throws ExecutionException {
		if (!saveDirtyEditor(event)) {
			// Cannot translate a dirty editor.
			return null;
		}
		final TLAEditor tlaEditor = getTLAEditor(activeEditor);
		if (tlaEditor == null || !tlaEditor.hasPlusCal()) {
			// If it's not a TLAEditor, it can't have PlusCal code.
			return null;
		}

		try {
			new PCalTranslator().translate(tlaEditor, HandlerUtil.getActiveShell(event));
		} catch (InvocationTargetException | InterruptedException e) {
			throw new ExecutionException(e.getMessage(), e);
		}
		return null;
	}
	
	private static TLAEditor getTLAEditor(IEditorPart anEditor) {
		if (anEditor instanceof TLAEditorAndPDFViewer) {
			final TLAEditorAndPDFViewer editor = (TLAEditorAndPDFViewer) anEditor;
			return editor.getTLAEditor();
		}
		if (anEditor instanceof TLAEditor) {
			return (TLAEditor) anEditor;
		}
		return null;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/ObjectPoolStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:35 PST by lamport  
//      modified on Tue Feb 22 15:59:47 PST 2000 by yuanyu   

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import tlc2.output.EC;
import tlc2.output.MP;
import util.FileUtil;

public class ObjectPoolStack {

  public ObjectPoolStack(int bufSize, String filePrefix) {
    this.filePrefix = filePrefix;
    this.buf = new Object[bufSize];
    this.hiPool = 0;
    this.isIdle = true;
    this.reader = new Reader();
    this.writer = new Writer();
    this.poolFile = null;
    this.reader.start();
    this.writer.start();
  }

  private String filePrefix;
  private Object[] buf;
  private int hiPool;
  private boolean isIdle;
  private Reader reader;
  private Writer writer;
  private File poolFile;
  
  public final Object[] write(Object[] outBuf)
  throws IOException, InterruptedException {
    synchronized(this) {
      while (!this.isIdle) this.wait();
    }
    Object[] res = this.buf;
    this.buf = outBuf;
    this.poolFile = new File(this.filePrefix + Integer.toString(this.hiPool++));
    this.isIdle = false;
    this.writer.notify();
    return res;
  }

  public final Object[] read(Object[] inBuf)
  throws IOException, InterruptedException {
    if (this.hiPool == 0) return null;
    synchronized(this) {
      while (!this.isIdle) this.wait();
    }
    Object[] res = this.buf;
    this.buf = inBuf;
    this.hiPool--;
    if (this.hiPool > 0) {
      this.poolFile = new File(this.filePrefix + Integer.toString(this.hiPool-1));
      this.isIdle = false;
      this.reader.notify();
    }
    return res;
  }

  public final synchronized void beginChkpt(ObjectOutputStream oos)
  throws IOException {
    oos.writeInt(this.hiPool);
  }

  /* Note that this method is not synchronized. */
  public final void recover(ObjectInputStream ois) throws IOException {
    this.hiPool = ois.readInt();
    if (this.hiPool > 0) {
      this.poolFile = new File(this.filePrefix + Integer.toString(this.hiPool-1));
      this.isIdle = false;
      this.reader.notify();
    }
  }

  class Reader extends Thread {
      public void run() {
          try {
              synchronized(this) {
                  while (true) {
                      while (ObjectPoolStack.this.poolFile == null) {
                          this.wait();
                      }
                      ObjectInputStream ois = FileUtil.newOBFIS(ObjectPoolStack.this.poolFile);
                      for (int i = 0; i < ObjectPoolStack.this.buf.length; i++) {
                          ObjectPoolStack.this.buf[i] = ois.readObject();
                      }
                      ois.close();
                      ObjectPoolStack.this.poolFile = null;
                      ObjectPoolStack.this.isIdle = true;
                      ObjectPoolStack.this.notify();	    
                  }
              }
          }
          catch (Exception e) 
          {
              MP.printError(EC.SYSTEM_ERROR_WRITING_POOL, e);
              System.exit(1);
          }
      }
  }

  class Writer extends Thread {
      public void run() {
          try {
              synchronized(this) {
                  while (true) {
                      while (ObjectPoolStack.this.poolFile == null) {
                          this.wait();
                      }
                      ObjectOutputStream oos = FileUtil.newOBFOS(ObjectPoolStack.this.poolFile);
                      for (int i = 0; i < ObjectPoolStack.this.buf.length; i++) {
                          oos.writeObject(ObjectPoolStack.this.buf[i]);
                      }
                      oos.close();
                      ObjectPoolStack.this.poolFile = null;
                      ObjectPoolStack.this.isIdle = true;
                      ObjectPoolStack.this.notify();
                  }
              }
          }
          catch (Exception e) 
          {
              MP.printError(EC.SYSTEM_ERROR_READING_POOL, e);
              System.exit(1);
          }
      }
  }
    
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/results/DataDisplay.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page.results;

import java.util.concurrent.TimeUnit;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.lamport.tla.toolbox.tool.tlc.output.data.StateSpaceInformationItem;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * The run method of this class creates a shell (a window) to display a graph of
 * the appropriate State Space Progress information when the user clicks on a
 * column heading. It then adds a PaintListener to that shell, and that listener
 * draws the graph initially and whenever the window is resized or some other
 * event requires it to be redrawn.
 * 
 * The constructor is used to pass the arguments needed by the run method to
 * display the data.
 * 
 * Note: The location at which the shells are displayed is fixed in code buried
 * deeply. There should probably be some thought given to where to pop up the
 * window, and perhaps a window should be popped up in the same place as the
 * last such window was popped--perhaps with a bit of random variation to
 * prevent them all from piling up.
 * 
 * @author lamport
 */
class DataDisplay implements Runnable {
    private final int m_columnNumber;
    private final ResultPage m_resultPage;
    private final String m_graphTitle;

	/**
	 * The constructor returns an object with null data and times arrays if there
	 * are not at least two data points.
	 * 
	 * @param ssInfo
	 * @param columnNumber
	 */
	public DataDisplay(final int columnNumber, final ResultPage resultPage) {
		m_columnNumber = columnNumber;
		m_resultPage = resultPage;
		
		final StateSpaceLabelProvider sslp
			= (StateSpaceLabelProvider)resultPage.getStateSpaceTableViewer().getLabelProvider();
		m_graphTitle = ((columnNumber == StateSpaceLabelProvider.COL_TIME) ? "Number of Progress Reports"
																		   : sslp.getColumnTitle(columnNumber))
				+ " " + ResultPage.getGraphTitleSuffix(resultPage);
	}

	/**
	 * Much of the stuff in this run() method was copied, without much understanding
	 * from Snippet245.java in the Eclipse examples.
	 */
	public void run() {
		/*
		 * The data and times arrays are set to contain the data items to be displayed
		 * and the elapsed time (in milliseconds) at which each item was posted. The
		 * data is obtained from the appropriate column of the ssInfo items. For the
		 * Time column, the number of reports is graphed.
		 */

		// We check if a shell exists with this title, and use it if
		// it does. Otherwise, we get a new shell.
		final Display display = UIHelper.getCurrentDisplay();
		boolean shellExists = false;
		Shell theShell = null;
		for (final Shell shell : display.getShells()) {
			if (shell.getText().equals(m_graphTitle)) {
				theShell = shell;
				shellExists = true;
				break;
			}
		}
		if (!shellExists) {
			theShell = new Shell(display, SWT.SHELL_TRIM);
		}
		
		final Shell shell = theShell;
		shell.setText(m_graphTitle);
		shell.setActive(); // should cause it to pop up to the top.
		if (shellExists) {
			shell.redraw();
			shell.update();
		} else {
			shell.addPaintListener(new PaintListener() {
				public void paintControl(PaintEvent event) {
					final StateSpaceInformationItem[] ssInfo = m_resultPage.getStateSpaceInformation();
					if (ssInfo.length < 2) {
						return;
					}

					final long[] data = new long[ssInfo.length + 1];
					final long[] times = new long[ssInfo.length + 1];
					data[0] = 0;
					times[0] = 0;

					long startTime = m_resultPage.getStartTimestamp();
					TLCUIActivator.getDefault().logDebug(
							"first reported time - starttime = " + (ssInfo[0].getTime().getTime() - startTime));
					if (startTime > ssInfo[0].getTime().getTime() - 1000) {
						startTime = ssInfo[0].getTime().getTime() - 1000;
					}
					for (int i = 1; i < data.length; i++) {
						switch (m_columnNumber) {
							case StateSpaceLabelProvider.COL_TIME:
								data[i] = i - 1;
								break;
							case StateSpaceLabelProvider.COL_DIAMETER:
								data[i] = ssInfo[i - 1].getDiameter();
								break;
							case StateSpaceLabelProvider.COL_FOUND:
								data[i] = ssInfo[i - 1].getFoundStates();
								break;
							case StateSpaceLabelProvider.COL_DISTINCT:
								data[i] = ssInfo[i - 1].getDistinctStates();
								break;
							case StateSpaceLabelProvider.COL_LEFT:
								data[i] = ssInfo[i - 1].getLeftStates();
								break;
							default:
								return;
						}
						times[i] = ssInfo[i - 1].getTime().getTime() - startTime;
					}

					final Rectangle rect = shell.getClientArea();
					// Set maxData to the largest data value;
					long maxData = 0;
					for (int i = 0; i < data.length; i++) {
						if (data[i] > maxData) {
							maxData = data[i];
						}
					}
					
					final long maxTime = times[times.length - 1];
					// event.gc.drawOval(0, 0, rect.width - 1, rect.height - 1);
					if (maxTime > 0) {
						final double maxTimeD = (double) maxTime;
						// In case maxData equals 0, we use 1 instead for computing
						// the coordinates of the points.
						// (Added by LL on 6 July 2011 to fix division by zero bug.)
						final double maxDataVal = (maxData == 0) ? 1 : maxData;
						final double width = (double) (rect.width - 6);
						final double height = (double) (rect.height - 6);
						final int[] pointArray = new int[2 * data.length];
						for (int i = 0; i < data.length; i++) {
							final double tFraction = (double) times[i] / maxTimeD;
							final double dFraction = (double) data[i] / maxDataVal;

							pointArray[2 * i] = (int) (tFraction * width) + 2;
							pointArray[(2 * i) + 1] = rect.height - (int) (dFraction * height) + 2;
						}
						event.gc.drawPolyline(pointArray);
					}
					String stringTime = "Time: ";
					long unreportedTime = maxTime;
					final long days = TimeUnit.MILLISECONDS.toDays(maxTime);
					if (days > 0) {
						unreportedTime = unreportedTime - TimeUnit.DAYS.toMillis(days);
						stringTime = stringTime + days + ((days == 1) ? (" day ") : (" days  "));

					}
					final long hours = TimeUnit.MILLISECONDS.toHours(unreportedTime);
					if (hours > 0) {
						unreportedTime = unreportedTime - TimeUnit.HOURS.toMillis(hours);
						stringTime = stringTime + hours + ((hours == 1) ? (" hour ") : (" hours  "));
					}
					unreportedTime = (unreportedTime + (1000 * 26)) / (1000 * 60);
					stringTime = stringTime + unreportedTime + ((unreportedTime == 1) ? (" minute ") : (" minutes  "));
					event.gc.drawString(stringTime, 0, 0);
					event.gc.drawString("Current: " + data[data.length - 1], 0, 15);
					if (maxData != data[data.length - 1]) {
						event.gc.drawString("Maximum: " + maxData, 0, 30);
					}
				}
			});
		}
		
		if (!shellExists) {
			shell.setBounds(100 + 30 * m_columnNumber, 100 + 30 * m_columnNumber, 400, 300);
		}
		
		shell.open();
		// The following code from the Eclipse example was eliminated.
		// It seems to cause the shell to survive after the Toolbox is
		// killed.
		//
		// while (!shell.isDisposed()) {
		// if (!display.readAndDispatch()) display.sleep();
		// }
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/PCalTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.junit.Before;

import util.TLAConstants;
import util.ToolIO;

public abstract class PCalTest {
	
	@Before
	public void setup() {
		// Make tool capture the output written to ToolIO.out. Otherwise,
		// ToolIO#getAllMessages returns an empty array.
		ToolIO.setMode(ToolIO.TOOL);
		
		// Reset ToolIO for each test case. Otherwise, a test case sees the output of
		// the previous tests.
		ToolIO.reset();
	}

	protected static String writeFile(String filename, String content) throws IOException {
		final Path path = Files.createFile(Paths.get(filename + TLAConstants.Files.TLA_EXTENSION));
		Files.write(path, content.getBytes());
		
		final File file = path.toFile();
		file.deleteOnExit();
		return file.getAbsolutePath();
	}
	
	protected static String writeTempFile(String filename, String content) throws IOException {
		final Path path = Files.createTempFile(filename, TLAConstants.Files.TLA_EXTENSION);
		Files.write(path, content.getBytes());
		
		final File file = path.toFile();
		file.deleteOnExit();
		return file.getAbsolutePath();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/GraphNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:37 PST by lamport
//      modified on Mon Nov 26 15:46:11 PST 2001 by yuanyu

package tlc2.tool.liveness;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import tlc2.util.BitVector;
import tlc2.util.BufferedRandomAccessFile;

public class GraphNode extends AbstractGraphNode {
	/**
	 * The record size indicates the number of integers used by each transition
	 * in the array of nnodes (2x32bit to keep the fp and 32bit to keep the tableau
	 * idx).
	 */
	private static final int NNODE_RECORD_SIZE = 3;
	/**
	 * GraphNode is a node in the behaviour graph. We're going to only store
	 * fingerprints of states, rather than actual states. So, as we encounter
	 * each state, we need to calculate all the <>[] and []<>'s listed in the
	 * order of solution. For each outgoing edge, we record the fingerprint of
	 * the target node and the checkActions along it.
	 *
	 * The field tidx is the unique index for the tableau graph node. If tindex
	 * = -1, then there is no tableau. So, the maximum size of tableau is 2^31.
	 */
	private final static int[] emptyIntArr = new int[0];

	final long stateFP; // fingerprint of the state
	/**
	 * Next nodes are the successor {@link GraphNode}s of the current
	 * {@link GraphNode}
	 */
	private int[] nnodes; // outgoing links
	final int tindex;

	public GraphNode(long fp, int tindex) {
		this(fp, tindex, emptyIntArr, new BitVector(0));
	}

	private GraphNode(long fp, int tindex, int[] nnodes, BitVector checks) {
		super(checks);
		this.stateFP = fp;
		this.tindex = tindex;
		this.nnodes = nnodes;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (stateFP ^ (stateFP >>> 32));
		result = prime * result + tindex;
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		GraphNode other = (GraphNode) obj;
		if (stateFP != other.stateFP) {
			return false;
		}
		if (tindex != other.tindex) {
			return false;
		}
		return true;
	}

	public final long getStateFP(int i) {
		long high = this.nnodes[NNODE_RECORD_SIZE * i];
		long low = this.nnodes[NNODE_RECORD_SIZE * i + 1];
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	public final int getTidx(int i) {
		return this.nnodes[NNODE_RECORD_SIZE * i + 2];
	}

	public final int succSize() {
		// offset being != NO_FREE_SLOTS indicates that the nnodes array has been
		// overallocated in preparation to batch-insert transitions but the
		// transitions have not been added yet. In this case the nnodes.length /
		// NNODE_RECORD_SIZE is *not* the actual number of transitions, offset / NNODE_RECORD_SIZE is!
		if (this.offset != NO_FREE_SLOTS) {
			return this.offset / NNODE_RECORD_SIZE;
		}
		return this.nnodes.length / NNODE_RECORD_SIZE;
	}

	/**
	 * Points to the first available slot in {@link GraphNode#nnodes} iff free
	 * slots are available. "NO_FREE_SLOTS" indicates no free slots are available.
	 * 
	 * @see GraphNode#allocate(int)
	 */
	private int offset = NO_FREE_SLOTS;

	private static final int NO_FREE_SLOTS = -1;
	
	/**
	 * Allocates memory for subsequent
	 * {@link GraphNode#addTransition(long, int, int, int, boolean[])} calls.
	 * This is useful if
	 * {@link GraphNode#addTransition(long, int, int, int, boolean[])} gets
	 * invoked from within a loop when the approximate number of invocations is
	 * known in advance. In this case {@link GraphNode} can reserve the memory
	 * for the number of transitions in advance which greatly improves the
	 * insertion time of
	 * {@link GraphNode#addTransition(long, int, int, int, boolean[])}. Once all
	 * transitions have been added to via
	 * {@link GraphNode#addTransition(long, int, int, int, boolean[])},
	 * optionally call the {@link GraphNode#realign()} method to discard of
	 * unused memory.
	 * <p>
	 * Technically this essentially grows GraphNode's internal data structure.
	 * <p>
	 * Do note that you can call addTransition <em>without</em> calling allocate
	 * first. It then automatically allocates a memory for a <em>single</em>
	 * transition.
	 * 
	 * @param transitions
	 *            The approximate number of transitions that will be added
	 *            subsequently.
	 * 
	 * @see GraphNode#addTransition(long, int, int, int, boolean[])
	 * @see GraphNode#realign()
	 */
	private final void allocate(final int transitions) {
		final int len = this.nnodes.length;
		int[] newNodes = new int[len + (NNODE_RECORD_SIZE * transitions)];
		System.arraycopy(this.nnodes, 0, newNodes, 0, len);
		this.nnodes = newNodes;

		this.offset = len;
	}

	/**
	 * Add a new transition to the node target.
	 * 
	 * @param fp
	 *            fingerprint to add
	 * @param tidx
	 *            tableau index to add
	 * @param slen
	 *            number of solutions
	 * @param alen
	 *            number of actions
	 * @param acts
	 *            A {@link BitVector} of action results. Each bit in the vector
	 *            represents the result of the corresponding action (true or
	 *            false) returned by
	 *            tlc2.tool.liveness.OrderOfSolution.checkAction(TLCState,
	 *            TLCState, BitVector, int). <code>null</code> if no action 
	 *            constraints to check.
	 * @param actsOffset
	 *            The offset into the {@link BitVector} acts. acts may hold
	 *            action results for more than just the currently added
	 *            transition. In this case, provide an zero-based offset for
	 *            where the action results in BitVector start. 0 if the given
	 *            {@link BitVector} is exclusively used for the current
	 *            transition.
	 * @param allocationHint
	 *            A (Naturals \ {0}) hint telling the method's implementation
	 *            how many memory to allocate for subsequent transition
	 *            additions (used when called from within for loop). Zero or
	 *            negative hints are ignored (negative hints are the result of
	 *            nested for loop where the 1. iteration produces a bad average
	 *            of how many additions are made across all iterations).
	 * @see GraphNode#allocate(int)
	 */
	public final void addTransition(long fp, int tidx, int slen, int alen, final BitVector acts, final int actsOffset,
			final int allocationHint) {
		// Grows BitVector "checks" and sets the corresponding field to true if
		// acts is true (false is default and thus can be ignored).
		if (acts != null) {
			int pos = slen + alen * this.succSize();
			for (int i = 0; i < alen; i++) {
				if (acts.get(actsOffset + i)) {
					this.checks.set(pos + i);
				}
			}
		}
		if (this.offset == NO_FREE_SLOTS) {
			// Have to create a new slot regardless of 0 or negative hint, thus
			// Math.max...
			this.allocate(Math.max(allocationHint, 1));
		}
		this.nnodes[this.offset] = (int) (fp >>> 32);
		this.nnodes[this.offset + 1] = (int) (fp & 0xFFFFFFFFL);
		this.nnodes[this.offset + 2] = tidx;
		this.offset = this.offset + NNODE_RECORD_SIZE;
		if (this.offset == this.nnodes.length) {
			this.offset = NO_FREE_SLOTS;
		}
	}

	/**
	 * Trims {@link GraphNode}'s internal data structure to its current real
	 * memory requirement.
	 * 
	 * @return The number of over allocated memory or zero if memory allocated
	 *         by corresponding allocate call has been used up completely.
	 * 
	 * @see GraphNode#allocate(int)
	 */
	public int realign() {
		int result = 0;
		// It is a noop iff offset == NO_FREE_SLOTS
		if (this.offset != NO_FREE_SLOTS) {
			result = (this.nnodes.length - this.offset) / NNODE_RECORD_SIZE;
			// shrink newNodes to correct size
			int[] newNodes = new int[this.offset];
			System.arraycopy(this.nnodes, 0, newNodes, 0, newNodes.length);
			this.nnodes = newNodes;
			this.offset = NO_FREE_SLOTS;
		}
		return result;
	}

	/* Return true iff there is an outgoing edge to target. */
	public final boolean transExists(long fp, int tidx) {
		// TODO Switch to a more efficient transExists implementation to handle
		// large numbers of transitions. The current implementation below uses a
		// linear search over all transitions.
		// The fact that the given fp is used as an index for hash-based lookup
		// methods in various places of TLC, makes it the obvious candidate as a
		// improved strategy. One behavioral difference a hash has, is that the
		// sequential iteration of all nnodes produces a different (yet stable)
		// order.
		int len = this.nnodes.length;
		// Stop linear search on internal nnodes buffer when a free slot has
		// been
		// reached. The free slot detection work with the allocation offset that
		// points to the end of the filled slots (slots are filled in ascending
		// order). If offset is marked invalid ("NO_FREE_SLOTS"), the nnodes buffer is
		// completely occupied and has to be searched to the end.
		if (this.offset != NO_FREE_SLOTS) {
			len = offset;
		}
		int high = (int) (fp >>> 32);
		int low = (int) (fp & 0xFFFFFFFFL);
		for (int i = 0; i < len; i += NNODE_RECORD_SIZE) {
			if (this.nnodes[i] == high && this.nnodes[i + 1] == low && this.nnodes[i + 2] == tidx) {
				return true;
			}
		}
		return false;
	}

	public boolean checkInvariants(final int slen, final int alen) {
		final Set<Transition> transitions = new HashSet<Transition>();
		for (int i = 0; i < succSize(); i++) {
			final Transition t = new Transition(getStateFP(i), getTidx(i), getCheckAction(slen, alen, i));
			transitions.add(t);
		}
		return transitions.size() == succSize();
	}
	
	public Set<Transition> getTransition() {
		return getTransition(0, 0);
	}
	
	public Set<Transition> getTransition(final int slen, final int alen) {
		final Set<Transition> transitions = new HashSet<Transition>();
		for (int i = 0; i < succSize(); i++) {
			final BitVector bv = new BitVector(alen);
			for (int j = 0; j < alen; j++) {
				if (getCheckAction(slen, alen, i, j)) {
					bv.set(j);
				}
			}
			transitions.add(new Transition(getStateFP(i), getTidx(i), bv));
		}
		return transitions;
	}
	
	public static class Transition {

		private final long fp;
		private final int tidx;
		private final BitVector bv;

		public Transition(long fp, int tidx, BitVector bv) {
			this.fp = fp;
			this.tidx = tidx;
			this.bv = bv;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((bv == null) ? 0 : bv.hashCode());
			result = prime * result + (int) (fp ^ (fp >>> 32));
			result = prime * result + tidx;
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Transition other = (Transition) obj;
			if (bv == null) {
				if (other.bv != null)
					return false;
			} else if (!bv.equals(other.bv))
				return false;
			if (fp != other.fp)
				return false;
			if (tidx != other.tidx)
				return false;
			return true;
		}
		
		public BitVector getChecks() {
			return bv;
		}

		public long getFP() {
			return fp;
		}
		
		public int getTidx() {
			return tidx;
		}
	}

	/* Return the tableau graph node used by this. */
	public final TBGraphNode getTNode(TBGraph tableau) {
		return tableau.getNode(this.tindex);
	}

	/**
	 * Writes this {@link GraphNode} into the given
	 * {@link BufferedRandomAccessFile}
	 * 
	 * @param nodeRAF
	 * @throws IOException
	 */
	void write(final BufferedRandomAccessFile nodeRAF) throws IOException {
		assert offset == NO_FREE_SLOTS; // assert that nnodes hasn't been overallocated.
		// Write nnodes
		final int cnt = nnodes.length;
		nodeRAF.writeNat(cnt);
		for (int i = 0; i < cnt; i++) {
			nodeRAF.writeInt(nnodes[i]);
		}
		// Write checks
		checks.write(nodeRAF);
	}

	void read(final BufferedRandomAccessFile nodeRAF) throws IOException {
		// Read nnodes
		final int cnt = nodeRAF.readNat();
		nnodes = new int[cnt];
		for (int i = 0; i < cnt; i++) {
			nnodes[i] = nodeRAF.readInt();
		}
		// Read checks
		checks = new BitVector();
		checks.read(nodeRAF);
		
		assert offset == NO_FREE_SLOTS;
	}

	public final String toString() {
		// A GraphNode does not know the action length. This is kept elsewhere in the code.
		return toString(0).replace("[] ", "");
	}

	public final String toString(final int alen) {
		StringBuffer buf = new StringBuffer();
		buf.append("<" + this.stateFP + "," + this.tindex + "> --> ");
		for (int i = 0; i < succSize(); i++) {
			// action checks
			buf.append("[");
			for (int j = 0; j < alen; j++) {
				if (getCheckAction(0, 2, i, j)) {
					buf.append("t");
				} else {
					buf.append("f");
				}
			}
			buf.append("] ");
			// fingerprint/tableau id
			buf.append("<" + getStateFP(i) + "," + getTidx(i) + ">");
			buf.append(", ");
		}
		return buf.substring(0, buf.length() - ", ".length()); // chop off dangling ", "
	}

	public String toDotViz(final boolean isInitState, final boolean hasTableau, final int slen, final int alen) {
		return toDotViz(isInitState, hasTableau, slen, alen, null);
	}

	public String toDotViz(final boolean isInitState, final boolean hasTableau, final int slen, final int alen, TableauNodePtrTable filter) {
		// The node's id including its tidx if any. It uses the complete
		// fingerprint.
		String id = Long.toString(this.stateFP);
		if (hasTableau) {
			id += "." + this.tindex;
		}
			
		// Nodes label and a marker if it is an init state. The label is
		// shortened to 8 chars max to avoid screen clutter. It's possible
		// that the resulting graph will have multiple nodes with an identical
		// label iff the first 6 (+2) chars of their fingerprint match. However
		// the graph will still contain all nodes regardless of the label
		// collision due to id.
		String label = Long.toString(this.stateFP).substring(0, 6) + (hasTableau ? "." + this.tindex : "");
		if (slen > 0) {
			label += "\n";
			for (int i = 0; i < slen; i++) {
				if (getCheckState(i)) {
					label += "t";
				} else {
					label += "f";
				}
			}
		}
		final StringBuffer buf = new StringBuffer();
		if (isInitState) {
			buf.append("\"" + id + "\" [style = filled][label = \"" + label + "\"]\n"); // node's label
		} else {
			buf.append("\"" + id + "\" [label = \"" + label + "\"]\n");
		}
		
		// Each outgoing transition
		for (int i = 0; i < succSize(); i++) {
			final long stateFP = getStateFP(i);
			final int tidx = getTidx(i);
			
			// If a filter is given, check if this node is in filter
			if (filter != null && filter.get(stateFP, tidx) == -1) {
				continue;
			}
			
			String fp = Long.toString(stateFP);
//			if (fp == this.stateFP) {
//				// skip self loops if edge count to large for dotViz to handle.
//				continue;
//			}
			
			buf.append("\"" + id + "\" -> ");
			if (hasTableau) {
				buf.append(("\"" + fp) + "." + tidx + "\"");
			} else {
				//Omit tableau index when it's -1 (indicating no tableau)
				buf.append(("\"" + fp) + "\"");
			}
			
			buf.append(" [label=\"");
			for (int j = 0; j < alen; j++) {
				if (getCheckAction(slen, alen, i, j)) {
					buf.append("t");
				} else {
					buf.append("f");
				}
			}
			buf.append("\"];");
			buf.append("\n");
		}
		return buf.toString();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/output/SpecTraceExpressionWriterTest.java<|end_filename|>
package tlc2.output;

import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import tla2sany.drivers.FrontEndException;
import tla2sany.drivers.SANY;
import tla2sany.modanalyzer.SpecObj;
import tlc2.model.Formula;
import tlc2.model.MCState;
import tlc2.model.TraceExpressionInformationHolder;
import util.TLAConstants;
import util.TestPrintStream;

/**
 * The genesis for these tests is regressions that were introduced by beautification changes made as part of #393.
 * 
 * As future spec-generation methods are touched, something implementing them should be added below.
 */
public class SpecTraceExpressionWriterTest {
	static private final String TRIVIAL_TWO_STATE_DEADLOCK_PREAMBLE
			= "VARIABLE x, y\n"
					+ "XIncr == (x' = x * 2)\n"
					+ "            /\\ (x < 8)\n"
					+ "            /\\ UNCHANGED y\n"
					+ "YIncr == (y' = x + y)\n"
					+ "            /\\ (y < 15)\n"
					+ "            /\\ UNCHANGED x\n";
	static private final String[] TRIVIAL_TWO_STATE_DEADLOCK_INIT
			= new String[] {
					"TestInit",
					"TestInit == x \\in 1 .. 10 /\\ y \\in 1 .. 10\n"
				};
	static private final String[] TRIVIAL_TWO_STATE_DEADLOCK_NEXT
			= new String[] {
					"TestNext",
					"TestNext == YIncr \\/ XIncr\n"
				};
	static private final String ERROR_STATE_IP
			= "1: <Initial predicate>\n"
					+ "/\\ x = 8\n"
					+ "/\\ y = 7\n";
	static private final String ERROR_STATE_1
			= "2: <YIncr line 8, col 10 to line 10, col 26 of module Bla>\n"
					+ "/\\ x = 8\n"
					+"/\\ y = 15\n";

	
	private SpecTraceExpressionWriter writer;
	private File tlaFile;
	private File cfgFile;
	
	@Before
	public void setUp() throws IOException {
		tlaFile = File.createTempFile("sptewt_", ".tla");
		tlaFile.deleteOnExit();
		cfgFile = File.createTempFile("sptewt_", ".cfg");
		cfgFile.deleteOnExit();
		
		final String tlaFilename = tlaFile.getName();
		final int baseNameLength = tlaFilename.length() - TLAConstants.Files.TLA_EXTENSION.length();
		final String specName = tlaFilename.substring(0, baseNameLength);
		writer = new SpecTraceExpressionWriter();
		writer.addPrimer(specName, "Naturals");
		writer.appendContentToBuffers(TRIVIAL_TWO_STATE_DEADLOCK_PREAMBLE, null);
	}
	
	private void concludeTest() throws FrontEndException, IOException {
		writer.writeFiles(tlaFile, cfgFile);
		
		final SpecObj so = new SpecObj(tlaFile.getAbsolutePath(), null);
		final TestPrintStream printStream = new TestPrintStream();
		
		final int result = SANY.frontEndMain(so, tlaFile.getAbsolutePath(), printStream);
		if (result != 0) {
			throw new FrontEndException("Parsing returned a non-zero success code (" + result + ")");
		}
	}
	
	private List<MCState> generateStatesForDeadlockCondition() { 
		final List<MCState> states = new ArrayList<>();
		
		states.add(MCState.parseState(ERROR_STATE_IP));
		states.add(MCState.parseState(ERROR_STATE_1));

		return states;
	}
	
	@Test
	public void testInitNextWithNoError() throws Exception {
		writer.addInitNextDefinitions(TRIVIAL_TWO_STATE_DEADLOCK_INIT, TRIVIAL_TWO_STATE_DEADLOCK_NEXT,
									  "writerTestInit", "writerTextNext");

		concludeTest();
	}
	
	@Test
	public void testInitNextWithError() throws Exception {
		final List<MCState> trace = generateStatesForDeadlockCondition();
		final StringBuilder tempCFGBuffer = new StringBuilder();
		final StringBuilder[] tlaBuffers
				= SpecTraceExpressionWriter.addInitNextToBuffers(tempCFGBuffer, trace, null, "STEWInit", "STEWNext",
						 										 "STEWAC", TRIVIAL_TWO_STATE_DEADLOCK_NEXT[0], true);
		
		writer.appendContentToBuffers(tlaBuffers[0].toString(), tempCFGBuffer.toString());
		writer.addTraceFunction(trace);
		writer.appendContentToBuffers(tlaBuffers[1].toString(), null);
		
		concludeTest();
	}
	
	@Test
	public void testInitNextWithErrorAndTraceExpression() throws Exception {
		final List<MCState> trace = generateStatesForDeadlockCondition();
		writer.addTraceFunction(trace);

		final List<Formula> expressions = new ArrayList<>();
		expressions.add(new Formula("ENABLED XIncr"));
		expressions.add(new Formula("y # 7"));
		final TraceExpressionInformationHolder[] traceExpressions
						= writer.createAndAddVariablesAndDefinitions(expressions, "writerTestTraceExpressions");
		writer.addInitNext(trace, traceExpressions, "STEWInit", "STEWNext", "STEWAC", TRIVIAL_TWO_STATE_DEADLOCK_NEXT[0]);
		
		concludeTest();
	}

	
	@Test
	public void testMultilineTraceExpression() throws Exception {
		final List<MCState> trace = generateStatesForDeadlockCondition();
		writer.addTraceFunction(trace);

		final List<Formula> expressions = new ArrayList<>();
		expressions.add(new Formula("\n"
				+ "/\\ y # 7\n"
				+ "/\\ \\/ TRUE\n"
				+ " \\* Comment"
				+ "   \\/ FALSE"));
		// Named expression
		final Formula e = new Formula("namedExpression == \n"
				+ "  (* A commend \n over two lines*)"
				+ "  /\\ \\/ TRUE\n"
				+ " \\* Comment"
				+ "     \\/ FALSE");
		assertTrue(e.isNamed());
		expressions.add(e);
		final TraceExpressionInformationHolder[] traceExpressions
						= writer.createAndAddVariablesAndDefinitions(expressions, "writerTestTraceExpressions");
		writer.addInitNext(trace, traceExpressions, "STEWInit", "STEWNext", "STEWAC", TRIVIAL_TWO_STATE_DEADLOCK_NEXT[0]);
		
		concludeTest();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/callable/CheckInvariantCallable.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp.callable;

import java.io.IOException;
import java.util.concurrent.Callable;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.distributed.fp.FPSetRMI;

public class CheckInvariantCallable implements Callable<Boolean> {
	private final FPSetRMI fpSetRMI;
	
	public CheckInvariantCallable(FPSetRMI fpSetRMI) {
		this.fpSetRMI = fpSetRMI;
	}

	/* (non-Javadoc)
	 * @see java.util.concurrent.Callable#call()
	 */
	public Boolean call() throws Exception {
		try {
			return fpSetRMI.checkInvariant();
		} catch (IOException e) {
			// not expected to happen.
			MP.printError(EC.GENERAL, e);
			// return max value to indicate to caller that the result is
			// incorrect.
			return false;
		}
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/contribution/SizeControlContribution.java<|end_filename|>
package org.lamport.tla.toolbox.ui.contribution;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.ToolboxDirectoryVisitor;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;

public class SizeControlContribution extends WorkbenchWindowControlContribution implements IResourceChangeListener
{
    // the element
    private Composite composite;
    // label to display status
    private Label sizeLabel;

    /**
     * 
     */
    public SizeControlContribution()
    {
        // We have no idea what this string does.
        // The corresponding one for ParseStatusContributionItem
        // does not appear elsewhere in the code.
        super("specDirectorySize");
        
		// Register a listener to find any changed .toobox directories of specs.
		// E.g. when the model checker is running for a long time, the size
		// should be shown eventually.
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
		
		// Register for Spec events like open, close, delete... to change
		// visibility of composite accordingly.
		Activator.getSpecManager().addSpecLifecycleParticipant(new SpecLifecycleParticipant() {
			/* (non-Javadoc)
			 * @see org.lamport.tla.toolbox.tool.SpecLifecycleParticipant#eventOccured(org.lamport.tla.toolbox.tool.SpecEvent)
			 */
			public boolean eventOccured(final SpecEvent event) {
				if (event.getType() == SpecEvent.TYPE_CLOSE || event.getType() == SpecEvent.TYPE_DELETE) {
					// SpecEvents don't give a guarantee that they are fired
					// from inside the UI thread.
					UIHelper.runUISync(new Runnable() {
						public void run() {
							composite.setVisible(false);
						}
					});
					return false;
				} else if (event.getType() == SpecEvent.TYPE_OPEN || event.getType() == SpecEvent.TYPE_OPEN) {
					final Job job = new ToolboxJob("Calculating spec size...") {
						protected IStatus run(IProgressMonitor monitor) {
							// TO-DO: If this is the currently opened spec,
							// change display of that spec's size.
							final Spec spec = event.getSpec();
							final long specSize = ResourceHelper
									.getSizeOfJavaFileResource(event.getSpec().getProject());
							spec.setSize(specSize);
							updateSize(specSize);
							return Status.OK_STATUS;
						}
					};
					job.schedule();
				}
				return true;
			}
		});
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.action.ControlContribution#createControl(org.eclipse.swt.widgets.Composite)
     */
    protected Control createControl(Composite parent)
    {
        // If the composite is good just return it.
        if (composite != null && !composite.isDisposed())
        {
            return composite;
        }

        // Create a composite to place the label in
        composite = new Composite(parent, SWT.NONE);
        // composite.setData(this);

        // Give some room around the control
        FillLayout layout = new FillLayout();
        layout.marginHeight = 2;
        layout.marginWidth = 20;
        composite.setLayout(layout);

        // label informing the user that this reflects the parse status of the spec
        Label description = new Label(composite, SWT.NONE);
        description.setText("Storage:");
        description.setSize(50, 20);
        // description.setBackground(description.getDisplay().getSystemColor(SWT.COLOR_YELLOW));

        // Create label inside composite.
        sizeLabel = new Label(composite, SWT.BORDER | SWT.CENTER);
        sizeLabel.setText("n/a");
		sizeLabel
				.setToolTipText("Size of .toolbox directory. If this appears large and the TLC"
						+ " model checker is *not* running, try removing TLC's volatile data "
						+ "like state/ subdirectories of the model directory.");
        sizeLabel.setSize(100, 20);
        sizeLabel.setBackground(description.getDisplay().getSystemColor(SWT.COLOR_YELLOW));
        composite.setVisible(false);
        return composite;
    }

    // Updates status from the specification currently loaded in the SpecManager
	private void updateSize(final long size) {
		if (sizeLabel == null || sizeLabel.isDisposed()) {
			return;
		}
		UIHelper.runUIAsync(new Runnable() {
			public void run() {
				if (!composite.isDisposed()) {
					composite.setVisible(false);
				}

				if (!sizeLabel.isDisposed() && !composite.isDisposed()) {
					// Si!
					if (size / (1000 * 1000 * 1000) > 0) {
						sizeLabel.setText(Long.toString(size / (1000 * 1000 * 1000) ) + " gB");
					} else if (size / (1000 * 1000) > 0) {
						sizeLabel.setText(Long.toString(size / (1000 * 1000)) + " mB");
					} else if (size / 1000 > 0) {
						sizeLabel.setText(Long.toString(size / 1000) + " kB");
					} else {
						sizeLabel.setText(Long.toString(size) + " bytes");
					}

					// Make invisible if less than the
					// I_MIN_DISPLAYED_SIZE preference.
					// Size calculated is in bytes, preference in kilobytes.
					if ((size / 1000L) < Activator.getDefault().getPreferenceStore()
							.getInt(IPreferenceConstants.I_MIN_DISPLAYED_SIZE)) {
						composite.setVisible(false);
						return;
					}
					sizeLabel.redraw();
					composite.setVisible(true);
				}
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
	 */
	public void resourceChanged(final IResourceChangeEvent event) {
		final IResourceDelta delta = event.getDelta();
		if (delta != null) {
			try {
				// We cannot get the spec manager if it has not been
				// instantiated because this would trigger a resource change
				// event, and this code is being called within a resourceChanged
				// method. Such an infinite loop is not allowed.
				if (Activator.isSpecManagerInstantiated()) {
					// delta.accept calls the visit method of the
					// visitor on the delta.
					final ToolboxDirectoryVisitor toolboxDirectoryFinder = new ToolboxDirectoryVisitor();
					delta.accept(toolboxDirectoryFinder);
					final List<IProject> directories = toolboxDirectoryFinder.getDirectories();
					// Set resource to the IResource representing a
					// project for a spec. This resource is embodied in
					// the file system as the spec's .toolbox director.
					for (Iterator<IProject> it = directories.iterator(); it.hasNext();) {
						final IProject resource = it.next();
						final long specSize = ResourceHelper.getSizeOfJavaFileResource(resource);

						// TO-DO: If this is the currently opened spec,
						// change display of that spec's size.
						final Spec curSpec = ToolboxHandle.getCurrentSpec();
						if (curSpec != null) {
							curSpec.setSize(specSize);
							if (curSpec.getProject().equals(resource)) {
								updateSize(specSize);
							}
						}
					}
				}
			} catch (CoreException e) {
				Activator.getDefault().logError("Error during post save status update", e);
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/management/DiskFPSetMXWrapper.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp.management;

import java.io.IOException;

import javax.management.NotCompliantMBeanException;

import tlc2.tool.fp.FPSetStatistic;
import tlc2.tool.management.TLCStandardMBean;

//TODO dispose when underlying diskfpset is nulled (otherwise we end up holding a reference and diskfpset is never gced) 
public class DiskFPSetMXWrapper extends TLCStandardMBean implements DiskFPSetMXBean {

	private static int COUNT = 0;
	
	protected final FPSetStatistic fpset;

	private final String objectName;
	
	public DiskFPSetMXWrapper(final FPSetStatistic diskFPSet) throws NotCompliantMBeanException {
		super(DiskFPSetMXBean.class);
		fpset = diskFPSet;
		
		// Append ",name=COUNT" suffix to objectname to expose all DiskFPSet instances
		// as children of type DiskFPSet. However, jfr2jmx does not support it, nor does
		// jmx2munin used by cloud based distributed TLC.
		objectName = "DiskFPSet" + COUNT++;
		registerMBean("tlc2.tool.fp:type=" + objectName/* + ",name=" + COUNT++*/);
	}
	
	public String getObjectName() {
		return objectName;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getTblCnt()
	 */
	public long getTblCnt() {
		return fpset.getTblCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getFileCnt()
	 */
	public long getFileCnt() {
		return fpset.getFileCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getIndexCnt()
	 */
	public long getIndexCnt() {
		return fpset.getIndexCapacity();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getDiskLookupCnt()
	 */
	public long getDiskLookupCnt() {
		return fpset.getDiskLookupCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getMemHitCnt()
	 */
	public long getMemHitCnt() {
		return fpset.getMemHitCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getDiskHitCnt()
	 */
	public long getDiskHitCnt() {
		return fpset.getDiskHitCnt();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getDiskWriteCnt()
	 */
	public long getDiskWriteCnt() {
		return fpset.getDiskWriteCnt();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getDiskSeekCnt()
	 */
	public long getDiskSeekCnt() {
		return fpset.getDiskSeekCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getDiskSeekCache()
	 */
	public long getDiskSeekCache() {
		return fpset.getDiskSeekCache();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getDiskSeekRate()
	 */
	public double getDiskSeekRate() {
		final long diskSeekCnt = getDiskSeekCnt();
		final long diskSeekCache = getDiskSeekCache();
		return diskSeekCache / (double) (diskSeekCache + diskSeekCnt);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getCheckPointMark()
	 */
	public int getGrowDiskMark() {
		return fpset.getGrowDiskMark();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetSamplerMXBean#getCheckPointMark()
	 */
	public int getCheckPointMark() {
		return fpset.getCheckPointMark();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getBucketCapacity()
	 */
	public long getBucketCapacity() {
		return fpset.getBucketCapacity();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getTblCapacity()
	 */
	public long getTblCapacity() {
		return fpset.getTblCapacity();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getOverallCapacity()
	 */
	public long getOverallCapacity() {
		return fpset.getOverallCapacity();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getTblLoad()
	 */
	public long getTblLoad() {
		return fpset.getTblLoad();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#sizeof()
	 */
	public long getSizeOf() {
		return fpset.sizeof();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getFlushTime()
	 */
	public long getFlushTime() {
		return fpset.getFlushTime();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getReaderWriterCnt()
	 */
	public int getReaderWriterCnt() {
		return fpset.getReaderWriterCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getLoadFactor()
	 */
	public double getLoadFactor() {
		return fpset.getLoadFactor();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#forceFlush()
	 */
	public void forceFlush() {
		fpset.forceFlush();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#checkInvariant()
	 */
	public boolean checkInvariant() throws IOException {
		return fpset.checkInvariant();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.management.DiskFPSetMXBean#getLockCnt()
	 */
	public int getLockCnt() {
		return fpset.getLockCnt();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/SimpleFilenameToStream.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Sat 28 June 2008 at  0:23:49 PST by lamport

package util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;


/**
 * Defines a translation from names to NamedInputStream's that will be
 * used by most tools whose input comes from files.
 * @author simonzam <NAME>, <NAME>
 * @version $Id$
 */
//SZ Feb 20, 2009: moved to util and fixed bugs

// If a file ``matching'' the module name is found then an instance of
// a stream - NamedInputStream is returned.

// This code contains a special detector trace for the presence of a
// newline in a string. This was a problem with earlier versions of java on PCs.


public class SimpleFilenameToStream implements FilenameToStream {

	public static final String TLA_LIBRARY = "TLA-Library";

	public static final String STANDARD_MODULES_FOLDER = "StandardModules";

	private static final ClassLoader cl = SimpleFilenameToStream.class.getClassLoader();

	private static final String STANDARD_MODULES = "tla2sany"
			+ '/' + STANDARD_MODULES_FOLDER + '/';

  /**
   * path of directories to be searched in order for the named file.  The setting of
   * a module's isStandard field depends on the path to the standard modules directory
   * being the last element of this array.
   */
  private String[] libraryPaths;
  private final Path tmpDir = FilenameToStream.getTempDirectory();

  public SimpleFilenameToStream() {
	  libraryPaths = getLibraryPaths(getInstallationBasePath(), null);
  }

  public SimpleFilenameToStream(final String libraryPath) {
	  this(new String[] {libraryPath});
  }
  
/**
 * August 2014 - TL
 * This constructor was on the interface but was not implemented.
 * Now one can pass additional libraries which will be added to the
 * installation path and instead the path supplied using the system property TLA_LIBRARY
 * (which is being used in the default constructor).
 */
  public SimpleFilenameToStream(String[] anLibraryPaths) {
	  libraryPaths = getLibraryPaths(getInstallationBasePath(), anLibraryPaths);
  }

  // Find the absolute path in the file system to the directory
  // that is the base of the entire installation of tlaSANY; this path
  // must have separators appropriate to the Unix ('/') or Windows ('\') world.

  private String getInstallationBasePath() {

    // get a "file:" URL for the base directory for package tla2sany
    final URL         url = cl.getResource("tla2sany");

    // jar expanded to the fs (make sure to handle whitespaces correctly
    final String path = url.toString();
	try {
    	// convert to URI which handles paths correctly (even OS dependently)
    	if(!FilenameToStream.isInJar(path)) {
    	final URI uri = new URI(path);
    		return new File(uri).getAbsolutePath();
    	}
    } catch (URISyntaxException e) {
    	System.err.println(path);
    	// may never happen
    	e.printStackTrace();
    } catch (IllegalArgumentException e) {
    	System.err.println(path);
    	// may never happen
    	e.printStackTrace();
    }
    return path;
   }

  /**
   * August 2014 - TL
   * added an informative method for returning the actual path used by this resolver
   */
  public String getFullPath() {
    StringBuffer buf = new StringBuffer();
    String[] ar = libraryPaths;
    for (int i=0; i<ar.length; i++)
    {
      buf.append(ar[i]);
      if (i <ar.length-1) {
        buf.append(", ");
      }
    }
    return buf.toString();
  }

  /**
   * August 2014 - TL
   * added functionality for supplying additional libraries.
   * All usage of this except the one added by TL is supplying libraries  = null
   */
  private String[] getLibraryPaths(final String installationBasePath, String[] libraries) {
    String[] res;
    String path = null;
    if (libraries == null) path = System.getProperty(TLA_LIBRARY);
    else {
      StringBuffer buf = new StringBuffer();
      for (int i=0; i<libraries.length; i++) {
        buf.append(libraries[i]);
        if (i < libraries.length-1) {
          buf.append(FileUtil.pathSeparator);
        }
      }
      path = buf.toString();
    }
    if (path == null) {
      res = new String[1];
      res[0] = installationBasePath + FileUtil.separator + STANDARD_MODULES_FOLDER + FileUtil.separator;
    }
    else {
      String[] paths = path.split(FileUtil.pathSeparator);
      res = new String[paths.length+1];
      for(int i=0;i<paths.length;i++){
	res[i] = paths[i];
	if (!res[i].endsWith(FileUtil.separator)){
	  res[i] = res[i] + FileUtil.separator;
	}
      }
      res[paths.length] = installationBasePath + FileUtil.separator + STANDARD_MODULES_FOLDER + FileUtil.separator;
    }
    return res;
  }

  /**
   *  From name, prepend path elements to try to find the actual
   *  file intended, and use the resulting fully-qualified name to initialize
   *  the File.  The first fully-qualified name that refers to a file that actually
   *  exists is the File returned; but if none exists, the last one tried is returned
   *  anyway.  Hence, the File object returned does not necessarily represent a file
   *  that actually exists in the file system.
   *
   *  @param  module name, used as basis of path name to the file that should contain it
   */
  private final File locate(String name)
  {

    String prefix      = "";                // directory to be prepended to file name before lookup

    File   sourceFile  = null;              // File object from fully-qualified name of file found by
                                            //   searching "libraryPath" for "name", as is done for PATHs and CLASSPATHs

    // The TLA standard modules are presumed to be in a directory tla2sany/StandardModules
    // i.e. a toplevel subdirectory of the main installation directory for SANY
    // We append the StandardModules director to the library path, so the user does
    // not have to do anything special and the standard modules are automatically accessible

    // Debug
    /*
    System.err.println("Installation base path = " + installationBasePath);
    for (int i=0;i<libraryPaths.length;i++)
    {
        System.err.println("libraryPaths = '" + libraryPaths[i] + "'");
    }
    */

    // This code ALWAYS looks in the current directory first for a file (and its capitalization
    // variants), regardless of what the TLA-Library property says the search path should be.
    /***********************************************************************
    * This was modified by LL on 14 May 2008 to change the way sourceFile  *
    * is obtained from sourceFileName.  See the comments for the userDir   *
    * field in util/ToolIO.                                                *
    ***********************************************************************/
    int idx = 0;
    InputStream is;
    while (true)
    {
        if ((idx == 0) && (ToolIO.getUserDir() != null)) {
            sourceFile = new TLAFile(ToolIO.getUserDir(), name, this );
        }
        else
        {
        	// StandardModules contained in jar
        	// need to load files into temp location
        	// from the resource stream
        	//
        	// This would be a lot simpler if TLC would not depend on
        	// File but on InputStream instead
        	if(FilenameToStream.isInJar(prefix)) {
				is = cl.getResourceAsStream(STANDARD_MODULES + name);
				if(is != null) {
					sourceFile = read(name, cl.getResource(STANDARD_MODULES + name), is);
				}
        	} else {
        		sourceFile = new TLAFile( prefix + name, true, this );
        	}
        }
        // Debug
        // System.out.println("Looking for file " + sourceFile);
        if ( sourceFile.exists() )  break;
        if (idx >= libraryPaths.length) {
			// As a last resort, try to load resource from the Java classpath. Give up, if it
			// fails.
			// The use case for this strategy is to load additional TLA+ module collections
			// - e.g. community-driven ones - which ship a single jar containing the .tla
			// operator definitions as well as Java module overwrites as .class files.
        	is = cl.getResourceAsStream(name);
        	if(is != null) {
				return read(name, cl.getResource(name), is);
			} else {
				break;
			}
        }
        prefix = libraryPaths[idx++];
    } // end while

    return sourceFile;

  } // end locate()

  private File read(String name, URL location, InputStream is) {
    final File sourceFile = new TLAFile(tmpDir.resolve(name), location, true, this);
	sourceFile.deleteOnExit();
	try {

		final FileOutputStream fos = new FileOutputStream(sourceFile);

		byte buf[] = new byte[1024];
		int len;
		while ((len = is.read(buf)) > 0) {
			fos.write(buf, 0, len);
		}
		fos.close();
		is.close();
	} catch (IOException e) {
		// must not happen
		e.printStackTrace();
	}
	return sourceFile;
  }

  /**
   * Returns a file
   * obtained by some standard method from the string name.  For example,
   * resolve("Foo") might equal the file "/udir/luser/current/path/Foo.tla".
   *
   * Returns null if the file does not exist
   */
  public File resolve(String name, boolean isModule)
  {
      // Strip off one NEWLINE and anything after it, if it is there
      int n;
      n = name.indexOf( '\n' );
      if ( n >= 0 ) {
          // SZ Feb 20, 2009: the message adjusted to what is actually done
          ToolIO.out.println("*** Warning: module name '" + name + "' contained NEWLINE; "
                  + "Only the part before NEWLINE is considered.");
          name = name.substring( 0, n );     // Strip off the newline
      }
      String sourceFileName = null;
      // SZ Feb 20, 2009:
      // if the name is a name of the module
      if (isModule)
      {
          // SZ Feb 20, 2009:
          // Make sure the file name ends with ".tla".
          if (name.toLowerCase().endsWith(TLAConstants.Files.TLA_EXTENSION))
          {
              name = name.substring(0, (name.length() - TLAConstants.Files.TLA_EXTENSION.length()));
          }
          sourceFileName = name + TLAConstants.Files.TLA_EXTENSION;
      } else
      {
          // SZ Feb 20, 2009: for other files
          // leave the name untouched
          sourceFileName = name;
      }
      // identify the library property
      // extract substrings with getProperty("path.separator");
      // repeat search for each substring until found.
      // locate() the file corresponding to the sourceFileName
      return locate(sourceFileName);
  }

	public File resolve(String name) {
		return resolve(name, false);
	}

	/**
	 * Returns true iff moduleName is the name of a standard module.  It
	 * assumes the empirically determined fact that libraryPaths is set to
	 * have the path of the standard modules as the last element of the array.
	 * This method is used to set the isStandard field of the module's ModuleNode.
	 * I don't know if this is every called with a module that
	 * Added by LL on 24 July 2013.
	 * @see tla2sany.modanalyzer.ParseUnit.isLibraryModule()
	 * @see StandardModules.isDefinedInStandardModule()
	 */
	public boolean isStandardModule(String moduleName) {
		 File file = this.resolve(moduleName, true) ;
		 if (file == null) {
			 return false ;
			 }
		 String path = file.getAbsolutePath() ;
		 if (path == null) {
			 return false ;
		 }
	     return path.startsWith(this.libraryPaths[this.libraryPaths.length - 1] ) ;
	}
} // end class


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/LongObjTable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:32 PST by lamport
//      modified on Mon Nov 26 15:41:48 PST 2001 by yuanyu

package tlc2.util;

public final class LongObjTable {
  private int count;
  private int length;
  private int thresh;
  private long[] keys;
  private Object[] elems;

  public LongObjTable(int size) {
    this.keys = new long[size];
    this.elems = new Object[size];
    this.count = 0;
    this.length = size;
    this.thresh = this.length / 2;
  }

  private final void grow() {
    long[] oldKeys = this.keys;
    Object[] oldElems = this.elems;
    this.count = 0;
    this.length = 2 * this.length + 1;
    this.thresh = this.length / 2;
    this.keys = new long[length];
    this.elems = new Object[length];
    for (int i = 0; i < oldKeys.length; i++) {
      Object elem = oldElems[i];
      if (elem != null) this.put(oldKeys[i], elem);
    }
  }

  public final int size() { return this.count; }

  public final int put(long k, Object elem) {
    if (count >= thresh) this.grow();
    int loc = ((int)k & 0x7FFFFFFF) % length ;
    while (true) {
      if (this.elems[loc] == null) {
	this.keys[loc] = k;
	this.elems[loc] = elem;
	this.count++;
	return loc;
      }
      else if (this.keys[loc] == k) {
	this.elems[loc] = elem;
	return loc;
      }
      loc = (loc + 1) % length;
    }
  }

  public final Object get(long k) {
    int loc = ((int)k & 0x7FFFFFFF) % length ;
    while (true) {
      Object elem = this.elems[loc];
      if (elem == null) return null;
      if (this.keys[loc] == k) return elem;
      loc = (loc + 1) % length;
    }
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/DiskGraph.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:36 PST by lamport
//      modified on Sat Dec 29 22:15:18 PST 2001 by yuanyu

package tlc2.tool.liveness;

import java.io.IOException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.util.LongVec;
import tlc2.util.MemIntQueue;
import tlc2.util.statistics.IBucketStatistics;

/**
 * A {@link DiskGraph} is an implementation of {@link AbstractDiskGraph}. It has
 * *not* tableau!
 * 
 * @see TableauDiskGraph for a version with tableau support.
 */
// TODO This implementation still (legacy) writes an int "-1" tableau id for
// each node. This should be removed! TODO markers are indicate the code
// positions that need changing.
public class DiskGraph extends AbstractDiskGraph {

	private NodePtrTable nodePtrTbl;
	
	public DiskGraph(String metadir, int soln, IBucketStatistics graphStats) throws IOException {
		super(metadir, soln, graphStats);
		nodePtrTbl = new NodePtrTable(255);
	}

	public final GraphNode getNode(long fp, int tidx) throws IOException {
		return getNode(fp);
	}
	
	/* Get the graph node. Return null if the node is not in this. */
	public final GraphNode getNode(long stateFP) throws IOException {
		long ptr = this.nodePtrTbl.get(stateFP);
		if (ptr < 0) {
			return  new GraphNode(stateFP, -1);
		}
		if (gnodes == null) {
			// No cache, get directly from disk.
			return this.getNodeFromDisk(stateFP, -1, ptr);
		}
		return this.getNode(stateFP, -1, ptr);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#getPtr(long, int)
	 */
	public final long getPtr(long fp, int tidx) {
		return getPtr(fp);
	}

	public final long getPtr(long fp) {
		return this.nodePtrTbl.get(fp);
	}

	public void reset() throws IOException {
		this.nodePtrRAF.reset();
		this.nodeRAF.reset();
		this.nodePtrTbl = new NodePtrTable(255);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#putNode(tlc2.tool.liveness.GraphNode, long)
	 */
	protected void putNode(GraphNode node, long ptr) {
		this.nodePtrTbl.put(node.stateFP, ptr);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#checkDuplicate(tlc2.tool.liveness.GraphNode)
	 */
	protected boolean checkDuplicate(final GraphNode node) {
		return this.nodePtrTbl.get(node.stateFP) != -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#getLink(long, int)
	 */
	public long getLink(long state, int tidx) {
		return this.nodePtrTbl.get(state);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#putLink(long, int, long)
	 */
	public long putLink(long state, int tidx, long link) {
		assert MAX_PTR <= link && link < MAX_LINK; 
		int loc = this.nodePtrTbl.getLoc(state);
		long oldLink = this.nodePtrTbl.getByLoc(loc);
		if (!isFilePointer(oldLink)) {
			return oldLink;
		}
		this.nodePtrTbl.putByLoc(state, link, loc);
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.DiskGraph#setMaxLink(long, int)
	 */
	public void setMaxLink(long state, int tidx) {
		this.nodePtrTbl.put(state, MAX_LINK);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.DiskGraph#makeNodePtrTbl(long)
	 */
	protected void makeNodePtrTbl(long ptr) throws IOException {
		this.nodePtrRAF.seek(0);
		while (this.nodePtrRAF.getFilePointer() < ptr) {
			long fp = this.nodePtrRAF.readLong();
			// skip the tableau idx that is not used by DiskGraph.
			this.nodePtrRAF.readInt();
			long loc = this.nodePtrRAF.readLongNat();
			this.nodePtrTbl.put(fp, loc);
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#size()
	 */
	public long size() {
		return this.nodePtrTbl.size();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public final String toString() {
		/*
		 * BEWARE THAT THIS ALTERS (populates) THE CACHE (this.gnodes)!!! 
		 */

		// The following code relies on gnodes not being null, thus safeguard
		// against accidental invocations.
		// Essentially one has to wrap the toString call with
		// createCache/destroyCache
		// for gnodes to be initialized.
		if (this.gnodes == null) {
			return "";
		}
		
		StringBuffer sb = new StringBuffer();
		try {
			long nodePtr = this.nodeRAF.getFilePointer();
			long nodePtrPtr = this.nodePtrRAF.getFilePointer();
			long len = this.nodePtrRAF.length();
			this.nodePtrRAF.seek(0);
			while (this.nodePtrRAF.getFilePointer() < len) {
				long fp = nodePtrRAF.readLong();
				int tidx = nodePtrRAF.readInt();
				long loc = nodePtrRAF.readLongNat();
				sb.append(fp + " -> ");
				GraphNode gnode = this.getNode(fp, tidx, loc);
				int sz = gnode.succSize();
				for (int i = 0; i < sz; i++) {
					sb.append(gnode.getStateFP(i) + " ");
				}
				sb.append("\n");
			}
			this.nodeRAF.seek(nodePtr);
			this.nodePtrRAF.seek(nodePtrPtr);
		} catch (IOException e) {
			MP.printError(EC.SYSTEM_DISKGRAPH_ACCESS, e);

			System.exit(1);
		}
		
		return sb.toString();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#toDotViz(tlc2.tool.liveness.OrderOfSolution)
	 */
	public final String toDotViz(final OrderOfSolution oos) {
		final int slen = oos.getCheckState().length;
		final int alen = oos.getCheckAction().length;
		// The following code relies on gnodes not being null, thus safeguard
		// against accidental invocations.
		// Essentially one has to wrap the toDotViz call with
		// createCache/destroyCache
		// for gnodes to be initialized.
		if (this.gnodes == null) {
			return "";
		}

		StringBuffer sb = new StringBuffer();
		try {
			sb.append("digraph DiskGraph {\n");
			sb.append("nodesep = 0.7\n");
			sb.append("rankdir=LR;\n"); // Left to right rather than top to bottom
			sb.append(toDotVizLegend(oos));
			sb.append("subgraph cluster_graph {\n"); 
	        sb.append("color=\"white\";\n"); // no border.
			long nodePtr = this.nodeRAF.getFilePointer();
			long nodePtrPtr = this.nodePtrRAF.getFilePointer();
			long len = this.nodePtrRAF.length();
			this.nodePtrRAF.seek(0);
			while (this.nodePtrRAF.getFilePointer() < len) {
				long fp = nodePtrRAF.readLong();
				int tidx = nodePtrRAF.readInt();
				long loc = nodePtrRAF.readLongNat();
				GraphNode gnode = this.getNode(fp, tidx, loc);
				sb.append(gnode.toDotViz(isInitState(gnode), false, slen, alen));
			}
			sb.append("}}");
			this.nodeRAF.seek(nodePtr);
			this.nodePtrRAF.seek(nodePtrPtr);
		} catch (IOException e) {
			MP.printError(EC.SYSTEM_DISKGRAPH_ACCESS, e);

			System.exit(1);
		}
		return sb.toString();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.AbstractDiskGraph#getPath(long, int)
	 */
	public final LongVec getPath(final long state, final int tidxIgnored) throws IOException {
		// If path requested just consists of an init node, return the single
		// init node. This is the trivial case.
		final int numOfInits = this.initNodes.size();
		for (int i = 0; i < numOfInits; i += 2) {
			final long state0 = this.initNodes.elementAt(i);
			if (state0 == state) {
				final LongVec res = new LongVec(1);
				res.addElement(state0);
				return res;
			}
		}
		// ...the path consists of more than just a single init node:

		// Restore the nodePtrTbl:
		this.makeNodePtrTbl();

		// Do breath-first search:
		final long offset = MAX_PTR + 1;
		final MemIntQueue queue = new MemIntQueue(this.metadir, null);

		// Initialize queue with initial states:
		for (int i = 0; i < numOfInits; i += 2) {
			final long state0 = this.initNodes.elementAt(i);
			long ptr = this.nodePtrTbl.get(state0);
			// Skip initial states without successors:
			// An initial state with a -1 (disk) pointer means that is has *no*
			// successors. Thus, it can safely be omitted from the path search
			// below. If the init state is the very state searched for, the
			// previous for loop will have caught it already.
			// Adding an init with negative pointer to the queue manifests in
			// an exception in the while loop below. This is because the
			// DiskGraph won't be able to return a GraphNode instance.
			if (ptr != -1) {
				queue.enqueueLong(state0);
				queue.enqueueLong(ptr);
				this.nodePtrTbl.put(state0, MAX_PTR);
			}
		}

		while (queue.hasElements()) {
			long curState = queue.dequeueLong();
			final long curPtr = queue.dequeueLong();
			final GraphNode curNode = this.getNode(curState, -1, curPtr);
			final int succCnt = curNode.succSize();

			for (int i = 0; i < succCnt; i++) {
				final long nextState = curNode.getStateFP(i);
				if (nextState == state) {
					// found a path to state: construct the path and return.
					final LongVec res = new LongVec(2);
					res.addElement(nextState);
					int curLoc = this.nodePtrTbl.getLoc(curState);
					while (true) {
						res.addElement(curState);
						final long ploc = this.nodePtrTbl.getByLoc(curLoc);
						// MAX_PTR indicates that this is an init state. Since
						// getPath is looking for the shortest path from the
						// given state back to *an* initial state, we are done.
						if (ploc == MAX_PTR) {
							break;
						}
						// Lookup the predecessor in the ptr table. (ploc -
						// offset) is the index of the predecessor in the
						// nodePtrTbl. See offset below at putByLoc(..).
						curLoc = (int) (ploc - offset);
						curState = this.nodePtrTbl.getKeyByLoc(curLoc);
					}
					return res;
				}
				final int nextLoc = this.nodePtrTbl.getLoc(nextState);
				if (nextLoc == -1) {
					// nextState is not on disk.
					//
					// Iff nextState itself is not on disk, its successor nodes
					// won't be either (or we don't know it's successors yet).
					// This scenario occurs when liveness checking is executed
					// on a *partial* graph only. The model checker has added
					// curState with nextState as its successor, nextState has
					// not been added yet though. Basically this is where the
					// partial graph has its border to the unknown.
					//
					// Continuing the for loop is fine. But we might as well add
					// nextState to the queue. Once it gets picked up by the outer
					// while loop, it will be skipped anyway as its succCnt is 0.
					//
					// If this case happens when LiveCheck is doing its
					// finalCheck (complete graph), it is most probably a bug.
					// Unfortunately, I don't know a proper assertion to check.
					continue;
				}
				final long nextPtr = this.nodePtrTbl.getByLoc(nextLoc);
				if (isFilePointer(nextPtr)) {
					// nextState is not visited:
					queue.enqueueLong(nextState);
					queue.enqueueLong(nextPtr);
					final int curLoc = this.nodePtrTbl.getLoc(curState);
					this.nodePtrTbl.putByLoc(nextState, offset + curLoc, nextLoc);
				}
			}
		}
		return super.getPath(state, tidxIgnored);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/gettingstarted/tla-preferences.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/gettingstarted/tla-preferences.html -->
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>TLA+ Preferences</title>
</head>
<!-- a comment -->

<body>
<h1>TLA+ Preferences</h1>

<p>There are three preferences that can be set on this page.</p>

<h3>Continue Previous Session on Restart</h3>

This option allows you to choose whether, when you close the Toolbox, it
resumes from where you were (the default) or opens the Welcome View.

<h3>Minimum spec storage displayed</h3>

<p>
The Toolbox keeps all the information about a specification name
<code>Spec</code>, other than its actual files, in a folder named
<code>Spec.toolbox</code>.&nbsp;

When that folder becomes sufficiently large, its size is
shown near the bottom right-hand corner of the Toolbox window.&nbsp;

This parameter specifies how large (in kilobytes) <em>sufficiently large</em>
is.&nbsp;

The default is 50 megabytes.
</p>

<p>
When the <code>.toolbox</code> folder becomes very large, it is probably
because it contains one or more checkpoints created by TLC.&nbsp;

The checkpoint is deleted if TLC completes successfully, but is saved
if TLC is stopped or finds an error.&nbsp;

A TLC execution that takes several days can create a checkpoint
with more than a gigabyte of data.&nbsp;

When a spec uses a lot of space, you should view the
<A href="../model/about-models.html">TLC models</A> you have created for it
to see if any have large checkpoints.&nbsp;

See <A href="../model/overview-page.html#checkpoint">Checkpoint
Recovery</A> to learn how you can find out how large a checkpoint
is and how you can delete a checkpoint.
</p>

<h3><a name="library-folders">Library Folders</a></h3>

This specifies a list of library folders that are for modules that may
be used in more than one specification.&nbsp;

When a specification imports a module (with an <code>EXTENDS</code> or
<code>INSTANCE</code> statement), the parser searches for that module
first in the root module's folder, then in the sequence of specified
library folders (in the order they appear in the list), then among the standard modules.&nbsp;

The list of library folders specified here can be overridden for a
particular spec with a different list in the spec's <a
href="../spec/opening-closing.html#spec-explorer"><em>Spec
Explorer</em> </a> entry.&nbsp;

<br/>

The growing effort of <a href="https://github.com/tlaplus/CommunityModules">Community Modules</a>
can be leveraged through this importing.

<hr>
<!-- delete rest of line to comment out
<dl>
<dt><b><font color=#0000c0>Topics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 -->
<!-- delete rest of line to comment out -->
<a href = "preferences.html">&uarr; Preferences</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/nature/TLAParsingBuilderConstants.java<|end_filename|>
package org.lamport.tla.toolbox.spec.nature;

import org.eclipse.core.runtime.QualifiedName;

/**
 * Constants for setting persistent properties on resources.
 * @author ricketts
 *
 */
public class TLAParsingBuilderConstants
{
    public static final QualifiedName LAST_BUILT = new QualifiedName(TLAParsingBuilder.BUILDER_ID, "LAST_BUILT");

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/Cache.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.util;

public interface Cache {
	/**
	 * Tests if the given fingerprint is in this cache, adding it as a side
	 * effect if not.
	 * 
	 * @param fingerprint
	 *            fingerprint to be tested
	 * @return true iff given fingerprint is in cache
	 */
	boolean hit(long fingerprint);
	/**
	 * @return Ratio of cache hits and misses
	 */
	double getHitRatio();
	/**
	 * @return A pretty printed version of {@link Cache#getHitRatio()}
	 */
	String getHitRatioAsString();
	/**
	 * @return Absolute value for cache hits
	 */
	long getHitRate();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/job/NewTLAModuleCreationOperation.java<|end_filename|>
package org.lamport.tla.toolbox.job;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * Creates a new TLA+ module
 * @author <NAME>
 * @version $Id$
 */
public class NewTLAModuleCreationOperation implements IWorkspaceRunnable
{
    private IPath modulePath;

    /**
     * @param name
     */
    public NewTLAModuleCreationOperation(IPath module)
    {
        this.modulePath = module;
    }

    /* (non-Javadoc)
     * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
     */
    public void run(IProgressMonitor monitor) throws CoreException
    {
        String moduleFileName = modulePath.lastSegment();

        byte[] content = ResourceHelper.getEmptyModuleContent(moduleFileName).append(ResourceHelper.getModuleClosingTag()).toString().getBytes();
        
        try
        {
        	// create parent folder unless pointing to root directory
        	if(modulePath.segmentCount() > 1) {
        		final IPath removeLastSegments = modulePath.removeLastSegments(1);
        		final File dir = new File(removeLastSegments.toOSString());
        		dir.mkdirs();
        	}
        	
            // create file
            File file = new File(modulePath.toOSString());
            if (file.createNewFile())
            {
                // successfully created
                // TODO 
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(content);
                fos.flush();
                fos.close();
            } else
            {
                throw new RuntimeException("Error creating a file");
            }
        } catch (IOException e)
        {
            throw new CoreException( new Status(Status.ERROR, Activator.PLUGIN_ID, "Error creating TLA+ file", e));
        }
        
    }

    /**
     * Job factory
     * @param module
     * @return
     */
    public static WorkspaceJob NEW_JOB(final IPath module)
    {
        return new WorkspaceJob("Creating TLA+ file")
        {
            NewTLAModuleCreationOperation op = new NewTLAModuleCreationOperation(module);

            public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException
            {
                op.run(monitor);
                return Status.OK_STATUS;
            }
        };
        
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ToolboxDirectoryVisitor.java<|end_filename|>

package org.lamport.tla.toolbox;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;

/**
 * Visitor for finding changed .toolbox directories.
 * 
 * @author lamport
 *
 */
public class ToolboxDirectoryVisitor implements IResourceDeltaVisitor
{
    List<IProject> iprojects = new LinkedList<IProject>();
    
    /**
     * 
     */
//    public ToolboxDirectoryVisitor()
//    {
//        // TODO Auto-generated constructor stub
//    }

    /** 
     * The visit method gets a resource and returns true or false depending on
     * whether or not it wants to be called with the children of the resource.
     * In this case, we return true unless the resource is a project representing
     * a spec (and thus whose resource is stored as a File (in this case a directory)
     * with extension toolbox.
     * 
     * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
     */
    public boolean visit(IResourceDelta delta) throws CoreException
    {
        IResource resource = delta.getResource(); 
        if ((resource instanceof IProject) ) {
            iprojects.add((IProject) resource);
            return false;
        }
        return true;
    }
    
    public List<IProject> getDirectories() {
        return iprojects;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/OSelement.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;

final class OSelement {
  Operator op;
  SyntaxTreeNode  node;
  int kind;

  OSelement( SyntaxTreeNode n ) { node = n; op = null; }
  OSelement( SyntaxTreeNode n, Operator o ) { node = n; op = o; }

  final Operator getOperator() { return op; }
  final SyntaxTreeNode  getNode() { return node; }
  final boolean  isOperator() { return op != null; }
}

<|start_filename|>general/bugzilla/css/buglist.css<|end_filename|>
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This Source Code Form is "Incompatible With Secondary Licenses", as
 * defined by the Mozilla Public License, v. 2.0.
 */
.bz_query_head {
  text-align: center;
}

.bz_query_timestamp {
  font-weight: bold;
}

.search_description {
  margin: .5em 0;
  padding: 0;
}
.search_description li {
  list-style-type: none;
  display: inline;
  margin-right: 2em;
}

.zero_results, .zero_result_links {
  font-size: 120%;
  font-weight: bold;
}

.bz_buglist_header th {
  text-align: left;
}

.bz_sort_order_primary,
.bz_sort_order_secondary {
    display: inline-block;
    padding-left: .2em;
    text-decoration: none;
}
.bz_sort_order_primary   { color: black; }
.bz_sort_order_secondary { color: #777;  }


.bz_id_column {
}

.bz_row_odd {
    background-color: #F7F7F7;
    color: #000000;
}

.bz_row_even {
    background-color: #FFFFFF;
    color: #000000;
}

/* Style bug rows according to severity. */
.bz_blocker { color: red; font-weight: bold; }
.bz_critical { color: red; }
.bz_enhancement { color: #666; background-color: white; }

/* Align columns in the "change multiple bugs" form to the right. */
table#form tr th { text-align: right; }

table.bz_buglist td, table.bz_buglist th { 
}

/* we use a first-child class and not the pseudo-class because IE
 * doesn't support it :-( */
tr.bz_secure td.first-child, a.bz_secure { 
  background-image: url("../../images/padlock.png");
  background-position: center left;
  background-repeat: no-repeat;
  background-color: inherit;
}

th.first-child, td.first-child, a.bz_secure {
  padding-left: 20px;
}

tr.bz_secure_mode_implied td.first-child {
}

tr.bz_secure_mode_manual td.first-child {
}

td.bz_estimated_time_column,
td.bz_remaining_time_column,
td.bz_actual_time_column,
td.bz_percentage_complete_column {
    text-align: right;
}

td.bz_total_label {
    font-weight: bold;
}

td.bz_total {
    border-top-style: solid;
    border-top-color: #929bb1;
    border-top-width: 3px;
    text-align: right;
}

#commit, #action {
  margin-top: .25em;
}

.bz_query_debug {
    text-align: left;
}

.bz_short_desc_column a, .bz_short_short_desc_column a {
    color: inherit;
}

/* The "filtering" table is specific to request.cgi.
 * Same for the "requests" class used for tables. */

#filtering #requester, #filtering #requestee {
    min-width: 8em;
}

#filtering th {
    text-align: right;
}

table.requests th {
    text-align: left;
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/UserModuleOverrideFromJarTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import tlc2.output.EC;
import tlc2.tool.liveness.ModelCheckerTestCase;

@RunWith(BlockJUnit4ClassRunner.class)
public class UserModuleOverrideFromJarTest extends ModelCheckerTestCase {

	public UserModuleOverrideFromJarTest() {
		// This test only works when executed from customBuild.xml because it requires an extra classpath setting.
		super("UserModuleOverrideBase");
	}
	
	@Test
	public void testSpec() {
		final List<String[]> mismatches = recorder.getRecordAsStringArray(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE_MISMATCH);
		assertEquals(2, mismatches.size());
		Collections.sort(mismatches, new Comparator<String[]>() {
			@Override
			public int compare(String[] o1, String[] o2) {
				return o1[0].compareTo(o2[0]);
			}
		});
		
		// arity mismatch
		String[] strs = mismatches.get(0);
		assertEquals("Get2", strs[0]);
		assertTrue(strs[1].endsWith("UserModuleOverrideFromJar.class")); // This contains a system dependent path.
		assertEquals("<Java Method: public static tlc2.value.impl.Value UserModuleOverrideFromJar.Get2(tlc2.value.impl.Value)>", strs[2]);
		
		// name mismatch (no such operator)
		strs = mismatches.get(1);
		assertEquals("Get3", strs[0]);
		assertTrue(strs[1].endsWith("UserModuleOverrideFromJar.class"));
		assertEquals("<Java Method: public static tlc2.value.impl.Value UserModuleOverrideFromJar.Get3()>", strs[2]);

		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "2", "1", "0"));
		assertFalse(recorder.recorded(EC.GENERAL));

		assertZeroUncovered();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/ErrorMessage.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

import java.util.List;

public class ErrorMessage {

	private final String message;
	private final String key;
	private final String modelEditorPageId;
	private final List<String> sections;
	private final String viewerId;

	public ErrorMessage(final String message, final String key, final String modelEditorPageId,
			final List<String> sections, final String viewerId) {
		this.message = message;
		this.key = key;
		this.modelEditorPageId = modelEditorPageId;
		this.sections = sections;
		this.viewerId = viewerId;
	}

	public List<String> getSections() {
		return sections;
	}

	public String getModelEditorPageId() {
		return modelEditorPageId;
	}

	public String getViewerId() {
		return viewerId;
	}

	public String getKey() {
		return key;
	}

	public String getMessage() {
		return message;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/handler/StandalonePDFViewerRunnable.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox.tool.tla2tex.handler;

import org.eclipse.core.resources.IResource;
import org.eclipse.ui.IWorkbenchPartSite;
import org.lamport.tla.toolbox.ui.view.PDFBrowser;
import org.lamport.tla.toolbox.util.UIHelper;

public class StandalonePDFViewerRunnable extends AbstractPDFViewerRunnable {

	public StandalonePDFViewerRunnable(ProducePDFHandler handler, IWorkbenchPartSite site, IResource aSpecFile) {
		super(handler, site, aSpecFile);
	}

	public void run() {
        monitor.subTask("Opening PDF File");
        
        // Can't use OS specific outputFileName as secondy id. On Windows, it 
        // contains illegal characters. Thus, use the portableString which 
        // fully identifies a module in a spec and only consists out of legal
        // chars.
        final String secondary = this.specFile.getFullPath().toPortableString();
		part = (PDFBrowser) UIHelper.openViewNoFocus(PDFBrowser.ID, secondary);
		((PDFBrowser) part).setInput(this.specFile.getName(), outputFileName);

        monitor.worked(1);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tla2tex.handler.AbstractPDFViewerRunnable#preUpdate()
	 */
	@Override
	protected void preUpdate() {
		((PDFBrowser) part).setBlank();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalCharReader.java<|end_filename|>
/***************************************************************************
* CLASS PcalCharReader                                                     *
*                                                                          *
* A PcalCharReader is an input stream that can be read one character at a  *
* time.  The class's constructor produces such a stream from a vector of   *
* strings and starting and ending positions within the vector.  The        *
* reader expands tabs into spaces.  A PcalCharReader object has the        *
* following public methods.                                                *
*                                                                          *
* char getNextChar()    : Returns the next input character, or '\t' if     *
*                         there is none.                                   *
*                                                                          *
* int getLineNumber()   : Returns the line number of the next char to be   *
*                         returned by getNextChar().                       *
*                                                                          *
* int getColumnNumber() : Returns the column number of the next char to    *
*                         be returned by getNextChar().                    *
*                                                                          *
* backspace() :                                                            *
*    Backspaces the stream by one character.  Does not work right          *
*    if this backspaces over a tab character.                              *
*                                                                          *
* String peek() ;                                                          *
*    Moves the input stream to the next non-space character, then          *
*    returns the string from that character to the end of the line         *
*    including the "\n".  (It leaves the input stream at that              *
*    non-space character.)  It returns "\t" if it comes to the             *
*    end of the input stream.                                              *
*                                                                          *
* Lines and columns are numbered starting from 0.                          *
***************************************************************************/
package pcal;
import java.util.Vector;

class PcalCharReader 
  { /***********************************************************************
    * The variables representing the state of the object.                  *
    ***********************************************************************/
    private Vector vec ;
      /*********************************************************************
      * This is the vector providing the input characters.                 *
      *********************************************************************/

    private String currentLine = null ;
      /*********************************************************************
      * The current line of input, or null if at the end of the input.     *
      *********************************************************************/

    protected int line  = 0;                
    private int column  = 0;                
    private int vcolumn = 0;
      /*********************************************************************
      * The line and column numbers of the next character to be returned   *
      * by getNextChar, where column is the actual position of the next    *
      * character in the input stream, and vcolumn is what the column      *
      * number would be if tabs had been "expanded".  When columm =        *
      * length of currentLine, the next character to be returned is '\n'.  *
      *                                                                    *
      * In Java fashion, these are numbered starting at 0.                 *
      *********************************************************************/

    private int lastLine   = 0 ;
    private int lastColumn = 0 ;
      /*********************************************************************
      * These values marks the position in the input vector immediately    *
      * following the last character in the input stream.                  *
      *********************************************************************/

    private boolean tabToSpaces = false ;
      /*********************************************************************
      * Equals true when a tab has been encountered in the input stream,   *
      * and the next getNextChar should return a space generated from      *
      * that tab.                                                          *
      *********************************************************************/

    /***********************************************************************
    * The methods.                                                         *
    ***********************************************************************/
    public int getLineNumber() 
      /*********************************************************************
      * Returns the line number of the next character to be returned by    *
      * getNextChar.  Following Java conventions, the first line is        *
      * numbered 0.                                                        *
      *********************************************************************/
      { return line ; } ;

    public int getColumnNumber() 
      /*********************************************************************
      * Returns the virtual column number of the next character to be      *
      * returned by getNextChar.  Following Java conventions, the first    *
      * column is numbered 0.                                              *
      *********************************************************************/
      { return vcolumn ; } ;

    public char getNextChar()
      /*********************************************************************
      * Returns the next character in the input stream and updates the     *
      * line and column numbers.  However, it replaces each '\t' (tab) in  *
      * the input stream with the appropriate number of spaces (assuming   *
      * the standard "tab stops").  If the current column is after the     *
      * last character on the current line, then it returns '\n'.  If the  *
      * end of the input has been reached, then it returns '\t'.  Note     *
      * that, for a nonempty input stream, the call preceding the one      *
      * that returns '\t' must return '\n'.  For an empty input stream,    *
      * the first call returns '\t'.                                       *
      *********************************************************************/
      { /*******************************************************************
        * If currentLine is null, then we must have reached the end of the *
        * input.                                                           *
        *******************************************************************/
        if (currentLine == null) { return '\t' ;} ;
  
        /*******************************************************************
        * If we are converting a tab to spaces, return a space.            *
        *******************************************************************/
        if (tabToSpaces)
          { vcolumn = vcolumn + 1;
            if ((vcolumn % 8) == 0) {tabToSpaces = false;};
            return ' ';
          }

       /********************************************************************
       * If the current position equals the final position, return '\t'.   *
       ********************************************************************/
       if (    (line > lastLine) 
            || ( (line == lastLine) && (column >= lastColumn) ) )
         { return '\t' ; }

        /*******************************************************************
        * If the current column is at the end of the current line, then    *
        * return '\n' after updating the line and column and reading in    *
        * the next line.                                                   *
        *********************************************************************/
        if (currentLine.length() == column) 
          { line        = line + 1 ;
            column      = 0 ;
            vcolumn     = 0 ;
            if (line >= vec.size())
                 {currentLine = null ;}
            else {currentLine = (String) vec.elementAt(line) ;} ;
            return '\n' ;
           } ;
  
        /*******************************************************************
        * We are not at the end of the input or of the line and are not    *
        * converting a tab to space.  Update column and vcolumn, and       *
        * return the next character.                                       *
        *******************************************************************/
        char readChar = currentLine.charAt(column) ;
        column = column + 1;
        vcolumn = vcolumn + 1;
        if (readChar == '\t')
          { if ((vcolumn % 8) != 0) {tabToSpaces = true;} ;
            return ' ';
          }
        return readChar ;
      } ;

    public void backspace()
      /*********************************************************************
      * Backspaces the output stream.  That is, a sequence of n            *
      * backspaces without a getNextChar makes the next getNextChar        *
      * return the character returned by the n-th preceding getNextChar.   *
      * line.                                                              *
      *                                                                    *
      * Incorrect results will occur if backspacing over a tab character.  *
      * (This could be corrected, but it's not needed, and getting it      *
      * right is tricky.)                                                  *
      *                                                                    *
      * This method allows backspacing beyond the logical beginning        *
      * of the reader, as specified by the firstLine and firstCol          *
      * arguments to the constructor.                                      *
      *********************************************************************/
      { if (column == 0)
         { if (line == 0)
             { PcalDebug.ReportBug(
                  "PcalCharReader.backspace trying to " +
                  "move past beginning of reader");
             } ;
           line = line - 1 ;
           currentLine = (String) vec.elementAt(line) ;
           column = 0 ;
           vcolumn = 0 ;

           /****************************************************************
           * Need to move forward from the first character of the line in  *
           * case there are tabs.                                          *
           ****************************************************************/
           while (column < currentLine.length() - 1)
             { char c = getNextChar() ; }
         }
        else
         { column = column - 1;
           vcolumn = vcolumn - 1;
         }
      } ;

    public String peek()
      /***************************************************************
      * Moves the input stream to the next non-space character,      *
      * then returns the string from that character to the end of    *
      * the line including the "\n".  (It leaves the input stream    *
      * at that non-space character.)  It returns "\t" if it comes   *
      * to the end of the input stream.                              *
      ***************************************************************/
      { 
// System.out.println("Peek called at line = " + line + ", col = " + column);
        char next = getNextChar() ;
        while (   (next == ' ')
               || (next == '\n'))
           { next = getNextChar() ;} ;
        if (next == '\t')
          { return "\t" ;} ;
        backspace() ;
// System.out.println("Peek returns `" +  currentLine.substring(column) + "' at line = " + line + ", col = " + column);
        return currentLine.substring(column) + "\n" ;
      }
      
    public PcalCharReader(Vector vector, int firstLine, int firstCol,
                            int lastLine, int lastCol) 
      /*********************************************************************
      * The class constructor.  The only tricky part is setting vcolumn    *
      * to account for tabs on the same line but before the starting       *
      * point.                                                             *
      *********************************************************************/
      { this.vec         = vector ;
        this.line        = firstLine ;
        this.column      = firstCol ;
        this.lastLine    = lastLine ;
        this.lastColumn  = lastCol ;
        /*******************************************************************
        * Compute the initial value of vcolumn.                            *
        *******************************************************************/
        if (firstLine < vector.size())
          { int i = 0 ;
            String ln = (String) vector.elementAt(firstLine) ;
            while (i < firstCol)
             { if (ln.charAt(i) == '\t')
                 { this.vcolumn = ((this.vcolumn / 8) + 1) * 8 ;}
               else {this.vcolumn = this.vcolumn + 1 ; } ;
               i = i + 1;
             }
          } ;

        /*******************************************************************
        * Set currentLine.                                                 *
        *******************************************************************/
        if (firstLine < vector.size())
          { this.currentLine = (String) vector.elementAt(firstLine) ; } ;
      } ;
  }     


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/StackElement.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;

class StackElement {
  int Kind;
  int Offset;

  StackElement( int o, int k) { Kind = k; Offset = o; }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/BigInt.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Random;


public class BigInt extends BigInteger implements Cloneable, ExternalSortable {

  public final static BigInt BigZero = new BigInt("0");
  public final static BigInt BigOne = new BigInt("1");
  public final static BigInt BigTwo = new BigInt("2");

  public BigInt(String val) { super(val); }
  
  public BigInt(byte[] val) { super(val); }

  public BigInt(int numBits, Random rnd) { super(numBits, rnd); }

  /* Returns the fingerprint of this. */
  public final long fingerPrint() {
    return FP64.New(this.toByteArray());
  }

  /**
    * Returns true iff x is a BigInt whose value is equal to this.value.
    * This method is provided so that BigInts can be used as hash keys.
    */
  public final boolean equals(Object x) {
    return ((x instanceof BigInt) && super.equals(x));
  }

  public final void write(OutputStream out) throws IOException {
    ByteUtils.writeSizeBigInt(out, this);
  }
    
  public final BigInt read(InputStream in) throws IOException {
    return ByteUtils.readSizeBigInt(in);
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/html/constant_dialog.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
	<title>Constant Spec Dialog</title>
</head>

<body>
<h1>The Heading of Constant Spec Dialog</h1>
Please enter your text here. this is ...tlc.ui/html/constant_dialog.html
</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/tool/fp/LongArrayBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import java.io.IOException;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

@State(Scope.Benchmark)
public class LongArrayBenchmark {
	private LongArray array;

    @Setup
    public void up() throws IOException {
        final long elements = 1L << 10;
		array = new LongArray(elements);
		array.zeroMemory(1);
		for (long i = 0L; i < elements; i++) {
			array.set(i, Long.MAX_VALUE - i);
		}
    }
    
    @Benchmark
    public void AswapWithCopy() {
    	array.swapCopy(0, array.size() - 1);
    }
    
	@Benchmark
	public void BswapGetSet() {
    	array.swap(0, array.size() - 1);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/ValueConstants.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:21:10 PST by lamport
//      modified on Tue Aug 15 16:45:14 PDT 2000 by yuanyu

package tlc2.value;

public interface ValueConstants {

  /* Type code for values. */
  byte BOOLVALUE        = 0;
  byte INTVALUE         = BOOLVALUE + 1;
  byte REALVALUE        = INTVALUE + 1;
  byte STRINGVALUE      = REALVALUE + 1;
  byte RECORDVALUE      = STRINGVALUE + 1;
  byte SETENUMVALUE     = RECORDVALUE + 1;
  byte SETPREDVALUE     = SETENUMVALUE + 1;
  byte TUPLEVALUE       = SETPREDVALUE + 1;
  byte FCNLAMBDAVALUE   = TUPLEVALUE + 1;
  byte FCNRCDVALUE      = FCNLAMBDAVALUE + 1;
  byte OPLAMBDAVALUE    = FCNRCDVALUE + 1;
  byte OPRCDVALUE       = OPLAMBDAVALUE + 1;
  byte METHODVALUE      = OPRCDVALUE + 1;
  byte SETOFFCNSVALUE   = METHODVALUE + 1;
  byte SETOFRCDSVALUE   = SETOFFCNSVALUE + 1;
  byte SETOFTUPLESVALUE = SETOFRCDSVALUE + 1;
  byte SUBSETVALUE      = SETOFTUPLESVALUE + 1;
  byte SETDIFFVALUE     = SUBSETVALUE + 1;
  byte SETCAPVALUE      = SETDIFFVALUE + 1;
  byte SETCUPVALUE      = SETCAPVALUE + 1;
  byte UNIONVALUE       = SETCUPVALUE + 1;
  byte MODELVALUE       = UNIONVALUE + 1;
  byte USERVALUE        = MODELVALUE + 1;
  byte INTERVALVALUE    = USERVALUE + 1;
  byte UNDEFVALUE       = INTERVALVALUE + 1;
  byte LAZYVALUE        = UNDEFVALUE + 1;
  byte DUMMYVALUE       = LAZYVALUE + 1;

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/UseOrHideNode.java<|end_filename|>
// Copyright (c) 2007 Microsoft Corporation.  All rights reserved.
// last modified on Fri  3 July 2009 at 12:41:45 PST by lamport
package tla2sany.semantic;

import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.xml.SymbolContext;
import util.UniqueString;

/***************************************************************************
* This class represents a USE or HIDE statement.  It is of kind            *
* UseKind or HideKind.                                                     *
***************************************************************************/
public class UseOrHideNode extends LevelNode {

  /*************************************************************************
  * The fields.                                                            *
  *                                                                        *
  * A use or hide has the syntax USE/HIDE [facts] [DEF[S] defs].  The      *
  * following two fields are the semantic nodes for the facts and defs.    *
  *************************************************************************/
  public LevelNode[]  facts = null ;
    /***********************************************************************
    * For each i, facts[i] will be either an ExprNode, a ModuleNode, or    *
    * an OpDefNode of type ModuleInstanceKind (with no parameters).  A     *
    * proof management tool will probably put restrictions on the class    *
    * of expressions that can be used as facts.                            *
    *                                                                      *
    * 4 Mar 2009: implemented a restriction that arbitrary expressions     *
    * can't be used as facts.  The only allowable expressions are the      *
    * names of theorems, assumptions, and steps.                           *
    ***********************************************************************/
  public SymbolNode[] defs  = null ;
    /***********************************************************************
    * For each i, defs[i] should be a UserDefinedOpDefKind or              *
    * ModuleInstanceKind OpDefNode or a ThmOrAssumpDefNode                 *
    ***********************************************************************/

  public boolean isOnly ;
    /***********************************************************************
    * True iff this node was formed from an "ONLY" step.  This is          *
    * possible only if the node is of kind UseKind or if it was            *
    * temporarily constructed for making a LeafProofNode for a "BY ONLY"   *
    * proof.  However, the "ONLY BY" construct might be disabled.          *
    ***********************************************************************/

  /**
   * If the UseOrHideNode is a proof step, this is the step number.  It
   * is made a UniqueString for consistency; there's no need to make
   * comparison efficient.
   * Added by LL on 6 June 2010.
   */
  private UniqueString stepName = null;

    public void setStepName(UniqueString stepName)
    {
        this.stepName = stepName;
    }

    /**
     * @return the stepName
     */
    public UniqueString getStepName()
    {
        return stepName;
    }
  /*************************************************************************
  * The constructor.                                                       *
  *************************************************************************/
  public UseOrHideNode(int kind, TreeNode stn, LevelNode[] theFacts,
                   SymbolNode[] theDefs, boolean only) {
    super(kind, stn) ;
    this.facts = theFacts ;
    this.defs = theDefs ;
    this.isOnly = only ;
  } ;

  /*************************************************************************
  * The following method was added 4 Mar 2009 to check the restriction     *
  * that only the names of facts (and of modules) can be used as facts in  *
  * a USE or HIDE.                                                         *
  *                                                                        *
  * It was modified on 1 Jul 2009 to allow the use of expressions as       *
  * facts in a USE.                                                        *
  *************************************************************************/
  public void factCheck() {
    if (this.facts == null || this.getKind() == UseKind) { return; };
    for (int i = 0; i < this.facts.length; i++) {
      if (    (this.facts[i].getKind() == OpApplKind)
           && (((OpApplNode) this.facts[i]).operator.getKind()
                   != ThmOrAssumpDefKind)) {
          errors.addError(
             this.facts[i].stn.getLocation(),
               "The only expression allowed as a fact in a HIDE " +
               "is \nthe name of a theorem, assumption, or step.");
      } ;
    } // for
  }

  @Override
  public boolean levelCheck(int iter) {
    /***********************************************************************
    * Level checking is performed by level-checking the facts.  Since the  *
    * defs should be defined operators, they have already been level       *
    * checked.                                                             *
    ***********************************************************************/
    if (this.levelChecked >= iter) return this.levelCorrect;
    return this.levelCheckSubnodes(iter, facts) ;
   }

  @Override
  public void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    for (int  i = 0; i < facts.length; i++) {
      facts[i].walkGraph(semNodesTable, visitor);
      } ;
    /***********************************************************************
    * Note: there's no need to walk the defs array because all the nodes   *
    * on it are walked from the nodes under which they appear.             *
    ***********************************************************************/
      visitor.postVisit(this);
   }

  /*
   * The children are the facts.
   * @see tla2sany.semantic.SemanticNode#getChildren()
   */
  @Override
  public SemanticNode[] getChildren() {
      if (this.facts == null || this.facts.length == 0) {
          return null;
      }
      SemanticNode[] res = new SemanticNode[this.facts.length];
      for (int i = 0; i < facts.length; i++) {
          res[i] = facts[i];
      }
      return res;
   }

  @Override
  public String toString(int depth) {
    if (depth <= 0) return "";
    String ret = "\n*UseOrHideNode:\n"
                  + super.toString(depth)
                  + Strings.indent(2, "\nisOnly: " + this.isOnly)
                  + Strings.indent(2, "\nfacts:") ;
    for (int i = 0 ; i < this.facts.length; i++) {
        ret += Strings.indent(4, this.facts[i].toString(1)) ;
      } ;
    ret += Strings.indent(2, "\ndefs:") ;
    for (int i = 0 ; i < this.defs.length; i++) {
        ret += Strings.indent(4, this.defs[i].toString(1)) ;
      } ;
    return ret;
   }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
    //SemanticNode.SymbolContext context = new SemanticNode.SymbolContext(context2);
    Element e = doc.createElement("UseOrHideNode");

    Element factse = doc.createElement("facts");
    Element definitions = doc.createElement("defs");

    for (int i=0; i<facts.length; i++) factse.appendChild(facts[i].export(doc,context));
    for (int i=0; i<defs.length; i++) definitions.appendChild(defs[i].export(doc,context));

    e.appendChild(factse);
    e.appendChild(definitions);
    if(isOnly) e.appendChild(doc.createElement("only"));
    if(getKind() == HideKind) e.appendChild(doc.createElement("hide"));


/*    if (stepName != null)
      e.setAttribute("step_name", stepName.toString());
*/

    // at the end, we append the context of the symbols used in this node
    //e.appendChild(context.getContextElement(doc));

    return e;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/AbstractGraphNode.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import tlc2.util.BitVector;

public abstract class AbstractGraphNode {

	protected BitVector checks; // truth values for state and action predicates

	public AbstractGraphNode(BitVector bitVector) {
		checks = bitVector;
	}

	public boolean getCheckState(int i) {
		return this.checks.get(i);
	}

	public BitVector getCheckAction(int slen, int alen, int nodeIdx) {
		final BitVector bv = new BitVector(alen);
		for (int j = 0; j < alen; j++) {
			bv.set(j, getCheckAction(slen, alen, nodeIdx, j));
		}
		return bv;
	}

	public boolean getCheckAction(int slen, int alen, int nodeIdx, int i) {
		int pos = slen + alen * nodeIdx + i;
		return this.checks.get(pos);
	}

	public boolean getCheckAction(int slen, int alen, int nodeIdx, int[] is) {
		int len = is.length;
		for (int i = 0; i < len; i++) {
			int pos = slen + alen * nodeIdx + is[i];
			if (!this.checks.get(pos)) {
				return false;
			}
		}
		return true;
	}

	public void setCheckState(boolean[] vals) {
		int len = vals.length;
		for (int i = 0; i < len; i++) {
			if (vals[i]) {
				this.checks.set(i);
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/AbstractHeapBasedDiskFPSetTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.rmi.RemoteException;

import org.junit.Test;

import tlc2.tool.TLCState;
import tlc2.tool.TLCTrace;
import tlc2.tool.queue.DummyTLCState;

public abstract class AbstractHeapBasedDiskFPSetTest {
	
	/* Test the lower limits */
	
	@Test
	public void testCtorLLMinus1() throws RemoteException {
		doTest(getLowerLimit() - 1);
	}
	
	@Test
	public void testCtorLL() throws RemoteException {
		doTest(getLowerLimit());
	}

	@Test
	public void testCtorLLPlus1() throws RemoteException {
		doTest(getLowerLimit() + 1);
	}
	
	@Test
	public void testCtorLLNextPow2Min1() throws RemoteException {
		doTest((getLowerLimit() << 1) - 1);
	}
	
	/* Test with a power far away from upper/lower limits */
	
	@Test
	public void testCtorPow16Minus1() throws RemoteException {
		doTest((1L << 16) - 1);
	}
	
	@Test
	public void testCtorPow16() throws RemoteException {
		doTest(1L << 16);
	}

	@Test
	public void testCtorPow16Plus1() throws RemoteException {
		doTest((1L << 16) + 1);
	}
	
	@Test
	public void testCtorPow16NextPow2Min1() throws RemoteException {
		doTest(((1L << 16) << 1) - 1);
	}
	
	/* Test the upper limits */
	
	@Test
	public void testCtorULMinus1() throws RemoteException {
		doTest(getUpperLimit() - 1);
	}
	
	@Test
	public void testCtorUL() throws RemoteException {
		doTest(getUpperLimit());
	}

	@Test
	public void testCtorULPlus1() throws RemoteException {
		doTest(getUpperLimit() + 1);
	}
	
	@Test
	public void testCtorULNextPow2Min1() throws RemoteException {
		doTest((getUpperLimit() << 1) - 1);
	}
	
	@Test
	public void testFPSetRecovery() throws IOException {
		final int limit = 99999;
		final String metadir = System.getProperty("java.io.tmpdir");
		final String filename = this.getClass().getCanonicalName();
		
		// First, create a trace file to recover from.
		final TLCTrace trace = new TLCTrace(metadir, filename,
				null);
		
		// Fill the trace file with random fingerprints
		final TLCState predecessor = new DummyTLCState();
		predecessor.uid = 1L;
		// an init state
		trace.writeState(predecessor.uid);
		// successor states
		for (long fp = predecessor.uid + 1; fp < limit; fp++) {
			trace.writeState(predecessor, fp);
			predecessor.uid = fp;
		}
		
		// Create a checkpoint file
		trace.beginChkpt();
		trace.commitChkpt();
		
		// Create a DiskFPSet 
		final DiskFPSet fpSet = getDiskFPSet(new FPSetConfiguration());
		fpSet.init(1, metadir, filename);
		fpSet.recover(trace);

		// Verify successful recovery
		assertEquals(limit-1, fpSet.size());
		for (long fp = 1L; fp < limit; fp++) {
			assertTrue(fpSet.contains(fp));
		}
	}
	
	@Test
	public void testFPSetRecovery2() throws IOException {
		final String metadir = System.getProperty("java.io.tmpdir");
		final String filename = this.getClass().getCanonicalName() + "testFPSetRecovery2";
		
		final DiskFPSet fpSet = getDiskFPSet(new FPSetConfiguration());
		fpSet.init(1, metadir, filename);

		// Make sure the FPSet tries to flush to disk.
		fpSet.forceFlush();
		
		for (long fp = 1; fp <= 1024; fp++) {
			fpSet.recoverFP(fp);
		}
	}

	/* Helper */

	@SuppressWarnings("deprecation")
	protected void doTest(final long physicalMemoryInBytes) throws RemoteException {
		final FPSetConfiguration fpSetConfig = new DummyFPSetConfiguration();
		fpSetConfig.setMemory(physicalMemoryInBytes);
		
		final DiskFPSet fpset = getDiskFPSet(fpSetConfig);
		long maxTblCntInBytes = fpset.getMaxTblCnt() * FPSet.LongSize; // Convert from logical to physical
		
		// Always allocate less storage than given 
		assertTrue("Internal storage exceeds allocated memory", physicalMemoryInBytes >= maxTblCntInBytes);
		
		// Storage with zero space for a fingerprint does make much sense, does it?
		assertTrue("Internal storage underflow allocated memory", 0L < maxTblCntInBytes);
		
		// We happen to know that LSBDiskFPSet reserves some memory to auxiliary
		// storage. Make this reservation the lower bound for the primary
		// storage. We div by 2 to account for the fact that both
		// implementations round down to the next power of 2.
		double lowerLimit = (physicalMemoryInBytes / 2) / fpset.getAuxiliaryStorageRequirement();
		assertTrue("Internal storage falls short lower allocation limit", lowerLimit <= maxTblCntInBytes);
	}

	protected abstract DiskFPSet getDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException;

	/**
	 * @return The lower size limit the {@link HeapBasedDiskFPSet} can handle.
	 *         It is determined by the implementation's
	 *         {@link DiskFPSet#getAuxiliaryStorageRequirement()}.
	 */
	protected abstract long getLowerLimit();

	/**
	 * @return The upper size limit the {@link HeapBasedDiskFPSet} can handle.
	 */
	protected abstract long getUpperLimit();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/job/ProverJobRule.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.job;

import org.eclipse.core.runtime.jobs.ISchedulingRule;

/**
 * This is the scheduling rule that should be used
 * to run a ProverJob. It allows at most one prover
 * job to be running at any given time from the toolbox.
 * 
 * @author <NAME>
 *
 */
public class ProverJobRule implements ISchedulingRule
{

    public boolean contains(ISchedulingRule rule)
    {
        return rule == this;
    }

    /**
     * Any job with an instance of this rule cannot
     * be run at the same time.
     */
    public boolean isConflicting(ISchedulingRule rule)
    {
        return rule instanceof ProverJobRule;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/BitVectorTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class BitVectorTest {

	/**
	 * Test method for {@link tlc2.util.BitVector#toString()}.
	 */
	@Test
	public void testToString() {
		final BitVector bitVector = new BitVector(8);
		bitVector.set(0);
		bitVector.set(1);
		// unset
		bitVector.set(3);
		bitVector.set(4);
		// unset
		// unset
		bitVector.set(7);
		
		assertEquals("[10011011]", bitVector.toString());
	}

	@Test
	public void testToStringRange() {
		final BitVector bitVector = new BitVector(8);
		bitVector.set(0);
		bitVector.set(1);
		// unset
		bitVector.set(3);
		bitVector.set(4);
		// unset
		// unset
		bitVector.set(7);
		
		assertEquals("[001]", bitVector.toString(4, 3));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/ContinueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.FileNotFoundException;
import java.io.IOException;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class ContinueTest extends ModelCheckerTestCase {

	public ContinueTest() {
		super("Continue", new String[] { "-continue" }, ExitStatus.SUCCESS);
	}

	@Override
	protected boolean noGenerateSpec() {
		return true;
	}

	@Test
	public void testSpec() throws FileNotFoundException, IOException {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "32", "29", "0"));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "29"));

		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT2));

		assertNoTESpec();
		
		// With -continue, TLC simply prints two or more consecutive traces in no given
		// order (determined by concurrent BFS) to stdout. This means that the
		// MPRecorder just concatenates the traces and it is difficult to check them.
		// For now we check that the concatenated trace has the expected number of states.
		assertEquals(32, recorder.getRecords(EC.TLC_STATE_PRINT2).size());
//		// Trace 1
//		final List<String> expectedTrace = new ArrayList<String>(2);
//		expectedTrace.add("/\\ x = 1\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 2\n/\\ y = 2");
//		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);
//		// Trace 2
//		final List<String> expectedTrace = new ArrayList<String>(30);
//		expectedTrace.add("/\\ x = 1\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 2\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 3\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 4\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 5\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 6\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 7\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 8\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 9\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 10\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 11\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 12\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 13\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 14\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 15\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 16\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 17\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 18\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 19\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 20\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 21\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 22\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 23\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 24\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 25\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 26\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 27\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 28\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 29\n/\\ y = 1");
//		expectedTrace.add("/\\ x = 30\n/\\ y = 1");
//		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);

		assertZeroUncovered();
	}

	@Override
	protected int getNumberOfThreads() {
		return 3;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/javacc/config.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>BNF for config.jj</TITLE>
</HEAD>
<BODY>
<H1 ALIGN=CENTER>BNF for config.jj</H1>
<H2 ALIGN=CENTER>NON-TERMINALS</H2>
<TABLE>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod1">ConfigurationUnit</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod2">OpDefinition</A> )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod2">OpDefinition</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;OPERATOR&gt; ( &lt;OPID&gt; ) ( <A HREF="#prod3">OpBody</A> | <A HREF="#prod4">OpNull</A> ) )</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod5">OpSynonym</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod6">OpBuiltin</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod3">OpBody</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;NUMBER&gt; &lt;NUMBER&gt; ( ( &lt;LEFTASSOC&gt; ) | ( &lt;RIGHTASSOC&gt; ) | ( &lt;NOASSOC&gt; ) ) ( ( &lt;INFIX&gt; ) | ( &lt;PREFIX&gt; ) | ( &lt;POSTFIX&gt; ) | ( &lt;NFIX&gt; ) ) ( &lt;OPID&gt; )?</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod5">OpSynonym</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;SYNONYM&gt; &lt;OPID&gt; &lt;OPID&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod4">OpNull</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;NOTOP&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod6">OpBuiltin</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;BUILTIN&gt; &lt;OPID&gt; &lt;RESTRICTED&gt; ( &lt;INFIX&gt; | &lt;PREFIX&gt; | &lt;POSTFIX&gt; | &lt;CONSTANT&gt; | &lt;NUMBER&gt; )</TD>
</TR>
</TABLE>
</BODY>
</HTML>


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ProverPreferenceInitializer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.dialog.LaunchProverDialog;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ColorPredicate;
import org.lamport.tla.toolbox.tool.prover.ui.preference.AdditionalPreferencesPage;
import org.lamport.tla.toolbox.tool.prover.ui.preference.ColorPredicatePreferencePage;
import org.lamport.tla.toolbox.tool.prover.ui.preference.MainProverPreferencePage;

/**
 * This class can be used to set default preferences for any preference
 * values that are stored in the preference store for this plugin. This
 * preference store is the one returned by ProverUIActivator.getDefault().getPreferenceStore().
 * 
 * @author <NAME>
 *
 */
public class ProverPreferenceInitializer extends AbstractPreferenceInitializer
{

    public void initializeDefaultPreferences()
    {
        IPreferenceStore store = ProverUIActivator.getDefault().getPreferenceStore();

        /*
         * Set the default values for the general prover launching
         * dialog.
         */
        store.setDefault(LaunchProverDialog.TOOLBOX_MODE_KEY, true);
        store.setDefault(LaunchProverDialog.EXTRA_OPTIONS_KEY, "");
        store.setDefault(LaunchProverDialog.PARANOID_KEY, false);
        store.setDefault(LaunchProverDialog.ISATOOL_KEY, true);
        store.setDefault(LaunchProverDialog.STATUS_CHECK_KEY, false);
        store.setDefault(LaunchProverDialog.ISACHECK_KEY, false);
        store.setDefault(LaunchProverDialog.NOISA_KEY, false);
        store.setDefault(LaunchProverDialog.FP_NORMAL_KEY, true);
        store.setDefault(LaunchProverDialog.FP_FORGET_ALL_KEY, false);
        store.setDefault(LaunchProverDialog.FP_FORGET_CURRENT_KEY, false);
        store.setDefault(MainProverPreferencePage.EXECUTABLE_LOCATION_KEY, "");
        store.setDefault(MainProverPreferencePage.NUM_THREADS_KEY, "");
        store.setDefault(MainProverPreferencePage.SOLVER_KEY, "");
        store.setDefault(MainProverPreferencePage.SAFEFP_KEY, false);
        
        /*
         * The following sets the default color predicates for the colors. First argument
         * is the key for each predicate for the logical color, and the second argument is
         * the predicate string (not the macro name).
         */
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(1), ColorPredicate.PREDICATE_NONE);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(2), ColorPredicate.PREDICATE_NONE);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(3), ColorPredicate.PREDICATE_BEING_PROVED);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(4), ColorPredicate.PREDICATE_STOPPED);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(5), ColorPredicate.PREDICATE_FAILED);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(6), ColorPredicate.PREDICATE_PROVED);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(7), ColorPredicate.PREDICATE_PROVED_OR_OMITTED);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(8), ColorPredicate.PREDICATE_PROVED_OR_OMITTED_OR_MISSING);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(9), ColorPredicate.PREDICATE_NONE);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(10), ColorPredicate.PREDICATE_NONE);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(11), ColorPredicate.PREDICATE_NONE);
        store.setDefault(ColorPredicatePreferencePage.getColorPredPrefName(12), ColorPredicate.PREDICATE_NONE);
     
        
       /*
        * Set the defaults for the user-specified color predicates
        */
        for (int i = 0; i < AdditionalPreferencesPage.USER_DEFINED_PREDICATE.length; i++) {
            store.setDefault(AdditionalPreferencesPage.USER_DEFINED_PREDICATE[i], "some");
        }     
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/FileToStringVectorException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class FileToStringVectorException extends UnrecoverableException
{

    /**
     * @param string
     */
    public FileToStringVectorException(String string)
    {
        super(string);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/InternRMI.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon Jan  1 23:19:07 PST 2001 by yuanyu

package tlc2.tool.distributed;

import java.rmi.Remote;
import java.rmi.RemoteException;

import util.UniqueString;

public interface InternRMI extends Remote {
	public UniqueString intern(String str) throws RemoteException;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/BucketStatistics.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util.statistics;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;

public class BucketStatistics extends AbstractBucketStatistics implements IBucketStatistics {

	/**
	 * The amount of samples seen by this statistics. It's identical
	 * to the sum of the value of all buckets.
	 */
	private long observations;
	
	/**
	 * Instead of using an ever-growing list of samples, identical
	 * samples are counted in a bucket. E.g. the sample 5 is stored
	 * in a bucket with key 5 and a value of 2 if the sample has been
	 * seen two times.
	 * The map is thread safe, so are the values.
	 */
	private final Map<Integer, Long> buckets;

	public BucketStatistics(String aTitle) {
		super(aTitle);
		this.buckets = new HashMap<Integer, Long>();
	}

	public BucketStatistics(String aTitle, final String pkg, final String name) {
		super(aTitle, pkg, name);
		this.buckets = new HashMap<Integer, Long>();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#addSample(int)
	 */
	public void addSample(int amount) {
		if (amount < 0) {
			throw new IllegalArgumentException("Negative amount invalid");
		}
		
		Long l = buckets.get(amount);
		if(l == null) {
			buckets.put(amount, 1L);
		} else {
			buckets.replace(amount, ++l);
		}
		observations++;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.AbstractBucketStatistics#getObservations()
	 */
	public long getObservations() {
		return observations;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getSamples()
	 */
	public NavigableMap<Integer, Long> getSamples() {
		final NavigableMap<Integer, Long> res = new TreeMap<Integer, Long>();
		for (Entry<Integer, Long> entry : this.buckets.entrySet()) {
			res.put(entry.getKey(), entry.getValue());
		}
		return res;
	}

	/**
	 * Adds the observations of <code>stat</code> to this {@link BucketStatistics}.
	 */
	public void add(final IBucketStatistics stat) {
		this.observations += stat.getObservations();
		
		for (Entry<Integer, Long> entry : stat.getSamples().entrySet()) {
			final Long l = this.buckets.get(entry.getKey());
			if (l == null) {
				this.buckets.put(entry.getKey(), entry.getValue());
			} else {
				this.buckets.replace(entry.getKey(), l + entry.getValue());
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/fp/FPSetManagerTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.distributed.fp;

import java.io.File;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import tlc2.tool.distributed.fp.FPSetManager.FPSets;
import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.FPSetConfiguration;
import tlc2.tool.fp.FPSetFactory;

public class FPSetManagerTest {

	protected static final String tmpdir = System.getProperty("java.io.tmpdir") + File.separator + "FPSetTest"
			+ System.currentTimeMillis();

	@Before
	public void before() {
		new File(tmpdir).mkdirs();
	}

	@Test
	public void test2() throws IOException {
		doTest(2);
	}

	@Test
	public void test3() throws IOException {
		doTest(3);
	}

	@Test
	public void test4() throws IOException {
		doTest(4);
	}

	@Test
	public void test5() throws IOException {
		doTest(5);
	}

	@Test
	public void test8() throws IOException {
		doTest(8);
	}

	private void doTest(int expectedNumOfServers) throws RemoteException, IOException, FPSetManagerException {
		final FPSetConfiguration fpSetConfiguration = new FPSetConfiguration();
		fpSetConfiguration.setFpBits(1); // two nested FPSets

		final List<FPSets> sets = new ArrayList<FPSets>();
		for (int i = 0; i < fpSetConfiguration.getMultiFPSetCnt(); i++) {
			final FPSet fpSet = FPSetFactory.getFPSet(fpSetConfiguration);
			fpSet.init(1, tmpdir, "test" + expectedNumOfServers);
			sets.add(new FPSets(fpSet, "localhost" + i));
		}

		final IFPSetManager manager = new DynamicFPSetManager(expectedNumOfServers);
		for (FPSets fpSets : sets) {
			manager.register(fpSets.getFpset(), fpSets.getFpset().toString());
		}

		// Index uses LSBs
		Assert.assertEquals(0, manager.getFPSetIndex(0));
		Assert.assertEquals(1, manager.getFPSetIndex(1));
		Assert.assertEquals(0, manager.getFPSetIndex(2));
		Assert.assertEquals(1, manager.getFPSetIndex(3));
		Assert.assertEquals(0, manager.getFPSetIndex((1L << 63) + 2L));
		Assert.assertEquals(1, manager.getFPSetIndex((1L << 63) + 1L));

		final Set<Long> fps = new HashSet<Long>();
		// fps.add(0L); // Not accepted by nested FPSets
		fps.add(1L);              // 00...0001
		fps.add((1L << 62) + 1L); // 01...0001
		fps.add((1L << 63) + 1L); // 10...0001
		fps.add((3L << 62) + 1L); // 11...0001
		fps.add(2L);              // 00...0010
		fps.add((1L << 62) + 2L); // 01...0010
		fps.add((1L << 63) + 2L); // 10...0010
		fps.add((3L << 62) + 2L); // 11...0010
		fps.add(3L);              // 00...0011
		fps.add((1L << 62) + 3L); // 01...0011
		fps.add((1L << 63) + 3L); // 10...0011
		fps.add((3L << 62) + 3L); // 11...0011
		fps.add(4L);              // 00...0100
		fps.add((1L << 62) + 4L); // 01...0100
		fps.add((1L << 63) + 4L); // 10...0100
		fps.add((3L << 62) + 4L); // 11...0100
		fps.add(5L);              // 00...0101
		fps.add((1L << 62) + 5L); // 01...0101
		fps.add((1L << 63) + 5L); // 10...0101
		fps.add((3L << 62) + 5L); // 11...0101
		fps.add(6L);              // 00...0110
		fps.add((1L << 62) + 6L); // 01...0110
		fps.add((1L << 63) + 6L); // 10...0110
		fps.add((3L << 62) + 6L); // 11...0110
		fps.add(7L);              // 00...0110
		fps.add((1L << 62) + 7L); // 01...0111
		fps.add((1L << 63) + 7L); // 10...0111
		fps.add((3L << 62) + 7L); // 11...0111
		fps.add(8L);              // 00...1000
		fps.add((1L << 62) + 8L); // 01...1000
		fps.add((1L << 63) + 8L); // 10...1000
		fps.add((3L << 62) + 8L); // 11...1000

		final Set<Long> unseen = new HashSet<Long>(fps);
		for (Long fp : fps) {
			// Unseen fingerprints must not be in set.
			for (Long unseenFP : unseen) {
				Assert.assertFalse(manager.contains(unseenFP));
			}
			Assert.assertTrue(unseen.remove(fp));

			Assert.assertFalse(printBinaryString("", fp), manager.put(fp));
			Assert.assertTrue(printBinaryString("", fp), manager.contains(fp));
		}

		Assert.assertEquals(fps.size(), manager.size());

		Assert.assertTrue(manager.checkInvariant());
	}

	private String printBinaryString(final String id, final long a) {
		return String.format(id + ":%64s", Long.toBinaryString(a)).replace(' ', '0');
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/TLCTimerTask.java<|end_filename|>
package tlc2.tool.distributed;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.distributed.TLCWorker.TLCWorkerRunnable;

/**
 * Periodically checks if the server is still alive and exits the worker otherwise
 */
public class TLCTimerTask extends TimerTask {
	public static final long PERIOD = 60000L;
	
	private static final Logger LOGGER = Logger.getLogger(TLCTimerTask.class.getName());

	private static final int TIMEOUT = Integer.getInteger(TLCTimerTask.class.getName() + ".timeout", 60) * 1000;

	private final String serverUrl;
	private final TLCWorkerRunnable[] runnables;
	private final Timer timer;

	public TLCTimerTask(final Timer keepAliveTimer, final TLCWorkerRunnable[] runnables, final String anUrl) {
		this.timer = keepAliveTimer;
		this.runnables = runnables;
		this.serverUrl = anUrl;
	}

	/* (non-Javadoc)
	 * @see java.util.TimerTask#run()
	 */
	public void run() {
		if(noActivityWithin(TIMEOUT)) {
			// If we haven't seen any activity within the timeout, we
			// actively call the server to find out if it is still alive and
			// model checking is ongoing.
			try {
				// If the master has crashed, the RMI lookup is going to fail
				final TLCServerRMI server = (TLCServerRMI) Naming.lookup(serverUrl);
				// At this point the master is responsive, but model checking
				// might has ended already
				if(server.isDone()) {
					exitWorker(null);
				}
			} catch (MalformedURLException e) {
				// not expected to happen
				LOGGER.log(Level.FINEST, "Failed to exit worker", e);
			} catch (RemoteException e) {
				exitWorker(e);
			} catch (NotBoundException e) {
				exitWorker(e);
			}
		}
	}
	
	private boolean noActivityWithin(final int timeout) {
		long lastInvocation = getMostRecentInvocation();
		if (lastInvocation == -1) {
			// The worker is currently computing states, thus we count this as
			// an activity
			return false;
		} else {
			long now = new Date().getTime();
			return lastInvocation == 0 || (now - lastInvocation) > timeout;
		}
	}

	private long getMostRecentInvocation() {
		long minInvocation = 0L;
		for (int i = 0; i < runnables.length; i++) {
			TLCWorker tlcWorker = runnables[i].getTLCWorker();
			/*
			 * If one of the TLCworker threads is computing states, we assume
			 * the TLCMaster/TLCServer to still be alive. At least we definitely
			 * want to finish the computation first. Under the condition of a
			 * server crash, all workers will eventually converge into a
			 * non-computing state though. Then, lastInvocation is going to
			 * matter. The same is the case, when the master is slow to request
			 * states from workers.
			 */
			if (tlcWorker.isComputing()) {
				return -1L;
			}
			long lastInvocation = tlcWorker.getLastInvocation();
			minInvocation = Math.max(minInvocation, lastInvocation);
		}
		return minInvocation;
	}

	private void exitWorker(Throwable e) {
		if (e != null) {
			MP.printError(EC.TLC_DISTRIBUTED_SERVER_NOT_RUNNING, e);
		} else {
			MP.printError(EC.TLC_DISTRIBUTED_SERVER_FINISHED);
		}
		for (int i = 0; i < runnables.length; i++) {
			try {
				TLCWorkerRunnable runnable = runnables[i];
				runnable.getTLCWorker().exit();
			} catch (NoSuchObjectException ex) {
				// not expected to happen
				LOGGER.log(Level.FINEST, "Failed to exit worker", ex);
			}
		}
		// Cancel this time after having exited the worker. Otherwise we keep on
		// going forever.
		this.timer.cancel();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/RandomAccessFile.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.util;

import java.io.File;
import java.io.IOException;

/**
 * 
 * 
 * @version $Id$
 * Bogus name!
 */
public class RandomAccessFile extends java.io.RandomAccessFile {
    
    public long superSeekCnt = 0L;
    public long superReadCnt = 0L;
    public long superWriteCnt = 0L;
    public long superSeekTime = 0L;
    public long superReadTime = 0L;
    public long superWriteTime = 0L;
    
    public RandomAccessFile(File file, String mode) throws IOException {
        super(file, mode);
    }

    public RandomAccessFile(String name, String mode) throws IOException {
        super(name, mode);
    }

    public void seek(long pos) throws IOException {
        this.superSeekCnt++;
        long start = System.currentTimeMillis();
        super.seek(pos);
        this.superSeekTime += System.currentTimeMillis() - start;
    }
    
    public int read() throws IOException {
        this.superReadCnt++;
        long start = System.currentTimeMillis();
        int res = super.read();
        this.superReadTime += System.currentTimeMillis() - start;
        return res;
    }
    
    public int read(byte[] b) throws IOException {
        this.superReadCnt++;
        long start = System.currentTimeMillis();
        int res = super.read(b);
        this.superReadTime += System.currentTimeMillis() - start;
        return res;
    }
    
    public int read(byte[] b, int off, int len) throws IOException {
        this.superReadCnt++;
        long start = System.currentTimeMillis();
        int res = super.read(b, off, len);
        this.superReadTime += System.currentTimeMillis() - start;
        return res;
    }
    
    public void write(int b) throws IOException {
        this.superWriteCnt++;
        long start = System.currentTimeMillis();
        super.write(b);
        this.superWriteTime += System.currentTimeMillis() - start;
    }
    
    public void write(byte[] b) throws IOException {
        this.superWriteCnt++;
        long start = System.currentTimeMillis();
        super.write(b);
        this.superWriteTime += System.currentTimeMillis() - start;
    }    
    
    public void write(byte[] b, int off, int len) throws IOException {
        this.superWriteCnt++;
        long start = System.currentTimeMillis();
        super.write(b, off, len);
        this.superWriteTime += System.currentTimeMillis() - start;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/dialog/TLAFilteredItemsSelectionDialog.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.ui.dialog;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.IDescriptionProvider;
import org.lamport.org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.util.ModelHelper;

public class TLAFilteredItemsSelectionDialog extends FilteredItemsSelectionDialog {
	
	private static final String SHOW_CONSTANTS = "ShowConstants"; //$NON-NLS-1$
	
	private static final String SHOW_CLOSED_SPECS = "ShowClosedSpecs"; //$NON-NLS-1$
	
	private static final String SASH_RATIO_TOP = "SashRatioTop"; //$NON-NLS-1$

	private static final String SASH_RATIO_BOTTOM = "SashRatioBottom"; //$NON-NLS-1$
	
	private static final String EMPTY_STRING = ""; //$NON-NLS-1$

	private static final Image ModelImage = TLCUIActivator.getImageDescriptor("/icons/full/choice_sc_obj.gif")
			.createImage();
	
	private final ItemsListSeparator modulesSep	= new ItemsListSeparator("Modules"); //$NON-NLS-1$

	private final ItemsListSeparator specsSep = new ItemsListSeparator("Closed Specs"); //$NON-NLS-1$

	private final ToggleShowAction toggleShowConstantsAction  = new ToggleShowAction("Show spec constants", getDialogSettings().getBoolean(SHOW_CONSTANTS));
	
	private final ToggleShowAction toggleShowSpecAction = new ToggleShowAction("Show closed specs", getDialogSettings().getBoolean(SHOW_CLOSED_SPECS));
	
	private SourceViewer sourceViewer;

	private SashForm sashForm;

	public TLAFilteredItemsSelectionDialog(final Shell shell) {
		super(shell, false);
		setInitialPattern("?"); // https://bugs.eclipse.org/308689
		setListLabelProvider(new TableLabelProvider());
		setDetailsLabelProvider(new DetailsLabelProvider());
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.dialogs.Dialog#getInitialSize()
	 */
	protected Point getInitialSize() {
		final Point defaultSize = super.getInitialSize();
		if (defaultSize.x == 500 && defaultSize.y == 600) {
			// Increase the parents default size
			defaultSize.x = (int) Math.round(defaultSize.x * 1.9); // x has room to align with the default spec line-wrapping
			defaultSize.y = (int) Math.round(defaultSize.y * 1.75);
		}
		return defaultSize;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.SelectionDialog#isResizable()
	 */
	protected boolean isResizable() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.ui.dialog.FilteredItemsSelectionDialog#createContentCoposite(org.eclipse.swt.widgets.Composite)
	 */
	protected Composite createContentComposite(final Composite parent) {
		sashForm = new SashForm(parent, SWT.VERTICAL);
		sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
		return sashForm;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
	 */
	protected Control createExtendedContentArea(final Composite parent) {
		
		final Composite content = new Composite(parent, SWT.BORDER);
		
		final GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
		layoutData.heightHint = 200;
		content.setLayoutData(layoutData);

		final GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		content.setLayout(layout);
		
		sourceViewer = new SourceViewer(content, null, SWT.WRAP | SWT.V_SCROLL);
		sourceViewer.getTextWidget().setLayoutData(new GridData(GridData.FILL_BOTH));
		sourceViewer.getTextWidget().setWordWrap(true);
		sourceViewer.getTextWidget().setEditable(false);
		sourceViewer.getTextWidget().setFont(TLCUIActivator.getDefault().getCourierFont());
		
		// The weights can only be set *after* its nested controls (content
		// above) are added. Thus it's done here instead of createContentControl(..).
		final int top = getDialogSettings().get(SASH_RATIO_TOP) == null ? 75
				: getDialogSettings().getInt(SASH_RATIO_TOP);
		final int bottom = getDialogSettings().get(SASH_RATIO_BOTTOM) == null ? 25
				: getDialogSettings().getInt(SASH_RATIO_BOTTOM);
		sashForm.setWeights(new int[] { top, bottom });

		return content;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getDialogSettings()
	 */
	protected IDialogSettings getDialogSettings() {
		final IDialogSettings settings = Activator.getDefault().getDialogSettings();
		if (settings.get(SHOW_CONSTANTS) == null) {
			// Show constants by default
			settings.put(SHOW_CONSTANTS, true);
		}
		return settings;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#storeDialog(org.eclipse.jface.dialogs.IDialogSettings)
	 */
	protected void storeDialog(IDialogSettings settings) {
		settings.put(SHOW_CONSTANTS, toggleShowConstantsAction.isChecked());
		settings.put(SHOW_CLOSED_SPECS, toggleShowSpecAction.isChecked());
		settings.put(SASH_RATIO_TOP, sashForm.getWeights()[0]);
		settings.put(SASH_RATIO_BOTTOM, sashForm.getWeights()[1]);
		super.storeDialog(settings);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillViewMenu(org.eclipse.jface.action.IMenuManager)
	 */
	protected void fillViewMenu(IMenuManager menuManager) {
		menuManager.add(toggleShowConstantsAction);
		menuManager.add(toggleShowSpecAction);
		super.fillViewMenu(menuManager);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#validateItem(java.lang.Object)
	 */
	protected IStatus validateItem(final Object item) {
		// Nothing to validate so far
		return Status.OK_STATUS;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#handleSelected(org.eclipse.jface.viewers.StructuredSelection)
	 */
	protected void handleSelected(StructuredSelection selection) {
		if (selection != null && selection.size() == 0) {
			// unset the sourceviewer when the filter turned the search results
			// empty
			sourceViewer.setDocument(new Document(EMPTY_STRING));
		} else if (selection != null && selection.getFirstElement() instanceof Module) {
			final Module module = (Module) selection.getFirstElement();
			try {
				sourceViewer.setDocument(new Document(new String(Files.readAllBytes(module.getFile().toPath()))));
			} catch (IOException e) {
				sourceViewer.setDocument(new Document(EMPTY_STRING));
			}
		} else if (selection != null && selection.getFirstElement() instanceof Model) {
			final Model model = (Model) selection.getFirstElement();
			try {
				// By default, show the model's comment/description and fall-back
				// to its constants. If there are no constants, the last fall-back
				// is the model's name.
				final List<String> fallbacksFallback = new ArrayList<String>();
				fallbacksFallback.add(model.getName());
				
				final String attribute = model.getComments();
				if (!EMPTY_STRING.equals(attribute)) {
					sourceViewer.setDocument(new Document(attribute));
				} else {
					sourceViewer.setDocument(new Document(ModelHelper.prettyPrintConstants(model, "\n", true)));
				}
			} catch (final CoreException ignored) {
				sourceViewer.setDocument(new Document(EMPTY_STRING));
			}
		} else if (selection != null && selection.getFirstElement() instanceof Spec) {
			final Spec spec = (Spec) selection.getFirstElement();
			final Path path = spec.getRootFile().getLocation().makeAbsolute().toFile().toPath();
			try {
				sourceViewer.setDocument(new Document(new String(Files.readAllBytes(path))));
			} catch (IOException e) {
				sourceViewer.setDocument(new Document(EMPTY_STRING));
			}
		} else if (selection != null && selection.getFirstElement() instanceof ItemsListSeparator) {
			sourceViewer.setDocument(new Document(EMPTY_STRING));
		}
		super.handleSelected(selection);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
	 */
	protected ItemsFilter createFilter() {
		return new TLCItemFilter();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
	 */
	protected Comparator<Object> getItemsComparator() {
		return new Comparator<Object>() {

			public int compare(final Object o1, final Object o2) {
				if (o1 instanceof Model && o2 instanceof Model) {
					final Model c1 = (Model) o1;
					final Model c2 = (Model) o2;
					return c1.getName().compareTo(c2.getName());
				} else if (o1 instanceof Module && o2 instanceof Module) {
					final Module m1 = (Module) o1;
					final Module m2 = (Module) o2;
					return m1.getModuleName().compareTo(m2.getModuleName());
				} else if (o1 instanceof ItemsListSeparator && o1 == modulesSep && o2 instanceof ItemsListSeparator) {
					return -1;
				} else if (o1 instanceof ItemsListSeparator && o1 == specsSep && o2 instanceof ItemsListSeparator) {
					return 1;
				} else if (o1 instanceof Spec && o2 instanceof Spec) {
					return ((Spec) o1).getName().compareTo(((Spec) o2).getName());
				} else if (o1 instanceof Model && o2 instanceof Module) {
					return -1;
				} else if (o1 instanceof Model && o2 instanceof Spec) {
					return -1;
				} else if (o1 instanceof Model && o2 instanceof ItemsListSeparator) {
					return -1;
				} else if (o1 instanceof Module && o2 instanceof Model) {
					return 1;
				} else if (o1 instanceof Module && o2 instanceof Spec) {
					return -1;
				} else if (o1 instanceof Module && o2 instanceof ItemsListSeparator && o2 == modulesSep) {
					return 1;
				} else if (o1 instanceof Module && o2 instanceof ItemsListSeparator) {
					return -1;
				} else if (o1 instanceof Spec && o2 instanceof Model) {
					return 1;
				} else if (o1 instanceof Spec && o2 instanceof Module) {
					return 1;
				} else if (o1 instanceof Spec && o2 instanceof ItemsListSeparator) {
					return 1;
				} else if (o1 instanceof ItemsListSeparator && o2 instanceof Model) {
					return 1;
				} else if (o1 instanceof ItemsListSeparator && o1 == modulesSep && o2 instanceof Module) {
					return -1;
				} else if (o1 instanceof ItemsListSeparator && o2 instanceof Module) {
					return 1;
				} else if (o1 instanceof ItemsListSeparator && o2 instanceof Spec) {
					return -1;
				} else {
					return 1;
				}
			}
		};
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider, org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter, org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected void fillContentProvider(final AbstractContentProvider contentProvider, final ItemsFilter itemsFilter,
			final IProgressMonitor progressMonitor) throws CoreException {
		final Spec spec = Activator.getSpecManager().getSpecLoaded();
		// On the initial/welcome page, no spec is open.
		if (spec != null) {
			// Models
			final Collection<Model> models = spec.getAdapter(TLCSpec.class).getModels().values();
			for (final Model model : models) {
				if (itemsFilter.isConsistentItem(model)) {
					contentProvider.add(model, itemsFilter);
				}
			}
			
			// Modules
			final List<Module> modules = spec.getModules();
			if (modules.size() > 0) {
				contentProvider.add(modulesSep, itemsFilter);
				for (Module module : modules) {
					if (itemsFilter.isConsistentItem(module)) {
						contentProvider.add(module, itemsFilter);
					}
				}
			}
		}
		
		// All closed specs
		if (toggleShowSpecAction.isChecked()) {
			final Spec[] specs = Activator.getSpecManager().getRecentlyOpened();
			if (specs.length > 0) {
				contentProvider.add(specsSep, itemsFilter);
				for (int i = 0; i < specs.length; i++) {
					final Spec aSpec = specs[i];
					if (!aSpec.equals(spec) && itemsFilter.isConsistentItem(aSpec)) {
						contentProvider.add(aSpec, itemsFilter);
					}
				}
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
	 */
	public String getElementName(final Object item) {
		return EMPTY_STRING;
	}

	public class TLCItemFilter extends ItemsFilter {

		private final TableLabelProvider labelProvider = new TableLabelProvider();
		
		/* (non-Javadoc)
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#isConsistentItem(java.lang.Object)
		 */
		public boolean isConsistentItem(final Object item) {
			return true;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#matchItem(java.lang.Object)
		 */
		public boolean matchItem(final Object item) {
			if (getPattern() == null || getPattern().length() == 0) {
				return true;
			}
			// Use the text shown by the label provider. The user definitely
			// wants to search inside what is actually shown.
			return patternMatcher.matches(labelProvider.getText(item));
		}
	}

	private class DetailsLabelProvider extends LabelProvider {

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
		 */
		public String getText(final Object element) {
			if (element instanceof Module) {
				final Module module = (Module) element;
				return module.getModuleName();
			} else if (element instanceof Model) {
				((Model) element).getName();
			} else if (element instanceof Spec) {
				final Spec spec = (Spec) element;
				return spec.getName();
			} else if (element instanceof ItemsListSeparator) {
				return EMPTY_STRING;
			}
			return super.getText(element);
		}
	}

	private class TableLabelProvider extends LabelProvider implements IDescriptionProvider, IStyledLabelProvider {

		private static final String DELIM = ":";

		public String getText(final Object element) {
			if (element == null) {
				return null;
			}
			if (element instanceof Spec) {
				final Spec spec = (Spec) element;
				final IFile root = spec.getRootFile();
				if (root == null) {
					return null;
				}
				return spec.getName() + " [ " + root.getName() + " ]";
			} else if (element instanceof Module) {
				return ((Module) element).getModuleName();
			} else if (element instanceof Model) {
				final Model model = (Model) element;
				try {
					String attribute = model.getComments();
					if (toggleShowConstantsAction.isChecked() && EMPTY_STRING.equals(attribute)) {
						attribute = ModelHelper.prettyPrintConstants(model, ", ");
					}
					if (!EMPTY_STRING.equals(attribute)) {
						if (attribute.contains("\n")) {
							attribute = attribute.split("\n")[0];
						}
						return model.getName() + DELIM + " " + attribute;
					}
				} catch (CoreException e) {
				}
				return model.getName();
			} else if (element instanceof ItemsListSeparator) {
				final ItemsListSeparator ils = (ItemsListSeparator) element;
				return ils.getName();
			}
			return null;
		}

		public String getDescription(final Object element) {
			return super.getText(element);
		}

		public Image getImage(final Object element) {
			if (element == null) {
				return null;
			}
			if (element instanceof Spec) {
				if (Activator.getSpecManager().isSpecLoaded((Spec) element)) {
					return Activator.getDefault().getImageRegistry().get(Activator.IMG_SPEC_OPEN);
				}
				return Activator.getDefault().getImageRegistry().get(Activator.IMG_SPEC_CLOSED);
			} else if (element instanceof Module) {
				return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
			} else if (element instanceof Model) {
				return ModelImage;
			}
			return null;
		}

		public StyledString getStyledText(Object element) {
			final String text = getText(element);
			if (text == null || EMPTY_STRING.equals(text)) {
				return new StyledString();
			}
			
			final StyledString string = new StyledString(text);
			
			if (element instanceof Spec) {
				string.setStyle(0, string.length(), StyledString.QUALIFIER_STYLER);
			} else if (element instanceof Model && text.indexOf(DELIM) != -1) {
				final int index = text.indexOf(DELIM);
				string.setStyle(index, text.length() - index, StyledString.DECORATIONS_STYLER);
			} else if (element instanceof ItemsListSeparator) {
				string.setStyle(0, string.length(), StyledString.QUALIFIER_STYLER);
			}
			return string;
		}
	}
	
	private class ToggleShowAction extends Action {

		public ToggleShowAction(final String label, final boolean checked) {
			super(label, IAction.AS_CHECK_BOX);
			setChecked(checked);
		}

		public void run() {
			// Doesn't do anything. The dialog has to be re-opened to see its effect.
		}
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/expression/CurrentSpecTester.java<|end_filename|>
package org.lamport.tla.toolbox.ui.expression;

import org.eclipse.core.expressions.PropertyTester;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;

/**
 * @author <NAME>
 * @version $Id$
 */
public class CurrentSpecTester extends PropertyTester
{

    /**
     * Tests if the spec is currently selected
     */
    public boolean test(Object receiver, String property, Object[] args, Object expectedValue)
    {
        if ("isCurrentSpec".equals(property))
        {
            if (receiver != null && receiver instanceof Spec) 
            {
                Spec spec = (Spec) receiver;
                Spec current = ToolboxHandle.getCurrentSpec();
                if (current == spec) 
                {
                    return true;
                }
            }
        }        
        return false;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/Github377CoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class Github377CoverageTest extends AbstractCoverageTest {

    public Github377CoverageTest () {
        super("Github377");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "1"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "2", "1", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertCoverage("<Action line 5, col 9 to line 5, col 16 of module Github377>: 1:1\n" + 
				"  line 5, col 9 to line 5, col 16 of module Github377: 1\n" + 
				"<Action line 5, col 24 to line 5, col 34 of module Github377>: 0:1\n" + 
				"  line 5, col 24 to line 5, col 34 of module Github377: 1\n" + 
				"<1Inv line 9, col 1 to line 9, col 4 of module Github377>\n" + 
				"  line 10, col 6 to line 10, col 69 of module Github377: 1\n" + 
				"  line 11, col 5 to line 11, col 13 of module Github377: 1\n" + 
				"<1InvNonRec line 15, col 1 to line 15, col 10 of module Github377>\n" + 
				"  line 16, col 6 to line 16, col 40 of module Github377: 1\n" + 
				"  line 17, col 5 to line 17, col 13 of module Github377: 1\n" + 
				"<2Inv line 21, col 1 to line 21, col 4 of module Github377>\n" + 
				"  line 25, col 10 to line 25, col 47 of module Github377: 1\n" + 
				"  line 26, col 7 to line 26, col 11 of module Github377: 1\n" + 
				"<2aInv line 28, col 1 to line 28, col 5 of module Github377>\n" + 
				"  line 32, col 10 to line 33, col 21 of module Github377: 1\n" + 
				"  line 34, col 7 to line 34, col 11 of module Github377: 1\n" + 
				"<2bInv line 36, col 1 to line 36, col 5 of module Github377>\n" + 
				"  line 40, col 10 to line 40, col 31 of module Github377: 1\n" + 
				"  line 41, col 7 to line 41, col 11 of module Github377: 1\n" + 
				"<3aInv line 44, col 1 to line 44, col 5 of module Github377>\n" + 
				"  line 48, col 10 to line 50, col 21 of module Github377: 1\n" + 
				"  line 51, col 7 to line 51, col 11 of module Github377: 1\n" + 
				"<3bInv line 55, col 1 to line 55, col 5 of module Github377>\n" + 
				"  line 58, col 11 to line 58, col 42 of module Github377: 1\n" + 
				"  line 57, col 11 to line 57, col 70 of module Github377: 1\n" + 
				"  line 60, col 13 to line 60, col 31 of module Github377: 1\n" + 
				"  line 61, col 7 to line 61, col 11 of module Github377: 1\n" + 
				"<4Inv line 66, col 1 to line 66, col 4 of module Github377>\n" + 
				"  line 71, col 11 to line 71, col 18 of module Github377: 1\n" + 
				"  line 72, col 7 to line 72, col 11 of module Github377: 1");
		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/IContextEnumerator.java<|end_filename|>
package tlc2.tool;

import tlc2.util.Context;

public interface IContextEnumerator {

	Context nextElement();

}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.uitest/src/org/lamport/tla/toolbox/tool/tlc/ui/test/DummyJobChangeListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.test;

import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swtbot.swt.finder.utils.internal.Assert;
import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.util.ToolboxJob;

public class DummyJobChangeListener extends DefaultCondition implements IJobChangeListener, ICondition {

	private final Model model;
	private Job job;

	public DummyJobChangeListener(final Model model) {
		Assert.isNotNull(model);
		this.model = model;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#test()
	 */
	public boolean test() throws Exception {
		return job != null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#getFailureMessage()
	 */
	public String getFailureMessage() {
		return String.format("Timed out waiting for job with %s ", model.getName());
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void done(IJobChangeEvent event) {
		final Job j = event.getJob();
		if(j.belongsTo(ToolboxJob.FAMILY)) {
			final String jobName = j.getName();
			if(jobName.endsWith(model.getName())) {
				job = j;
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void aboutToRun(IJobChangeEvent event) {
		// nop
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#awake(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void awake(IJobChangeEvent event) {
		// nop
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#running(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void running(IJobChangeEvent event) {
		// nop
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void scheduled(IJobChangeEvent event) {
		// nop
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#sleeping(org.eclipse.core.runtime.jobs.IJobChangeEvent)
	 */
	public void sleeping(IJobChangeEvent event) {
		// nop
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/ChangedModulesGatheringDeltaVisitor.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.util.List;
import java.util.Vector;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;

/**
 * Visitor to find out what files changed
 */

public class ChangedModulesGatheringDeltaVisitor implements IResourceDeltaVisitor
{
    Vector modules = new Vector();

    public ChangedModulesGatheringDeltaVisitor()
    {
    }

    /**
     * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
     */
    public boolean visit(IResourceDelta delta) throws CoreException
    {
        final IResource resource = delta.getResource();
        if (IResource.FILE == resource.getType())
        {
            // a file found
            if (resource.exists() && ResourceHelper.isModule(resource))
            {
                modules.add(resource);
            }
        }
        // we want the visitor to visit the whole tree
        return true;
    }

    /**
     * Retrieves found modules, or an empty list, if nothing found
     * @return a list with found modules
     */
    public List getModules()
    {
        return modules;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/ConfigFileException.java<|end_filename|>
package tlc2.tool;

import tlc2.output.MP;

/**
 * Exceptions signaling errors in the config file
 * <br><b>Note:</b>This class is used instead of Assert.fail inside of the ModelConfig.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class ConfigFileException extends RuntimeException
{
    public ConfigFileException(int errorCode, String[] parameters)
    {
        super(MP.getMessage(errorCode, parameters));
    }

    public ConfigFileException(int errorCode, String[] parameters, Exception cause)
    {
        super(MP.getMessage(errorCode, parameters), cause);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/PcalSymTabException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class PcalSymTabException extends UnrecoverableException
{

    /**
     * @param message
     */
    public PcalSymTabException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/MemIntQueue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:33 PST by lamport
//      modified on Mon Dec 18 22:56:08 PST 2000 by yuanyu

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.util.NoSuchElementException;

import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;

public final class MemIntQueue extends MemBasedSet {
	private final static int InitialSize = 4096;

	private int start;
	private String diskdir;
	private String filename;

	public MemIntQueue(String metadir, String filename) {
		this(metadir, filename, InitialSize);
	}

	public MemIntQueue(String metadir, String filename, final int initialCapacity) {
		super(initialCapacity);
		this.start = 0;
		this.diskdir = metadir;
		this.filename = filename;
	}

	public final void enqueueInt(int elem) {
		if (this.size == this.elems.length) {
			// grow the array
			final int[] newElems = ensureCapacity(InitialSize);
			// copy old content to new array
			int copyLen = this.elems.length - this.start;
			System.arraycopy(this.elems, this.start, newElems, 0, copyLen);
			System.arraycopy(this.elems, 0, newElems, copyLen, this.start);
			this.elems = newElems;
			this.start = 0;
		}
		int last = (this.start + this.size) % this.elems.length;
		this.elems[last] = elem;
		this.size++;
	}

	public final void enqueueLong(long elem) {
		this.enqueueInt((int) (elem >>> 32));
		this.enqueueInt((int) (elem & 0xFFFFFFFFL));
	}

	public final int dequeueInt() {
		// Assert.check(this.len > 0);
		if (this.size < 1) {
			throw new NoSuchElementException();
		}
		int res = this.elems[this.start];
		this.size--;
		this.start = (this.start + 1) % this.elems.length;
		return res;
	}

	public final long dequeueLong() {
		long high = this.dequeueInt();
		long low = this.dequeueInt();
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	public int popInt() {
		// Assert.check(this.len > 0);
		if (this.size < 1) {
			throw new NoSuchElementException();
		}
		return this.elems[--this.size];
	}

	public long popLong() {
		long low = this.popInt();
		long high = this.popInt();
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	// Checkpoint.
	public final void beginChkpt() throws IOException {
		String tmpName = this.diskdir + FileUtil.separator + this.filename + ".tmp";
		BufferedDataOutputStream bos = new BufferedDataOutputStream(tmpName);
		bos.writeInt(this.size);
		int index = this.start;
		for (int i = 0; i < this.size; i++) {
			bos.writeInt(this.elems[index++]);
			if (index == this.elems.length)
				index = 0;
		}
		bos.close();
	}

	public final void commitChkpt() throws IOException {
		String oldName = this.diskdir + FileUtil.separator + this.filename + ".chkpt";
		File oldChkpt = new File(oldName);
		String newName = this.diskdir + FileUtil.separator + this.filename + ".tmp";
		File newChkpt = new File(newName);
		if ((oldChkpt.exists() && !oldChkpt.delete()) || !newChkpt.renameTo(oldChkpt)) {
			throw new IOException("MemStateQueue.commitChkpt: cannot delete " + oldChkpt);
		}
	}

	public final void recover() throws IOException {
		String chkptName = this.diskdir + FileUtil.separator + this.filename + ".chkpt";
		BufferedDataInputStream bis = new BufferedDataInputStream(chkptName);
		this.size = bis.readInt();
		for (int i = 0; i < this.size; i++) {
			this.elems[i] = bis.readInt();
		}
		bis.close();
	}

	/*
	 * The detailed formatter below can be activated in Eclipse's variable view
	 * by choosing "New detailed formatter" from the MemIntQueue context menu.
	 * Insert "MemIntQueue.DetailedFormatter.fpAndtidxAndptr(this);".
	 */
	public static class DetailedFormatter {

		// An Eclipse detailed formatter for when this Queue holds pairs of long
		// (fp) and int (tableau idx)
		public static String fpAndtidx(MemIntQueue aQueue) {
			final StringBuffer buf = new StringBuffer(aQueue.size / 3);
			for (int i = 0; i < aQueue.size; i += 3) {
				final long fp = ((long) aQueue.elems[i] << 32) | ((long) (aQueue.elems[i + 1]) & 0xFFFFFFFFL);
				buf.append("fp: " + fp);
				buf.append(" tidx: " + aQueue.elems[i + 2]);
				buf.append("\n");
			}
			return buf.toString();
		}

		// An Eclipse detailed formatter for when this Queue holds pairs of long
		// (fp), int (tableau idx) and long (disk graph pointer).
		public static String fpAndtidxAndptr(MemIntQueue aQueue) {
			final StringBuffer buf = new StringBuffer(aQueue.size / 5);
			for (int i = 0; i < aQueue.size; i += 5) {
				final long fp = ((long) aQueue.elems[i] << 32) | ((long) (aQueue.elems[i + 1]) & 0xFFFFFFFFL);
				buf.append("fp: " + fp);
				buf.append(" tidx: " + aQueue.elems[i + 2]);
				final long ptr = ((long) aQueue.elems[i + 3] << 32) | ((long) (aQueue.elems[i + 4]) & 0xFFFFFFFFL);
				buf.append(" ptr: " + ptr);
				buf.append("\n");
			}
			return buf.toString();
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/ModelWriter.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.model;

import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.PlatformUI;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tlc2.output.AbstractSpecWriter;

/**
 * Encapsulates two buffers and provides semantic methods to add content to the TLA file and the CFG file of the model 
 */
public class ModelWriter extends AbstractSpecWriter {
    /**
     * Constructs new model writer
     */
	public ModelWriter() {
		super(true);
	}

    /**
     * {@inheritDoc}
     */
	@Override
    protected String getTLAModuleClosingTag() {
        final StringBuilder sb = ResourceHelper.getModuleClosingTag();
    	
    	return sb.toString();
    }
	
    /**
     * Write the content to files
     * @param tlaFile
     * @param cfgFile
     * @param monitor
     * @throws CoreException
     */
	public void writeFiles(final IFile tlaFile, final IFile cfgFile, final IProgressMonitor monitor) throws CoreException {
		final ContentWriter cw = (inputStream, forTLAFile) -> {
			final IFile file = forTLAFile ? tlaFile : cfgFile;
			
			if (file.exists()) {
				try {
					file.setContents(inputStream, IResource.FORCE, monitor);
				} catch (final CoreException ce) {
					throw new IOException("Exception writing file " + ce.getMessage(), ce);
				}
			} else {
				throw new IOException("Expected file " + file.getName() + " has been removed externally.");
			}
		};
		
		try {
			super.writeFiles(cw);
		} catch (final IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR,
									"Exception encountered attempting to write modules for the model checking.", e));
		}
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/what-is.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/spec/what-is.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>What Is A Spec?</title>
</head>
<!-- a comment -->

<body>
<h1>What Is A Spec?</h1>

 <P> 
In TLA+, the term <em>specification</em> (or <em>spec</em>) is used to mean one of two
things:
<ol> <li>The collection of modules consisting of the root module and and all modules that are imported by the 
root module, either directly or indirectly, with <code>EXTENDS</code> or <code>INSTANCE</code> statements.&nbsp;
In the context of the Toolbox, we exclude from this collection the standard TLA+ modules such as the 
<code>Naturals</code> module.&nbsp;  All the specification's module files must be in the same directory
as the root module file.
</li>

<li>The TLA formula that specifies the set of allowed behaviors of the system or algorithm being specified.</li>
</ol>
We take the word <em>specification</em> by itself to have the first meaning.&nbsp;  We use the term
<em>behavior specification</em> when we mean the second.
 </P> 

<hr> 
<!-- delete rest of line to comment out 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
--> 
<!-- delete rest of line to comment out -->  
<a href = "spec.html">&uarr; Managing Your Specifications</a>
<!-- --> 
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/DistributedFPSetTLCServer.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed;

import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.concurrent.CountDownLatch;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.distributed.fp.DynamicFPSetManager;
import tlc2.tool.distributed.fp.FPSetRMI;
import tlc2.tool.distributed.fp.IFPSetManager;

@SuppressWarnings("serial")
public class DistributedFPSetTLCServer extends TLCServer {
	
	protected final CountDownLatch latch;
	private final int expectedFPSetCount;

	public DistributedFPSetTLCServer(final TLCApp work, final int expectedFPSetCount) throws IOException,
			NotBoundException {
		super(work);
		this.expectedFPSetCount = expectedFPSetCount;
		this.latch = new CountDownLatch(expectedFPSetCount);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCServer#getFPSetManagerImpl(tlc2.tool.distributed.TLCApp, java.lang.String, int)
	 */
	protected IFPSetManager getFPSetManagerImpl(final TLCApp work,
			final String metadir, final int fpsetCount) throws IOException {
		return new DynamicFPSetManager(fpsetCount);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCServerRMI#getFPSetManager()
	 */
	public IFPSetManager getFPSetManager() {
		try {
			this.latch.await();
		} catch (InterruptedException e) {
			// not expected to happen
			MP.printError(EC.GENERAL, e);
		}
		return this.fpSetManager;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCServer#waitForFPSetManager()
	 */
	protected void waitForFPSetManager() throws InterruptedException {
		MP.printMessage(EC.TLC_DISTRIBUTED_SERVER_FPSET_WAITING,
				Integer.toString(this.expectedFPSetCount));
		latch.await();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCServer#registerFPSet(tlc2.tool.distributed.fp.FPSetRMI, java.lang.String)
	 */
	public synchronized void registerFPSet(FPSetRMI fpSet, String hostname) throws RemoteException {
		this.fpSetManager.register(fpSet, hostname);
		latch.countDown();
		
		long diff = this.expectedFPSetCount - latch.getCount();
		MP.printMessage(EC.TLC_DISTRIBUTED_SERVER_FPSET_REGISTERED,
				new String[] { Long.toString(diff),
				Integer.toString(this.expectedFPSetCount)});
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/output/internal/FileProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.internal;

import java.io.ByteArrayInputStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * Sink writing the MC.out file
 * @author <NAME>
 */
public class FileProcessOutputSink implements IProcessOutputSink
{
    protected ISchedulingRule rule;
    protected IFile outFile;
	private Model model;

    public FileProcessOutputSink()
    {

    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#appendText(java.lang.String)
     */
    public synchronized void appendText(final String text)
    {
        try
        {
            ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException
                {
                    // System.out.print(Thread.currentThread().getId() + " : " + message);
                    outFile.appendContents(new ByteArrayInputStream(text.getBytes()), IResource.FORCE, monitor);
                }
            }, rule, IWorkspace.AVOID_UPDATE, new NullProgressMonitor());

            // if the console output is active, print to it
        } catch (CoreException e)
        {
            TLCActivator.logError("Error writing the TLC process output file for " + model.getName(), e);
        }

    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#initializeSink(java.lang.String, int)
     */
    public void initializeSink(Model model, int sinkType)
    {
        boolean isTraceExplore = sinkType == TYPE_TRACE_EXPLORE;

        this.model = model;
        this.outFile = model.getOutputLogFile(isTraceExplore);
        this.rule = ResourceHelper.getModifyRule(outFile);
    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#processFinished()
     */
    public void processFinished()
    {
        /*
                try
                {
                    ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {

                        public void run(IProgressMonitor monitor) throws CoreException
                        {
                            ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE,
                                    new NullProgressMonitor());

                        }
                    }, ResourcesPlugin.getWorkspace().getRoot(), IResource.NONE, new NullProgressMonitor());
                } catch (CoreException e)
                {
                    TLCActivator.getDefault().logError("Error synchronizing the workspace", e);
                }
        */
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/ParseSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Triggers parsing of specification's root file
 * 
 * @author <NAME>
 * @version $Id$
 */
public class ParseSpecHandler extends AbstractHandler implements IHandler
{
    // TODO improve
    private IProgressMonitor monitor = new NullProgressMonitor();

    /**
     * @see IHandler#execute(ExecutionEvent event)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        // List references = UIHelper.checkOpenResources("Modified resources",
        // "Some resources are modified.\nDo you want to save the modified resources?");
        // for (int i = 0; i < references.size(); i++)
        // {
        // // save resources
        // // TODO!!!!
        // // ((EditorReference)references.get(i)).getEditor(false);
        // // saveDirtyEditors();
        // }

        // List editorReferences = UIHelper.getDirtyEditorReferences();
        // if (editorReferences.size() > 0)
        // {
        // boolean saveResources = UIHelper.promptUserForSave("Modified resources",
        // "Some resources are modified.\nDo you want to save the modified resources?");
        // if (saveResources)
        // {
        // UIHelper.saveResources(editorReferences);
        // }
        // }

        boolean proceed = UIHelper.promptUserForDirtyModules();

        if (!proceed)
        {
            return null;
        }

        final Spec spec = Activator.getSpecManager().getSpecLoaded();

        if (spec != null)
        {
            	Job job = new ToolboxJob("Parsing spec handler...") {
					@Override
					protected IStatus run(IProgressMonitor monitor) {
						try
						{
			            	// this only cleans up
			                spec.getProject().build(IncrementalProjectBuilder.CLEAN_BUILD, monitor);
			                // this starts the build process
			                spec.getProject().build(IncrementalProjectBuilder.FULL_BUILD, monitor);
						} catch (CoreException e)
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						return Status.OK_STATUS;
					}
            	};
            	job.schedule();
        } else
        {
            // TODO handle this case (could it occur?, declare in plugin.xml to activate the parse button on active
            // editor only)
        }
        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (Activator.getSpecManager().getSpecLoaded() == null) {
			return false;
		}
		return super.isEnabled();
	}

    /**
     * @deprecated
     */
    protected void saveDirtyEditors()
    {
        Display display = UIHelper.getCurrentDisplay(); 
        display.syncExec(new Runnable() {
            public void run()
            {
                IWorkbenchWindow[] windows = Activator.getDefault().getWorkbench().getWorkbenchWindows();
                for (int i = 0; i < windows.length; i++)
                {
                    IWorkbenchPage[] pages = windows[i].getPages();
                    for (int j = 0; j < pages.length; j++)
                        pages[j].saveAllEditors(false);
                }
            }
        });
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/BEGraphNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:36 PST by lamport
//      modified on Mon Nov 26 14:28:11 PST 2001 by yuanyu

package tlc2.tool.liveness;

import tlc2.util.BitVector;
import util.WrongInvocationException;

public class BEGraphNode extends AbstractGraphNode {
	/**
	 * BEGraphNode is a node in the behaviour graph. We're going to only store
	 * fingerprints of states, rather than actual states. So, as we encounter
	 * each state, we will calculate all the <>[] and []<>s listed in our order
	 * of solution. For each arrow we must record the target node and the
	 * checkActions along it.
	 */
	public long stateFP; // fingerprint of the state
	private BEGraphNode[] nnodes; // outgoing links
	private long number; // for DFS and SCC

	private static final BEGraphNode[] emptyNodes = new BEGraphNode[0];

	public BEGraphNode(long fp) {
		super(new BitVector(0));
		this.stateFP = fp;
		this.nnodes = emptyNodes;
		this.number = 0;
	}

	public final long resetNumberField() {
		long old = this.number;
		this.number = 0;
		return old;
	}

	public final long getNumber() {
		return (this.number & 0x7FFFFFFFFFFFFFFFL);
	}

	public final void incNumber() {
		this.number++;
	}

	public final void setNumber(long num) {
		this.number = (this.number < 0) ? (num | 0x8000000000000000L) : num;
	}

	public final boolean getVisited() {
		return this.number < 0;
	}

	public final void flipVisited() {
		this.number = this.number ^ 0x8000000000000000L;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (stateFP ^ (stateFP >>> 32));
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		BEGraphNode other = (BEGraphNode) obj;
		if (stateFP != other.stateFP) {
			return false;
		}
		return true;
	}

	public final BEGraphNode nextAt(int i) {
		return this.nnodes[i];
	}

	public final int nextSize() {
		return this.nnodes.length;
	}

	public final void addTransition(BEGraphNode target, int slen, int alen, boolean[] acts) {
		int num = this.nnodes.length;
		if (acts != null) {
			int pos = slen + alen * num;
			for (int i = 0; i < acts.length; i++) {
				if (acts[i]) {
					this.checks.set(pos + i);
				}
			}
		}
		BEGraphNode[] newNodes = new BEGraphNode[num + 1];
		System.arraycopy(this.nnodes, 0, newNodes, 0, num);
		newNodes[num] = target;
		this.nnodes = newNodes;
	}

	public final boolean transExists(BEGraphNode target) {
		int len = this.nnodes.length;
		for (int i = 0; i < len; i++) {
			if (target.equals(this.nnodes[i])) {
				return true;
			}
		}
		return false;
	}

	public TBGraphNode getTNode(TBGraph tableau) {
		throw new WrongInvocationException("TLC bug: should never call BEGraphNode.getTNode().");
	}

	public String nodeInfo() {
		return Long.toString(this.stateFP);
	}

	/**
	 * Set node to be the parent of this. This would destroy the original graph.
	 * Use with caution.
	 */
	public final void setParent(BEGraphNode node) {
		if (this.nnodes.length == 0) {
			this.nnodes = new BEGraphNode[1];
		}
		this.nnodes[0] = node;
	}

	public final BEGraphNode getParent() {
		return this.nnodes[0];
	}

	/**
	 * This method assumes that the visited field of all the nodes is set to the
	 * same value. It flips the visited field. We use the high-order bit of
	 * this.number as the visited bit.
	 */
	public final String toString() {
		StringBuffer buf = new StringBuffer();
		this.toString(buf, this.getVisited());
		return buf.toString();
	}

	protected void toString(StringBuffer buf, boolean unseen) {
		if (this.getVisited() == unseen) {
			this.flipVisited();
			buf.append(this.stateFP + " --> ");
			int size = this.nnodes.length;
			if (size != 0) {
				buf.append(this.nextAt(0).stateFP);
			}
			for (int i = 1; i < size; i++) {
				buf.append(", ");
				buf.append(this.nextAt(i).stateFP);
			}
			buf.append("\n");
			for (int i = 0; i < size; i++) {
				this.nextAt(i).toString(buf, unseen);
			}
		}
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tla2sany/drivers/Github429Test.java<|end_filename|>
package tla2sany.drivers;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import tla2sany.modanalyzer.SpecObj;
import tlc2.tool.CommonTestCase;
import util.SimpleFilenameToStream;
import util.ToolIO;

public class Github429Test {

	private SpecObj moduleSpec;

	@Before
	public void setUp() throws Exception {
		// create a model and initialize
		moduleSpec = new SpecObj(CommonTestCase.BASE_PATH + "Github429.tla", new SimpleFilenameToStream());
		SANY.frontEndInitialize(moduleSpec, ToolIO.out);
	}

	@Test
	public void testForFailedParse() {
        try {
			SANY.frontEndParse(moduleSpec, ToolIO.out);
			SANY.frontEndSemanticAnalysis(moduleSpec, ToolIO.out, false);
		} catch (final Exception e) {
			Assert.fail("No exception should occur during parse. Instead encountered [" + e.getClass()
								+ "] with message: " + e.getMessage());
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCRecordVariableValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.List;

/**
 * @author <NAME>
 */
public class TLCRecordVariableValue extends TLCVariableValue implements TLCMultiVariableValue {

    private static final String[] DELIMETERS = { "[", ",", "]" };

    /**
     * @param recordPairs
     */
	public TLCRecordVariableValue(List<TLCVariableValue> recordPairs) {
        this.value = recordPairs;
    }

	public TLCNamedVariableValue[] getPairs() {
		return (TLCNamedVariableValue[]) ((List<TLCNamedVariableValue>) this.value)
				.toArray(new TLCNamedVariableValue[((List<TLCNamedVariableValue>) this.value).size()]);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#getValue()
	 */
	public Object getValue() {
		return getPairs();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#toSimpleString()
	 */
	public String toSimpleString() {
		return arrayToSimpleStringBuffer(getPairs(), DELIMETERS).toString();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCMultiVariableValue#asList()
	 */
	public List<TLCVariableValue> asList() {
		return (List<TLCVariableValue>) this.value;
	}


	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#innerDiff(org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue)
	 */
	protected void innerDiff(TLCVariableValue other) {
		/*
		 * RECORDS We mark a record element as added or deleted if its label
		 * does not appear in one of the elements of the other record. We
		 * mark the element as changed, and call setInnerDiffInfo on the
		 * elements' values if elements with same label but different values
		 * appear in the two records.
		 */
		if (!(other instanceof TLCRecordVariableValue)) {
			return;
		}
		TLCVariableValue[] firstElts = this.getPairs();
		TLCVariableValue[] secondElts = ((TLCRecordVariableValue) other).getPairs();

		String[] firstLHStrings = new String[firstElts.length];
		for (int i = 0; i < firstElts.length; i++) {
			firstLHStrings[i] = ((TLCNamedVariableValue) firstElts[i]).getName();
		}
		String[] secondLHStrings = new String[secondElts.length];
		for (int i = 0; i < secondElts.length; i++) {
			secondLHStrings[i] = ((TLCNamedVariableValue) secondElts[i]).getName();
		}

		setElementArrayDiffInfo(firstElts, firstLHStrings, secondElts, secondLHStrings);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/TLCLifecycleParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc;

import org.eclipse.core.runtime.jobs.Job;
import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;
import org.lamport.tla.toolbox.tool.tlc.job.TLCJob;

/**
 * Stop all running org.lamport.tla.toolbox.tool.tlc jobs on shutdown
 * 
 * @author <NAME>
 */
public class TLCLifecycleParticipant extends ToolboxLifecycleParticipant {

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.ToolboxLifecycleParticipant#terminate()
	 */
	public void terminate() {
		Job.getJobManager().cancel(TLCJob.AllJobsMatcher);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/callable/FPSetManagerCallable.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp.callable;

import java.util.List;
import java.util.concurrent.Callable;

import tlc2.tool.distributed.fp.FPSetManager;
import tlc2.tool.distributed.fp.FPSetManager.FPSets;
import tlc2.util.BitVector;
import tlc2.util.LongVec;
import util.ToolIO;

public abstract class FPSetManagerCallable implements Callable<BitVectorWrapper> {
	
	protected final FPSetManager fpSetManager;
	protected final List<FPSets> fpset;
	protected final LongVec[] fps;
	protected final int index;
	
	public FPSetManagerCallable(FPSetManager fpSetManager, List<FPSets> fpSets, LongVec[] fps, int index) {
		this.fpSetManager = fpSetManager;
		this.fpset = fpSets;
		this.fps = fps;
		this.index = index;
	}
	
	protected BitVectorWrapper reassign(Exception e) throws Exception {
		ToolIO.out.println("Warning: Failed to connect from "
				+ fpSetManager.getHostName() + " to the fp server at "
				+ fpset.get(index).getHostname() + ".\n" + e.getMessage());
		if (fpSetManager.reassign(index) == -1) {
			ToolIO.out
			.println("Warning: there is no fp server available.");
			// Indicate for all fingerprints of the lost fpset that they are
			// new. This is achieved by setting all bits in BitVector.
			return new BitVectorWrapper(index, new BitVector(fps[index].size(), true));
		} else {
			// Retry with newly assigned FPSet for the given index
			return call();
		}
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/output/MPTest.java<|end_filename|>
package tlc2.output;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import util.ToolIO;

public class MPTest
{

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    @Before
	public void setUp() throws Exception
    {
        ToolIO.setMode(ToolIO.TOOL);
        ToolIO.reset();
    }

    /**
     * Test method for {@link tlc2.output.MP#printError(int)}.
     */
    @Test
	public void testPrintErrorInt()
    {
        MP.printError(EC.UNIT_TEST);
        String[] allMessages = ToolIO.getAllMessages();
        assertEquals(1, allMessages.length);
        assertEquals("Error: [%1%][%2%]", allMessages[0]);
    }

    /**
     * Test method for {@link tlc2.output.MP#printError(int, java.lang.String)}.
     */
    @Test
	public void testPrintErrorIntString()
    {
        String parameter = "EXPECTED";
        MP.printError(EC.UNIT_TEST, parameter);
        String[] allMessages = ToolIO.getAllMessages();
        assertEquals(1, allMessages.length);
        assertEquals("Error: [" + parameter + "][%2%]", allMessages[0]);
    }

    /**
     * Test method for {@link tlc2.output.MP#printError(int, java.lang.String[])}.
     */
    @Test
	public void testPrintErrorIntStringArray()
    {
        String[] parameters = new String[] { "EXPECTED", "EXPECTED2", "TOO MANY" };
        MP.printError(EC.UNIT_TEST, parameters);
        String[] allMessages = ToolIO.getAllMessages();
        assertEquals(1, allMessages.length);
        assertEquals("Error: [" + parameters[0] + "][" + parameters[1] + "]", allMessages[0]);
    }

    @Test
    public void testPrintProgressStats() {
        String[] parameters = new String[] {
                "this.trace.getLevelForReporting()",
                MP.format(3000000),
                MP.format(5000),
                MP.format(1222333444),
                MP.format(10000),
                MP.format(1234)
        };
        MP.printMessage(EC.TLC_PROGRESS_STATS, parameters);
        String[] allMessages = ToolIO.getAllMessages();
        assertEquals(1, allMessages.length);
		assertTrue(allMessages[0], allMessages[0].contains(
				"3,000,000 states generated (10,000 s/min), 5,000 distinct states found (1,234 ds/min), 1,222,333,444 states left on queue.")
				|| allMessages[0].contains(
						"3.000.000 states generated (10.000 s/min), 5.000 distinct states found (1.234 ds/min), 1.222.333.444 states left on queue."));
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/Reducible.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:21:02 PST by lamport
//      modified on Tue Mar 23 00:37:35 PST 1999 by yuanyu

package tlc2.value.impl;

public interface Reducible {

  int size();
  boolean member(Value elem);
  Value diff(Value val);
  Value cap(Value val);
  Value cup(Value val);

  ValueEnumeration elements();
}



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/SetOfLong.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:39 PST by lamport
//      modified on Thu Jul 12 16:10:42 PDT 2001 by yuanyu

package tlc2.util;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;

public final class SetOfLong {
  private int count;
  private int length;
  private int thresh;
  private long table[];
  private boolean hasZero;

  public SetOfLong(int size) {
    this.table = new long[size];
    this.count = 0;
    this.length = size;
    this.thresh = length / 2;
    this.hasZero = false;
  }

  public SetOfLong(int size, float ignore) { this(size); }

  private final void grow() {
    long[] old = table;
    this.count = 0;
    this.length = 2 * this.length + 1;
    this.thresh = this.length / 2;
    this.table = new long[this.length];
    for (int i = 0; i < old.length; i++) {
      long k = old[i];
      if (k != 0) this.put(k);
    }
  }

  /**
   * Add k into the table. Return true iff the table has already
   * contained k.
   */
  public final boolean put(long k) {
    if (count >= thresh) this.grow();
    if (k == 0) {
      if (this.hasZero) return true;
      this.hasZero = true;
      this.count++;
      return false;
    }
    else {
      int loc = ((int)k & 0x7FFFFFFF) % this.length;
      while (true) {
	long ent = this.table[loc];
	if (ent == k) return true;
	if (ent == 0) {
	  table[loc] = k;
	  count++;
	  return false;
	}
	loc = (loc + 1) % this.length;
      }
    }
  }

  /* Return true iff the table contains k. */
  public final boolean contains(long k) {
    if (k == 0) {
      return this.hasZero;
    }
    else {
      int loc = ((int)k & 0x7FFFFFFF) % this.length;
      while (true) {
	long ent = this.table[loc];
	if (ent == k) return true;
	if (ent == 0) return false;
	loc = (loc + 1) % this.length;
      }
    }
  }

  public final int size() { return this.count; }

  public final long sizeof() { return 20 + (8 * this.length); }

  public final long checkFPs() {
    int cnt = 0;
    for (int i = 0; i < this.length; i++) {
      long x = this.table[i];
      if (x != 0) {
	this.table[cnt++] = this.table[i];
      }
    }
    Arrays.sort(this.table, 0, cnt);

    long dis = Long.MAX_VALUE;
    long x = 0;
    int i = 0;
    if (!this.hasZero && cnt > 0) {
      x = this.table[0];
      i = 1;
    }
    for (; i < cnt; i++) {
      dis = Math.min(dis, this.table[i]-x);
      x = this.table[i];
    }
    return dis;
  }

  public final void beginChkpt(DataOutputStream dos) throws IOException {
    dos.writeInt(this.count);
    dos.writeInt(this.length);
    dos.writeInt(this.thresh);
    dos.writeBoolean(this.hasZero);
    for (int i = 0; i < this.length; i++) {
      long k = this.table[i];
      if (k != 0) dos.writeLong(k);
    }
  }

  public final void recover(DataInputStream dis) throws IOException {
    this.count = dis.readInt();
    this.length = dis.readInt();
    this.thresh = dis.readInt();
    this.hasZero = dis.readBoolean();
    this.table = new long[this.length];
    int num = this.hasZero ? this.count-1 : this.count;
    for (int i = 0; i < num; i++) {
      this.put(dis.readLong());
    }
  }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/LetInNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import tla2sany.xml.SymbolContext;

public class LetInNode extends ExprNode
implements ExploreNode, LevelConstants {

  /**
   * This node represents a LET expression, for example
   *
   * LET Foo(a) == a + x
   *     Bar == Foo(a) + a
   * IN body
   */

  private SymbolNode[] opDefs;
  public Context context;
    /***********************************************************************
    * opDefs is an array of the OpDefNode and ThmOrAssumpDefNode objects   *
    * defined in the LET. For TLA+1, these LET definitions were never      *
    * visible outside the IN expression.  The only reason for remembering  *
    * them was for level checking and printing them out.  Since in TLA+2   *
    * the definitions can be referred to from outside the IN expression,   *
    * the Context `context' was added that captures everything in the      *
    * LET, including ModuleInstanceKind OpDef nodes, and allows            *
    * convenient name lookup of them.  However, to minimize changes and    *
    * the possibility that allows for errors, the opDefs field has been    *
    * maintained.                                                          *
    ***********************************************************************/
  private InstanceNode[] insts;
    /***********************************************************************
    * Like opDefs, except for the OpDef nodes of kind ModuleInstanceKind.  *
    * Used only for level checking.                                        *
    ***********************************************************************/
  private ExprNode body;

  /* Constructor */
  public LetInNode(TreeNode             treeNode,
                   SymbolNode[]          defs,
                   InstanceNode[]       insts,
                   ExprNode bdy,
                   Context ctext) {
    super(LetInKind, treeNode);
    this.opDefs = defs;
    this.insts = insts;
    this.body = bdy;
    this.context = ctext;
  }

  /**
   * Return the array of LET operator definitions. In the example above,
   * getLets()[1] is the OpDefNode representing the definition of Bar.
   */
  /*************************************************************************
  * The following method is not used by the parser and was provided for    *
  * use by tools.  It is no longer needed, since tools, can obtain that    *
  * information from the (public) context field.  However, TLC uses it,    *
  * until it is changed, we must provide it.  Since opDefs was changed to  *
  * include both ThmOrAssumpDefNode objects and ModuleInstanceKind         *
  * OpDefNode objects, it must be reimplemented.                           *
  *************************************************************************/
  private OpDefNode[] gottenLets = null ;
  public final OpDefNode[] getLets() {
    if (gottenLets == null) {
      /*********************************************************************
      * First count how many UserDefinedOpKind OpDefNode objects are in    *
      * opDefs.                                                            *
      *********************************************************************/
      int cnt = 0 ;
      for (int i = 0 ; i < opDefs.length ; i++) {
        if (opDefs[i].getKind() == UserDefinedOpKind) {cnt++;} ;
       }
      gottenLets = new OpDefNode[cnt] ;
      cnt = 0 ;
      for (int i = 0 ; i < opDefs.length ; i++) {
        if (opDefs[i].getKind() == UserDefinedOpKind) {
          gottenLets [cnt] = (OpDefNode) opDefs[i] ;
          cnt++;} ;
       }

     }
    return this.gottenLets;
    }

  /* Return the body of the LET expression (the IN expression). */
  public final ExprNode getBody() { return this.body; }

  /* Level checking */
// These fields are now part of all LevelNode subclasses.
//  private boolean levelCorrect;
//  private int level;
//  private HashSet levelParams;
//  private SetOfLevelConstraints levelConstraints;
//  private SetOfArgLevelConstraints argLevelConstraints;
//  private HashSet argLevelParams;

  @Override
  @SuppressWarnings("unchecked")
  public final boolean levelCheck(int itr) {
    if (this.levelChecked >= itr) return this.levelCorrect;
    levelChecked = itr ;

    // Level check all the components:
    this.levelCorrect = true;
    for (int i = 0; i < this.opDefs.length; i++) {
    /***********************************************************************
    * In TLA+2, opDefs contains ModuleInstanceKind OpDefNode objects,      *
    * which should not be level checked.  (They have no body to level      *
    * check.)                                                              *
    ***********************************************************************/
      if (   (this.opDefs[i].getKind() != ModuleInstanceKind)
          && !this.opDefs[i].levelCheck(itr)) {
        this.levelCorrect = false;
      }
    }
    if (!this.body.levelCheck(itr)) {
      this.levelCorrect = false;
    }
    for (int i = 0; i < this.insts.length; i++) {
      if (!this.insts[i].levelCheck(itr)) {
        this.levelCorrect = false;
      }
    }

    // Calculate level information:
    this.level = this.body.getLevel();

    /***********************************************************************
    * 23 February 2009: Added ".clone" to the following statements.  I     *
    * don't think this is needed and that everything works fine despite    *
    * the aliasing of the levelParams and allParams fields of this node    *
    * and its body to the same HashSets, but it doesn't hurt to be safe.   *
    ***********************************************************************/
    this.levelParams = (HashSet<SymbolNode>)this.body.getLevelParams().clone();
    this.allParams   = (HashSet<SymbolNode>) this.body.getAllParams().clone();

//    this.levelConstraints = new SetOfLevelConstraints();
    this.levelConstraints.putAll(this.body.getLevelConstraints());
    for (int i = 0; i < this.opDefs.length; i++) {
      if (this.opDefs[i].getKind() != ModuleInstanceKind) {
         this.levelConstraints.putAll(opDefs[i].getLevelConstraints());} ;
        /*******************************************************************
        * opDefs[i] is level checked above.                                *
        *******************************************************************/
    }

//    this.argLevelConstraints = new SetOfArgLevelConstraints();
    this.argLevelConstraints.putAll(this.body.getArgLevelConstraints());
    for (int i = 0; i < this.opDefs.length; i++) {
      if (this.opDefs[i].getKind() != ModuleInstanceKind) {
        this.argLevelConstraints.putAll(opDefs[i].getArgLevelConstraints());} ;
    }

//    this.argLevelParams = new HashSet();
    this.argLevelParams.addAll(this.body.getArgLevelParams());
    for (int i = 0; i < this.opDefs.length; i++) {
      if (this.opDefs[i].getKind() != ModuleInstanceKind) {
        /*******************************************************************
        * opDefs[i] is either an OpDefNode or a ThmOrAssumpDefNode; only   *
        * an OpDefNode can have parameters.                                *
        *******************************************************************/
        FormalParamNode[] params = new FormalParamNode[0] ;
        if (this.opDefs[i].getKind() != ThmOrAssumpDefKind){
          params = ((OpDefNode) this.opDefs[i]).getParams();
          } ;
        Iterator<ArgLevelParam> iter = this.opDefs[i].getArgLevelParams().iterator();
        while (iter.hasNext()) {
          ArgLevelParam alp = iter.next();
          if (!alp.occur(params)) {
            this.argLevelParams.add(alp);
          }
         }
       }
    }
    for (int i = 0; i < this.insts.length; i++) {
      this.argLevelParams.addAll(this.insts[i].getArgLevelParams());
        /*******************************************************************
        * insts[i] level checked above.                                    *
        *******************************************************************/
     }
    return this.levelCorrect;
  }

//  public final int getLevel() { return this.level; }
//
//  public final HashSet getLevelParams() { return this.levelParams; }
//
//  public final SetOfLevelConstraints getLevelConstraints() {
//    return this.levelConstraints;
//  }
//
//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    return this.argLevelConstraints;
//  }
//
//  public final HashSet getArgLevelParams() {
//    return this.argLevelParams;
//  }

  /**
   * toString, levelDataToString, and walkGraph methods to implement
   * ExploreNode interface
   */
//  public final String levelDataToString() {
//    return "Level: "               + this.level               + "\n" +
//           "LevelParameters: "     + this.levelParams         + "\n" +
//           "LevelConstraints: "    + this.levelConstraints    + "\n" +
//           "ArgLevelConstraints: " + this.argLevelConstraints + "\n" +
//           "ArgLevelParams: "      + this.argLevelParams      + "\n" ;
//  }

  @Override
  public SemanticNode[] getChildren() {
      SemanticNode[] res =
         new SemanticNode[this.opDefs.length + this.insts.length + 1];
      res[res.length-1] = this.body;
      int i;
      for (i = 0; i < this.opDefs.length; i++) {
          res[i] = this.opDefs[i];
      }
      for (int j = 0; j < this.insts.length; j++) {
          res[i+j] = this.insts[j];
      }
      return res;
   }

  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);

    if (semNodesTable.get(uid) != null) return;

    semNodesTable.put(uid, this);
    visitor.preVisit(this);

    /***********************************************************************
    * Can now walk LET nodes from context, don't need to use opDefs        *
    * (which is incomplete).                                               *
    ***********************************************************************/
    if (context != null){context.walkGraph(semNodesTable, visitor);} ;
//    if (opDefs != null) {
//      for (int i = 0; i < opDefs.length; i++) {
//        if (opDefs[i] != null) opDefs[i].walkGraph(semNodesTable);
//      }
//    }
    if (body != null) body.walkGraph(semNodesTable, visitor);
    visitor.postVisit(this);
  }

  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";

    String ret = "\n*LetInNode: " + super.toString(depth);
    /***********************************************************************
    * Print context.                                                       *
    ***********************************************************************/
    Vector contextEntries = context.getContextEntryStringVector(1,false);
      /*********************************************************************
      * The depth argument 1 of getContextEntryStringVector causes only    *
      * the name and node uid of the entry and not the node itself to be   *
      * printed.                                                           *
      *********************************************************************/
    if (contextEntries != null) {
      for (int i = 0; i < contextEntries.size(); i++) {
        if (contextEntries.elementAt(i) != null) {
          ret += Strings.indent(2, (String)contextEntries.elementAt(i));
        }
        else {
          ret += "*** null ***"; };
        } ;
      } ;

    /***********************************************************************
    * We no longer print opDefs because the information is in the context. *
    ***********************************************************************/
//    for (int i = 0; i < opDefs.length; i++) {
//      ret += Strings.indent(2,"\nDef:" + Strings.indent(2, opDefs[i].toString(depth-1)));
//    }
    ret += Strings.indent(2, "\nBody:" + Strings.indent(2, body.toString(depth-1)));
    return ret;
  }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
    Element ret = doc.createElement("LetInNode");
    ret.appendChild(appendElement(doc,"body",body.export(doc,context)));
    Element arguments = doc.createElement("opDefs");
    for (int i=0; i<opDefs.length; i++) arguments.appendChild(opDefs[i].export(doc,context));
    ret.appendChild(arguments);

    return ret;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/ParseModuleHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.nature.ParserHelper;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Parses the current module in the editor
 * @author <NAME>
 * @version $Id$
 */
public class ParseModuleHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        IEditorPart activeEditor = UIHelper.getActiveEditor();

        // if (activeEditor.isDirty())
        // {
        // // editor is not saved
        // // TODO react on this!
        // }

        // prompt to save any unsaved resources
        // the module open in the active editor could be dependent upon
        // any open module
        boolean proceed = UIHelper.promptUserForDirtyModules();
        if (!proceed)
        {
            return null;
        }

        IEditorInput editorInput = activeEditor.getEditorInput();
        if (editorInput instanceof IFileEditorInput)
        {
            IResource fileToBuild = ((IFileEditorInput) editorInput).getFile();
            // explicitly invoke the module rebuild
            // if the module is the root module, rebuild the spec (and change the status afterwards)
            Spec currentSpec = ToolboxHandle.getCurrentSpec();
            if (currentSpec != null && currentSpec.getRootFile().equals(fileToBuild))
            {
                ParserHelper.rebuildSpec(new NullProgressMonitor());
            } else
            {
                ParserHelper.rebuildModule(fileToBuild, new NullProgressMonitor());
            }
        }

        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActiveEditor() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/TLAMarkerResolutionGenerator.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import org.eclipse.core.resources.IMarker;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IMarkerResolution;
import org.eclipse.ui.IMarkerResolutionGenerator;
import org.eclipse.ui.views.markers.WorkbenchMarkerResolution;
import org.lamport.tla.toolbox.Activator;

/**
 * Marker resolution generator is a factory of marker resoution (also known as quick fixes)
 * @author zambrovski
 */
public class TLAMarkerResolutionGenerator implements IMarkerResolutionGenerator
{

    public IMarkerResolution[] getResolutions(IMarker marker)
    {
        return new DummyMarkerResolution[]{new DummyMarkerResolution(marker)};
    }

    
    public static class DummyMarkerResolution implements IMarkerResolution
    {

        private IMarker problem;
        
        public DummyMarkerResolution(IMarker problem)
        {
            this.problem = problem;
        }
        
        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution#getLabel()
         */
        public String getLabel()
        {
            return "Resolution of the problem " + problem.getAttribute(IMarker.MESSAGE, "");
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution#run(org.eclipse.core.resources.IMarker)
         */
        public void run(IMarker marker)
        {
            Activator.getDefault().logDebug("Marker on " + marker.getAttribute(IMarker.LOCATION, "") + " quick fixed.");
        }
        
    }
    
    
    public static class DummyWBMarkerResolution extends WorkbenchMarkerResolution 
    {

        /* (non-Javadoc)
         * @see org.eclipse.ui.views.markers.WorkbenchMarkerResolution#findOtherMarkers(org.eclipse.core.resources.IMarker[])
         */
        public IMarker[] findOtherMarkers(IMarker[] markers)
        {
            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution2#getDescription()
         */
        public String getDescription()
        {
            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution2#getImage()
         */
        public Image getImage()
        {
            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution#getLabel()
         */
        public String getLabel()
        {
            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.ui.IMarkerResolution#run(org.eclipse.core.resources.IMarker)
         */
        public void run(IMarker marker)
        {
            
        }
        
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/IMessagePrinterRecorder.java<|end_filename|>
package tlc2.output;

/**
 * Interface for recording messages that pass through {@link tlc2.output.MP}.
 */
public interface IMessagePrinterRecorder {
	
	/**
	 * Records a message.
	 * @param code Code identifying the message type.
	 * @param objects Data comprising the message.
	 */
	public void record(int code, Object... objects);
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/TLAPlusExecutor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import tla2sany.semantic.SymbolNode;
import tlc2.tool.impl.FastTool;
import tlc2.tool.impl.Tool;
import tlc2.util.Context;
import tlc2.value.IValue;
import tlc2.value.impl.Value;
import util.SimpleFilenameToStream;

public class TLAPlusExecutor {

	public class Mapping {
		private final Action action;
		private final Map<SymbolNode, IValue> params;
		private final Map<String, SymbolNode> symbol2node;

		public Mapping(final Action a, final String... params) {
			this.action = a;
			this.params = new HashMap<>();
			this.symbol2node = new HashMap<>();
			for (String param : params) {
				final SymbolNode node = action.con.lookupName(s -> s.getName().equals(param));
				this.symbol2node.put(param, node);
			}
		}

		public Mapping set(final String param, final IValue value) {
			final SymbolNode node = this.symbol2node.get(param);
			this.params.put(node, value);
			return this;
		}

		public Context getContext() {
			// Replace TLC's values in ctx with the given ones by extending the pointer list
			// of ctxs.
			Context ctx = action.con;
			for (Map.Entry<SymbolNode, IValue> entry : params.entrySet()) {
				ctx = ctx.cons(entry.getKey(), entry.getValue());
			}
			return ctx;
		}
	}

	private final ReentrantLock lock = new ReentrantLock();
	private final FastTool tool;

	private TLCState state;

	public TLAPlusExecutor(String spec, String config) {
		this.tool = new FastTool(spec, config, new SimpleFilenameToStream(), Tool.Mode.Executor);

		// Initialize the TLA+ executor by generating the initial state.
		this.state = this.tool.getInitStates().first();
	}

	public Mapping map(final String actionName, final String processNode, final IValue v, final String... params) {
		final Action[] actions = tool.getActions();
		for (Action action : actions) {
			if (action.getName().equals(actionName)) {
				final Object lookup = action.con.lookup(s -> s.getName().equals(processNode));
				if (lookup != null) {
					if (lookup.equals(v)) {
						return new Mapping(action, params);
					}
				}
			}
		}
		throw new RuntimeException("failed to create mapping");
	}

	public Object step(final Mapping m) throws Exception {
		final Context ctx = m.getContext();
		lock.lock();
		try {
			while (true) {
				final StateVec nextStates = this.tool.getNextStates(m.action, ctx, state);
				assert !nextStates.isEmpty();
				this.state = nextStates.first();

				// Check invariants.
				for (int k = 0; k < this.tool.getInvariants().length; k++) {
					if (!tool.isValid(this.tool.getInvariants()[k], this.state)) {
						throw new INextStateFunctor.InvariantViolatedException();
					}
				}

				final Object result = this.state.execCallable();
				if (result != null) {
					return result;
				}
			}
		} finally {
			lock.unlock();
		}
	}

	public ReentrantLock getLock() {
		return lock;
	}
	
	public Value getConstant(final String string) {
		return (Value) this.tool.getSpecProcessor().getDefns().get(string);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/ui/util/SemanticHelperTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import java.util.Date;

import junit.framework.TestCase;

/**
 * Tests for semantic helper
 * @author <NAME>
 * @version $Id$
 */
public class SemanticHelperTest extends TestCase
{
    private SemanticHelper helper;

    /**
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
        helper = new SemanticHelper();
        helper.resetModelNames();
    }

    public void testTest()
    {
        assertTrue(true);
    }

    /**
     * Testing the keywords
     */
    public void testKeywords()
    {
        for (int i = 0; i < ITLAReserveredWords.ALL_WORDS_ARRAY.length; i++)
        {
            // all keywords should be found
            assertEquals(SemanticHelper.KEYWORD, helper.getUsedHint(ITLAReserveredWords.ALL_WORDS_ARRAY[i]));
        }
    }

    /**
     * Test of the items on using the same page id
     */
    public void testPutIsGet()
    {
        String[] name = { "<NAME>", "<NAME>" };
        String[] description = { "foo", "bar" };
        Object pageKey = new Integer(1);

        // check pre-condition
        assertFalse(helper.isNameUsed(name[0]));
        assertFalse(helper.isNameUsed(name[1]));
        assertNull(helper.getUsedHint(name[0]));
        assertNull(helper.getUsedHint(name[1]));

        helper.addName(name[0], pageKey, description[0]);

        // check post-condition
        assertTrue(helper.isNameUsed(name[0]));
        assertFalse(helper.isNameUsed(name[1]));
        assertEquals(description[0], helper.getUsedHint(name[0]));
        assertNull(helper.getUsedHint(name[1]));

        helper.addName(name[1], pageKey, description[1]);

        // check post-condition
        assertTrue(helper.isNameUsed(name[0]));
        assertTrue(helper.isNameUsed(name[1]));
        assertEquals(description[0], helper.getUsedHint(name[0]));
        assertEquals(description[1], helper.getUsedHint(name[1]));
    }

    /**
     * Check the opage independence
     */
    public void testPageIndepenednce()
    {
        String name = "my name";
        String[] description = { "foo", "bar" };
        Object[] pageKey = { new Integer(1), new Date() };

        // check pre-condition
        assertFalse(helper.isNameUsed(name));
        assertNull(helper.getUsedHint(name));

        helper.addName(name, pageKey[0], description[0]);

        // check post-condition
        assertTrue(helper.isNameUsed(name));
        assertEquals(description[0], helper.getUsedHint(name));

        // adding it twice
        helper.addName(name, pageKey[1], description[1]);
        // should not change anything
        assertTrue(helper.isNameUsed(name));
        // one of the pages
        assertTrue(helper.getUsedHint(name).equals(description[0]) || helper.getUsedHint(name).equals(description[1]));

        // reset the first page
        helper.resetModelNames(pageKey[0]);
        // should not change anything
        assertTrue(helper.isNameUsed(name));
        // should be still on the second page
        assertTrue(helper.getUsedHint(name).equals(description[1]));

        // reset the second page
        helper.resetModelNames(pageKey[1]);

        // should be not there
        assertFalse(helper.isNameUsed(name));
        assertNull(helper.getUsedHint(name));
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/ParsingTLCOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output;

import org.eclipse.jface.text.BadLocationException;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.source.ITLCOutputSource;
import org.lamport.tla.toolbox.tool.tlc.output.source.TagBasedTLCOutputIncrementalParser;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * A sink that uses TLC output parser for parsing
 * @author <NAME>
 * @version $Id$
 */
public class ParsingTLCOutputSink implements IProcessOutputSink
{
    // private TLCOutputIncrementalParser parser;
    private TagBasedTLCOutputIncrementalParser parser;
	private String buffer = "";

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#appendText(java.lang.String)
     */
    public synchronized void appendText(String text)
    {
    	// parser only handles complete lines, thus we buffer incomplete
    	// lines here (speeds up parsing too)

    	// a) prepend the previous text
    	text = buffer + text;
    	buffer = "";
    	
    	final int lastLineBreak = text.lastIndexOf(10);
    	final int length = text.length();
    	// b) complete lines are directly fed to the parser
		if (lastLineBreak == length) {
    		addIncrement(text);
    	// c) Feed all complete lines of a multi-line input
    	} else {
    		final String substring = text.substring(0, lastLineBreak + 1);
    		addIncrement(substring);
    		// d) suffix is saved for next invocation or done()
    		buffer = text.substring(lastLineBreak + 1);
    	}
    }

    private void addIncrement(final String input) {
		try {
			parser.addIncrement(input);
		} catch (BadLocationException e) {
            TLCUIActivator.getDefault().logError("Error parsing the TLC output stream for "
                    + this.parser.getSource().getModel(), e);
		}
    }
    
    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#initializeSink(java.lang.String, int)
     */
    public void initializeSink(Model model, int sinkType)
    {
        boolean isTraceExploration = sinkType == IProcessOutputSink.TYPE_TRACE_EXPLORE;
        // parser = new TLCOutputIncrementalParser(processName, ITLCOutputSource.PRIO_HIGH);
        parser = new TagBasedTLCOutputIncrementalParser(model, ITLCOutputSource.PRIO_HIGH, isTraceExploration);
    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#processFinished()
     */
    public void processFinished()
    {
    	// feed the rest of the buffer to the parser
    	if(buffer.length() > 0) {
    		addIncrement(buffer);
    	}
        this.parser.done();
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/FPSet.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:13:19 PST by lamport
//      modified on Tue May 15 11:44:57 PDT 2001 by yuanyu

package tlc2.tool.fp;

import java.io.IOException;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import tlc2.tool.TLCTrace;
import tlc2.tool.distributed.fp.DistributedFPSet;
import tlc2.tool.distributed.fp.FPSetRMI;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

/**
 * An <code>FPSet</code> is a set of 64-bit fingerprints.
 *
 * Note: All concrete subclasses of this class are required to
 * guarantee that their methods are thread-safe.
 */
@SuppressWarnings("serial")
public abstract class FPSet extends UnicastRemoteObject implements FPSetRMI
{
	/**
	 * Size of a Java long in bytes
	 */
	protected static final long LongSize = 8;

	/**
	 * Counts the amount of states passed to the containsBlock method
	 */
	//TODO need AtomicLong here to prevent dirty writes to statesSeen?
	protected long statesSeen = 0L;

	protected final FPSetConfiguration fpSetConfig;
	
    protected FPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
    	this.fpSetConfig = fpSetConfig;
    }

    /**
     * Performs any initialization necessary to handle "numThreads"
     * worker threads and one main thread. Subclasses will need to
     * override this method as necessary. This method must be called
     * after the constructor but before any of the other methods below.
     */
    public abstract FPSet init(int numThreads, String metadir, String filename) throws IOException;
    
    public void incWorkers(int num) {
    	// subclasses may override
    }

    /* Returns the number of fingerprints in this set. */
    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#size()
     */
    public abstract long size();

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#put(long)
     */
    public abstract boolean put(long fp) throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#contains(long)
     */
    public abstract boolean contains(long fp) throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#close()
     */
    public void close()
    { /*SKIP*/
    }

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#addThread()
     */
    public void addThread() throws IOException
    { /*SKIP*/
    }

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#exit(boolean)
     */
    public void exit(boolean cleanup) throws IOException {
		// If DistributedFPSet is running, signal termination and wake it up.
		// This is necessary when a SecurityManager intercepts System.exit(int)
		// calls which has the side effect that DistributedFPSet's reporting
		// loop does not terminate and keeps going forever.
		DistributedFPSet.shutdown();
		synchronized (this) {
			this.notify();
		}
    }

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#checkFPs()
     */
    public abstract long checkFPs() throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#beginChkpt()
     */
    public abstract void beginChkpt() throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#commitChkpt()
     */
    public abstract void commitChkpt() throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#recover()
     */
    public abstract void recover(TLCTrace trace) throws IOException;

    public abstract void recoverFP(long fp) throws IOException;

    /* The set of checkpoint methods for remote checkpointing. */
    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#beginChkpt(java.lang.String)
     */
    public abstract void beginChkpt(String filename) throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#commitChkpt(java.lang.String)
     */
    public abstract void commitChkpt(String filename) throws IOException;

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#recover(java.lang.String)
     */
    public abstract void recover(String filename) throws IOException;
    
	/**
	 * @return true iff no invaritant is violated.
	 * @throws IOException
	 */
	public boolean checkInvariant() throws IOException {
		return true;
	}
	
	/**
	 * @param expectFPs
	 *            The expected amount of fingerprints stored in this
	 *            {@link FPSet}
	 * @return true iff no invaritant is violated and the FPSet contains the
	 *         expected amount of fingerprints.
	 * @throws IOException
	 */
	public boolean checkInvariant(long expectFPs) throws IOException {
		return true;
	}

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#putBlock(tlc2.util.LongVec)
     */
    public BitVector putBlock(LongVec fpv) throws IOException
    {
        int size = fpv.size();
		BitVector bv = new BitVector(size);
        for (int i = 0; i < fpv.size(); i++)
        {
			// TODO Figure out why corresponding value in BitVector is inverted
			// compared to put(long)
            if (!this.put(fpv.elementAt(i)))
            {
                bv.set(i);
            }
        }
        return bv;
    }

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#containsBlock(tlc2.util.LongVec)
     */
    public BitVector containsBlock(LongVec fpv) throws IOException
    {
    	statesSeen += fpv.size();
        BitVector bv = new BitVector(fpv.size());
        for (int i = 0; i < fpv.size(); i++)
        {
			// TODO Figure out why corresponding value in BitVector is inverted
			// compared to contains(long)
            if (!this.contains(fpv.elementAt(i)))
            {
                bv.set(i);
            }
        }
        return bv;
    }

    /* (non-Javadoc)
     * @see tlc2.tool.distributed.fp.FPSetRMI#getStatesSeen()
     */
    public long getStatesSeen() throws RemoteException {
    	return statesSeen;
    }
    
    public FPSetConfiguration getConfiguration() {
    	return fpSetConfig;
    }

	/**
	 * @param fpBits
	 * @return
	 */
	public static boolean isValid(int fpBits) {
		return fpBits >= 0 && fpBits <= MultiFPSet.MAX_FPBITS;
	}

	/**
	 * @see UnicastRemoteObject#unexportObject(java.rmi.Remote, boolean)
	 * @param force
	 * @throws NoSuchObjectException
	 */
	public void unexportObject(boolean force) throws NoSuchObjectException {
		UnicastRemoteObject.unexportObject(this, force);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/IModuleLocatable.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.lamport.tla.toolbox.tool.tlc.output.data.CoverageInformationItem;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;

import tla2sany.st.Location;

/**
 * All implementing classes should have a corresponding location
 * within a module and a model name. The model name should correspond to
 * the name of the model that was run to create the implementing class.
 * 
 * Currently this is implemented by {@link TLCState} and {@link CoverageInformationItem}
 * because they both have a corresponding action in a module.
 * @author <NAME>
 *
 */
public interface IModuleLocatable
{

    /**
     * The {@link Location} in the module.
     * @return
     */
    public Location getModuleLocation();

    /**
     * The name of the model.
     * 
     * @return
     */
    public String getModelName();

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ParseUnitRelatives.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.modanalyzer;

import tla2sany.utilities.Vector;

class ParseUnitRelatives {

  Vector extendees  = new Vector();  // vector of ParseUnit objects

  Vector extendedBy = new Vector();  // vector of ParseUnit objects

  Vector instancees = new Vector();  // vector of ParseUnit objects  

  Vector instancedBy = new Vector();  // vector of ParseUnit objects

  public final String toString() {
    return "[ extendees = "   + extendees.toString() +
           ", extendedBy = "  + extendedBy.toString() +
           ", instancees = "  + instancees.toString() +
           ", instancedBy = " + instancedBy.toString() +
           " ]";
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/CombinatoricsTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util;

import static org.junit.Assert.assertEquals;

import java.math.BigInteger;

import org.junit.Test;

public class CombinatoricsTest {
	@Test
	public void testChoose() {
		for (int n = 0; n < Combinatorics.MAXCHOOSENUM; n++) {
			for (int k = 0; k < Combinatorics.MAXCHOOSENUM; k++) {
				long choose = Combinatorics.choose(n, k);
				long binomial = Combinatorics.binomial(n, k);
				assertEquals(String.format("n=%s, k=%s", n, k), choose, binomial);
			}
		}
	}
	@Test
	public void testChooseBigChoose() {
		for (int n = 0; n < Combinatorics.MAXCHOOSENUM + 1; n++) {
			for (int k = 0; k < Combinatorics.MAXCHOOSENUM + 1; k++) {
				long choose = Combinatorics.choose(n, k);
				long bigChoose = Combinatorics.bigChoose(n, k).longValueExact();
				assertEquals(String.format("n=%s, k=%s", n, k), choose, bigChoose);
			}
		}
	}
	@Test
	public void testSlowChooseBigChoose() {
		for (int n = Combinatorics.MAXCHOOSENUM + 1; n < Combinatorics.MAXCHOOSENUM << 2; n++) {
			for (int k = Combinatorics.MAXCHOOSENUM + 1; k < Combinatorics.MAXCHOOSENUM << 2; k++) {
				BigInteger slowBigChoose = Combinatorics.slowBigChoose(n, k);
				BigInteger bigChoose = Combinatorics.bigChoose(n, k);
				assertEquals(String.format("n=%s, k=%s", n, k), slowBigChoose, bigChoose);
			}
		}
	}
	@Test
	public void testBigChoose50c1() {
		final BigInteger bigChoose = Combinatorics.bigChoose(50, 1);
		assertEquals(6, bigChoose.bitLength());
		assertEquals(50L, bigChoose.longValueExact());
	}
	@Test
	public void testBigChoose50c10() {
		final BigInteger bigChoose = Combinatorics.bigChoose(50, 10);
		assertEquals(34, bigChoose.bitLength());
		assertEquals(10272278170L, bigChoose.longValueExact());
	}
	@Test
	public void testBigChoose50c20() {
		final BigInteger bigChoose = Combinatorics.bigChoose(50, 20);
		assertEquals(46, bigChoose.bitLength());
		assertEquals(47129212243960L, bigChoose.longValueExact());
	}
	@Test
	public void testBigChoose50c30() {
		final BigInteger bigChoose = Combinatorics.bigChoose(50, 30);
		assertEquals(46, bigChoose.bitLength());
		assertEquals(47129212243960L, bigChoose.longValueExact());
	}
	@Test
	public void testBigChoose400c1() {
		final BigInteger bigChoose = Combinatorics.bigChoose(400, 1);
		assertEquals(9, bigChoose.bitLength());
		assertEquals(400L, bigChoose.longValueExact());
	}
	@Test
	public void testBigChoose400c50() {
		final BigInteger bigChoose = Combinatorics.bigChoose(400, 50);
		assertEquals(214, bigChoose.bitLength());
		assertEquals(
				"17035900270730601418919867558071677342938596450600561760371485120",
				bigChoose.toString());
	}
	@Test
	public void testBigChoose400c100() {
		final BigInteger bigChoose = Combinatorics.bigChoose(400, 100);
		assertEquals(321, bigChoose.bitLength());
		assertEquals(
				"2241854791554337561923210387201698554845411177476295990399942258896013007429693894018935107174320",
				bigChoose.toString());
	}
	@Test
	public void testBigChoose400c200() {
		final BigInteger bigChoose = Combinatorics.bigChoose(400, 200);
		assertEquals(396, bigChoose.bitLength());
		assertEquals(
				"102952500135414432972975880320401986757210925381077648234849059575923332372651958598336595518976492951564048597506774120",
				bigChoose.toString());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/Location.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.st;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import pcal.PCalLocation;
import pcal.Region;
import util.Assert;
import util.TLAConstants;
import util.UniqueString;

/**
 * A location specifies the position of a syntactic unit in the source.
 * A location is immutable and consists of beginning and ending line and column numbers 
 * and a source name -- usually the name of the file from which the input
 * comes.
 * @author <NAME>, <NAME>
 * @version $Id$                                                              
 */
public final class Location implements Comparable<Location>
{
    // strings used in toString() and Regex
    private static final String LINE = TLAConstants.LINE;
    private static final String LINE_CAP = "Line ";
    private static final String TO_LINE = " to line ";
    private static final String COL = ", col ";
    private static final String COLUMN = ", column ";
    private static final String OF_MODULE = " of module ";
    private static final String IN_MODULE = "In module ";
    private static final String IN = " in ";
    private static final String UNKNOWN_LOCATION = "Unknown location";
    private static final String NATURAL = "([0-9]+)";
    private static final String MODULE_ID = "([A-Za-z_0-9]+)";
    private static final String CLOSE_ACTION = ">";
    private static final String OPEN_ACTION = "<[A-Za-z_0-9]+ "; // The regex used to just be "Action" but the most recent TLC prints the name of the action instead of just the location.

    private static final UniqueString unknown = UniqueString.uniqueStringOf("--unknown--");

    /**
     * Unknown location
     */
    public static final Location nullLoc = new Location(unknown, 0, 0, 0, 0);

    /**
     * A REGEX pattern to match the locations 
     * <br>
     * The usual code will look like following:
     * <pre>
     * Matcher matcher = Location.LOCATION_MATCHER.matcher(inputString);
     * if (matcher.find()) 
     * {
     *      String locationString = matcher.group();
     *      Location location = Location.parseLocation(locationString); 
     * }
     * </pre>
     * @see {@link Location#parseLocation(String)}
     * @see Location#getParsedLocations(String)
     */
    public static final Pattern LOCATION_MATCHER = Pattern
            .compile(LINE + NATURAL /* bl group */+ COL + NATURAL
            /* bc group */+ TO_LINE + NATURAL /* el group */+ COL + NATURAL /* ec group */+ OF_MODULE + MODULE_ID /* module group */);

    /**
     * A REGEX pattern to match the locations 
     */
    public static final Pattern LOCATION_MATCHER2 = Pattern.compile(IN_MODULE + MODULE_ID /* module group */);

    /**
     * A pattern to match locations in states.
     */
    public static final Pattern LOCATION_MATCHER3 = Pattern.compile(OPEN_ACTION + LINE + NATURAL /* bl group */+ COL
            + NATURAL
            /* bc group */+ TO_LINE + NATURAL /* el group */+ COL + NATURAL /* ec group */+ OF_MODULE + MODULE_ID /* module group */
            + CLOSE_ACTION);

    /**
     * A pattern to match locations when there is an error evaluating a nested expression.
     */
    public static final Pattern LOCATION_MATCHER4 = Pattern
            .compile(LINE_CAP + NATURAL /* bl group */+ COLUMN + NATURAL
            /* bc group */+ TO_LINE + NATURAL /* el group */+ COLUMN + NATURAL /* ec group */+ IN + MODULE_ID /* module group */);

    /**
     * An array containing all {@link Pattern} currently defined
     * in this class.
     */
    public static final Pattern[] ALL_PATTERNS = new Pattern[] { LOCATION_MATCHER, LOCATION_MATCHER2,
            LOCATION_MATCHER3, LOCATION_MATCHER4 };

    protected UniqueString name;
    protected int bLine, bColumn, eLine, eColumn;

	public Location(final String fName, final String bl, final String bc, final String el, final String ec) {
		this(UniqueString.uniqueStringOf(fName), Integer.valueOf(bl), Integer.valueOf(bc), Integer.valueOf(el),
				Integer.valueOf(ec));
	}

	public Location(final String fName, int bl, int bc, int el, int ec) {
		this(UniqueString.uniqueStringOf(fName), bl, bc, el, ec);
	}
    
   /**
     * Constructs a location
     * @param fName name of the source
     * @param bl begin line
     * @param bc begin column
     * @param el end line
     * @param ec end column
     */
    public Location(UniqueString fName, int bl, int bc, int el, int ec)
    {
        name = fName;
        bLine = bl;
        bColumn = bc;
        eLine = el;
        eColumn = ec;
    }

    public Location(int bl, int bc, int el, int ec) {
		this((UniqueString) null, bl, bc, el, ec);
	}

	
	/**
	 * @param coordinates
	 *            An int array of size 4 with 0-based coordinates: 0=beginLine,
	 *            1=beginColum, 2=endLine, 3=endColumn. 2 & 3 may be smaller
	 *            than 1 & 2, in which case they get set to 1 & 2.
	 */
	public Location(final int[] coordinates) {
	    // LL modified error message on 7 April 2012
		Assert.check(coordinates != null && coordinates.length == 4, "Illegal coordinates found.");

        bLine = coordinates[0];
        bColumn = coordinates[1];

        eLine = coordinates[2];
		eColumn = coordinates[3];
		
		if (eLine < bLine) {
			eLine = bLine;
		}
		
		if (eColumn < bColumn) {
			eColumn = bColumn;
		}
	}

	/**
     * Factory method to create unknown locations in a given module
     * @param moduleName, string representation of the module name
     * @return a location
     */
    public static Location moduleLocation(String moduleName)
    {
        return new Location(UniqueString.uniqueStringOf(moduleName), 0, 0, 0, 0);
    }

    /**
     * Parses location from its string representation  
     * @param locationString the string representation produced by {@link Location#toString()} method
     * @return location if it could be parsed, or a {@link Location#nullLoc} otherwise
     */
    public static Location parseLocation(String locationString)
    {
        if (locationString == null || locationString.length() == 0 || UNKNOWN_LOCATION.equals(locationString))
        {
            return nullLoc;
        }

        Matcher matcher;
        /*
         * In module (unknown coordinates) 
         */
        if ((matcher = LOCATION_MATCHER2.matcher(locationString)).matches())
        {
            // the REGEX LOCATION_MATCHER2 defines one group
            // which captures the module name
            return moduleLocation(matcher.group(1));
        } else if ((matcher = LOCATION_MATCHER.matcher(locationString)).matches())
        {
            // REGEX LOCATION_MATCHER defines 5 groups
            // these are: bl, bc, el, ec, moduleName
            try
            {
                return new Location(UniqueString.uniqueStringOf(matcher.group(5)), Integer.parseInt(matcher.group(1)),
                        Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)), Integer
                                .parseInt(matcher.group(4)));
            } catch (NumberFormatException e)
            {
                return nullLoc;
            }
        } else if ((matcher = LOCATION_MATCHER3.matcher(locationString.trim())).matches())
        {
            // REGEX LOCATION_MATCHER3 defines 5 groups
            // these are: bl, bc, el, ec, moduleName
            try
            {
                return new Location(UniqueString.uniqueStringOf(matcher.group(5)), Integer.parseInt(matcher.group(1)),
                        Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)), Integer
                                .parseInt(matcher.group(4)));
            } catch (NumberFormatException e)
            {
                return nullLoc;
            }
        } else if ((matcher = LOCATION_MATCHER4.matcher(locationString.trim())).matches())
        {
            // REGEX LOCATION_MATCHER3 defines 5 groups
            // these are: bl, bc, el, ec, moduleName
            try
            {
                return new Location(UniqueString.uniqueStringOf(matcher.group(5)), Integer.parseInt(matcher.group(1)),
                        Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)), Integer
                                .parseInt(matcher.group(4)));
            } catch (NumberFormatException e)
            {
                return nullLoc;
            }
        } else
        {
            // not recognized pattern
            return nullLoc;
        }
    }

    public static Location parseCoordinates(final String source, final String coordinates) {
    	final String[] c = coordinates.split(" ");
		return new Location(source, c[0], c[1], c[2], c[3]);
    }
    
    /**
     * Returns an array of {@link Location} that can be parsed
     * from the input. More precisely, this method returns all
     * instances of {@link Location} <code>loc</code> such that
     * 
     * <pre>
     * loc != null && !loc.equals(Location.nullLoc)
     * </pre>
     * 
     * and such that there exists some substring <code>sub</code> of input
     * for which
     * 
     * <pre>
     * Location loc = Location.parseLocation(sub)
     * </pre>
     * 
     * @param input
     * @return
     * @see Location#nullLoc
     */
    public static Location[] getParsedLocations(String input)
    {
        /*
         * The Toolbox does not support generics,
         * so generics cannot be used here.
         */
        List<Location> locations = new ArrayList<Location>();
        /*
         * For each Pattern defined in this class, we find
         * all matches of the pattern and add this to the list
         * of locations.
         * 
         * Do not add locations that are null or equal
         * to nullLoc.
         */
        Matcher matcher;
        for (int i = 0; i < ALL_PATTERNS.length; i++)
        {
            matcher = ALL_PATTERNS[i].matcher(input);
            while (matcher.find())
            {
                String locationString = matcher.group();
                Location location = Location.parseLocation(locationString);
                if (location != null && !location.equals(nullLoc))
                {
                    locations.add(location);
                }
            }
        }

        return (Location[]) locations.toArray(new Location[locations.size()]);
    }

    /** 
     * gets the begin line number of this location. 
     */
    public final int beginLine()
    {
        return this.bLine;
    }

    /** 
     * gets the begin column number of this location. 
     */
    public final int beginColumn()
    {
        return this.bColumn;
    }

    /** 
     * gets the end line number of this location. 
     */
    public final int endLine()
    {
        return this.eLine;
    }

    public final int[] getCoordinates() {
		return new int[] { bLine, bColumn, eLine, eColumn };
    }
    
    /** 
     * gets the end column number of this location. 
     */
    public final int endColumn()
    {
        return this.eColumn;
    }

    /** 
     * gets the file name of this location. 
     */
    public final String source()
    {
        return name != null ? name.toString() : null;
    }

    public final UniqueString sourceAsUniqueString() {
    	return name;
    }
    
    /**
     * This method should be called by all tools to print the location, so
     * users see a consistent method of identifying a location. I        
     * recommend something like                                           
     *                                                                    
     *   line 17, col 22 to line 18, col 13 of module Foo                   
     *                                                                    
     * where source() = "Foo".                                       
     */
    public final String toString()
    {
        if (this == nullLoc)
        {
            return UNKNOWN_LOCATION;
        } else if (this.name == null) // this arm added by LL on 12 Jun 2010
        {
            return (LINE + bLine + COL + bColumn + TO_LINE + eLine + COL + eColumn + OF_MODULE + "null");
        }
        else if (
             !this.name.equals(unknown) && this.bColumn == 0 && this.eColumn == 0 && this.bLine == 0
                && this.eLine == 0)
        {
            return IN_MODULE + name; // Changed from "Unknown location in module..." by LL on 4 Aug 2009
        } else
        {
            return (LINE + bLine + COL + bColumn + TO_LINE + eLine + COL + eColumn + OF_MODULE + name);
        }
    }

    /**
     * Returns true if object is an instance of Location
     * and has the same begin line, begin column, end line,
     * end column, and module name.
     */
    public boolean equals(Object object)
    {
        if (object instanceof Location)
        {
            Location loc = (Location) object;
            return loc.bLine == bLine && loc.bColumn == bColumn && loc.eLine == eLine && loc.eColumn == eColumn
                    && loc.source().equals(source());
        }

        return false;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + bColumn;
		result = prime * result + bLine;
		result = prime * result + eColumn;
		result = prime * result + eLine;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	/**
	 * Translates the {@link Location} into a PCal {@link Region} adjusting the
	 * 1-based offset to a 0-based one.
	 * 
	 * @return a 0-based {@link Region}
	 */
	public Region toRegion() {
		return new pcal.Region(new PCalLocation(bLine - 1, bColumn - 1),
				new PCalLocation(eLine - 1, eColumn - 1));
	}
	
	/**
	 * @param line
	 * @return returns true if line is in [beginLine, endLine]
	 */
	public boolean containsLine(final int line) {
		return ((line >= bLine) && (line <= eLine));
	}

	@Override
	public int compareTo(final Location other) {
		if (this.equals(other)) {
			return 0;
		}
		if (this.name.compareTo(other.name) != 0) {
			return this.name.compareTo(other.name);
		}

		if (this.bLine > other.bLine) {
			return 1;
		} else if (this.bLine < other.bLine) {
			return -1;
		}

		if (this.bColumn > other.bColumn) {
			return 1;
		} else if (this.bColumn < other.bColumn) {
			return -1;
		}
		
		if (this.eLine > other.eLine) {
			return 1;
		} else if (this.eLine < other.eLine) {
			return -1;
		}

		if (this.eColumn < other.eColumn) {
			return -1;
		}
		return 1;
	}
	
	/**
	 * @return true if other is a location within this location (same module file
	 *         and the range of chars is within this range of chars).
	 */
	public boolean includes(final Location other) {
		if (this.name != other.name) {
			return false;
		}
		if (this.bLine > other.bLine) {
			return false;
		}
		if (this.beginLine() == other.beginLine() && this.beginColumn() > other.beginColumn()) {
			return false;
		}
		if (this.eLine < other.eLine) {
			return false;
		}
		if (this.endLine() == other.endLine() && this.endColumn() < other.endColumn()) {
			return false;
		}
		return true;
	}

	public String linesAndColumns() {
		return toString().replaceAll(OF_MODULE + ".*", "");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/management/BucketStatisticsMXWrapper.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util.statistics.management;

import javax.management.NotCompliantMBeanException;

import tlc2.tool.management.TLCStandardMBean;
import tlc2.util.statistics.IBucketStatistics;

public class BucketStatisticsMXWrapper extends TLCStandardMBean implements BucketStatisticsMXBean {

	private IBucketStatistics graphStats;

	private final String objectName;

	public BucketStatisticsMXWrapper(final IBucketStatistics graphStats, final String graphName, final String pkg)
			throws NotCompliantMBeanException {
		super(BucketStatisticsMXBean.class);
		this.graphStats = graphStats;
		
		objectName = graphName;
		registerMBean(String.format("%s:type=%s", pkg, objectName));
	}
	
	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getObjectName()
	 */
	public String getObjectName() {
		return objectName;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getObservations()
	 */
	public long getObservations() {
		return graphStats.getObservations();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getMedian()
	 */
	public int getMedian() {
		return graphStats.getMedian();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getMean()
	 */
	public double getMean() {
		return graphStats.getMean();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getMin()
	 */
	public int getMin() {
		return graphStats.getMin();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getMax()
	 */
	public int getMax() {
		return graphStats.getMax();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#getStdDev()
	 */
	public double getStdDev() {
		return graphStats.getStdDev();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#get75Percentile()
	 */
	public double get75Percentile() {
		return graphStats.getPercentile(0.75d);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#get95Percentile()
	 */
	public double get95Percentile() {
		return graphStats.getPercentile(0.95d);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#get98Percentile()
	 */
	public double get98Percentile() {
		return graphStats.getPercentile(0.98d);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#get99Percentile()
	 */
	public double get99Percentile() {
		return graphStats.getPercentile(0.99d);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.management.GraphStatisticsMXBean#get999Percentile()
	 */
	public double get999Percentile() {
		return graphStats.getPercentile(0.999d);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/part/ValidateableConstantSectionPart.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.part;

import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.page.BasicFormPage;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.provider.AssignmentContentProvider;
import org.lamport.tla.toolbox.tool.tlc.ui.wizard.AssignmentWizard;
import org.lamport.tla.toolbox.tool.tlc.ui.wizard.AssignmentWizardPage;

import tlc2.model.Assignment;

/**
 * Section part for the constants 
 * @author <NAME>
 */
public class ValidateableConstantSectionPart extends ValidateableTableSectionPart
{
    public ValidateableConstantSectionPart(Composite composite, String title, String description, FormToolkit toolkit,
            int flags, BasicFormPage page, String sectionName)
    {
        super(composite, title, description, toolkit, flags, page, sectionName);
    }

    protected Assignment doEditFormula(Assignment formula) // gets called when editing a constant and ...
    {
        Assert.isNotNull(formula);

        // Create the wizard
        AssignmentWizard wizard = new AssignmentWizard(getSection().getText(), getSection().getDescription(),
                (Assignment) formula, AssignmentWizard.SHOW_OPTION, AssignmentWizardPage.CONSTANT_WIZARD_ID);
        // Create the wizard dialog
        WizardDialog dialog = new WizardDialog(getTableViewer().getTable().getShell(), wizard);
        wizard.setWizardDialog(dialog);
        dialog.setHelpAvailable(true);

        // Open the wizard dialog
        if (Window.OK == dialog.open())
        {
            return wizard.getFormula();
        } else
        {
            return null;  // We get here if the user cancels.
        }
    }

    /**
     * Add assignment to the list -- Despite Simon's comments, this is actually called when clicking on ADD 
     * for  Definition Override
     */
    @Override
    @SuppressWarnings("unchecked")  // Generic casting...
    protected void doAdd()
    {
        Assignment formula = doEditFormula((Assignment) null);

        // add a formula
        if (formula != null)
        {
            Vector<Assignment> input = ((Vector<Assignment>) tableViewer.getInput()); // this seems to be the place to check for duplicate overrides.
            input.add(formula);
            tableViewer.setInput(input);
            this.doMakeDirty();
        }
    }

    // This is called when hitting EDIT or double clicking to enter a Constant's value or to change a Definition override.
    @Override
    protected void doEdit()  
    {
        IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
        Assignment formula = (Assignment) selection.getFirstElement();
        if (formula == null) {
        	// User clicked on an empty line in the formula table
        	return;	
        }
        Assignment editedFormula = doEditFormula(formula);
        if (editedFormula != null)
        {
            formula.setParams(editedFormula.getParams());
            formula.setRight(editedFormula.getRight());
            super.doMakeDirty();
            tableViewer.refresh();
        }
    }

    /**
     * create the viewer
     */
    @Override
    protected TableViewer createTableViewer(Table table)
    {
        // create
        TableViewer tableViewer = new TableViewer(table);
        // represent formulas in the view
        tableViewer.setContentProvider(new AssignmentContentProvider());
        // on changed selection change button enablement
        tableViewer.addSelectionChangedListener(fSelectionChangedListener);
        // edit on double-click
        tableViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event)
            {
                doEdit();
            }
        });

        return tableViewer;
    }

    /**
     * create the table (no check boxes)
     */
    @Override
    protected Table createTable(Composite sectionArea, FormToolkit toolkit)
    {
        Table table = toolkit.createTable(sectionArea, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION);
        table.setLinesVisible(false);
        table.setHeaderVisible(false);
        return table;
    }

    /**
     * Only create the edit button
     */
    @Override
    protected void createButtons(Composite sectionArea, FormToolkit toolkit, boolean add, boolean edit, boolean remove)
    {
        doCreateButtons(sectionArea, toolkit, false, true, false);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/frontpage.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
	<title>Close specification</title>
</head>

<body>
<h1>TLA+ Toolbox</h1>
Welcome to TLA+ Toolbox help... As you see this is a custom page called 
<b>frontpage.html</b> located in the <b>html</b> folder of  ..doc
</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools.impl.distributed/src/org/lamport/tlatools/impl/distributed/TLCWrapper.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tlatools.impl.distributed;

import java.io.PrintStream;

import util.ToolIO;

public abstract class TLCWrapper {

	public void connect(String string) {
		PrintStream ps = new OSGiPrintStream(string);
		ToolIO.err = ps;
		ToolIO.out = ps;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/results-page.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/results-page.html  -->

 
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Model Checking Results Page</title>
</head>
<!-- a comment here -->

<body>
<h1>Model Checking Results Page</h1>

<pre>
Contents
  <a href="#general">General</a>
  <a href="#statistics">Statistics</a>
  <a href="#evaluate">Evaluate Constant Expression</a> 
  <a href="#user">User Output</a>
  <a href="#progress">Progress Output</a>

</pre>
 <P> 
This page reports the history and status of the current or most recent execution of
TLC on this model.&nbsp;  This information is retained after TLC stops (either successfully or
with an error).&nbsp;  Even if you close
the spec and open another one, or if you close the Toolbox, it will be there the next time you
open the spec and this model.&nbsp;  The information is lost only if you run TLC on the model
 again or delete the model or the entire spec.&nbsp;  So, don't re-run TLC on this model
 until you are sure you're through examining the results of running it the last time.&nbsp;
 </p><p>Note that you can set the Toolbox to automatically snapshot (clone) the model
 when you re-run it. Please click the corresponding checkbox on the TLC Model Checker
 preference page on the File/Preferences menu. A model snapshot appears in the spec explorer
 tree as a child of its (parent) model. The snapshot's name indicates the date and time of its creation.
 Alternatively, you can manually create a clone of this model to run TLC on.&nbsp;  (See the
 <a href="about-models.html"><em>Models</em></a> help page.)
 </P>


<h2><a name="general">General</a></h2>

<p>
The information reported in this section is self-explanatory.&nbsp;  See the
<a href="overview-page.html#how-to-run">How to run</a> section of the 
<a href="overview-page.html"><em>Model Overview Page</em></a>  help page.&nbsp;  
Clicking on the <em>Errors detected</em> field's link raises the 
<a href="executing-tlc.html#error-reports">TLC Errors View</a>;
ignore the number of errors the field reports.
</p>

<h2><a name="statistics">Statistics</a></h2>

Two kinds of statistics are reported:
<h3>State space progress</h3>

<p>
This shows a history of TLC's reachable state space computation.&nbsp;  The columns have the
following meanings.&nbsp;  (See Section&nbsp;14.26 [page 237] of
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em>.)  </p>
<dl>
<dt><b>Diameter</b></dt>
<dd>The diameter of the reachable-state graph.&nbsp;  It is the length of the longest behavior
found so far.</dd>

<dt><b>States Found</b></dt>
<dd>The total number of states TLC has examined so far.</dd>

<dt><b>Distinct States</b></dt>
<dd>The number of distinct states among the states found.</dd>

<dt><b>Queue Size</b></dt>
<dd>The number of (distinct) states found whose successor states TLC has not
yet determined.  
</dd>
</dl>

<p>Clicking on the heading of any column displays a graph of that column's value
(the vertical axis) versus execution time (the horizontal axis).</p>

<p>
The queue size is the best guide to how far along TLC is in its computation 
of the reachable states.&nbsp;  For most behavior specs, the graph of the queue size versus time
is a convex curve that grows to a maximum and then decreases. 
</p>

<h3>Sub-Actions of next-state</h3>
<p>
A common error in writing a behavior spec is for an action not to be enabled when
it should be, so the spec cannot reach states that represent reachable states of
the actual system being specified.&nbsp;  This kind of error leads to a violation of desired
liveness properties, but does not cause any violation of safety.&nbsp;  The action
statistics give you a way of catching such an error even if you're not
checking liveness.&nbsp;
</p>

<p>Sub-Actions of next-state shows the number of states generated by each sub-action of 
the next-state relation.  Don't worry about how TLC decides what a 
sub-action is; just look at the values reported and the corresponding 
parts of the specification to which they refer.  A sub-action that
generates no states - emphasized by yellow background coloring of the
table row - usually indicates an error in the spec.&nbsp; 
Double-clicking on an entry takes you to the indicated location.  The time shown 
above the table indicates the execution time the numbers were recorded.
</p>

<h2><a name="evaluate">Evaluate Constant Expression</a> </h2>
<p>
This section is described <a href="evaluate-constant-expression.html">on its own page.</a>
</p>

<h2><a name="user">User Output</a></h2>

<p>This section shows the output generated by TLC when it evaluates <code>Print</code>
and <code>PrintT</code> expressions in the spec.&nbsp;  (A PlusCal <code>print</code> statement
generates a TLA<sup>+</sup> <code>PrintT</code> expression.)&nbsp;  These expressions are most often used
for debugging.&nbsp;  The <code>Print</code> operator is described in Section&nbsp;14.4 (page&nbsp;248) of
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em>;  <code>PrintT(exp)</code> is defined to equal <code>Print(exp,TRUE)</code>.
</p>

<h2><a name="progress">Progress Output</a></h2>

This section shows certain progress messages generated by 
TLC.&nbsp; All the useful information that it contains should be summarized in the <em>General</em>
section above.&nbsp;  However, it's possible that we've forgotten about something and that 
you will want to see this TLC output.&nbsp;  Check this section if something you
don't understand happens when the Toolbox
runs
TLC.&nbsp;  If you don't find anything that helps you here, try 
the <a href="executing-tlc.html#console">TLC Console View</a>.


<hr> 
<!-- delete rest of line to comment out 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 --> 
<!-- delete rest of line to comment out -->  
<a href = "creating-model.html">&uarr; Creating a Model</a>
<!-- --> 
</hr>

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/ExpandableSpaceReclaimer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.events.IExpansionListener;
import org.eclipse.ui.forms.widgets.Section;

/**
 * There are a few scenarios in which we want the collapse of a section to force a neighboring component to expand into
 * 	that space. This class begins to address that.
 * 
 * <b>Note</b> this class presently only handles N-child SashForms and is only coded to handle those with vertical
 * 	layout.
 */
public class ExpandableSpaceReclaimer implements IExpansionListener {
	private static final double MINIMUM_SASH_PART_PERCENTAGE = 0.1;
	
	
	private final Section m_section;
	private final SashForm m_sashForm;
	
	private final int m_sectionIndex;
	private final int m_otherChildrenCount;
	
	private Point m_lastSectionSizeOnCollapse;
	
	/**
	 * An instance should be constructed only after all children have been added to the sash form.
	 * 
	 * @param s the section which we will listen for collapse and expansion on
	 * @param sf the sash form in which the section sits
	 * @throws IllegalArgumentException if the section is not one of the sash form's children
	 */
	public ExpandableSpaceReclaimer(final Section s, final SashForm sf) {
		m_section = s;
		m_sashForm = sf;
		
		final Control[] children = m_sashForm.getChildren();
		int index = -1;
		for (int i = 0; i < children.length; i++) {
			if (s == children[i]) {
				index = i;
				
				break;
			}
		}
		
		if (index == -1) {
			throw new IllegalArgumentException("Section could not be found in the sash form.");
		}
		
		m_sectionIndex = index;
		m_otherChildrenCount = children.length - 1;
		m_section.addExpansionListener(this);
		
		m_lastSectionSizeOnCollapse = null;
	}
	
	@Override
	public void expansionStateChanging(final ExpansionEvent ee) {
		if (!ee.getState()) {
			m_lastSectionSizeOnCollapse = m_section.getSize();
		}
	}

	@Override
	public void expansionStateChanged(final ExpansionEvent ee) {
		final Point sashFormSize = m_sashForm.getSize();
		final int totalSashConsumption = m_sashForm.getSashWidth() * m_otherChildrenCount;
		
		if (ee.getState()) { // => now expanded
			final Point desiredSize = (m_lastSectionSizeOnCollapse != null)
											? m_lastSectionSizeOnCollapse
											: m_section.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
			
			if (m_sashForm.getOrientation() == SWT.VERTICAL) {
				final int minimumHeight = (int)(MINIMUM_SASH_PART_PERCENTAGE * (double)sashFormSize.y);
				final int totalMinimumHeight = (minimumHeight  * m_otherChildrenCount) + totalSashConsumption;
				final double usableSashFormHeight = sashFormSize.y - totalSashConsumption;
				
				if (desiredSize.y < (sashFormSize.y - totalMinimumHeight)) {
					final double remainingHeight = usableSashFormHeight - desiredSize.y;
					final int[] weights = m_sashForm.getWeights();
					double sumOfOtherWeights = 0;
					
					for (int i = 0; i < weights.length; i++) {
						if (i != m_sectionIndex) {
							sumOfOtherWeights += weights[i];
						}
					}

					final double[] newHeights = new double[weights.length];
					int heightSum = 0;
					for (int i = 0; i < weights.length; i++) {
						if (i != m_sectionIndex) {
							final double percentage = (double)weights[i] / sumOfOtherWeights;
							newHeights[i] = (int)(percentage * remainingHeight);
							heightSum += newHeights[i];
						}
					}
					newHeights[m_sectionIndex] = usableSashFormHeight - heightSum;

					final int[] newWeights = new int[weights.length];
					for (int i = 0; i < weights.length; i++) {
						newWeights[i] = (int)(newHeights[i] * 100.0 / usableSashFormHeight);
					}
					
					m_sashForm.setWeights(newWeights);
				} // else let the user fend for themselves
			} else {
				final int minimumWidth = (int)(MINIMUM_SASH_PART_PERCENTAGE * (double)sashFormSize.x);
				final int totalMinimumWidth = (minimumWidth + m_sashForm.getSashWidth()) * m_otherChildrenCount;
				
				if (desiredSize.x < (sashFormSize.x - totalMinimumWidth)) {
					
				} // else let the user fend for themselves
			}
		} else {
			final Point sectionSize = m_section.getSize();
			final Point sectionClientSize = m_section.getClient().getSize();
			
			if (m_sashForm.getOrientation() == SWT.VERTICAL) {
				final double titleBarHeight = sectionSize.y - sectionClientSize.y;
				final double usableSashFormHeight = sashFormSize.y - (totalSashConsumption + titleBarHeight);
				final int[] weights = m_sashForm.getWeights();
				double sumOfOtherWeights = 0;
				
				for (int i = 0; i < weights.length; i++) {
					if (i != m_sectionIndex) {
						sumOfOtherWeights += weights[i];
					}
				}

				final double[] newHeights = new double[weights.length];
				for (int i = 0; i < weights.length; i++) {
					if (i != m_sectionIndex) {
						final double percentage = (double)weights[i] / sumOfOtherWeights;
						newHeights[i] = (int)(percentage * usableSashFormHeight);
					}
				}
				newHeights[m_sectionIndex] = (int)titleBarHeight;

				final int[] newWeights = new int[weights.length];
				for (int i = 0; i < weights.length; i++) {
					newWeights[i] = (int)(newHeights[i] * 100.0 / usableSashFormHeight);
				}
				
				m_sashForm.setWeights(newWeights);
			} else {
				
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/ToolIO.java<|end_filename|>
package util;

import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.Locale;

/***************************************************************************
* SANY and TLC were written to communicate only by calling the             *
* System.out or System.err println() or print() methods.  The GUI needs    *
* to call the tools directly so it can access data produced by the tool    *
* but not output directly--for example, the ModuleNode objects produced    *
* by SANY. However, it also needs to capture the information contained     *
* in the printed output.  The easiest way to do that would be simply to    *
* attach System.out and System.err to a PipedInputStream and read the      *
* output from it.  Unfortunately, I haven't been able to figure out how    *
* to do that robustly.  The PipedInputStream seems to get broken when it   *
* has stopped receiving output for a while, and I don't know how to        *
* reattach it.  Moreover, I don't know how to detach System.{out,err}      *
* from the PipedInputStream and attach it to another one.                  *
*                                                                          *
* So, I am planning to replace all instances of System.out and             *
* System.err by ToolIO.out and ToolIO.err.  What this does will depend     *
* on the mode, which can currently have one of two values:                 *
*                                                                          *
*   SYSTEM : ToolIO.out and ToolIO.err will be equal to System.out         *
*            and System.err.  This is the default value.                   *
*                                                                          *
*   TOOL   : Output produced by calling ToolIO.out.println, etc.,          *
*             buffered and delivered on calls to the class's methods.      *
***************************************************************************/
public class ToolIO
{
    /**
     * In this mode, print() and println() write to System.out.             
     */
    public static final int SYSTEM = 0;

    /**
     * In this mode, print() and println() write to System.err.             
     */
    public static final int TOOL = 1;

    /**
     * MODE HANDLING                                                            
     *                                                                          
     * The two public methods are the obvious ones for setting and reading the  
     * mode:                                                                    
     *                                                                          
     *    boolean setMode(int mode)                                             
     *    int     getMode()                                                     
     */
    private static int mode = SYSTEM;

    /**
     * Default resolver is responsible for the resolution from module name to
     * input stream. It is used only if no resolver is specified. 
     */
    private static FilenameToStream defaultResolver;

    /**
     * The GUI needs to change the user directory--the default path for     
     * looking up files.  This seems to be impossible with Java.  So, when  
     * this value is non-null, tools should use it for looking up file      
     * names--looking up a file named filename with                         
     *                                                                      
     *    new File(userDir, filename)                                       
     */
    private static String userDir = null;

    public static PrintStream out = System.out;
	/**
	 * Care must be taken with out and err not being synchronized. Concurrent
	 * writes will cause interleaved output.
	 * 
	 * @see Bug #221 in general/bugzilla/index.html
	 */
    public static PrintStream err = System.err;

    // = 1 for testing. Should be set to reasonable value like 1000.
    private static final int InitialMaxLength = 1;

    /**
     * The current sequence of messages is messages[0] ...                  
     * messages[length-1] A single message may contain \n characters.       
     * There will be one message for every call of println().               
     */
    static String[] messages = new String[InitialMaxLength];
    static int length = 0;

    /**
     * The portion of the next message written by invocations of print()    
     * not followed by an invocation of println().                          
     */
    static String nextMessage = "";

    public static String getUserDir()
    {
        return userDir;
    }

    public static void setUserDir(String dir)
    {
        userDir = dir;
    }

    /**
     * Returns the mode of the ToolIO
     * @return one of {@link ToolIO#SYSTEM},{@link ToolIO#TOOL} 
     */
    public static int getMode()
    {
        return mode;
    }

    /**
     * Set the mode and returns true if the mode argument is legal,         
     * otherwise does nothing and returns false.
     * @param m - the mode, use {@link ToolIO#SYSTEM},{@link ToolIO#TOOL}
     */
    public static boolean setMode(int m)
    {
        if (m == SYSTEM)
        {
            mode = m;
            out = System.out;
            err = System.err;
            return true;
        } else if (m == TOOL)
        {
            mode = m;
            out = new ToolPrintStream();
            err = new ToolPrintStream();
            return true;
        }
        return false;
    }

    /**
     * Resets the ToolIO and deletes the messages   
     * the mode and user directory are not changed 
     */
    public static synchronized void reset()
    {
        /*
         * Throws away all messages obtained so far.                            
         */
        messages = new String[InitialMaxLength];
        length = 0;
        nextMessage = "";
    }

    /**
     * Retrieves the messages send to the err and out streams
     */
    public static synchronized String[] getAllMessages()
    {

        // System.out.println("getAllMessages called with length = " + length) ;
        // for (int i = 0 ; i < messages.length; i++) {
        // System.out.println("GetAllMessages: "+ i + ":") ;
        // System.out.println(messages[i]) ;
        // };

        int retLen = length;
        if (!nextMessage.equals(""))
        {
            retLen++;
        }
        String[] ret = new String[retLen];
        System.arraycopy(messages, 0, ret, 0, retLen);
        if (!nextMessage.equals(""))
        {
            ret[length] = nextMessage;
        }
        return ret;
    } // getAllMessages

    /**
     * Prints all messages to system out
     */
    public static synchronized void printAllMessages()
    {
        /*
         * For debugging use.                                                   
         */
        System.out.println("---- Begin all messages");
        String[] msgs = getAllMessages();
        for (int i = 0; i < msgs.length; i++)
        {
            System.out.println("Msg " + i + ":");
            System.out.println(msgs[i]);
        }
        System.out.println("---- End all messages");
    }

    /**
     * Retrieves the default resolver
     * @return always not null
     */
    public static FilenameToStream getDefaultResolver()
    {
        if (defaultResolver == null)
        {
            setDefaultResolver(null);
        }
        return defaultResolver;
    }

    /**
     * Sets default resolver
     * @param resolver
     */
    public static void setDefaultResolver(FilenameToStream resolver)
    {
        if (resolver == null)
        {
            resolver = new SimpleFilenameToStream();
        }
        ToolIO.defaultResolver = resolver;
    }

} // class ToolIO

class ToolPrintStream extends PrintStream
{
    /**
     * Constructor
     */
    public ToolPrintStream()
    {
        super(new PipedOutputStream());
        ToolIO.out = this;
        ToolIO.err = this;
    }
    
    /* (non-Javadoc)
     * @see java.io.PrintStream#printf(java.lang.String, java.lang.Object[])
     */
    @Override
	public PrintStream printf(String format, Object... args) {
		// See special logic in println. If super.printf(...) gets used, Toolbox
		// functionality breaks.
    	throw new UnsupportedOperationException("use println instead");
	}

	/* (non-Javadoc)
	 * @see java.io.PrintStream#printf(java.util.Locale, java.lang.String, java.lang.Object[])
	 */
	@Override
	public PrintStream printf(Locale l, String format, Object... args) {
		// See special logic in println. If super.printf(...) gets used, Toolbox
		// functionality breaks.
    	throw new UnsupportedOperationException("use println instead");
	}

	/**
     * Prints a string in to the ToolIO buffer in a separate line
     * @param str String to be printed
     */
    public void println(String str)
    {
        // SZ February 20 2009:
        // This is equivalent to
        // synchronized (this.getClass())
        // but is better to understand
        // that the actual synchronization is
        // performed on the static class object
        synchronized (ToolPrintStream.class)
        {
            // System.out.println("Println called with string:") ;
            // System.out.println(str) ;
            String thisMessage = ToolIO.nextMessage + str;
            ToolIO.nextMessage = "";
            /*****************************************************************
             * Enlarge the array if necessary.                                *
             *****************************************************************/
            if (ToolIO.messages.length == ToolIO.length)
            {
                String[] newMessages = new String[2 * ToolIO.messages.length];
                System.arraycopy(ToolIO.messages, 0, newMessages, 0, ToolIO.messages.length);
                ToolIO.messages = newMessages;
            }
            ToolIO.messages[ToolIO.length] = thisMessage;
            ToolIO.length++;

            // SZ February 20 2009:
            // This is a bug: Class.forName("ToolOutput").notifyAll();
            // throws an exception on every invocation
            // and has an empty catch this is a performance killer
            // 
            // The class has been renamed and the synchronization
            // is executed on another object.
            // In order to avoid this kind of bugs in future
            // just changed to another way of doing this
            // try { Class.forName("ToolOutput").notifyAll(); }
            // catch (Exception e) {
            // /*******************************************************************
            // * I have no idea why this exception could be thrown, or what to do *
            // * with it if it is. *
            // *******************************************************************/
            // } ; // catch

            /* **********************************************************************
             * Notify anyone who's waiting for a message.                           *
             * **********************************************************************/
            ToolPrintStream.class.notifyAll();
        } // synchronized
    } // println

    /**
     * Prints a string to the ToolIO message buffer.
     *
     * @param str The <code>String</code> to be printed
     */
    public synchronized void print(String str)
    {
        // SZ February 20 2009:
        // This is equivalent to the next line, but
        // it is better visible, that
        // the synchronization is executed on the static class
        // instance itself
        // synchronized (this.getClass()) {
        synchronized (ToolPrintStream.class)
        {
            // SZ February 20 2009:
            // printing bug fixed instead of printing the string str
            // the string "str" has been printed
            ToolIO.nextMessage += str;
            // SZ February 20 2009:
            // This is a bug: Class.forName("ToolOutput").notifyAll();
            // since the class has been renamed
            // this method throws an exception on every invocation
            // and has an empty catch this is a performance killer
            //
            // try { Class.forName("ToolOutput").notifyAll(); }
            // catch (Exception e) {
            // /******************************************************************
            // * I have no idea why this exception could be thrown, or what to *
            // * do with it if it is. *
            // ******************************************************************/
            // } ;

            /* *********************************************************************
             * Notify anyone who's waiting for a message.                          *
             * *********************************************************************/
            ToolPrintStream.class.notifyAll();
        } // synchronized
    } // print
} // class ToolPrintStream


<|start_filename|>tlatools/org.lamport.tlatools/src/util/FilenameToStream.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package util;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.regex.Pattern;


/**
 * Resolver for the name to file handle.
 *
 * LL comment: 24 July 2013: I believe that the only classes that implements this
 * are SimpleFileNameToStream, RCPNameToFileIStream, and RMIFilenameToStreamResolver.
 * I added the isStandardModule method.
 *
 * @author <NAME>
 * @author <NAME>
 */
public interface FilenameToStream
{

	/*
	 * Higher layers of TLC (and the Toolbox) have to determine if a module was
	 * loaded from a library location s.a. those defined by TLA_LIBRARY (see
	 * SimpleFilenameToStream). Thus, capture this information at module load
	 * time when it is known where a module was loaded from.
	 */
	@SuppressWarnings("serial")
	public static class TLAFile extends File {
		// The following regex is concerned with determining whether the provided 'parent' string to our
		//	parent/child constructor looks like the start of a legal absolute file path potentially including
		//	a drive letter.
		private static final String ROOT_PATH_REGEX
								= "^([a-zA-Z]+:)?" + ((File.separatorChar == '\\') ? "\\\\" : File.separator);
		private static final Pattern ROOT_PATH_PATTERN = Pattern.compile(ROOT_PATH_REGEX);
		
		
		private final boolean isLibraryModule;
		private transient final FilenameToStream resolver;
		// may be null.
		private final URI libraryPath;

		public TLAFile(String pathname, FilenameToStream fts) {
			this(pathname, false, fts);
		}

		public TLAFile(String pathname, boolean isLibraryModule, FilenameToStream fts) {
			super(pathname);
			this.isLibraryModule = isLibraryModule;
			this.libraryPath = this.exists() ? this.toURI() : null;
			this.resolver = fts;
		}

		public TLAFile(Path path, boolean isLibraryModule, FilenameToStream fts) {
			this(path.toFile().toString(), isLibraryModule, fts);
		}

		public TLAFile(String parent, String child, FilenameToStream fts) {
			super(parent,
				  ((ROOT_PATH_PATTERN.matcher(parent).find() && child.startsWith(parent))
						  ? child.substring(parent.length())
					      : child));
			this.libraryPath = this.exists() ? this.toURI() : null;
			this.isLibraryModule = false;
			this.resolver = fts;
		}

		public TLAFile(String pathname, URL location, boolean isLibraryModule, FilenameToStream fts) {
			super(pathname);
			// Do not check exists here like in the other ctors because it returns false
			// before the file is actually read in util.SimpleFilenameToStream.read(String,
			// URL, InputStream). Instead, assume that the file exists if we get here. After
			// all, we know that its inputstream exists.
			// If the conversion from URL to URI fails, we continue with null an hope that
			// everything goes fine.
			this.libraryPath = toNullOrURI(location);
			this.isLibraryModule = isLibraryModule;
			this.resolver = fts;
		}

		public TLAFile(Path path, URL location, boolean isLibraryModule, FilenameToStream fts) {
			this(path.toFile().toString(), location, isLibraryModule, fts);
		}

		private static URI toNullOrURI(URL location) {
	  		try {
	  			return location.toURI();
	  		} catch (URISyntaxException e) {
	  			return null;
	        }
		}

		public boolean isLibraryModule() {
			return isLibraryModule;
		}

		/**
		 * @return null if no TLC module override for this module exists.
		 */
		public File getModuleOverride() {
			final File moduleOverride = resolver.resolve(getName().replaceAll(".tla$", ".class"), false);
			if (moduleOverride.exists()) {
				// resolve(...) return a File instance even if the file doesn't exist.
				return moduleOverride;
			}
			return null;
		}

		/**
		 * This method enables us to keep track of the original path (or library) 
		 * of the module.
		 */
		public URI getLibraryPath() {
			return libraryPath;
		}

		public boolean hasLibraryPath() {
			return libraryPath != null;
		}
	}
	
    /**
     * This method resolves the logical name to the OS-resource
     * @param filename
     * @param isModule
     * @return
     */
    public File resolve(String filename, boolean isModule);

      /**
       * August 2014 - TL
       * Added this method which returns all the path locations stored in the resolver
      */
    public String getFullPath();

    /**
     * Returns true iff moduleName is the name of a standard module, which
     * is identified by the directory in which its source file resides.
     *
     * @param moduleName
     * @return
	 * @see tla2sany.modanalyzer.ParseUnit.isLibraryModule()
	 * @see StandardModules.isDefinedInStandardModule()
     */
    public boolean isStandardModule(String moduleName) ;

	default boolean isLibraryModule(String moduleName) {
		return isStandardModule(moduleName);
	}
 	
	static boolean isInJar(final String aString) {
		return aString.startsWith("jar:") || aString.endsWith(".jar");
	}

	static boolean isArchive(String aString) {
		return isInJar(aString) || aString.endsWith(".zip");
	}
	
	static Path getTempDirectory() {
  		try {
			return Files.createTempDirectory("tlc-");
		} catch (IOException e) {
			// This is unfortunately how we handle things over here. :-(
			e.printStackTrace();
		}
  		return null;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/HCoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class HCoverageTest extends AbstractCoverageTest {

    public HCoverageTest () {
        super("H");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "3"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "26", "6", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertCoverage("<Inv line 22, col 1 to line 22, col 3 of module H>: 1:31\n" + 
				"  line 22, col 11 to line 22, col 16 of module H: 1\n" + 
				"  line 23, col 11 to line 23, col 15 of module H: 31\n" + 
				"<A line 11, col 1 to line 11, col 1 of module H>: 1:6\n" + 
				"  line 11, col 6 to line 11, col 12 of module H: 6\n" + 
				"<BandC line 13, col 1 to line 13, col 5 of module H (13 13 14 28)>: 2:15\n" + 
				"  line 13, col 16 to line 13, col 26 of module H: 11\n" + 
				"  |line 13, col 16 to line 13, col 16 of module H: 6\n" + 
				"  |line 13, col 22 to line 13, col 26 of module H: 6\n" + 
				"  line 14, col 16 to line 14, col 28 of module H: 15\n" + 
				"  |line 14, col 23 to line 14, col 28 of module H: 5\n" + 
				"<BandC line 13, col 1 to line 13, col 5 of module H (15 13 16 22)>: 1:3\n" + 
				"  line 15, col 16 to line 15, col 21 of module H: 3\n" + 
				"  |line 15, col 16 to line 15, col 16 of module H: 6\n" + 
				"  line 16, col 16 to line 16, col 22 of module H: 3\n" + 
				"<DandE line 18, col 1 to line 18, col 5 of module H (18 11 18 27)>: 1:1\n" + 
				"  line 18, col 11 to line 18, col 16 of module H: 7\n" + 
				"  |line 18, col 11 to line 18, col 11 of module H: 6\n" + 
				"  line 18, col 21 to line 18, col 27 of module H: 1\n" + 
				"<DandE line 18, col 1 to line 18, col 5 of module H (18 34 18 53)>: 0:0\n" + 
				"  line 18, col 34 to line 18, col 40 of module H: 6\n" + 
				"  line 18, col 45 to line 18, col 53 of module H: 0");
		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/wizard/NewSpecWizard.java<|end_filename|>
package org.lamport.tla.toolbox.ui.wizard;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;

/**
 * A wizard for creation of new specifications
 * 
 * @author zambrovski
 */
public class NewSpecWizard extends Wizard implements INewWizard
{

    private IStructuredSelection selection;
    private NewSpecWizardPage page;

    private String specName;
	private String rootFilename;
	private boolean importExisting;
	private final String absolutePath;

	public NewSpecWizard() {
		this("");
	}
	
	public NewSpecWizard(String absolutePath) {
		this.absolutePath = absolutePath;
	}

	/*
     * (non-Javadoc)
     * @see org.eclipse.jface.wizard.Wizard#performFinish()
     */
    public boolean performFinish()
    {

		// cache values now (won't be possible later from the page
		// due to widgets getting disposed of)
        rootFilename = page.getRootFilename();
        specName = page.getSpecName();
        importExisting = page.importExisting();

        return true;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench,
     * org.eclipse.jface.viewers.IStructuredSelection)
     */
    public void init(IWorkbench workbench, IStructuredSelection selection)
    {
        this.selection = selection;
    }

    /**
     * Adding the page to the wizard.
     */
    public void addPages()
    {
        page = new NewSpecWizardPage(this.absolutePath);
        addPage(page);
    }

    public ISelection getSelection()
    {
        return this.selection;
    }

	/**
	 * @return the specName
	 */
	public String getSpecName() {
		return specName;
	}

	/**
	 * @return the rootFilename
	 */
	public String getRootFilename() {
		return rootFilename;
	}

    /**
	 * @return the importExisting
	 */
	public boolean isImportExisting() {
		return importExisting;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/data/ActionInformationItemTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.output.data;

import static org.junit.Assert.*;

import org.junit.Test;

public class ActionInformationItemTest {

	@Test
	public void testParseInit() {
		final ActionInformationItem item = ActionInformationItem
				.parseInit("<Init line 13, col 1 to line 14, col 5 of module H>: 3:15", "Model");
		assertNotNull(item);
		assertNull(item.getDefinition());

		assertEquals("H", item.getModule());
		assertEquals("Model", item.getModelName());

		assertEquals("Init", item.getName());
		
		assertEquals(13, item.getModuleLocation().beginLine());
		assertEquals(1, item.getModuleLocation().beginColumn());
		assertEquals(14, item.getModuleLocation().endLine());
		assertEquals(5, item.getModuleLocation().endColumn());

		assertEquals(3, item.getCost());
		assertEquals(15, item.getCount());
	}
	
	@Test
	public void testParseInit2() {
		final ActionInformationItem item = ActionInformationItem
				.parseInit("<Init line 13, col 1 to line 17, col 5 of module H (14 16 15 28)>: 3:15", "Model");
		assertNotNull(item);
		
		assertEquals(14, item.getDefinition().beginLine());
		assertEquals(16, item.getDefinition().beginColumn());
		assertEquals(15, item.getDefinition().endLine());
		assertEquals(28, item.getDefinition().endColumn());

		assertEquals("H", item.getModule());
		assertEquals("Model", item.getModelName());

		assertEquals("Init", item.getName());
		
		assertEquals(13, item.getModuleLocation().beginLine());
		assertEquals(1, item.getModuleLocation().beginColumn());
		assertEquals(17, item.getModuleLocation().endLine());
		assertEquals(5, item.getModuleLocation().endColumn());

		assertEquals(3, item.getCost());
		assertEquals(15, item.getCount());
	}

	@Test
	public void testParseNext() {
		final ActionInformationItem item = ActionInformationItem
				.parseNext("<BandC line 13, col 1 to line 14, col 5 of module H>: 2:15", "Model");
		assertNotNull(item);
		assertNull(item.getDefinition());

		assertEquals("H", item.getModule());
		assertEquals("Model", item.getModelName());

		assertEquals("BandC", item.getName());
		
		assertEquals(13, item.getModuleLocation().beginLine());
		assertEquals(1, item.getModuleLocation().beginColumn());
		assertEquals(14, item.getModuleLocation().endLine());
		assertEquals(5, item.getModuleLocation().endColumn());

		assertEquals(2, item.getCost());
		assertEquals(15, item.getCount());
	}

	@Test
	public void testParseNextWithDefinition() {
		final ActionInformationItem item = ActionInformationItem
				.parseNext("<BandC line 13, col 1 to line 17, col 5 of module H (14 16 15 28)>: 2:15", "Model");
		assertNotNull(item);
		
		assertEquals(14, item.getDefinition().beginLine());
		assertEquals(16, item.getDefinition().beginColumn());
		assertEquals(15, item.getDefinition().endLine());
		assertEquals(28, item.getDefinition().endColumn());

		assertEquals("H", item.getModule());
		assertEquals("Model", item.getModelName());

		assertEquals("BandC", item.getName());
		
		assertEquals(13, item.getModuleLocation().beginLine());
		assertEquals(1, item.getModuleLocation().beginColumn());
		assertEquals(17, item.getModuleLocation().endLine());
		assertEquals(5, item.getModuleLocation().endColumn());

		assertEquals(2, item.getCost());
		assertEquals(15, item.getCount());
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/IParseConstants.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

/**
 * Parse constants (must be in the descending order)
 * @author zambrovski
 * @version $Id$
 */
public interface IParseConstants
{
    /** PARSED = no SANY error */ 
    public static final int PARSED                = 0;
    /** SEMANTIC_WARNING = warnings were produced, but no error. */ 
    public static final int SEMANTIC_WARNING      = -1;
    /** SEMANTIC_ERROR = an error in semantic processing */
    public static final int SEMANTIC_ERROR        = -2;
    /** SYNTAX_ERROR = a parsing error */
    public static final int SYNTAX_ERROR          = -3;
    /** UNKNOWN_ERROR = SANY.frontEndInitialize returned an error, indicating some serious problem that I don't understand. */
    public static final int UNKNOWN_ERROR         = -4;
    /** COULD_NOT_FIND_MODULE = the root module was not found. */
    public static final int COULD_NOT_FIND_MODULE = -5;
    /** UNPARSED = the root module was not parsed */
    public static final int UNPARSED              = -99;
    /** UNKNOW status - the spec is not loaded  */
    public static final int UNKNOWN               = -100;
    
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TLAWordDetector.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import org.eclipse.jface.text.rules.IWordDetector;

/**
 * Detects TLA+ words
 * @author <NAME>
 * @version $Id$
 */
public class TLAWordDetector implements IWordDetector
{

    /* (non-Javadoc)
     * Method declared on IWordDetector.
     */
    public boolean isWordPart(char character)
    {
        return Character.isJavaIdentifierPart(character);
    }

    /* (non-Javadoc)
     * Method declared on IWordDetector.
     */
    public boolean isWordStart(char character)
    {
        return Character.isJavaIdentifierStart(character);
    }
}



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/BuiltInOPs.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.


package tlc2.tool;

import util.UniqueString;

public class BuiltInOPs implements ToolGlobals {

  private static int[] OpCodeTable;

  static {
    OpCodeTable = new int[200];
    
    /* Operators */
    put(OP_aa,   OPCODE_aa);
    put(OP_bc,   OPCODE_bc);
    put(OP_be,   OPCODE_be);
    put(OP_bf,   OPCODE_bf);    
    put(OP_case, OPCODE_case);
    put(OP_cp,   OPCODE_cp);
    put(OP_cl,   OPCODE_cl);
    put(OP_dl,   OPCODE_dl);
    put(OP_exc,  OPCODE_exc);
    put(OP_fa,   OPCODE_fa);
    put(OP_fc,   OPCODE_fc);
    put(OP_ite,  OPCODE_ite);
    put(OP_nrfs, OPCODE_nrfs);
    put(OP_pair, OPCODE_pair);
    put(OP_rc,   OPCODE_rc);
    put(OP_rs,   OPCODE_rs);
    put(OP_rfs,  OPCODE_rfs);
    put(OP_seq,  OPCODE_seq);
    put(OP_sa,   OPCODE_sa);
    put(OP_se,   OPCODE_se);
    put(OP_sf,   OPCODE_sf);
    put(OP_soa,  OPCODE_soa);
    put(OP_sor,  OPCODE_sor);
    put(OP_sof,  OPCODE_sof);
    put(OP_sso,  OPCODE_sso);
    put(OP_tup,  OPCODE_tup);
    put(OP_te,   OPCODE_te);
    put(OP_tf,   OPCODE_tf);
    put(OP_uc,   OPCODE_uc);
    put(OP_ue,   OPCODE_ue);
    put(OP_uf,   OPCODE_uf);
    put(OP_wf,   OPCODE_wf);

    /* Prefix operators */
    put(OP_lnot,      OPCODE_lnot);
    put(OP_subset,    OPCODE_subset);
    put(OP_union,     OPCODE_union);
    put(OP_domain,    OPCODE_domain);
    put(OP_box,       OPCODE_box);
    put(OP_diamond,   OPCODE_diamond);
    put(OP_enabled,   OPCODE_enabled);
    put(OP_unchanged, OPCODE_unchanged);
    
    /* Infix operators */
    put(OP_eq,       OPCODE_eq);
    put(OP_land,     OPCODE_land);
    put(OP_lor,      OPCODE_lor);
    put(OP_implies,  OPCODE_implies);
    put(OP_cdot,     OPCODE_cdot);
    put(OP_equiv,    OPCODE_equiv);
    put(OP_leadto,   OPCODE_leadto);
    put(OP_arrow,    OPCODE_arrow);
    put(OP_noteq,    OPCODE_noteq);
    put(OP_subseteq, OPCODE_subseteq);
    put(OP_in,       OPCODE_in);
    put(OP_notin,    OPCODE_notin);
    put(OP_setdiff,  OPCODE_setdiff);
    put(OP_cap,      OPCODE_cap);
    /***********************************************************************
    * The following added by LL on 2 Aug 2007.                             *
    ***********************************************************************/
    put(OP_nop,      OPCODE_nop);

    put(OP_cup,      OPCODE_cup);

    /* Postfix operators */
    put(OP_prime,    OPCODE_prime);
  }

  private static void put(UniqueString op, int opcode) {
    int loc = op.getTok();
    if (loc >= OpCodeTable.length) {
      int len1 = loc + 20;
      int[] OpCodeTable1 = new int[len1];
      for (int i = 0; i < OpCodeTable.length; i++) {
	OpCodeTable1[i] = OpCodeTable[i];
      }
      OpCodeTable = OpCodeTable1;
    }
    OpCodeTable[loc] = opcode;
  }
	
  /* Return the opcode for op. If it is not builtin, return 0. */
  public static int getOpCode(UniqueString op) {
    int loc = op.getTok();
    return (loc < OpCodeTable.length) ? OpCodeTable[loc] : 0;
  }

  public static int getOpCode(int loc) {
    return (loc < OpCodeTable.length) ? OpCodeTable[loc] : 0;
  }

  public static boolean isTemporal(int opcode) {
    return OPCODE_sf <= opcode && opcode <= OPCODE_diamond;
  }

  public static boolean isAction(int opcode) {
    return OPCODE_prime <= opcode && opcode <= OPCODE_cdot;
  }

}



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/LongArray.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/*
 * On Java 11 (probably starting with 9) sun.misc.Unsafe is implemented on top
 * of jdk.internal.misc.Unsafe which provides a similar though not quiet
 * identical API.  While sun.misc.Unsafe remains available to client code such
 * as LongArray in Java 11, parts of its API have already been dissolved
 * (see e.g. https://bugs.openjdk.java.net/browse/JDK-8202999).  This does not
 * affect LongArray yet, but will probably affect LongArray in the future. 
 * Refactoring LongArray to replace sun.misc.Unsafe with jdk.internal.misc.Unsafe
 * requires the following changes:
 * - Replace sun.misc.Unsafe with jdk.internal.misc.Unsafe
 * - Change Unsafe#compareAndSwapLong with Unsafe#compareAndSetLong in LongArray#trySet
 * - Run LongArray on Java 11 with "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED"
 *   to configure Java's module system (Jigsaw) to expose jdk.internal.misc.Unsafe
 *   to LongArray.
 * The last requirement is visible to TLA+ users who run tla2tools.jar on the
 * command-line.  As we do not want to expose JVM parameters to them, we keep
 * sun.misc.Unsafe for now.
 */
import sun.misc.Unsafe; // jdk.internal.misc.Unsafe;
import tlc2.output.EC;
import util.Assert;
import util.TLCRuntime;

/**
 * This implementation uses sun.misc.Unsafe instead of a wrapping
 * java.nio.ByteBuffer due to the fact that the former's allocateMemory
 * takes a long argument, while the latter is restricted to
 * Integer.MAX_VALUE as its capacity.<br>
 * In 2012 this poses a too hard limit on the usable memory, hence we trade
 * generality for performance.
 */
@SuppressWarnings("restriction")
public final class LongArray {

	private final Unsafe unsafe;
	
	/**
	 * The base address of this direct memory allocated with Unsafe.
	 */
	private final long baseAddress;

	/**
	 * Maximum number of elements that can be contained in this array.
	 */
	private final long length;
	
	/**
	 * CHOOSE logAddressSize \in 1..(Long.SIZE / 8): 2^logAddressSize = (Long.SIZE / 8)
	 */
	private static final int logAddressSize = 3;

	LongArray(final long positions) {
		this.length = positions;
		this.unsafe = getUnsafe();
		
		// LongArray is only implemented for 64bit architectures. A 32bit
		// implementation might be possible. However, implementing CAS (see
		// trySet) seems impossible when values have to be split in two
		// parts (low/hi) on a 32 bit architecture.
		// addressSize(): Report the size in bytes of a native pointer, as
		// stored via #putAddress . This value will be either 4 or 8. We
		// expect 8 (Long.SIZE / 8) which is the size of a TLC fingerprint
		// (see FP64).
		Assert.check(this.unsafe.addressSize() == (Long.SIZE / 8), EC.GENERAL);
		baseAddress = this.unsafe.allocateMemory(positions << logAddressSize);
	}
	
	LongArray(final Collection<Long> from) {
		this(from.size());
		
		final Iterator<Long> itr = from.iterator();
		long i = 0L;
		while(itr.hasNext()) {
			Long next = itr.next();
			set(i++, next);
		}
	}

	/**
	 * @return true iff LongArray can be used on the current JVM. It cannot be used
	 *         if the architecture is not 64 bit and the sun.misc.Unsafe class
	 *         cannot be loaded (on some JVM implementations, this isn't possible).
	 */
	public static boolean isSupported() {
		if (TLCRuntime.ARCH.x86_64 != TLCRuntime.getInstance().getArchitecture()) {
			return false;
		}
		try {
			if (getUnsafe() != null) {
				return true;
			}
			return false;
		} catch (RuntimeException e) {
			return false;
		}
	}
	
	/**
	 * @return An Unsafe object or a {@link RuntimeException} wrapping any {@link Exception}. 
	 */
	private static sun.misc.Unsafe getUnsafe() {
		// More Details can be found at: http://www.mydailyjava.blogspot.no/2013/12/sunmiscunsafe.html
		try {
			// Use reflection API to unhide Unsafe
			final Field f = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
			f.setAccessible(true);
			return (sun.misc.Unsafe) f.get(null);
		} catch (Exception e) {
			throw new RuntimeException(
					"Trying to use Sun VM specific sun.misc.Unsafe implementation but no Sun based VM detected.",
					e);
		}
	}

	/**
	 * Initializes the memory by overriding each byte with zero starting at
	 * <code>baseAddress</code> and ending when all positions have been written.
	 * 
	 * @throws IOException
	 */
	public final void zeroMemory()
			throws IOException {
		this.unsafe.setMemory(baseAddress, length * 8L, (byte) 0); // times 8L because it only writes a single byte.
	}
	
	/**
	 * Initializes the memory by overriding each byte with zero starting at
	 * <code>baseAddress</code> and ending when all positions have been written.
	 * <p>
	 * To speed up the initialization, <code>numThreads</code> allows to set a
	 * thread count with which zeroing is done in parallel.
	 * 
	 * @param numThreads
	 *            Number of threads used to zero memory
	 * @throws IOException
	 */
	public final void zeroMemory(final int numThreads)
			throws IOException {

		final long segmentSize = (long) Math.floor(length / numThreads);
		
		final ExecutorService es = Executors.newFixedThreadPool(numThreads);
		try {
			final Collection<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>(numThreads);
			for (int i = 0; i < numThreads; i++) {
				final int offset = i;
				tasks.add(new Callable<Boolean>() {

					public Boolean call() throws Exception {
						// Null memory (done in parallel on segments).
						// This is essential as allocateMemory returns
						// uninitialized memory and
						// memInsert/memLockup utilize 0L as a mark for an
						// unused fingerprint position.
						// Otherwise memory garbage wouldn't be distinguishable
						// from a true fp.
						final long lowerBound = segmentSize * offset;
						// The last threads zeros up to the end.
						final long upperBound = offset == numThreads - 1 ? length : (1 + offset) * segmentSize;
						for (long pos = lowerBound; pos < upperBound; pos++) {
							set(pos, 0L);
						}
						return true;
					}
				});
			}
			final List<Future<Boolean>> invokeAll = es.invokeAll(tasks);
			Assert.check(!invokeAll.isEmpty(), EC.GENERAL);
		} catch (InterruptedException e) {
			// not expected to happen
			e.printStackTrace();
		} finally {
			es.shutdown();
		}
	}

	/**
	 * Converts from logical positions to 
	 * physical memory addresses.
	 * 
	 * @param logical position (zero indexed)
	 * @return The physical address of the fp slot
	 */
	private final long log2phy(long logicalAddress) {
		return baseAddress + (logicalAddress << logAddressSize);
	}
	
    private final void rangeCheck(final long position) {
		assert position >= 0 && position < this.length;
    }
	
	/**
	 * CAS (compare and swap) variant of {@link LongArray#set(long, long)}.
	 * 
	 * @param position
	 * @param expected
	 * @param value
	 * @return true iff successful 
     * @throws IndexOutOfBoundsException
	 */
	public final boolean trySet(final long position, final long expected, final long value) {
		rangeCheck(position);
		return this.unsafe.compareAndSwapLong(null, log2phy(position), expected, value);
	}
	
    /**
     * Inserts the specified element at the specified position in this
     * array. Overwrites any previous occupant of the specified position.
     *
     * @param position position at which the specified element is to be inserted
     * @param value element to be inserted
     * @throws IndexOutOfBoundsException
     */
	public final void set(final long position, final long value) {
		rangeCheck(position);
		this.unsafe.putAddress(log2phy(position), value);
	}

    /**
     * Returns the element at the specified position in this array.
     *
     * @param  position position of the element to return
     * @return the element at the specified position in this array
     * @throws IndexOutOfBoundsException
     */
	public final long get(final long position) {
		rangeCheck(position);
		return this.unsafe.getAddress(log2phy(position));
	}

	/**
	 * Swaps elements at pos1 and pos2. This is not atomic. The element at pos1
	 * will for a moment not be an element of {@link LongArray}.
	 */
	public final void swap(final long position1, final long position2) {
		rangeCheck(position1);
		rangeCheck(position2);
		final long tmp = get(position1);
		set(position1, get(position2));
		set(position2, tmp);
	}
	
	/*
	 * Variant of swap that uses copyMemory. This implementation - suprisingly - is
	 * *not* faster compared to swap above (see LongArrayBenchmark).
	 */
	void swapCopy(final long position1, final long position2) {
		final long tmp = unsafe.getAddress(log2phy(position1));
		unsafe.copyMemory(log2phy(position2), log2phy(position1), 8L);
		unsafe.putAddress(log2phy(position2), tmp);
	}

	
    /**
     * Returns the number of elements in this array.
     *
     * @return the number of elements in this array
     */
	public final long size() {
		return length;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return toString(0L, length - 1L);
	}

	public String toString(long start, long end) {
        long iMax = end;
        if (iMax == -1L) {
        	return "[]";
        }

        final StringBuilder b = new StringBuilder();
        b.append('[');
        for (long i = start; ; i++) {
            final long lng = get(i);
            if (lng == 0L) {
            	b.append("e");
            } else {
            	b.append(lng);
            }
            if (i == iMax) {
            	return b.append(']').toString();
            }
            b.append(", ");
        }
	}
	
	public static void main(final String[] args) throws IOException {
		final long elements = 1L << Integer.valueOf(args[0]);
		System.out.format("Allocating LongArray with %,d elements.\n", elements);
		final LongArray longArray = new LongArray(elements);
		longArray.zeroMemory();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalResourceFileReader.java<|end_filename|>
/***************************************************************************
* CLASS PcalResourceFileReader                                             *
*                                                                          *
* A PcalResourceFileReader returns an object for reading a resource file,  *
* which is a file kept in the same directory as the pcal.AST class.        *
* The constructor takes a file name as argument.  The object's two public  *
* methods are                                                              *
*                                                                           *
*   getLine() : Returns the next line of the file as a string.  Returns    *
*               null after the last line.                                  *
*                                                                          *
*   close()   : Closes the file.                                           *
***************************************************************************/
package pcal ; 

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Vector;

import pcal.exception.PcalResourceFileReaderException;

public class PcalResourceFileReader
  { public PcalResourceFileReader(String fileName) throws PcalResourceFileReaderException
      /*********************************************************************
      * The constructor, where fileName is the name of a file that's       *
      * in the same directory as pcal.AST.                             *
      *********************************************************************/
     { name = fileName ;
       Class cl = null ;
       
       // TODO fix this!
       try { cl = Class.forName("pcal.AST"); }
       catch (ClassNotFoundException e)
           { throw new PcalResourceFileReaderException( 
               "Java could not find class pcal.AST.  There \n"
             + "    is probably something wrong with the way\n"
             + "    the +cal translator is installed");
           } ;             
       InputStream input = cl.getResourceAsStream(fileName) ; 
       if (input == null)
         { throw new PcalResourceFileReaderException( 
               "Could not find resource file " + fileName + ".\n"
             + "    There is probably something wrong with the way\n"
             + "    the +cal translator is installed");
         } ;  
       inputReader = new BufferedReader(new InputStreamReader(input)) ;
      };

  public static Vector<String> ResourceFileToStringVector(String fileName) throws PcalResourceFileReaderException
    /***********************************************************************
    * Reads file fileName into a StringVector, a vector in which each      *
    * element is a line of the file.                                       *
    ***********************************************************************/
    { Vector<String> inputVec = new Vector<String>(100) ;
       PcalResourceFileReader wordFileReader
                     = new PcalResourceFileReader(fileName);

       String word = wordFileReader.getLine();
       while (word != null)
         { inputVec.addElement(word) ;
           word = wordFileReader.getLine() ;
         } ;
       wordFileReader.close();
       return inputVec ;
     }

    public String getLine() throws PcalResourceFileReaderException
      /*********************************************************************
      * Returns the next line of input.  After it returns the last line    *
      * of input, it returns null.                                         *
      *********************************************************************/
      { try { return inputReader.readLine();
            }
        catch (java.io.IOException e)
          { throw new PcalResourceFileReaderException( 
                   "Error reading the +cal translator resource file " 
                 + name + ".\n"
                 + "    You may be having file system problems");
          }
      }
    private boolean done = false;
      /*********************************************************************
      * If the last line of input doesn't end with a '\n', then getLine()  *
      * returns that line and sets done to true.                           *
      *********************************************************************/

    private BufferedReader inputReader ;
      /*********************************************************************
      * The actual reader for the resource file.                           *
      *********************************************************************/

    private String name ;
      /*********************************************************************
      * A copy of the resource file name, kept for error messages.         *
      *********************************************************************/
      
    public void close() throws PcalResourceFileReaderException
      { try { inputReader.close(); }
        catch (java.io.IOException e)
          { throw new PcalResourceFileReaderException( 
               "Error trying to close the +cal translator resource file " 
            + name + ".\n"
             + "    You may be having file system problems");
          } ;
      } ;


  }      


/* Last modified on Wed  3 Aug 2005 at 18:41:43 UT by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/value/impl/EnumerateSubsetBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import tlc2.util.FP64;
import tlc2.value.RandomEnumerableValues;

@State(Scope.Benchmark)
public class EnumerateSubsetBenchmark {

	static {
		RandomEnumerableValues.setSeed(15041980L);
		RandomEnumerableValues.reset();

		FP64.Init();
	}
	
	@Param({"0", "1", "2", "3", "4", "8", "10", "12", "14", "16", "18", "19"})
	public int numOfElements;

	@Benchmark
	public Enumerable elementsAlwaysNormalized() {
		final IntervalValue inner = new IntervalValue(1, numOfElements);
		final SubsetValue subset = new SubsetValue(inner);

		final ValueVec vals = new ValueVec(subset.size());
		final ValueEnumeration Enum = subset.elementsNormalized();
		Value  elem;
		while ((elem = Enum.nextElement()) != null) {
			vals.addElement(elem);
		}
        return (Enumerable) new SetEnumValue(vals, true).normalize();
	}

	@Benchmark
	public Enumerable kElementsNotNormalized() {
		final IntervalValue inner = new IntervalValue(1, numOfElements);
		final SubsetValue subset = new SubsetValue(inner);

		final ValueVec vec = new ValueVec(subset.size());
		for (int i = 0; i <= inner.size(); i++) {
			final ValueEnumeration Enum = subset.kElements(i);
			Value  elem;
			while ((elem = Enum.nextElement()) != null) {
				vec.addElement(elem);
			}
		}
        return (Enumerable) new SetEnumValue(vec, false);
	}
	
	@Benchmark
	public Enumerable kElementsNormalized() {
		final IntervalValue inner = new IntervalValue(1, numOfElements);
		final SubsetValue subset = new SubsetValue(inner);

		final ValueVec vec = new ValueVec(subset.size());
		for (int i = 0; i <= inner.size(); i++) {
			final ValueEnumeration Enum = subset.kElements(i);
			Value  elem;
			while ((elem = Enum.nextElement()) != null) {
				vec.addElement(elem);
			}
		}
        return (Enumerable) new SetEnumValue(vec, false).normalize();
	}

	@Benchmark
	public Enumerable elementsNotNormalized() {
		final IntervalValue inner = new IntervalValue(1, numOfElements);
		final SubsetValue subset = new SubsetValue(inner);
		
		final ValueVec vals = new ValueVec(subset.size());
		final ValueEnumeration Enum = subset.elementsLexicographic();
		Value  elem;
		while ((elem = Enum.nextElement()) != null) {
			vals.addElement(elem);
		}
		return (Enumerable) new SetEnumValue(vals, false);
	}

	@Benchmark
	public Enumerable elementsNormalized() {
		final IntervalValue inner = new IntervalValue(1, numOfElements);
		final SubsetValue subset = new SubsetValue(inner);
		
		final ValueVec vals = new ValueVec(subset.size());
		final ValueEnumeration Enum = subset.elementsLexicographic();
		Value  elem;
		while ((elem = Enum.nextElement()) != null) {
			vals.addElement(elem);
		}
		return (Enumerable) new SetEnumValue(vals, false).normalize();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/selector/DummyTLCWorker.java<|end_filename|>
package tlc2.tool.distributed.selector;

import java.rmi.RemoteException;

import tlc2.tool.TLCState;
import tlc2.tool.TLCStateVec;
import tlc2.tool.WorkerException;
import tlc2.tool.distributed.NextStateResult;
import tlc2.tool.distributed.TLCWorkerRMI;
import tlc2.tool.distributed.TLCWorkerSmartProxy;
import tlc2.util.LongVec;

public class DummyTLCWorker extends TLCWorkerSmartProxy implements TLCWorkerRMI {

	private long duration;

	public DummyTLCWorker(long duration) {
		super(null);
		this.duration = duration;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerSmartProxy#getNextStates(tlc2.tool.TLCState[])
	 */
	public NextStateResult getNextStates(TLCState[] states) throws RemoteException, WorkerException {
		return new NextStateResult((TLCStateVec[]) null, (LongVec[]) null, duration, -1L);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/DeleteSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Delete specifications.
 * 
 * This command removes the spec from the Toolbox's list of specs and
 * deletes the .toolbox directory.  Class modified slightly by LL
 * on 3 August 2011 because of the addition of the Forget command.
 * 
 * @author <NAME>
 */
public class DeleteSpecHandler extends AbstractHandler implements IHandler {
    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
	public Object execute(ExecutionEvent event) throws ExecutionException {
         /*
         * No parameter try to get it from active navigator if any
         */
		final IWorkbenchPage activePage = UIHelper.getActivePage();
		if (activePage != null) {
            final ISelection selection = activePage.getSelection(ToolboxExplorer.VIEW_ID);
			if ((selection != null) && (selection instanceof IStructuredSelection)
					&& !((IStructuredSelection) selection).isEmpty()) {
                final Iterator<?> selectionIterator = ((IStructuredSelection) selection).iterator();
				while (selectionIterator.hasNext()) {
                	final Object next = selectionIterator.next();
                	if (!(next instanceof Spec)) {
                		// The selection can contain models and groups too.
                		continue;
                	}
                	
                    final Spec spec = (Spec) next;
                    // 3 Aug 2011: LL changed the dialog's message to make it clearer what the Delete command does.
                    final boolean answer
                    	= MessageDialog.openQuestion(UIHelper.getShellProvider().getShell(),
                    								 "Delete specification?",
                    								 "Do you really want the Toolbox to forget the specification "
                    										 		+ spec.getName() + " and delete all its models?");
					if (answer) {
                    	// close the spec handler (in the ui thread)
                    	final WorkspaceSpecManager specManager = Activator.getSpecManager();
                        if (specManager.isSpecLoaded(spec)) {
                        	final CloseSpecHandler handler = new CloseSpecHandler();
                        	final Boolean result = (Boolean)handler.execute(event);
                        	
                        	if ((result != null) && !result.booleanValue()) {
                        		// there was a dirty editor and the user cancelled out of the closing
                        		return null;
                        	}
                        }
                    	
    					final Job j = new ToolboxJob("Deleting spec...") {
    						protected IStatus run(final IProgressMonitor monitor) {
    							Activator.getSpecManager().removeSpec(spec, monitor, false);
    							return Status.OK_STATUS;
    						}
    					};
    					j.schedule();
                    }
                }
            }
        }
        
        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActivePage() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/TLCUINotification.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import java.util.Date;

import org.eclipse.core.runtime.Platform;
import org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification;
import org.eclipse.swt.graphics.Image;

@SuppressWarnings("restriction")
public class TLCUINotification extends AbstractUiNotification {
	
	private final String label;
	private final String description;
	private final Date date;
	
	private Image image;
	private Image kindImage;

	public TLCUINotification(final String label, final String description, final Date date) {
		super("org.lamport.tla.toolbox.tool.tlc.ui.notification.event");
		this.label = label;
		this.description = description;
		this.date = date;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	@Override
	public <T> T getAdapter(Class<T> adapter) {
		return Platform.getAdapterManager().getAdapter(this, adapter);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.core.AbstractNotification#getDate()
	 */
	@Override
	public Date getDate() {
		return date;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.core.AbstractNotification#getDescription()
	 */
	@Override
	public String getDescription() {
		return description;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.core.AbstractNotification#getLabel()
	 */
	@Override
	public String getLabel() {
		return label;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification#getNotificationImage()
	 */
	@Override
	public Image getNotificationImage() {
		return image;
	}
	
	public TLCUINotification setImage(Image image) {
		return this;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification#getNotificationKindImage()
	 */
	@Override
	public Image getNotificationKindImage() {
		return kindImage;
	}

	public TLCUINotification setKindImage(Image image) {
		this.kindImage = image;
		return this;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification#open()
	 */
	@Override
	public void open() {
		// Do nothing
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/OffHeapIndexerTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import java.rmi.RemoteException;

import org.junit.Assert;
import org.junit.Test;

import tlc2.tool.fp.OffHeapDiskFPSet.Indexer;

public class OffHeapIndexerTest {

	@Test
	public void testBitshifting() throws RemoteException {
		final int fpBits = 1;
		final long positions = 128L;
		final int logPos = 8;
		doTest(fpBits, positions, logPos, new OffHeapDiskFPSet.BitshiftingIndexer(positions, fpBits));
	}

	@Test
	public void testRescale() throws RemoteException {
		final int fpBits = 1;
		final long positions = 96L;
		
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(positions, fpBits);

		// indexer spreads over all positions
		Assert.assertEquals(0, indexer.getIdx(1, 0));
		Assert.assertEquals(48, indexer.getIdx(((0xFFFFFFFFFFFFFFFFL >>> fpBits) / 2L)));
		Assert.assertEquals(positions - 1, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits)));
		
		// Correctly wraps around when end of array is reached
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), 1));
		// Correctly wraps around when end of array is reached twice
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), (int)positions+1));
	}

	@Test
	public void testRescale99() throws RemoteException {
		final int fpBits = 1;
		final long positions = 99L;
		
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(positions, fpBits);

		// indexer spreads over all positions
		Assert.assertEquals(0, indexer.getIdx(1));
		Assert.assertEquals(49, indexer.getIdx(((0xFFFFFFFFFFFFFFFFL >>> fpBits) / 2L)));
		Assert.assertEquals(positions - 1, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits)));
		
		// Correctly wraps around when end of array is reached
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), 1));
		// Correctly wraps around when end of array is reached twice
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), (int)positions+1));
	}

	@Test
	public void testBitshifting2() throws RemoteException {
		final int fpBits = 2;
		final long positions = 128L;
		final int logPos = 9;
		doTest(fpBits, positions, logPos, new OffHeapDiskFPSet.BitshiftingIndexer(positions, fpBits));
	}

	@Test
	public void testRescale2() throws RemoteException {
		final int fpBits = 2;
		final long positions = 96L;
		
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(positions, fpBits);

		// indexer spreads over all positions
		Assert.assertEquals(0, indexer.getIdx(1));
		Assert.assertEquals(48, indexer.getIdx(((0xFFFFFFFFFFFFFFFFL >>> fpBits) / 2L)));
		Assert.assertEquals(95, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits)));
		
		// Correctly wraps around when end of array is reached
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), 1));
		// Correctly wraps around when end of array is reached twice
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), 97));
	}

	@Test
	public void testRescale299() throws RemoteException {
		final int fpBits = 2;
		final long positions = 99L;
		
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(positions, fpBits);

		// indexer spreads over all positions
		Assert.assertEquals(0, indexer.getIdx(1));
		Assert.assertEquals(49, indexer.getIdx(((0xFFFFFFFFFFFFFFFFL >>> fpBits) / 2L)));
		Assert.assertEquals(positions - 1, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits)));
		
		// Correctly wraps around when end of array is reached
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), 1));
		// Correctly wraps around when end of array is reached twice
		Assert.assertEquals(0, indexer.getIdx((0xFFFFFFFFFFFFFFFFL >>> fpBits), (int)positions+1));
	}

	@Test
	public void testRescaleMaximum() throws RemoteException {
		final int fpBits = 1;
		final long positions = 11L;
		
		final Indexer indexer = new OffHeapDiskFPSet.Indexer(positions, fpBits, 11L);

		// indexer spreads over all positions
		Assert.assertEquals(0, indexer.getIdx(1));
		Assert.assertEquals(10, indexer.getIdx(11));
		
		// Correctly wraps around when end of array is reached
		Assert.assertEquals(0, indexer.getIdx(11, 1));
	}
	
	@Test
	public void testBitshiftOvershoot() throws RemoteException {
		final int fpBits = 1;
		final long positions = 536870912L;
		
		final Indexer indexer = new OffHeapDiskFPSet.BitshiftingIndexer(positions, fpBits);
		Assert.assertEquals(0, indexer.getIdx(9223371952792813846L, 5));
	}
	
	private void doTest(final int fpBits, final long positions, final int logPos, final Indexer indexer) {
		Assert.assertTrue(Double.compare(Math.pow(2, logPos - fpBits), positions) == 0);
		
		Assert.assertEquals(fpBits, Long.numberOfLeadingZeros((positions << (Long.SIZE - logPos)) - 1));
		
		for (long l = 0; l < positions; l++) {
			final long fp = l << (Long.SIZE - logPos);
			Assert.assertEquals(l, indexer.getIdx(fp));
			final long fpNext = ((l+1L) << (Long.SIZE - logPos)) - 1;
			Assert.assertEquals(l, indexer.getIdx(fpNext));
		}
		Assert.assertEquals(0, indexer.getIdx(positions << (Long.SIZE - logPos)));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/eclipse/jface/dialogs/ForkedProgressMonitorDialog.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.dialogs;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

/**
 * A modal dialog that displays progress during a long running operation.
 * <p>
 * This concrete dialog class can be instantiated as is, or further subclassed
 * as required.
 * </p>
 * <p>
 * Typical usage is:
 * </p>
 * <pre>
 *    try {
 *       IRunnableWithProgress op = ...;
 *       new ProgressMonitorDialog(activeShell).run(true, true, op);
 *    } catch (InvocationTargetException e) {
 *       // handle exception
 *    } catch (InterruptedException e) {
 *       // handle cancelation
 *    }
 * </pre>
 *
 * <p>
 * Note that the ProgressMonitorDialog is not intended to be used with multiple
 * runnables - this dialog should be discarded after completion of one
 * IRunnableWithProgress and a new one instantiated for use by a second or
 * sebsequent IRunnableWithProgress to ensure proper initialization.
 * </p>
 * <p>
 * Note that not forking the process will result in it running in the UI which
 * may starve the UI. The most obvious symptom of this problem is non
 * responsiveness of the cancel button. If you are running within the UI Thread
 * you should do the bulk of your work in another Thread to prevent starvation.
 * It is recommended that fork is set to true in most cases.
 * </p>
 */
public class ForkedProgressMonitorDialog extends IconAndMessageDialog implements
		IRunnableContext {
	/**
	 * Name to use for task when normal task name is empty string.
	 */
	private static String DEFAULT_TASKNAME = JFaceResources
			.getString("ProgressMonitorDialog.message"); //$NON-NLS-1$

	/**
	 * Constants for label and monitor size
	 */
	private static int LABEL_DLUS = 40;

	private static int BAR_DLUS = 9;

	/**
	 * The progress indicator control.
	 */
	protected ProgressIndicator progressIndicator;

	/**
	 * The label control for the task. Kept for backwards compatibility.
	 */
	protected Label taskLabel;

	/**
	 * The label control for the subtask.
	 */
	protected Label subTaskLabel;

	/**
	 * The Cancel button control.
	 */
	protected Button cancel;

	/**
	 * Indicates whether the Cancel button is to be shown.
	 */
	protected boolean operationCancelableState = false;

	/**
	 * Indicates whether the Cancel button is to be enabled.
	 */
	protected boolean enableCancelButton;

	/**
	 * The progress monitor.
	 */
	private ProgressMonitor progressMonitor = new ProgressMonitor();

	/**
	 * The name of the current task (used by ProgressMonitor).
	 */
	private String task;

	/**
	 * The nesting depth of currently running runnables.
	 */
	private int nestingDepth;

	/**
	 * The cursor used in the cancel button;
	 */
	protected Cursor arrowCursor;

	/**
	 * Flag indicating whether to open or merely create the dialog before run.
	 */
	private boolean openOnRun = true;

	/**
	 * Internal progress monitor implementation.
	 */
	private class ProgressMonitor implements IProgressMonitorWithBlocking {
		private String fSubTask = "";//$NON-NLS-1$

		private volatile boolean fIsCanceled;

		/**
		 * is the process forked
		 */
		protected boolean forked = false;

		/**
		 * is locked
		 */
		protected boolean locked = false;

		@Override
		public void beginTask(String name, int totalWork) {
			if (progressIndicator.isDisposed()) {
				return;
			}
			if (name == null) {
				task = "";//$NON-NLS-1$
			} else {
				task = name;
			}
			String s = task;
			if (s.length() <= 0) {
				s = DEFAULT_TASKNAME;
			}
			setMessage(s, false);
			if (!forked) {
				update();
			}
			if (totalWork == UNKNOWN) {
				progressIndicator.beginAnimatedTask();
			} else {
				progressIndicator.beginTask(totalWork);
			}
		}

		@Override
		public void done() {
			if (!progressIndicator.isDisposed()) {
				progressIndicator.sendRemainingWork();
				progressIndicator.done();
			}
		}

		@Override
		public void setTaskName(String name) {
			if (name == null) {
				task = "";//$NON-NLS-1$
			} else {
				task = name;
			}
			String s = task;
			if (s.length() <= 0) {
				s = DEFAULT_TASKNAME;
			}
			setMessage(s, false);
			if (!forked) {
				update();
			}
		}

		@Override
		public boolean isCanceled() {
			return fIsCanceled;
		}

		@Override
		public void setCanceled(boolean b) {
			fIsCanceled = b;
			if (locked) {
				clearBlocked();
			}
		}

		@Override
		public void subTask(String name) {
			if (subTaskLabel.isDisposed()) {
				return;
			}
			if (name == null) {
				fSubTask = "";//$NON-NLS-1$
			} else {
				fSubTask = name;
			}
//			subTaskLabel.setText(shortenText(fSubTask, subTaskLabel));
			subTaskLabel.setText(fSubTask);
			if (!forked) {
				subTaskLabel.update();
			}
		}

		@Override
		public void worked(int work) {
			internalWorked(work);
		}

		@Override
		public void internalWorked(double work) {
			if (!progressIndicator.isDisposed()) {
				progressIndicator.worked(work);
			}
		}

		@Override
		public void clearBlocked() {
			if (getShell() == null || getShell().isDisposed())
				return;
			locked = false;
			updateForClearBlocked();
		}

		@Override
		public void setBlocked(IStatus reason) {
			if (getShell() == null || getShell().isDisposed())
				return;
			locked = true;
			updateForSetBlocked(reason);
		}
	}

	/**
	 * Clear blocked state from the receiver.
	 */
	protected void updateForClearBlocked() {
		progressIndicator.showNormal();
		setMessage(task, true);
		if (imageLabel != null) {
			imageLabel.setImage(getImage());
		}
	}

	/**
	 * Set blocked state from the receiver.
	 *
	 * @param reason
	 *            IStatus that gives the details
	 */
	protected void updateForSetBlocked(IStatus reason) {
		progressIndicator.showPaused();
		setMessage(reason.getMessage(), true);
		if (imageLabel != null) {
			imageLabel.setImage(getImage());
		}
	}

	/**
	 * Creates a progress monitor dialog under the given shell. The dialog has a
	 * standard title and no image. <code>open</code> is non-blocking.
	 *
	 * @param parent
	 *            the parent shell, or <code>null</code> to create a top-level
	 *            shell
	 */
	public ForkedProgressMonitorDialog(Shell parent) {
		super(parent);
		// no close button on the shell style
		if (isResizable()) {
			setShellStyle(getDefaultOrientation() | SWT.BORDER | SWT.TITLE
					| SWT.APPLICATION_MODAL | SWT.RESIZE | SWT.MAX);
		} else {
			setShellStyle(getDefaultOrientation() | SWT.BORDER | SWT.TITLE
					| SWT.APPLICATION_MODAL);
		}
		setBlockOnOpen(false);
	}

	/**
	 * Enables the cancel button (asynchronously).
	 *
	 * @param b
	 *            The state to set the button to.
	 */
	private void asyncSetOperationCancelButtonEnabled(final boolean b) {
		if (getShell() != null) {
			getShell().getDisplay().asyncExec(() -> setOperationCancelButtonEnabled(b));
		}
	}

	/**
	 * The cancel button has been pressed.
	 *
	 * @since 3.0
	 */
	@Override
	protected void cancelPressed() {
		// NOTE: this was previously done from a listener installed on the
		// cancel button. On GTK, the listener installed by
		// Dialog.createButton is called first and this was throwing an
		// exception because the cancel button was already disposed
		cancel.setEnabled(false);
		progressMonitor.setCanceled(true);
		super.cancelPressed();
	}

	/**
	 * The <code>ProgressMonitorDialog</code> implementation of this method
	 * only closes the dialog if there are no currently running runnables.
	 */
	@Override
	public boolean close() {
		if (getNestingDepth() <= 0) {
			clearCursors();
			return super.close();
		}
		return false;
	}

	/**
	 * Clear the cursors in the dialog.
	 *
	 * @since 3.0
	 */
	protected void clearCursors() {
		if (cancel != null && !cancel.isDisposed()) {
			cancel.setCursor(null);
		}
		Shell shell = getShell();
		if (shell != null && !shell.isDisposed()) {
			shell.setCursor(null);
		}
		if (arrowCursor != null) {
			arrowCursor.dispose();
		}
		arrowCursor = null;
	}

	@Override
	protected void configureShell(final Shell shell) {
		super.configureShell(shell);
		shell.setText(JFaceResources.getString("ProgressMonitorDialog.title")); //$NON-NLS-1$
		shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT));
		// Add a listener to set the message properly when the dialog becomes
		// visible
		shell.addListener(SWT.Show, event -> shell.getDisplay().asyncExec(() -> setMessage(message, true)));
	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		// cancel button
		createCancelButton(parent);
	}

	/**
	 * Creates the cancel button.
	 *
	 * @param parent
	 *            the parent composite
	 * @since 3.0
	 */
	protected void createCancelButton(Composite parent) {
		cancel = createButton(parent, IDialogConstants.CANCEL_ID,
				IDialogConstants.CANCEL_LABEL, false);
		if (arrowCursor == null) {
			arrowCursor = new Cursor(cancel.getDisplay(), SWT.CURSOR_ARROW);
		}
		cancel.setCursor(arrowCursor);
		setOperationCancelButtonEnabled(enableCancelButton);
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		setMessage(DEFAULT_TASKNAME, false);
		createMessageArea(parent);
		// Only set for backwards compatibility
		taskLabel = messageLabel;
		// progress indicator
		progressIndicator = new ProgressIndicator(parent);
		GridData gd = new GridData();
		gd.heightHint = convertVerticalDLUsToPixels(BAR_DLUS);
		gd.horizontalAlignment = GridData.FILL;
		gd.grabExcessHorizontalSpace = true;
		gd.horizontalSpan = 2;
		progressIndicator.setLayoutData(gd);
		// label showing current task
		subTaskLabel = new Label(parent, SWT.LEFT | SWT.WRAP);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.heightHint = convertVerticalDLUsToPixels(LABEL_DLUS);
		gd.horizontalSpan = 2;
		subTaskLabel.setLayoutData(gd);
		subTaskLabel.setFont(parent.getFont());
		return parent;
	}

	@Override
	protected Point getInitialSize() {
		Point calculatedSize = super.getInitialSize();
		if (calculatedSize.x < 450) {
			calculatedSize.x = 450;
		}
		return calculatedSize;
	}

	/**
	 * Returns the progress monitor to use for operations run in this progress
	 * dialog.
	 *
	 * @return the progress monitor
	 */
	public IProgressMonitor getProgressMonitor() {
		return progressMonitor;
	}

	/**
	 * This implementation of IRunnableContext#run(boolean, boolean,
	 * IRunnableWithProgress) runs the given <code>IRunnableWithProgress</code>
	 * using the progress monitor for this progress dialog and blocks until the
	 * runnable has been run, regardless of the value of <code>fork</code>.
	 * The dialog is opened before the runnable is run, and closed after it
	 * completes. It is recommended that <code>fork</code> is set to true in
	 * most cases. If <code>fork</code> is set to <code>false</code>, the
	 * runnable will run in the UI thread and it is the runnable's
	 * responsibility to call <code>Display.readAndDispatch()</code> to ensure
	 * UI responsiveness.
	 */
	@Override
	public void run(boolean fork, boolean cancelable,
			IRunnableWithProgress runnable) throws InvocationTargetException,
			InterruptedException {
		setCancelable(cancelable);
		try {
			aboutToRun();
			// Let the progress monitor know if they need to update in UI Thread
			progressMonitor.forked = fork;
			ModalContext.run(runnable, fork, getProgressMonitor(), getShell()
					.getDisplay());
		} finally {
			finishedRun();
		}
	}

	/**
	 * Returns whether the dialog should be opened before the operation is run.
	 * Defaults to <code>true</code>
	 *
	 * @return <code>true</code> to open the dialog before run,
	 *         <code>false</code> to only create the dialog, but not open it
	 * @since 3.0
	 */
	public boolean getOpenOnRun() {
		return openOnRun;
	}

	/**
	 * Sets whether the dialog should be opened before the operation is run.
	 * NOTE: Setting this to false and not forking a process may starve any
	 * asyncExec that tries to open the dialog later.
	 *
	 * @param openOnRun
	 *            <code>true</code> to open the dialog before run,
	 *            <code>false</code> to only create the dialog, but not open
	 *            it
	 * @since 3.0
	 */
	public void setOpenOnRun(boolean openOnRun) {
		this.openOnRun = openOnRun;
	}

	/**
	 * Returns the nesting depth of running operations.
	 *
	 * @return the nesting depth of running operations
	 * @since 3.0
	 */
	protected int getNestingDepth() {
		return nestingDepth;
	}

	/**
	 * Increments the nesting depth of running operations.
	 *
	 * @since 3.0
	 */
	protected void incrementNestingDepth() {
		nestingDepth++;
	}

	/**
	 * Decrements the nesting depth of running operations.
	 *
	 * @since 3.0
	 *
	 */
	protected void decrementNestingDepth() {
		nestingDepth--;
	}

	/**
	 * Called just before the operation is run. Default behaviour is to open or
	 * create the dialog, based on the setting of <code>getOpenOnRun</code>,
	 * and increment the nesting depth.
	 *
	 * @since 3.0
	 */
	protected void aboutToRun() {
		if (getOpenOnRun()) {
			open();
		} else {
			create();
		}
		incrementNestingDepth();
	}

	/**
	 * Called just after the operation is run. Default behaviour is to decrement
	 * the nesting depth, and close the dialog.
	 *
	 * @since 3.0
	 */
	protected void finishedRun() {
		decrementNestingDepth();
		close();
	}

	/**
	 * Sets whether the progress dialog is cancelable or not.
	 *
	 * @param cancelable
	 *            <code>true</code> if the end user can cancel this progress
	 *            dialog, and <code>false</code> if it cannot be canceled
	 */
	public void setCancelable(boolean cancelable) {
		if (cancel == null) {
			enableCancelButton = cancelable;
		} else {
			asyncSetOperationCancelButtonEnabled(cancelable);
		}
	}

	/**
	 * Helper to enable/disable Cancel button for this dialog.
	 *
	 * @param b
	 *            <code>true</code> to enable the cancel button, and
	 *            <code>false</code> to disable it
	 * @since 3.0
	 */
	protected void setOperationCancelButtonEnabled(boolean b) {
		operationCancelableState = b;
		if (cancel != null && !cancel.isDisposed()) {
			cancel.setEnabled(b);
		}
	}

	@Override
	protected Image getImage() {
		return getInfoImage();
	}

	/**
	 * Set the message in the message label.
	 *
	 * @param messageString
	 *            The string for the new message.
	 * @param force
	 *            If force is true then always set the message text.
	 */
	private void setMessage(String messageString, boolean force) {
		// must not set null text in a label
		message = messageString == null ? "" : messageString; //$NON-NLS-1$
		if (messageLabel == null || messageLabel.isDisposed()) {
			return;
		}
		if (force || messageLabel.isVisible()) {
			messageLabel.setToolTipText(message);
			messageLabel.setText(shortenText(message, messageLabel));
		}
	}

	/**
	 * Update the message label. Required if the monitor is forked.
	 */
	private void update() {
		if (messageLabel == null || messageLabel.isDisposed()) {
			return;
		}
		messageLabel.update();
	}

	@Override
	public int open() {
		// Check to be sure it is not already done. If it is just return OK.
		if (!getOpenOnRun()) {
			if (getNestingDepth() == 0) {
				return OK;
			}
		}
		int result = super.open();
		// update message label just in case beginTask() has been invoked
		// already
		if (task == null || task.length() == 0)
			setMessage(DEFAULT_TASKNAME, true);
		else
			setMessage(task, true);
		return result;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/editing-modules.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/spec/editing-modules.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Editing Modules</title>
</head>
<!-- a comment -->

<body>
<h1>Editing Modules</h1>
<pre>
Contents
  <a href="#module">Module Editors</a>
  <a href="#finding">Finding Definitions and Declarations and Their Uses</a>
  <a href="#finding-pcal">Finding PlusCal Source Code</a>
  <a href="#comments">Editing Comments</a>
  <a href="#proofs">Editing and Viewing Proofs</a>
  <a href="#misc">Miscellaneous Commands</a>
  <a href="#key-bindings">Module Editor Key Bindings</a>

</pre>
<h2><a name="module">Module Editors</a></h2>
 <P> 
When you first open a spec, the Toolbox shows the root module in a module editor view.&nbsp;  
You can open additional modules in separate module editor views by clicking&nbsp; <samp>File/Open Module</samp>.&nbsp;
This will allow you to select a module, either from a list of modules that are or were part of the spec
or from a file browser.&nbsp;  You can also create a new module file in the file browser.&nbsp;  You can select a module
only from the same folder as the root-module file.
</P>

<p>
If you have multiple module editors open, you can switch between them by clicking on the
editor's tab.&nbsp;  A&nbsp; <samp>*</samp>&nbsp; in the tab means that there are unsaved changes
to the module.&nbsp;
Clicking on the&nbsp; <samp>X</samp>&nbsp; at the right of the tab deletes the module editor (but
not the module).&nbsp;  If you accidentally delete a module editor, you can re-open the module as
described above.
</p>
<p>
 It's sometimes useful to open two views on the same module, so you can view different parts of it
at the same time.&nbsp;  You can do this by right-clicking on the module editor's tab and selecting&nbsp; 
<samp>New Editor</samp>.&nbsp;  See the <a href="../gettingstarted/views.html">Managing Views</a> help page
for how to put model editors where you want them in the Toolbox window.&nbsp;  See the 
<a href="pretty-printing.html">Pretty-Printing Modules</a> help page for how to view the pretty-printed
versions of your modules.
</p>

<p>A module editor provides the usual text editing commands for editing the module.&nbsp;
There are&nbsp; 
<samp>Save</samp>&nbsp; and&nbsp;  <samp>Save As</samp>&nbsp; commands on the &nbsp;  <samp>File</samp>&nbsp;
menu.&nbsp;  (Typing&nbsp; <code>Control+s</code>&nbsp; also performs the save command.)&nbsp;  The&nbsp;  <samp>Edit</samp>&nbsp;
menu provides a few familiar commands.&nbsp;  
<a href="#key-bindings">Below</a> is a list of available commands and the keys to which they are bound.&nbsp;

</p>

<p>
If you create a new module file with the Toolbox, the module editor will create
a modification history at the end of the file that begins with the line
<pre>
   \* Modification History   
</pre>
You can move the modification history anywhere you want in the file.&nbsp;

If you created the file outside the Toolbox, you can put this history-beginning
line anywhere you want.&nbsp;

However, the line must appear exactly as shown, with no spaces before
the &nbsp;<code>\*</code>&nbsp; and exactly one space after it.
</p>

<p>
If you want to prevent the Toolbox from adding the modification history comment,
you can disable this in the <samp>TLA+ Preferences/Model Viewer</samp> section of
the <a href="../gettingstarted/preferences.html">Preference</a> menu.
</p>


<p>
The Toolbox maintains a history of previous versions of a module.&nbsp;  
It adds the current version to the history every time you save the module.&nbsp;
You can examine and revert to a version from the history by right-clicking on
in the module editor and selecting <code>Team</code>, <code>Compare With</code>,
or <code>Replace With</code>.&nbsp;  

You can also right-click on any module of the open specification in the 
 <a
href="../spec/opening-closing.html">Spec Explorer</a>
 and select
<code>Show in History</code>.
</p>

<h2><a name="finding">Finding  Definitions,  Declarations, and Their Uses</a></h2>
<p>
The module editor provides commands for finding the PlusCal code that 

finding the definition or declaration of a user-defined symbol, 
for finding all uses of that definition or declaration, and for finding all symbols defined and declared 
in the module.&nbsp; 


For brevity, the names of all of these commands use the term <em>declaration</em> instead of <em>declaration
or definition</em>.

These commands can be executed by right-clicking on the editor and selecting the command from the
popped-up menu, or with the keystroke indicated on the menu.&nbsp;  

The <samp>General/Keys</samp> item on
the <a href="../gettingstarted/preferences.html">Preference</a> menu allows you to change those
key bindings.&nbsp; 

The <em>Goto Declaration</em>
command can also be executed by <em>control + click</em>, as explained below.  
</p>

<p>
For the commands that find the declaration or uses of a symbol, the symbol is the one containing the cursor (caret) 
or that the cursor is right before.&nbsp;  

It is not the one being pointed at by the mouse--except when using the <em>control + click</em> version of
the <em>Goto Declaration</em> command.
</p> 

<p>
Most of these commands work only if the spec is successfully parsed--that is, if its status (indicated at the bottom 
of the window) is <em>parsed</em> (green).&nbsp;

If the module has been modified since the spec was parsed, a command may not work properly.  The <em>Goto Declaration</em>
command may not recognize the symbol, and a command that should highlight and/or jump to someplace in the module may highlight
or jump to the wrong place.&nbsp;

However, if the <em>Show Uses</em> command is executed before the module is modified, then the highlighting and subsequent
<em>Goto Prev/Next Use</em> commands will work properly.
</p>

<h3>Goto Declaration (F3)</h3>

<p>
This command jumps to the definition or declaration of the chosen symbol, which must not be a built-in TLA+ symbol or
a symbol defined in a standard module.&nbsp;  

This could mean jumping to a different module.&nbsp;  

In addition to executing the command from a menu or by typing <code>F3</code>, you can also hold down the <code>Control</code> key
and move the mouse over the symbol.&nbsp;  

When the mouse is over a declared or user-defined symbol, the symbol will change appearance and turn into
a link that you can left-click on to jump to the symbol's declaration or definition.
</p>


<h3>Return From Goto (F4)</h3>

This command jumps back to the location from which the most recent <em>Goto Declaration</em> 
or <em>Goto PCal Source</em> command was executed.&nbsp;  
The <em>Go back in history</em> command (<samp>Alt+LeftArrow</samp>) has the same effect
when executed immediately after the <em>Goto</em> command.

<h3>Show Declarations (F5)</h3>

<p>
This command raises a menu containing a list of all the symbols defined and declared in the current module.&nbsp;

You can jump to a symbol's definition or declaration by selecting that symbol from the list.&nbsp;

You can select an item from the list by clicking on it, or by selecting the desired item--with a combination of the
arrow keys and typing the first few letters of its name--and then typing <code>Enter</code>.&nbsp;
</p>

<p>Typing <code>space</code> causes the menu to toggle between showing and hiding definitions that are
imported by instantiation.&nbsp;  

(More precisely, it applies to definitions that are imported with renaming and/or with substitution
for module parameters.)
</p>

<h3><a name ="showUses">Show Uses (F6)</a></h3>
<p>
This command highlights all uses of the selected symbol and enables the <em>Goto Next Use</em>
and <em>Goto Prev Use</em> commands.&nbsp;  

If the symbol is used in more than one module, it
raises a menu allowing you to select the desired module from a list.&nbsp;  

You can select a module from the list by clicking on it, or by selecting it--with a combination of the
arrow keys and typing the first few letters of its name--and then typing <code>Enter</code>.
</p>
<p>
The highlighting of the uses is cleared by executing another <em>Show Uses</em> command or by re-parsing
the specification.&nbsp;  

Whether or not re-parsing the specification  clears the highlighting is controlled by an editor
<a href="../gettingstarted/preferences.html">preference</a>.
</p>

<h3>Goto Prev/Next Use (F7/F8)</h3>

These commands jump to the previous or next (earlier or later in the module) use of the
symbol selected by the most recent <em>Show Uses</em> command.

<h2><a name="finding-pcal">Finding PlusCal Source Code</a></h2>

<p>
After you have successfully run the PlusCal translator to translate an algorithm,
the <em>Goto PCal Source</em> command (F10) allows you to jump from a selected region of
the TLA+ translation to the PlusCal code that generated it.&nbsp;  Select a
region of the TLA+ specification, and the command jumps to and highlights approximately
the smallest syntactic unit of the PlusCal algorithm whose translation contains the
selected region.&nbsp;  (You can select a single token by putting the cursor in or
next to it.)&nbsp;  The command does nothing if that smallest syntactic unit is
the entire algorithm, or if the selected region does not lie within the algorithm's
translation.  The <em>Return From Goto</em> command (F4) jumps back to the original
selection.&nbsp; 
</p>

<p>
Clicking on parsing error reports, and on error reports and some other 
fields in a TLC model window, highlights and jumps to a region of the
TLA+ spec.&nbsp;  If that region of the spec was produced by the PlusCal
translation, the <em>Goto PCal Source</em> command should then take you to the
appropriate part of the PlusCal source code.&nbsp;  You can also
jump directly to the PlusCal source 
 by control-clicking (holding the <samp>CONTROL</samp> key while clicking) on the error report.&nbsp;
That will take you to the region of the TLA+ spec if it has no corresponding
PlusCal region.

</p>

<p>
The mapping from regions of the TLA+ translation to regions of the PlusCal source 
is determined at the time of translation.&nbsp;  If the PlusCal source, the
translation, or any part of the module lying between them is changed, then the
command may jump to the wrong place.&nbsp;  It's best to put the translation immediately
after the comment containing the algorithm.&nbsp;  If you omit the 
<code>BEGIN/END TRANSLATION</code> comments, that is where the translation will be 
put.
</p>

<h2><a name="comments">Editing Comments</a></h2>

<p>
The <a href="pretty-printing.html">TLA+ Pretty Printer</a> regards
a comment "boxed" as follows to be a sequence of paragraphs.
<pre>
  (**************************************)
  (* This is the                        *)
  (*   first paragraph.                 *)
  (*                                    *)
  (*   This text is a display           *)
  (*                                    *)
  (* This is another paragraph.         *)
  (**************************************)
</pre>
Such a box can be placed on a series of lines by itself, or
it can appear to the right of other text.&nbsp;
</p>

<p>
The module editor provides the commands for creating and
editing boxed comments.&nbsp;  

They make boxed comments that extend from some specified point to a right
margin--a column specified by a 
<a href="../gettingstarted/module-editor-preferences.html">preference.</a>.&nbsp; 

These commands are executed by typing two characters, the first of
which is <samp>Ctl+O</samp>.&nbsp; 

If you type <samp>Ctl+O</samp> and wait a moment, the list of all these
commands will appear.&nbsp;

The commands can also be executed by right-clicking on the mouse.&nbsp;

For these commands, the <em>current position</em> is the location where
the typing cursor is, not where the mouse is pointing.&nbsp;
</p>

<p>
To create a comment, you first position cursor where you
want the top left-hand corner of the comment and execute the
<em>Start Boxed Comment</em> by typing <samp>Ctl+O Ctl+S</samp>.&nbsp;

This produces the comment begin and end tokens like this:
<pre>
Beauty == TRUE  (***********************************

                ***********************************)</pre>
showing where the finished box will be positioned, and it leaves the cursor
between them in the first column.&nbsp;

Type your comment like ordinary text, with all paragraph lines
starting in column 1, like this:

<pre>
Beauty == TRUE  (***********************************
This is 
a
very interesting formula, 
because it expresses Keats' famous dictum

  Beauty is truth
  and truth beauty.
         
How much more than this do you really need to know?
               ***********************************)</pre>
When you have finished the contents of the comment, execute
the <em>Format Comment</em> command by typing 
<samp>Ctl+O Ctl+F</samp>.&nbsp;

This will format each sequence of non-blank lines that all begin in column 1
as a paragraph, with lines broken so the paragraphs will fit snugly in the
comment box--like this:&nbsp;

<pre>
Beauty == TRUE  (***********************************
This is a very interesting 
formula, because it expresses
Keats' famous dictum

  Beauty is truth
  and truth beauty.
         
How much more than this do you 
really need to know?
               ***********************************)</pre>


Note that lines that do not begin in column 1 are not changed.&nbsp;

If it looks right, execute the <em>Box Comment</em> command by
typing <samp>Ctl+O Ctl+B</samp> to create the box, like this:

<pre>
Beauty == TRUE  (**********************************)
                (* This is a very interesting     *)
                (* formula, because it expresses  *)
                (* Keats' famous dictum           *)
                (*                                *)
                (*   Beauty is truth              *)
                (*   and truth beauty.            *)
                (*                                *)
                (* How much more than this do you *)
                (* really need to know?           *)
                (**********************************)</pre>



If the result doesn't look right, type <samp>Ctl+Z</samp> to undo the <em>Box
Comment</em> command and do whatever manual formatting seems necessary.&nbsp;
Then execute <em>Box Comment</em> again.&nbsp;

Both the formatting and the boxing can be done together with the
<em>Format and Box Comment</em> command by typing <samp>Ctl+O Ctl+O</samp>.

</p>

<p>
To modify an existing boxed comment, put the cursor inside the
comment box and execute the <em>Unbox Comment</em> command
by typing <samp>Ctl+O Ctl+U</samp>.&nbsp;  You can then edit and
rebox it with the commands described above.  
</p>


<h2><a name="proofs">Editing and Viewing Proofs</a></h2>

Editor commands for hierarchically viewing proofs are
described in <a href="../prover/reading.html">Viewing Structured Proofs</a>.&nbsp;

We hope eventually to provide commands to aid in writing
and editing proofs.&nbsp;  

We would appreciate any suggestions for what commands we should
implement.&nbsp;

Meanwhile, <a href="#block-selection">block selection mode</a> may be
useful in copying and indenting parts of a proof.

<h2><a name="misc">Miscellaneous Commands</a></h2>

<h3><a name="paren">Goto Matching Parenthesis (Control+Shift+p)</a></h3>

Placing the cursor just to the right of a parenthesis and executing this
command cause the cursor to jump to the right of the matching parenthesis.&nbsp;
The pairs of matching "parentheses" are:
<pre>
     (  )    [  ]    {  }    <<  >>    (*  *)
</pre>
The cursor does not move and an error message appears at the bottom
left of the Toolbox window if there is no matching parenthesis or
there are mismatched parentheses.&nbsp;  Mismatched parentheses are highlighted.&nbsp;
(Look to the right of the scroll bar to find them if they are off the screen.)&nbsp;
End-of-line comments (started with <samp>\*</samp>) and strings are treated
as independent regions for parenthesis matching.


<h3><a name="block-selection">Toggle Block Selection Mode (Alt+Shift+a)</a></h3>

This command causes the editor to enter or leave block-selection mode.&nbsp;
In block-selection mode, you can select a rectangular region (which may have zero width).&nbsp;
You can delete, type into, or copy and paste the region.&nbsp;  Typing space or <code>LeftArrow</code>
(backspace) into a zero-width region allows you to move a block of text left or right, which
is useful for adjusting alignment.&nbsp;  In general, typing a single character into
a zero-width region inserts that character on each line of the region.&nbsp;

<p> 
The module is displayed in Text Editor Block Selection Font
instead of Text Font when in Block Selection Mode.&nbsp;  You can change those fonts by 
selecting <samp>General / Appearance / Colors and Fonts</samp>  on the 
<a href="../gettingstarted/preferences.html">Preference</a> menu.


<h2><a name="key-bindings">Module Editor Key Bindings</a></h2>

The following are the default key bindings for module editors.&nbsp;  The <samp>General/Keys</samp> item on
the <a href="../gettingstarted/preferences.html">Preference</a> menu allows you to change those
key bindings.&nbsp;  Its <em>Emacs</em> scheme  binds a few commands to the keys used in the
Emacs editor, making the module editor almost, but not quite, completely unlike Emacs. <br></br>

<TABLE frame=box rules=all>
       <!-- style="font-style:italic;font-size:80%"  -->
<!-- <CAPTION align=left><h3>Module Editor Key Bindings</h3></CAPTION> -->
<TBODY>
<COL align=left> <!-- style="font-family:consolas,courier"--> 
<col align=left >
<TR> <TH colspan=2 align=left> <font color=000000>
Insert, Delete, and Move Text</font></TH>
<TR> <TD><CODE>Ctl+Shift+Enter</CODE></TD> <TD> Insert line above current line</TD></TR>

<TR> <TD><CODE>Shift+Enter</CODE></TD> <TD> Insert line below current line</TD></TR>

<TR> <TD><CODE>Ctl+Shift+Del</CODE></TD> <TD> Delete to end of current line</TD></TR>

<TR> <TD><CODE>Ctl+Backspace</CODE></TD> <TD> Delete to beginning of current or previous word</TD></TR>

<TR> <TD><CODE>Ctl+Del</CODE></TD> <TD> Delete to end of current word</TD></TR>

<TR> <TD><CODE>Alt+Up/DownArrow</CODE></TD> <TD> Move current line up/down</TD></TR>

<TR> <TD><CODE>Shift+Tab</CODE></TD> <TD>If there are (at least) 4 spaces at beginning of line,
                                         delete them</TD></TR>

<TR> <TD><CODE>Ctl+/</CODE></TD> <TD>Comment out or uncomment selected lines</TD></TR>

<TR> <TD><CODE>Ctl+Alt+J</CODE></TD> <TD> Join next line to current line</TD></TR>

<TR><TD><CODE>Ctl+C</CODE></TD> <TD> Copy selected text</TD></TR>

<TR><TD><CODE>Ctl+V</CODE></TD> <TD> Paste</TD></TR>

<TR><TD><CODE>Ctl+Z</CODE></TD> <TD> Undo</TD></TR>

<TR><TD><CODE>Ctl+A</CODE></TD> <TD> Select all</TD></TR>

<TR><TD><CODE>Alt+Shift+A</CODE></TD> <TD><a href="#block-selection">Toggle block selection mode<a></TD></TR>

<TR> <TD colspan=2> <BR> </TD></TR>
<TR> <TH colspan=2 align=left> <font color=000000>Moving Around</font></TH>
<TR> <TD colspan=2 align=left>For most of these commands, holding Shift down also selects the text.</TD>

<TR> <TD><CODE>Home/End</CODE></TD> <TD> Go to beginning/end of current line</TD></TR>

<TR> <TD><CODE>Ctl+Home/End</CODE></TD> <TD> Go to beginning/end of module</TD></TR>

<!-- 
<TR> <TD><CODE>Home</CODE></TD> <TD> Go to beginning of current line</TD></TR>
<TR> <TD><CODE>Ctl+Home</CODE></TD> <TD> Go to beginning of module</TD></TR>
 -->
 
<TR> <TD><CODE>Ctl+RightArrow</CODE></TD> <TD> Go to beginning of next word</TD></TR>

<TR> <TD><CODE>Ctl+LeftArrow</CODE></TD> <TD> Go to beginning of current or previous word</TD></TR>

<TR> <TD><CODE>Alt+RightArrow</CODE></TD> <TD> Go forward in history.</TD></TR>

<TR> <TD><CODE>Alt+LeftArrow</CODE></TD> <TD> Go back in history.</TD></TR>

<TR> <TD><CODE>Ctl+L</CODE></TD> <TD> Go to line [asks for line number]</TD></TR>

<TR> <TD><CODE>Ctl+Q</CODE></TD> <TD> Go to last edit location</TD></TR>

<TR> <TD><CODE>Ctl+Shift+P</CODE></TD> <TD> <a href="#paren">Go to matching parenthesis</a></TD></TR>

<TR> <TD><CODE>Ctl+Up/DownArrow</CODE></TD> <TD> Scroll up/down one line</TD></TR>
<TR> <TD colspan=2 align=left>The arrow and page-up/down keys behave as usual.</TD>

<!-- 
<TR> <TD colspan=2> <BR> </TD></TR>
<TR> <TH colspan=2 align=left> <font color=000000>Selecting Text</font></TH>
-->

<TR> <TD colspan=2> <BR> </TD></TR>

<TR> <TH colspan=2 align=left> <font color=000000>Find and Replace</font></TH>
<TR> <TD><CODE>Ctl+F</CODE></TD> <TD> Raise Find/Replace dialog</TD></TR>

<TR> <TD><CODE>Ctl+K</CODE></TD> <TD> Find next (in forward direction) instance of last search item</TD></TR>

<TR> <TD><CODE>Ctl+Shift+K</CODE></TD> <TD> Find previous (in backwards direction) instance of last search item</TD></TR>

<TR> <TD><CODE>Ctl+J</CODE></TD> <TD> Incremental forward find</TD></TR>

<TR> <TD><CODE>Ctl+Shift+J</CODE></TD> <TD> Incremental backwards find</TD></TR>



<TR> <TD colspan=2> <BR> </TD></TR>

<TR> <TH colspan=2 align=left> <font color=000000><a href="#finding">Finding Definitions and Declarations and Their Uses</a></font></TH>
<TR> <TD><CODE>F3</CODE></TD> <TD> Goto declaration or definition</TD></TR>
<TR> <TD><CODE>F4</CODE></TD> <TD> Return from goto declaration or definition</TD></TR>
<TR> <TD><CODE>F5</CODE></TD> <TD> Show declarations and definitions</TD></TR>
<TR> <TD><CODE>F6</CODE></TD> <TD> Show uses of declaration or definition</TD></TR>
<TR> <TD><CODE>F7</CODE></TD> <TD> Goto previous use of declaration or definition</TD></TR>
<TR> <TD><CODE>F7</CODE></TD> <TD> Goto next use of declaration or definition</TD></TR>

<TR> <TD colspan=2> <BR> </TD></TR>

<TR> <TH colspan=2 align=left> <font color=000000><a href="#comments">Editing Comments</a></font></TH>
<TR> <TD><CODE>Ctl+O Ctl+S</CODE></TD> <TD> Begin comment</TD></TR>

<TR> <TD><CODE>Ctl+O Ctl+F</CODE></TD> <TD>Format comment</TD></TR>

<TR> <TD><CODE>Ctl+O Ctl+B</CODE></TD> <TD>Box comment</TD></TR>

<TR> <TD><CODE>Ctl+O Ctl+O</CODE></TD> <TD>Format and box comment</TD></TR>

<TR> <TD><CODE>Ctl+O Ctl+U</CODE></TD> <TD>Unbox comment</TD></TR>

<TR> <TD colspan=2> <BR> </TD></TR>

<TR> <TH colspan=2 align=left> <font color=000000>Viewing Proofs</font></TH>
<TR> <TD><CODE>Ctl+G Ctl+S</CODE></TD> <TD>Show current subtree</TD></TR>

<TR> <TD><CODE>Ctl+G Ctl+H</CODE></TD> <TD>Hide current subtree</TD></TR>

<TR> <TD><CODE>Ctl+G Ctl+C</CODE></TD> <TD>Show children only</TD></TR>

<TR> <TD><CODE>Ctl+G Ctl+F</CODE></TD> <TD>Focus on step</TD></TR>

<TR> <TD><CODE>Ctl+G Ctl+A</CODE></TD> <TD>Show all proofs</TD></TR>
<TR> <TD><CODE>Ctl+G Ctl+N</CODE></TD> <TD>Hide all proofs</TD></TR>

<TR> <TD colspan=2> <BR> </TD></TR>

<TR> <TH colspan=2 align=left> <font color=000000>Other</font></TH></TR>



<TR> <TD><CODE>Ctl+S</CODE></TD> <TD> Save module</TD></TR>

<TR> <TD><CODE>Ctl+Shift+A</CODE></TD> <TD> Open Quick Access window</TD></TR>

<TR> <TD><CODE>Alt+X</CODE></TD> <TD> Exit toolbox</TD></TR>

<TR> <TD><CODE>Ctl+M</CODE></TD> <TD> Maximize or unmaximize current editor or view</TD></TR>

<TR> <TD><CODE>Ctl+R</CODE></TD> <TD> Parse module</TD></TR>

<TR> <TD><CODE>Ctl+Alt+R</CODE></TD> <TD> Parse spec</TD></TR>

<TR> <TD><CODE>F1</CODE></TD> <TD> Raise Help view</TD></TR>

<TR> <TD><CODE>Ctl+PageUp/Down</CODE></TD> <TD> Go to previous/next editor view </TD></TR>

<TR> <TD><CODE>Ctl+F6</CODE></TD> <TD> Go to another editor view  (Use up/down arrow to select view, 
  then type Enter.)</TD></TR>

<TR> <TD><CODE>Ctl+F7</CODE></TD> <TD> Go to another view  (Use up/down arrow to select view, 
  then type Enter.)</TD></TR>
  
  <TR> <TD><CODE>Ctl+F10</CODE></TD> <TD>Can use to set line-numbering preference or go to&nbsp; 
     <samp>Preferences /General/Editors/Text Editors</samp></TD></TR>
  
  


<!-- 
<TR> <TD><CODE>Ctl+Shift+R</CODE></TD> <TD> Open Resource.  <BR>
         This can open a resource from a different spec.
     It should be disabled.

<TR> <TD><CODE>Alt+Shift+N</CODE></TD> <TD> DOES NOTHING</TD></TR>

<TR> <TD><CODE>Ctl+.</CODE></TD> <TD> Seems to do nothing</TD></TR>

<TR> <TD><CODE>Ctl+F</CODE></TD> <TD> Next Editor</TD></TR>

<TR> <TD><CODE>Ctl+F</CODE></TD> <TD> Next Page</TD></TR>

<TR> <TD><CODE>Ctl+Shift+F</CODE></TD> <TD> Previous Page</TD></TR>

<TR> <TD><CODE>Ctl+Shift+F</CODE></TD> <TD> Previous Editor</TD></TR>

<TR> <TD><CODE>Ctl+,</CODE></TD> <TD> SEEMS TO DO NOTHING</TD></TR>

<TR> <TD><CODE>Ctl+.</CODE></TD> <TD> SEEMS TO DO NOTHING</TD></TR>

<TR> <TD><CODE>Alt+PageDown</CODE></TD> <TD> Next SubTab  (Goes from module tab to pdf tab)</TD></TR>

<TR> <TD><CODE>Alt+PageUp  </CODE></TD> <TD> Previous SubTab DOES NOTHING</TD></TR>
<TR> <TD><CODE>Ctl+N</CODE></TD> <TD> Raises a "New" menu that allows user to do weird things. Probably best to disable this.</TD></TR>

<TR> <TD><CODE>Alt+F4</CODE></TD> <TD> Windows command to kill program.</TD></TR>
-->
</TBODY>
</TABLE>

<hr> 
<!-- delete rest of line to comment out  
<dl>
<dt><b><font color=#0000c0>Topics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 --> 
<!-- delete rest of line to comment out -->
<a href = "spec.html">&uarr; Managing Your Specifications</a>
<!-- --> 
</hr>

 

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/util/DocumentHelper.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.util;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.rules.IWhitespaceDetector;
import org.eclipse.jface.text.rules.IWordDetector;
import org.lamport.tla.toolbox.editor.basic.tla.TLAWhitespaceDetector;
import org.lamport.tla.toolbox.editor.basic.tla.TLAWordDetector;
import org.lamport.tla.toolbox.util.AdapterFactory;

import tla2sany.st.Location;

/**
 * Toolkit for document helper methods
 * @author <NAME>
 */
public class DocumentHelper
{

    /**
     * Factory method for the word detector
     */
    public static IWordDetector getDefaultWordDetector()
    {
        return new TLAWordDetector();
    }

    /**
     * Factory method for the whitespace detector
     */
    public static IWhitespaceDetector getDefaultWhitespaceDetector()
    {
        return new TLAWhitespaceDetector();
    }

    /**
     * At a given position in text retrieves the region marking the word, starting before and ending on current position 
     * @param document document
     * @param documentOffset offset (position of the cursor)
     * @param detector for identification of words 
     * @return a region expanded backwards
     */
    public static IRegion getRegionExpandedBackwards(IDocument document, int documentOffset, IWordDetector detector)
    {

        // Use string buffer to collect characters
        int charCounter = 0;
        while (true)
        {
            try
            {

                // Read character backwards
                char c = document.getChar(--documentOffset);

                // This was the start of a word
                if (!detector.isWordPart(c))
                    break;

                // Count character
                charCounter++;

            } catch (BadLocationException e)
            {

                // Document start reached, no word
                break;
            }
        }
        return new Region(documentOffset + 1, charCounter);
    }

    /**
     * At a given position in text retrieves the region marking the word, starting at and ending after the current position 
     * @param document document
     * @param documentOffset offset (position of the cursor)
     * @param detector for identification of words 
     * @return a region expanded forward
     */
    public static IRegion getRegionExpandedForwards(IDocument document, int documentOffset, IWordDetector detector)
    {

        // Use string buffer to collect characters
        int charCounter = 0;
        while (true)
        {
            try
            {
                // Read character forward
                char c = document.getChar(++documentOffset);

                // This was the start of a word
                if (!detector.isWordPart(c))
                    break;

                // Count character
                charCounter++;

            } catch (BadLocationException e)
            {

                // Document end reached, no word
                break;
            }
        }

        return new Region(documentOffset - charCounter, charCounter + 1);
    }
    
    /**
     * @see DocumentHelper#getRegionExpandedBoth(IDocument, int, IWordDetector)
     */
    public static WordRegion getRegionExpandedBoth(IDocument document, int documentOffset) throws BadLocationException
    {
    	return getRegionExpandedBoth(document, documentOffset, getDefaultWordDetector());
    }

    /**
     * Combines the effect of backwards and forwards region expansion
     * @param document
     * @param offset
     * @param defaultWordDetector
     * @return A {@link WordRegion} or null if no region could be found.
     * @throws BadLocationException 
     */
    public static WordRegion getRegionExpandedBoth(IDocument document, int documentOffset, IWordDetector detector) throws BadLocationException
    {
        final IRegion backwards = getRegionExpandedBackwards(document, documentOffset, detector);
        final IRegion forwards = getRegionExpandedForwards(document, documentOffset, detector);
        final String word = document.get(backwards.getOffset(), backwards.getLength() + forwards.getLength());
        return new WordRegion(backwards.getOffset(), backwards.getLength() + forwards.getLength(), word);
    }

    /**
     * Converts four-int-location that is 1-based to a two int {@link IRegion} that is
     * 0-based.
     * 
     * TODO: unit test!
     * @param document
     * @param location
     * @return
     * @throws BadLocationException 
     * @deprecated use {@link AdapterFactory#locationToRegion(IDocument, Location)} instead
     */
    public static IRegion locationToRegion(IDocument document, Location location) throws BadLocationException
    {
        /* 
         * The coordinates returned by location are 1-based and the coordinates
         * for a region in a document should be 0-based to be consistent with Positions
         * in documents. Therefore, we subtract 1 from each location coordinate.
         */
        int offset = document.getLineOffset(location.beginLine() - 1) + location.beginColumn() - 1;
        /*
         * If location describes a two-character sequence beginning at column x, then it would
         * have location.endColumn() = x+1. This means that when computing the length, we add 1 to
         * the offset of the second point described by location. In other words, the offset of the
         * second point described by location is:
         * 
         * document.getLineOffset(location.endLine() - 1) + location.endColumn()-1
         * 
         * So the length is:
         * 
         * (document.getLineOffset(location.endLine() - 1) + location.endColumn()-1)+1 - offset
         * 
         * which equals:
         * 
         * document.getLineOffset(location.endLine() - 1) + location.endColumn() - offset
         */
        int length = document.getLineOffset(location.endLine() - 1) + location.endColumn() - offset;
        return new Region(offset, length);
    }

    /**
     * Returns a new region that ends at the end of the input region and begins
     * at the first character of the line before the line containing the offset
     * of the input region. If the input region's offset is on the first
     * line of the document, this method does nothing.
     * 
     * @param document
     * @param region
     * @return
     * @throws BadLocationException
     */
    public static IRegion getRegionWithPreviousLine(IDocument document, IRegion region) throws BadLocationException
    {
        // the first line of the region
        int currentFirstLine = document.getLineOfOffset(region.getOffset());
        if (currentFirstLine > 0)
        {
            int newOffset = document.getLineOffset(currentFirstLine - 1);
            return new Region(newOffset, region.getLength() + (region.getOffset() - newOffset));
        } else
        {
            // no previous line so do nothing
            return region;
        }
    }
    
    public static class WordRegion extends Region implements IRegion {

		private final String word;

		public WordRegion(int offset, int length, String word) {
			super(offset, length);
			this.word = word;
		}
		
		public String getWord() {
			return word;
		}
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/ErrorTraceMessagePrinterRecorder.java<|end_filename|>
package tlc2.output;

import java.util.List;
import java.util.Optional;

import tlc2.model.MCError;
import tlc2.model.MCState;
import tlc2.tool.TLCStateInfo;

/**
 * Saves all messages containing info about error traces that pass through {@link tlc.output.MP}.
 * Ideally this will eventually go away and all of TLC's model checking implementations will
 * bubble their error traces up through their top-level .run() methods, but until that
 * refactoring takes place this is how we get the error trace: by hooking into the static
 * console output handler class and intercepting TLC output.
 * 
 * There are a number of places that error traces are generated within TLC:
 *  - Basic local BFS model checking in {@link tlc2.tool.ModelChecker#doNextCheckInvariants}
 *    > note: appears to be dead, the concurrent BFS implementation is always used instead
 *  - Concurrent local BFS model checking in {@link tlc2.tool.Worker#doNextCheckInvariants}
 *  - DFID local model checking in {@link tlc2.tool.DFIDModelChecker#doNext}
 *  - Simulator local model checking in {@link tlc2.tool.Simulator#simulate}
 *  - Liveness checking in {@link tlc2.tool.liveness.LiveCheck#check0}
 *  - Distributed model checking in {@link tlc2.tool.distributed.TLCServerThread#run}
 * All of these pass through {@link tlc2.output.StatePrinter} then {@link tlc.output.MP}.
 *  
 * The purpose of this class is to record error trace output from all of those sources while
 * ignoring output that is not an error trace (some of which superficially resembles error
 * traces, for example printing out an invalid/incomplete state transition).
 */
public class ErrorTraceMessagePrinterRecorder implements IMessagePrinterRecorder {
	
	/**
	 * The error trace, if one exists.
	 */
	private Optional<MCError> errorTrace = Optional.empty();
	
	/**
	 * Whether the trace has terminated or more states are expected;
	 */
	private boolean traceFinished = false;
	
	/**
	 * Gets the error trace, if it exists.
	 * @return The error trace.
	 */
	public Optional<MCError> getMCErrorTrace() {
		return this.errorTrace;
	}
	
	@Override
	public void record(int code, Object... objects) {
		if (!traceFinished) {
			switch (code) {
				case EC.TLC_STATE_PRINT2:
					if (objects.length >= 2
						&& objects[0] instanceof TLCStateInfo
						&& objects[1] instanceof Integer) {
						TLCStateInfo stateInfo = (TLCStateInfo)objects[0];
						Integer stateOrdinal = (Integer)objects[1];
						stateInfo.stateNumber = stateOrdinal;

						// Idempotent transition from no trace to safety trace
						this.errorTrace = Optional.of(this.errorTrace.orElse(new MCError()));

						// Add state to trace
						MCState state = new MCState(stateInfo);
						this.errorTrace.ifPresent(trace -> trace.addState(state));
					}

					break;
				case EC.TLC_STATE_PRINT3:
					// Mark trace as ending in stuttering
					this.traceFinished = true;
					this.errorTrace.ifPresent(trace -> {
						List<MCState> states = trace.getStates();
						if (states.size() > 0) {
							MCState finalState = states.get(states.size() - 1);
							MCState stutteringState = new MCState(finalState, true, false);
							trace.addState(stutteringState);
						}
					});

					break;
				case EC.TLC_BACK_TO_STATE:
					// Lasso reporting output varies based on -tool setting
					Optional<Integer> stateOrdinal = Optional.empty();
					if (objects.length >= 2
						&& objects[0] instanceof TLCStateInfo
						&& objects[1] instanceof Integer) {
						stateOrdinal = Optional.of((Integer)objects[1]);
					} else if (objects.length >= 2
						&& objects[0] instanceof String
						&& objects[1] instanceof String) {
						try {
							stateOrdinal = Optional.of(Integer.parseInt((String)objects[0]));
						} catch (NumberFormatException e) { }
					}

					stateOrdinal.ifPresent(ord -> {
						this.traceFinished = true;
						this.errorTrace.ifPresent(trace -> {
							List<MCState> states = trace.getStates();
							if (0 < ord && ord <= states.size()) {
								MCState finalState = states.get(ord - 1);
								MCState lassoState = new MCState(finalState, false, true);
								trace.addState(lassoState);
							}
						});
					});
					
					break;
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/TLACoverageEditor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.editor;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.DefaultTextHover;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextPresentationListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.editor.basic.TLAEditorReadOnly;
import org.lamport.tla.toolbox.editor.basic.TLASourceViewerConfiguration;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.output.data.CoverageInformationItem;
import org.lamport.tla.toolbox.tool.tlc.output.data.ModuleCoverageInformation;
import org.lamport.tla.toolbox.tool.tlc.output.data.Representation;
import org.lamport.tla.toolbox.tool.tlc.output.data.Representation.Grouping;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.UIHelper;

import util.TLAConstants;

public class TLACoverageEditor extends TLAEditorReadOnly {

	static {
		JFaceResources.getColorRegistry().put("LIGHT_GRAY", new RGB(245,245,245));
		JFaceResources.getColorRegistry().put("DARK_GRAY", new RGB(200,200,200));
	}
	
	private static final Color lightGray = JFaceResources.getColorRegistry().get("LIGHT_GRAY");
	private static final Color darkGray = JFaceResources.getColorRegistry().get("DARK_GRAY");

	// Icon displayed left of the editor tab's name.
	protected final Image coverageEditorImage = TLAEditorActivator
			.imageDescriptorFromPlugin(TLCUIActivator.PLUGIN_ID, "/icons/full/report2_obj.gif").createImage();

	private static class ResizeListener implements Listener {
		
		private final Point size = new Point(1024,768);

		@Override
		public void handleEvent(final Event event) {
			final Widget widget = event.widget;
			if (widget instanceof Composite) {
				final Composite c = (Composite) widget;
				size.x = c.getSize().x;
				size.y = c.getSize().y;
			}
		}
		
		public int getWidth() {
			return size.x;
		}
	}
	
	/* TLACoverageEditor */

	private final ResizeListener resizeListener = new ResizeListener();
	
	private ModuleCoverageInformation coverage;

	private Composite heatMapComposite;

	private TLACoveragePainter painter;

	public TLACoverageEditor(final ModuleCoverageInformation coverage) {
		this.coverage = coverage;
	}

	@Override
	public void dispose() {
		painter.queue.offer(TERMINATE);
		super.dispose();
	}

	@Override
	protected ISourceViewer createSourceViewer(final Composite parent, IVerticalRuler ruler, int styles) {
		// Create composite inside of parent (of which we don't control the layout) to
		// place heatMap with a fixed height below the editor.
		
		final Composite composite = new Composite(parent, SWT.BORDER);
		final GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 0;
		composite.setLayout(layout);
		composite.addListener(SWT.Resize, resizeListener);

		// Inside editor use again a FillLayout to let super.create... use all available
		// space.
		final Composite editorComposite = new Composite(composite, SWT.NONE);
		editorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		final FillLayout fillLayout = new FillLayout(SWT.VERTICAL);
		fillLayout.marginHeight = 0;
		fillLayout.marginWidth = 0;
		fillLayout.spacing = 0;
		editorComposite.setLayout(fillLayout);

		heatMapComposite = new Composite(composite, SWT.BORDER);
		final GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
		heatMapComposite.setLayoutData(layoutData);

		// Inside of heatMap, use a horizontally FillLayout to place individuals heat
		// map item next to each other.
		heatMapComposite.setLayout(new FillLayout(SWT.HORIZONTAL));
		
		final ISourceViewer createSourceViewer = super.createSourceViewer(editorComposite, ruler, styles);
		
		// Make TLACoverageEditor distinguishable from regular TLAEditor.
		final StyledText textWidget = createSourceViewer.getTextWidget();
		textWidget.setCursor(new Cursor(textWidget.getDisplay(), SWT.CURSOR_HAND));
		// Flash the editor on keystrokes as a form of a visual bell.
		textWidget.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				// whitelist modifier keys to not flash on ctrl+click to navigate the spec.
				if (e.keyCode == SWT.MOD1 || e.keyCode == SWT.MOD2 || e.keyCode == SWT.MOD3 || e.keyCode == SWT.MOD4) {
					return;
				}
				textWidget.setBackground(darkGray);
			}
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.keyCode == SWT.MOD1 || e.keyCode == SWT.MOD2 || e.keyCode == SWT.MOD3 || e.keyCode == SWT.MOD4) {
					return;
				}
				textWidget.setBackground(lightGray);
			}
		});
		
		return createSourceViewer;
	}
	
	@Override
	protected void initEditorNameAndDescription(final IEditorInput input) {
		if (input instanceof FileEditorInput) {
			final FileEditorInput fei = (FileEditorInput) input;
			// Replace useless filename extension in tab title with read-only indicator.
            this.setPartName(fei.getName().replaceFirst(".tla$", " (ro)"));
            // Use dedicated image to distinguish from regular TLA editor.
            this.setTitleImage(coverageEditorImage);
		} else {
			TLCActivator.logDebug("Unexpected input for TLACoverageEditor of type: " + input.getClass().getName());
		}
	}
	
	@Override
	protected boolean isEditorInputIncludedInContextMenu() {
		// Exclude menu items from the editor's right-click context menu, contributed by
		// the Eclipse foundation such as "Run As..." or "Debug As...". Those are
		// completely bogus in the Toolbox's context and especially for the coverage
		// editor. The crux is, that AbstractTextEditor sucks the contributions in and
		// this seems to be the way to exclude them.
		return false;
	}

	@Override
    protected TLASourceViewerConfiguration getTLASourceViewerConfiguration(IPreferenceStore preferenceStore) {
    	return new TLACoverageSourceViewerConfiguration(preferenceStore, this); 
    }

	@Override
	protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
		//TODO Initialize painter after editor input has been set.
		painter = new TLACoveragePainter(this);
		((TextViewer) viewer).addTextPresentationListener(painter);
		
		return super.getSourceViewerDecorationSupport(viewer);
	}

	public void resetInput(final ModuleCoverageInformation ci) throws PartInitException {
		if (this.coverage == ci) {
			// The CoverageInformation from which the FileCoverageInformation has been
			// projected, is identical to the one already open. No need to update the ui.
			// This case occurs when the TLCModelLaunchDataProvider parses the MC.out of a
			// finished model with more than one block of coverage statistics. For each it
			// notifies ResultPage but - due to TLCModelLaunchDataProvider sending strings
			// instead of the actual values and threading - we read a newer/more up-to-date
			// instance of CoverageInformation before a notification reaches us.
			return;
		}
		this.coverage = ci;
		// Trigger the editor's coverage painter.
		painter.queue.offer(ALL);
	}

	/* TLASourceViewerConfiguration */

	private class TLACoverageSourceViewerConfiguration extends TLASourceViewerConfiguration {

		public TLACoverageSourceViewerConfiguration(IPreferenceStore preferenceStore,
				TLAEditor tlaCoverageEditor) {
			super(preferenceStore, tlaCoverageEditor);
		}
		
		@Override
		public ITextHover getTextHover(final ISourceViewer sourceViewer, String contentType) {
			return new DefaultTextHover(sourceViewer) {
				@Override
				public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
					return coverage.getHoverInfo(hoverRegion.getOffset());
				}
			};
		}
    }
	
	private static final DecimalFormat df = new DecimalFormat("0.0E0");
	
	private static class Pair {
		public final int offset;
		public final Representation rep;

		public Pair(int offset) {
			this(offset, Representation.INV);
		}

		public Pair(int offset, Representation rep) {
			this.offset = offset;
			this.rep = rep;
		}
	}

	private static final Pair ALL = new Pair(-1);
	
	private static final Pair TERMINATE = new Pair(-42);
	
	public class TLACoveragePainter implements ITextPresentationListener {
		
		private ComboViewer viewer;
		
		private final TLACoverageEditor editor;
		
		private final BlockingQueue<Pair> queue = new ArrayBlockingQueue<>(10);
		
		// Each module editor has a painter (system) job which serializes the
		// paint/annotation requests. Requests are generated either by opening the
		// editor, via editor selection changes or legend changes. Requests have
		// to be serialized because ModuleCoverageInformation and its nested data
		// structures are not thread-safe. Additional we try to minimize the requests
		// by skipping redundant requests triggered by rapid mouse clicks.
		private final Job painter = new Job("Coverage Painter") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				while (true) {
					final Pair p = getPair();
					if (TERMINATE.offset == p.offset || monitor.isCanceled()) {
						return Status.OK_STATUS;
					} else {
						monitor.beginTask(String.format("Painting coverage for %s", p.offset), 1);
					}
					
					// Do not clear old style ranges before creating new ones as clear removes TLA+ syntax highlighting.
					//textPresentation.clear(); 
					
					final Grouping grouping = ALL.offset == p.offset ? Grouping.COMBINED : Grouping.INDIVIDUAL;
					
					// Create new style ranges (and the legend)
					TreeSet<CoverageInformationItem> legend = new TreeSet<>();
					if (grouping == Grouping.COMBINED) {
						coverage.getRoot().style(textPresentation, p.rep);
						legend = coverage.getLegend(p.rep);
					} else {
						final CoverageInformationItem node = coverage.getNode(p.offset);
						if (node != null) {
							// Style all unrelated parts gray.
							coverage.getRoot().style(textPresentation, JFaceResources.getColorRegistry().get(ModuleCoverageInformation.GRAY), p.rep);
							
							node.style(textPresentation, p.rep);
							legend = node.getLegend(p.rep);
						}
					}
					
					if (monitor.isCanceled()) {
						return Status.OK_STATUS;
					}
					
					final Collection<CoverageInformationItem> fLegend = collapseLegend(legend);
					UIHelper.runUISync(new Runnable() {
						@Override
						public void run() {
							final TextViewer viewer = editor.getViewer();
							// viewer might have been disposed by the time the outer thread styled the presentation.
							if (viewer == null || viewer.getTextWidget() == null
									|| viewer.getTextWidget().isDisposed()) {
								return;
							}
							viewer.getTextWidget().removeListener(SWT.MouseDown, listener);

							viewer.changeTextPresentation(textPresentation, true);
							updateLegend(fLegend, grouping);
							
							viewer.getTextWidget().addListener(SWT.MouseDown, listener);
						}
					});
					
					monitor.done();
				}
			}
			
			private Collection<CoverageInformationItem> collapseLegend(final TreeSet<CoverageInformationItem> legend) {
				final double numLabel = resizeListener.getWidth() / 47d; // 47 pixel per label seems to fit most text and still looks pleasant.
				if (legend.size() <= (int) Math.ceil(numLabel)) {
					// can fit all elements, nothing to do.
					return legend;
				}
				
				// TODO Select a subset of legend of size numLabels s.t. the distance between
				// any two elements in subset is maximized. The code below approximates the
				// problem by simply constructing the subset where the distance is the position
				// in the set not the actual value. In other words, the set of distances of all
				// adjacent elements in the legend will be non-uniform.
				
				// Cannot fit more than N labels into the legend. Thus, only take N elements
				// out of legend (even distribution).
				final int nth = (int) Math.ceil(legend.size() / numLabel);

				// Add lowest/first CCI.
				final List<CoverageInformationItem> result = new ArrayList<>((int)Math.ceil(numLabel));
				result.add(legend.first());

				// Pick nth - 2 CCIs in-between.
				int i = 1;
				final Iterator<CoverageInformationItem> iterator = legend.iterator();
				while (iterator.hasNext()) {
					final CoverageInformationItem cii = iterator.next();
					if (i++ % nth == 0) {
						result.add(cii);
					}
				}
				
				// Add highest/last CCI from legend.
				result.add(legend.last());
				return result;
			}

			private Pair getPair() {
				try {
					return queue.take();
				} catch (InterruptedException notExpectedException) {
					notExpectedException.printStackTrace();
					return TERMINATE;
				}
			}

			private void updateLegend(Collection<CoverageInformationItem> legend, final Representation.Grouping grouping) {
				final Composite parent = heatMapComposite.getParent();
				if (legend.isEmpty()) {
					heatMapComposite.setVisible(false);
				} else {
					final Representation currentRepresentation = getActiveRepresentation();
					heatMapComposite.dispose();

					// Assume a spec with a Next action such as Next == (x' \in S) \/ (x' \in T)
					// In other words, consider a spec where an action has sub-actions (disjuncts).
					// If this is reported as COMBINED, the legend is bogus bc the value for Next
					// appears twice (for the first and second disjunct) but the value is both
					// times the combined one.
					Representation.Grouping grpng = grouping;
					if (currentRepresentation == Representation.STATES
							|| currentRepresentation == Representation.STATES_DISTINCT) {
						grpng = Grouping.INDIVIDUAL;
					}
					
					heatMapComposite = new Composite(parent, SWT.BORDER);
					final GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
					heatMapComposite.setLayoutData(layoutData);
					
					// Inside of heatMap, use a horizontally FillLayout to place individuals heat
					// map item next to each other.
					heatMapComposite.setLayout(new FillLayout(SWT.HORIZONTAL));
					
					// Create the actual SWT labels for the elements in legend. 
					// TODO Rendering the text vertically would save horizontal screen estate but is
					// unfortunately not easily possible with SWT.
					for (CoverageInformationItem cii : legend) {
						final Label label = new Label(heatMapComposite, SWT.BORDER);
						label.setAlignment(SWT.CENTER);
						
						// A label has a background color and a text indicating the actual value
						// (cost/invocations/...).
						label.setBackground(currentRepresentation.getColor(cii, grpng));

						final long value = currentRepresentation.getValue(cii, grpng);
						// Format numbers > 1000 in scientific notation.
						if (value > 1000) {
							label.setText(df.format(value));
						} else {
							label.setText(String.format("%,d", value));
						}
						
						// Indicate the location to where the mouse click takes the user.
						label.setToolTipText(String.format(currentRepresentation.getToolTipText(), value, cii.getLocation()));
						
						// The mouse listener takes the user to the related
						// region in the module.
						label.addMouseListener(new MouseAdapter() {
							@Override
							public void mouseDown(final MouseEvent e) {
								final IRegion region = cii.getRegion();
								editor.selectAndReveal(region.getOffset(), cii.getRegion().getLength());
							}
						});
					}

					// Show a drop-down list (combo) to let the user select a different representation. 
					viewer = new ComboViewer(heatMapComposite, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
				    viewer.setContentProvider(ArrayContentProvider.getInstance());
				    viewer.setLabelProvider(new LabelProvider() {
				        @Override
				        public String getText(Object element) {
				            if (element instanceof Representation) {
				            	Representation current = (Representation) element;
				            	return current.toString();
				            }
				            return super.getText(element);
				        }
				    });
				    
					// Do not allow users to set the legend to states or distinct states if the
					// module does not have values for these two representations. Otherwise, update
					// legend will hide the legend (because legend is empty) without means to switch
					// back (the buttons are hidden).
					viewer.setInput(coverage.hasStates() ? Representation.values() : Representation.valuesNoStates());
				    viewer.setSelection(new StructuredSelection(currentRepresentation));
				    viewer.addSelectionChangedListener(event -> {
					    final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
					    final Representation rep = (Representation)selection.getFirstElement();
						final int offset = JFaceTextUtil.getOffsetForCursorLocation(editor.getViewer());
						queue.offer(new Pair(offset, rep));
					});
				}
				parent.layout();
			}
		};

		private Representation getActiveRepresentation() {
			if (viewer != null) {
				final IStructuredSelection structuredSelection = viewer.getStructuredSelection();
				return (Representation) structuredSelection.getFirstElement();
			}
			return Representation.INV;
		}
		
		private final Listener listener = new Listener() {
			@Override
			public void handleEvent(final Event event) {
				final Representation activeRepresentation = getActiveRepresentation();
				final int offset = JFaceTextUtil.getOffsetForCursorLocation(editor.getViewer());
				final Pair peek = queue.peek();
				final boolean isControlClick = ((event.stateMask & SWT.MOD1) != 0);
				
				if (isControlClick) {
					editor.getViewer().getTextWidget().notifyListeners(SWT.MouseUp, null);
					event.doit = false;
					
					final String moduleName = getModuleName() + TLAConstants.Files.TLA_EXTENSION;
					final TLAEditor editor = EditorUtil.openTLAEditor(moduleName);
					
					if (editor != null) {
						editor.selectAndReveal(offset, 0);
					} else {
						TLCUIActivator.getDefault().logError("Unable to open editor for name: " + moduleName);
					}
				} else if ((peek == null) || (peek.offset != offset) || (peek.rep != activeRepresentation)) {
//					System.out.println(String.format("Scheduling offset %s, %s after %s", offset, activeRepresentation, peek));
					queue.offer(new Pair(offset, activeRepresentation));
				} else {
					//System.out.println("Skipping redundant offset " + offset);
				}
			}
		};
		
		private TextPresentation textPresentation;

		public TLACoveragePainter(TLACoverageEditor editor) {
			this.editor = editor;
			
			this.painter.setPriority(Job.LONG);
			this.painter.setRule(null);
			this.painter.setSystem(true);
		}

		@Override
		public synchronized void applyTextPresentation(final TextPresentation textPresentation) {
			// Set the background color down here instead of in createSourceViewer above
			// where it is overridden by the OS's default background color.
			editor.getSourceViewer().getTextWidget().setBackground(lightGray);

			// Unregister this to not rerun the initialization again.
			editor.getViewer().removeTextPresentationListener(this);
			
			this.textPresentation = textPresentation;
			
			editor.getViewer().addTextInputListener(new ITextInputListener() {
				@Override
				public synchronized void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
					editor.getViewer().removeTextInputListener(this);
					
					// Register listener to update coverage information based on mouse clicks.
					final StyledText textWidget = editor.getViewer().getTextWidget();
					textWidget.addListener(SWT.MouseDown, listener);

					// Color the editor with coverage information initially.
					queue.add(ALL);
					painter.schedule();
				}
				
				@Override
				public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
				}
			});
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-long/tlc2/tool/liveness/MultiThreadedSpecTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.junit.Before;
import org.junit.Test;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.tool.WorkerMonitor;

/**
 * This test takes about four minutes with 32 cores on an EC2 cr1.8xlarge instance.
 * On a Thinkpad T430s it takes eight times as long and uses up 4GB of memory (see customBuild.xml).
 * 
 * The purpose of this test is to establish a thread contention baseline that TLC shows for
 * liveness checking (with and without tableaux). More precisely the time each TLC worker
 * thread spends in the WAITING and BLOCKED state must not exceed more than waitedRatio and
 * blockedRatio. The current values for waitedRatio and blockedRatio have been obtained empirically.
 */
public abstract class MultiThreadedSpecTest extends ModelCheckerTestCase {

	private final String statesGenerated;
	private final String distinctStatesGenerated;
	private final List<PerformanceResult> performanceResults = new ArrayList<PerformanceResult>();
	private final CountDownLatch latch = new CountDownLatch(getNumberOfThreads());
	private final double waitedRatio;
	private final double blockedRatio;
	
	public MultiThreadedSpecTest(String spec, String path, String statesGenerated, String distinctStatesGenerated, double blockedRatio, double waitedRatio) {
		super(spec, path);
		this.statesGenerated = statesGenerated;
		this.distinctStatesGenerated = distinctStatesGenerated;
		this.blockedRatio = blockedRatio;
		this.waitedRatio = waitedRatio;
	}

	public MultiThreadedSpecTest(String spec, String path, String[] extraArguments, String statesGenerated, String distinctStatesGenerated, double blockedRatio, double waitedRatio) {
		super(spec, path, extraArguments);
		this.statesGenerated = statesGenerated;
		this.distinctStatesGenerated = distinctStatesGenerated;
		this.blockedRatio = blockedRatio;
		this.waitedRatio = waitedRatio;
	}

	@Test
	public void testSpec() throws BrokenBarrierException, InterruptedException, TimeoutException {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, statesGenerated, distinctStatesGenerated));
		
		// Assert it has found the temporal violation and also a counter example
		assertTrue(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
		assertTrue(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));
		
		// Assert the error trace
		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT3));
		
		// Allow TLC worker threads to take 10 seconds to shutdown and report
		// their PerformanceResults to us. TLC's master thread has no reason to
		// wait for the final termination of all worker threads once it has
		// received the signal from one of them. After all the VM itself is
		// going to shutdown after TLC is done printing results.
		latch.await(10, TimeUnit.SECONDS);

		// Except as many results as we have started worker threads.
		//
		// If this assert fails, make sure that AspectJ is loaded and the
		// WorkerMonitorAspect is woven. This is done automatically by the ant
		// build (customBuild.xml) but not when this test is executed inside
		// Eclipse. AJDT (the AspectJ development tools) should not be a general
		// requirement to compile the tlatools/ project in Eclipse.
		//
		// If you ask why it uses AspectJ the first place... Rather than adding
		// API to the TLC code making in more and more complex just to test its
		// performance behavior, I deemed the extra test complexity caused by
		// AspectJ acceptable. We trade less complexity in program code with
		// higher complexity in test code.
		//
		// To run this test in Eclipse, install AJDT (http://eclipse.org/ajdt/),
		// convert the tlatools/ project into an AspectJ project via the 
		// Package Explorers context menu and add 
		// "-javaagent:${project_loc:tlatools}/lib/aspectjweaver-1.8.5.jar" 
		// as a program argument to your JUnit launch config.
		//
		// If you get some but not all results, it's most certainly unrelated to
		// AspectJ and indicates a programming bug.
		assertEquals("PerfResult size is 0? => Is AspectJ load time weaving enabled?", getNumberOfThreads(),
				performanceResults.size());
		
		// None of the workers threads should have been blocked or waiting for
		// more than 25%
		for (PerformanceResult result : performanceResults) {
			assertTrue(String.format("Blocked(%s): %.3f", result.getThreadName(), result.getBlockedRatio()),
					result.getBlockedRatio() < blockedRatio);
			assertTrue(String.format("Waiting(%s): %.3f", result.getThreadName(), result.getWaitedRatio()),
					result.getWaitedRatio() < waitedRatio);
		}
	}
	
	@Before
	public void setUp() {
		// Set the threshold before TLC (periodically) checks liveness to
		// the largest possible value. This essentially stops TLC from checking
		// liveness during model checking and delays it until the end when one
		// final liveness check is run. We only then get deterministic behavior
		// needed by this test to e.g. check the number of states generated...
		TLCGlobals.livenessThreshold = Double.MAX_VALUE;
		
		final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
		// Enable contention thread statistics to have the JVM measure
		// BlockedTime and WaitedTime.
		threadBean.setThreadContentionMonitoringEnabled(true);

		// Register a listener hot for the termination of the TLC worker
		// threads. 
		// Using ThreadMXBean directly to lookup all threads after TLC has
		// finished has the potential that the JVM deletes the worker threads
		// before this test gets a chance to collect statistics.
		WorkerMonitor.addThreadListener(new WorkerMonitor.ThreadListener() {
			public synchronized void terminated(final Thread thread, final long runningTime) {
				final ThreadInfo threadInfo = threadBean.getThreadInfo(thread.getId());
				double d = threadInfo.getBlockedTime() / (runningTime * 1.0d);
				double d2 = threadInfo.getWaitedTime() / (runningTime * 1.0d);
				performanceResults.add(new PerformanceResult(thread.getName(), d, d2));
				latch.countDown();
			}
		});
	}
	
	protected int getNumberOfThreads() {
		// Run this test with as many threads possible to hopefully spot concurrency issues.
		return Runtime.getRuntime().availableProcessors();
	}
	
	private static class PerformanceResult {

		private final double blockedRatio;
		private final double waitedRatio;
		private final String threadName;

		public PerformanceResult(String threadName, double blockedRatio, double waitedRatio) {
			this.threadName = threadName;
			this.blockedRatio = blockedRatio;
			this.waitedRatio = waitedRatio;
		}

		public double getWaitedRatio() {
			return waitedRatio;
		}

		public double getBlockedRatio() {
			return blockedRatio;
		}
		
		public String getThreadName() {
			return threadName;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ExternalModuleTable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

// Last modified on Sat 17 Mar 2007 at 11:28:08 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.semantic;

import java.util.Enumeration;
import java.util.Hashtable;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import util.UniqueString;

public class ExternalModuleTable implements ExploreNode {

  public class ExternalModuleTableEntry implements ExploreNode {

    ModuleNode   moduleNode;  // the ModuleNode
    Context      ctxt;        // and its full context, including all Builtin ops, ops from EXTENDS and INSTANCE,
                              //   and module nodes for inner modules (but NOT its defined ops)

    ExternalModuleTableEntry (Context ctxt, ModuleNode modn) {
      this.ctxt = ctxt;
      this.moduleNode = modn;
    } 

    public ModuleNode getModuleNode() { return moduleNode; }

    public void printMTE(int depth, boolean b) {
      if (moduleNode != null) {
        System.out.print(Strings.indent(2, "\nModule: ")); 
        moduleNode.print(2,depth,b);
      }
      else {
        System.out.print(Strings.indent(2, "\nModule: " + 
                         Strings.indent(2, "\n***Null ExternalModuleTable entry; " + 
                                           "module contained error and was not created."))
                        );
      }
    } // end printMTE()

    /**  
     * walkGraph, levelDataToString, and toString methods to implement ExploreNode interface
     */
    public String levelDataToString() { return "Dummy level string"; }

    public void walkGraph(Hashtable<Integer, ExploreNode> moduleNodesTable, ExplorerVisitor visitor) {
      if (moduleNode != null)   moduleNode.walkGraph(moduleNodesTable, visitor);
      if (ctxt != null)      ctxt.walkGraph(moduleNodesTable, visitor);
    } // end walkGraph()

    public String toString(int depth) {
      if (depth <= 0) return "";
      
      if (moduleNode != null) {
	return Strings.indent(2, "\nModule: " + Strings.indent(2,moduleNode.toString(depth)) );
      } else {
	return Strings.indent(2, "\nModule: " + Strings.indent(2, "\n***Null ExternalModuleTable entry; " + 
							       "module contained error and was not created."));
      }
    } // end toString()

  } // end internal class ModuleTableEntry

  // Each entry in the Hashtable "ht" is a tuple of the form
  //
  //   (moduleName, <context, ModuleNode>)
  //
  // where the moduleName is the hash key.  The modules included are
  // the root module, and all of those other top-level (i.e. external)
  // modules it depends upon, directly or indirectly, by EXTENDS or
  // INSTANCE (but NOT including internal modules)
  /*************************************************************************
  * I presume the comment above is really about the HashTable              *
  * moduleHashTable, and that each of its entries has a moduleName as the  *
  * key and a value that's an ExternalModuleTableEntry object.             *
  *************************************************************************/
  public Hashtable<UniqueString, ExternalModuleTableEntry> moduleHashTable;

  // Vector moduleVector contains ModuleNodes (the same ones as
  // moduleHashTable), but preserves the order in which they were
  // inserted.  If module A depends on module B, then A has a HIGHER
  // index than B.
  public Vector<ModuleNode>    moduleNodeVector;

  // The nodule node of the root module
  public ModuleNode rootModule;

  // Constructor
  public ExternalModuleTable() {
    moduleHashTable  = new Hashtable<>();
    moduleNodeVector = new Vector<>();
  }

  // Set and get the rootModule field
  public ModuleNode getRootModule()              { return rootModule; }
  public void       setRootModule(ModuleNode mn) { rootModule = mn; }

  public final Context getContext( UniqueString key ) {
    ExternalModuleTableEntry p = moduleHashTable.get(key);
    if (p == null) return null;
    return p.ctxt;
  }

  public final Context getContextForRootModule() {
	  return getContext(getRootModule().getName());
  }
  
  /**
   *  Returns a vector of ModuleNodes, one for each outer module (i.e. not
   *  inner modules) in the specification.  InnerModules can be obtained 
   *  via getInnerModules() applied to a ModuleNode.
   *
   *  The modules are ordered so that if module A EXTENDS or INSTANCE's
   *  module B, then A has a higher index than B in the array.
   */
  public ModuleNode[] getModuleNodes() {
    ModuleNode [] mods = new ModuleNode[moduleNodeVector.size()];
    for (int i = 0; i < mods.length; i++) {
      mods[i] = (ModuleNode)moduleNodeVector.elementAt(i);
    }
    return mods;
  }

  public final ModuleNode getModuleNode( String key ) {
	  return getModuleNode(UniqueString.of(key));
  }

  public final ModuleNode getModuleNode( UniqueString key ) {
    ExternalModuleTableEntry p = moduleHashTable.get(key);
    if (p == null) return null;
    return p.moduleNode;
  }

  public final void put( UniqueString key, Context ctxt, ModuleNode moduleNode ) {
    ExternalModuleTableEntry c = moduleHashTable.get( key );
    if (c == null) {
      moduleHashTable.put( key, new ExternalModuleTableEntry(ctxt, moduleNode) );
      moduleNodeVector.addElement(moduleNode);
    }
  }

  @Override
  public String toString() {
    Enumeration<ExternalModuleTableEntry> Enum = moduleHashTable.elements();
    String ret = "";

    while (Enum.hasMoreElements()) {
      ExternalModuleTableEntry mte = Enum.nextElement();
      ret = ret + mte.toString();
    }
    return "\nModule Table:" + Strings.indent(2,ret);
  }

  public void printExternalModuleTable(int depth, boolean b) {
    System.out.print("\nExternal Module Table:");

    for (int i = 0; i < moduleNodeVector.size(); i++) {
      ModuleNode mn = moduleNodeVector.elementAt(i);

      if (mn != null) {
        System.out.print(Strings.indent(2, "\nModule: ")); 
        mn.print(2,depth,b);
      } else {
        System.out.print(Strings.indent(2, "\nModule: " + 
                         Strings.indent(2, "\n***Null ExternalModuleTable entry; " + 
                                           "module contained error and was not created.")));
      }
    }
  }

  /**  
   * walkGraph, levelDataToString, and toString methods to implement ExploreNode interface
   */
  public String levelDataToString() { return "Dummy level string"; }

  public String toString(int depth) {
    if (depth <= 0) return "";

    String ret = "";
    for (int i = 0; i < moduleNodeVector.size(); i++) {
      ModuleNode mn = (ModuleNode)moduleNodeVector.elementAt(i);
      if (mn != null) {
        ret += Strings.indent(2, "\nModule: " + Strings.indent(2, mn.toString(depth)) );
      } else {
	String str = "\n***Null ExternalModuleTable entry; module contained error and was not created.";
	ret += Strings.indent(2, "\nModule: " + Strings.indent(2, str));
      }
    }
    return ret;
  }

  public void walkGraph(Hashtable<Integer, ExploreNode> moduleNodesTable) {
	  walkGraph(moduleNodesTable, ExplorerVisitor.NoopVisitor);
  }

  public void walkGraph(Hashtable<Integer, ExploreNode> moduleNodesTable, ExplorerVisitor visitor) {
    Enumeration<ExternalModuleTableEntry> Enum = moduleHashTable.elements();

    while ( Enum.hasMoreElements() ) {
	ExternalModuleTableEntry mte = Enum.nextElement();
	mte.walkGraph(moduleNodesTable, visitor);
    }
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/AssignmentToUndeclaredVariableTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Arrays;

import org.junit.Test;

import util.ToolIO;

public class AssignmentToUndeclaredVariableTest extends PCalTest {
	@Test
	public void procedure() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo {\n" + 
				"  variables v, w;\n" + 
				"    procedure Proc1() \n" + 
				"      {p1 : v := 23;\n" + 
				"            c := 42 }\n" + 
				" {\n" +
				"  i: call Proc1();\n" + // Assignment to constant
				" }\n" + 
				"}*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 8, column 13.\n"));
	}
	
	@Test
	public void process() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo {\n" + 
				"  variables v, w;\n" + 
				"  process (proc \\in {1,2})\n" + 
				"    variable loc\n" + 
				" {\n" +
				"   lbl1: loc := 42;\n" +
				"   lbl2: v := 23;\n" +
				"   lbl3: w := 174;\n" +
				"   lbl4: c := \"fail\";\n" + // Assignment to constant
				" }\n" + 
				"}*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 12, column 10.\n"));
	}
	
	@Test
	public void multiAssignment() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo {\n" + 
				"  variables v, w;\n" + 
				" {\n" +
				"  v := 42 || w := 23;\n" +
				"  v := 42 || c := 23;\n" + // Assignment to constant
				" }\n" + 
				"}*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 8, column 11.\n"));
	}

	@Test
	public void macro() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo {\n" + 
				"  variables v;\n" + 
				"  macro Mac() { v := \"pmac\";\n c := 42; }\n" + 
				" {\n" +
				"  Mac();\n" + // Assignment to constant
				" }\n" + 
				"}*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.toString(ToolIO.getAllMessages()),
				Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 7, column 2 of macro called at line 9, column 3.\n"));
	}
	
	@Test
	public void macroParam() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo {\n" + 
				"  variables v;\n" + 
				"  macro Mac2(p) { p := \"pmac\"}\n" + 
				" {\n" +
				"  lbl1: Mac2(v);\n" +
				"  lbl2: Mac2(c);\n" + // Assignment to constant
				" }\n" + 
				"}*)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 6, column 19 of macro called at line 9, column 9.\n"));
	}
	
	@Test
	public void boundIdentifier() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
							writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo\n" + 
				"  variables v;\n" + 
				"begin\n" +
				"   with n \\in {1,2,3} do\n" +
				"      v := n;\n" + 
				"      n := 42;\n" + // Assignment to bound identifier!
				"   end with;" +
				"end algorithm\n" + 
				" *)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable n\n"
					+ "    at line 9, column 7.\n"));
	}
	
	@Test
	public void constant() throws IOException {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS, trans.runMe(new String[] {"-nocfg", 
			writeTempFile("AssignmentToUndeclaredVariableTest", 
				"---- MODULE algo ----\n" + 
				"CONSTANT c\n" + 
				"(*\n" + 
				"--algorithm algo\n" + 
				"  variables v;\n" + 
				"begin\n" + 
				"   v := 23;\n" + 
				"   c := 42;\n" + // Assignment to constant! 
				"end algorithm\n" + 
				" *)\n" + 
				"===="
			)}));
		
		assertTrue(Arrays.asList(ToolIO.getAllMessages()).contains("\nUnrecoverable error:\n"
					+ " -- Assignment to undeclared variable c\n"
					+ "    at line 8, column 4.\n"));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/Module.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.spec;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

import org.eclipse.core.resources.IResource;

import tla2sany.modanalyzer.ParseUnit;
import tla2sany.semantic.ModuleNode;
import tlc2.module.BuiltInModuleHelper;
import util.FilenameToStream.TLAFile;
import util.NamedInputStream;
import util.TLAConstants;

/**
 * Representation of a module
 */
public class Module
{
    private final File file;
    
    private ModuleNode node;
    private boolean isRoot = false;
	private IResource resource;

	private final ParseUnit parseUnit;

    public Module(ParseUnit parseUnit)
    {
        this.file = new File(parseUnit.getNis().sourceFile().getAbsolutePath());
        this.parseUnit = parseUnit;
    }

    public Module(IResource resource) {
    	this.file = new File(resource.getLocation().toOSString());
    	this.parseUnit = null;
    	this.resource = resource;
	}

	/**
     * Retrieves absolute path of the module file
     * 
     * @return path of the module file
     */
    public String getAbsolutePath()
    {
        return file.getAbsolutePath();
    }

    /**
     * Retrieves the file handle
     * 
     * @return the file
     */
    public File getFile()
    {
        return file;
    }

	/**
	 * @return null or the Eclipse specific resource handle for this module. A
	 *         IResource is the pendant to the non-Eclipse specific
	 *         java.io.File.
	 * 
	 * @see {@link Module#getFile()}
	 */
    public IResource getResource() {
    	return resource;
    }

	public void setResource(IResource aResource) {
		this.resource = aResource;
	}
   
    /**
     * Retrieves the module name
     * @return the name of the module
     */
    public String getModuleName()
    {
        String filename = file.getName();
        final int tlaSuffixIndex = filename.toLowerCase().indexOf(TLAConstants.Files.TLA_EXTENSION);
        if (tlaSuffixIndex != -1)
        {
            filename = filename.substring(0, tlaSuffixIndex);
        }
        return filename;
    }

    /**
     * Retrieves the semantic node of the module (only available if the module has been parsed successfully)
     * 
     * @return the node
     */
    public ModuleNode getNode()
    {
        return node;
    }

    /**
     * Sets the semantic module node
     * 
     * @param node
     *            the node to set
     */
    public void setNode(ModuleNode node)
    {
        this.node = node;
    }

    public boolean isStandardModule() {
    	if (this.node != null) {
    		// As standard module such as FiniteSets, ... are considered library modules.
    		return this.node.isStandardModule();
    	}
    	// TODO Fishy method; improve/unify!
        return (getAbsolutePath().indexOf(BuiltInModuleHelper.STANDARD_MODULES) != -1);
    }
    
    /**
	 * Determines if current module has been loaded from the library path, i.e. it
	 * is a standard module or part of a module archive such as CommuinityModules.
	 */
    public boolean isLibraryModule()
    {
    	if (this.parseUnit != null && parseUnit.isLibraryModule()) {
    		return true;
    	}
    	return isStandardModule();
    }
    
    public boolean isRoot()
    {
        return isRoot;
    }
    
    public void setRoot(boolean isRoot)
    {
        this.isRoot = isRoot;
    }

	public void copyTo(final Path dst) throws IOException {
		Files.copy(file.toPath(), dst.resolve(file.getName()), StandardCopyOption.REPLACE_EXISTING);

		// Attempt to copy corresponding TLC module override (.class file) if any for this Module. 
		if (this.parseUnit != null) {
			final NamedInputStream nis = this.parseUnit.getNis();
			if (nis != null && nis.sourceFile() instanceof TLAFile) {
				final TLAFile tlaFile = (TLAFile) nis.sourceFile();
				final File moduleOverride = tlaFile.getModuleOverride();
				if (moduleOverride != null) {
					Files.copy(moduleOverride.toPath(), dst.resolve(moduleOverride.getName()), StandardCopyOption.REPLACE_EXISTING);
				}
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/NewModelHandlerCurrentDelegate.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Delegates the model creation for the currently selected spec
 * @author <NAME>
 * @version $Id$
 */
public class NewModelHandlerCurrentDelegate extends AbstractHandler implements IHandler
{
    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        // get the current spec
        Spec current = ToolboxHandle.getCurrentSpec();
        if (current != null)
        {
            Map<String, String> parameters = new HashMap<String, String>();
            // fill the spec name for the handler
            parameters.put(NewModelHandler.PARAM_SPEC_NAME, ((Spec) current).getName());
            // delegate the call to the new model handler
            UIHelper.runCommand(NewModelHandler.COMMAND_ID, parameters);
        }
        return null;
    }
	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (ToolboxHandle.getCurrentSpec() == null) {
			return false;
		}
		return super.isEnabled();
	}
	

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/AnyDefNode.java<|end_filename|>
/**
 * The AnyDefNode interface is implemented by OpDefNode and ThmOrAssumpDefNode.
 * It was added by LL on 24 Oct 2012 to fix a bug in the level-checking of
 * ThmOrAssumpDefNode objects.  When a module containing a theorem or assumption 
 * such as 
 * 
 *    THEOREM Fab == ...
 *    
 * is instantiated with parameters in a statement like
 * 
 *     I(x, y) == INSTANCE M WITH ...
 *     
 * then level checking of the expression I(e1, e2)!Fab did not check that
 * the levels of e1 and e2 were appropriate for the instantiation.  This was
 * because the levelCheck method of OpApplNode treated an operator like Fab
 * defined with a ThmOrAssumpDefNode differently from one defined with an 
 * OpDefNode.  To solve this problem, level checking of ThmOrAssumpDefNode was 
 * changed to be essentially the same as for OpDefNode.  The levelCheck method
 * of OpApplNode was changed to handle ThmOrAssumpDefNode and OpDefNode operators
 * the same by changing OpDefNode to AnyDefNode in a couple of places, and by 
 * replacing one access to an OpDefNode field by a call of a new method that
 * returns the value of that field.    
 */
package tla2sany.semantic;

import java.util.HashSet;

import util.UniqueString;

/**
 * @author lamport
 *
 */
public interface AnyDefNode {
    public boolean levelCheck(int itr) ;
    public int getMaxLevel(int i) ;
    public UniqueString getName() ;
    public int getMinMaxLevel(int i, int j) ;
    public boolean getOpLevelCond(int i, int j, int k) ;
    public int getLevel() ;
    public int getWeight(int i) ;
    public HashSet<SymbolNode> getLevelParams() ;
    public HashSet<SymbolNode> getAllParams() ;
    public HashSet<SymbolNode> getNonLeibnizParams() ;
    public int getArity() ;
    public boolean[] getIsLeibnizArg() ;
    public boolean getIsLeibniz() ;
    public SetOfLevelConstraints getLevelConstraints() ;
    public HashSet<ArgLevelParam> getArgLevelParams() ;
    public SetOfArgLevelConstraints getArgLevelConstraints() ;
    public FormalParamNode[] getParams() ;
    public AnyDefNode getSource();
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/WorkerException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:45 PST by lamport  
//      modified on Wed Dec  5 15:35:42 PST 2001 by yuanyu   

package tlc2.tool;

@SuppressWarnings("serial")
public class WorkerException extends Exception {

	public TLCState state1;
	public TLCState state2;
	public boolean keepCallStack;

	public WorkerException(String msg) {
		this(msg, null, null, false);
	}

	public WorkerException(String msg, TLCState s1, TLCState s2, boolean keep) {
		super(msg);
		this.state1 = s1;
		this.state2 = s2;
		this.keepCallStack = keep;
	}

	public WorkerException(String msg, Throwable cause, TLCState s1, TLCState s2, boolean keep) {
		super(msg, cause);
		this.state1 = s1;
		this.state2 = s2;
		this.keepCallStack = keep;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/WarningMessage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;

/**
 * Class representing a warning message sent from the tlapm
 * to the Toolbox. For example, "bad fingerprints format - notloaded".
 * 
 * @author <NAME>
 *
 */
public class WarningMessage extends TLAPMMessage
{

    /**
     * The field name whose value is the warning message. 
     */
    public static final String MSG_FIELD = "msg";

    /**
     * The warning message.
     */
    private String message;

    /**
     * Creates a new {@link WarningMessage} from the {@link Set}
     * of {@link Entry} where the key of each {@link Entry} is the field
     * name and the value is the field value string as output by the TLAPM.
     * 
     * This method expects the only field to have the name "msg".
     * 
     * @param fieldPairs
     * @param moduleName
     * @return
     */
    public static WarningMessage getWarningMessage(Set fieldPairs, String moduleName)
    {

        WarningMessage message = new WarningMessage();

        for (Iterator it = fieldPairs.iterator(); it.hasNext();)
        {
            Map.Entry nextEntry = (Map.Entry) it.next();
            String fieldName = (String) nextEntry.getKey();
            String fieldValue = (String) nextEntry.getValue();
            if (fieldName != null && fieldValue != null)
            {
                if (fieldName.equals(MSG_FIELD))
                {
                    message.message = fieldValue;
                } else
                {
                    ProverUIActivator.getDefault().logDebug("Unknown field name for warning message : " + fieldName + ".");
                }
            }
        }

        return message;

    }

    /**
     * Returns the warning message from the tlapm.
     * 
     * @return
     */
    public String getMessage()
    {
        return message;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/OpenSpecHandlerDelegate.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Handler that opens the spec selected in the CNF and delegates to the open spec handler
 * @author <NAME>
 * @version $Id$
 */
public class OpenSpecHandlerDelegate extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {

        /*
         * Try to get the spec from active navigator if any
         */
        IWorkbenchPage activePage = UIHelper.getActivePage();
        if (activePage != null)
        {
            ISelection selection = activePage.getSelection(ToolboxExplorer.VIEW_ID);
            if (selection != null && selection instanceof IStructuredSelection
                    && ((IStructuredSelection) selection).size() == 1)
            {
                Object selected = ((IStructuredSelection) selection).getFirstElement();
                if (selected instanceof Spec)
                {
                    final Map<String, String> parameters = new HashMap<String, String>();
                    // fill the spec name for the handler
                    parameters.put(OpenSpecHandler.PARAM_SPEC, ((Spec) selected).getName());

                    // delegate the call to the open spec handler
                    UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
                }
            }
        }

        return null;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/management/TLCStandardMBean.java<|end_filename|>
// Copyright (c) Jan 4, 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.management;

import java.lang.management.ManagementFactory;

import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;

import tlc2.TLCGlobals;

/**
 * @author <NAME>
 */
public abstract class TLCStandardMBean extends StandardMBean {

	private ObjectName mxbeanName;

	protected TLCStandardMBean(@SuppressWarnings("rawtypes") final Class mbeanInterface)
			throws NotCompliantMBeanException {
		super(mbeanInterface);
	}

	public String getVersion() {
		return TLCGlobals.versionOfTLC;
	}
	
	public String getRevision() {
		if (TLCGlobals.getRevision() == null) {
			return "N/A";
		}
		return TLCGlobals.getRevision();
	}

	/**
	 * Registers a new MBean with the platform's MBean server after which this MBean will be visible in JMX.
	 * 
	 * 
	 * @param objectName The name under which to register this mbean
	 * @return true iff successfully registered
	 * 
	 * @see MBeanServer#registerMBean(Object, ObjectName)
	 */
	protected boolean registerMBean(final String objectName){
		// register monitoring mx bean
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
		try {
			mxbeanName = new ObjectName(objectName);
			mbs.registerMBean(this, mxbeanName);
		} catch (MalformedObjectNameException e1) {
			e1.printStackTrace();
			return false;
		} catch (NullPointerException e1) {
			e1.printStackTrace();
			return false;
		} catch (InstanceAlreadyExistsException e) {
			e.printStackTrace();
			return false;
		} catch (MBeanRegistrationException e) {
			e.printStackTrace();
			return false;
		} catch (NotCompliantMBeanException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * Unregisters the JMX wrapper with the {@link MBeanServer}
	 */
	public boolean unregister() {
		final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		try {
			if (mbs.isRegistered(mxbeanName)) {
				mbs.unregisterMBean(mxbeanName);
			}
		} catch (MBeanRegistrationException e) {
			e.printStackTrace();
			return false;
		} catch (InstanceNotFoundException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * @return A null bean that makes NPE checks obsolete
	 */
	public static TLCStandardMBean getNullTLCStandardMBean() {
		NullTLCStandardMBean nullTLCStandardMBean = null;
		try {
			nullTLCStandardMBean = new NullTLCStandardMBean();
		} catch (NotCompliantMBeanException e) {
			e.printStackTrace();
		}
		return nullTLCStandardMBean;
	}
	
	private static class NullTLCStandardMBean extends TLCStandardMBean implements DynamicMBean {

		public NullTLCStandardMBean() throws NotCompliantMBeanException {
			super(DynamicMBean.class);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.management.TLCStandardMBean#registerMBean(java.lang.String)
		 */
		@Override
		protected boolean registerMBean(String objectName) {
			return true;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.management.TLCStandardMBean#unregister()
		 */
		@Override
		public boolean unregister() {
			return true;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/TLAOpenElementSelectionDialogHandler.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.ui.dialog.TLAFilteredItemsSelectionDialog;
import org.lamport.tla.toolbox.ui.handler.OpenModuleHandler;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;
import org.lamport.tla.toolbox.util.UIHelper;

public class TLAOpenElementSelectionDialogHandler extends AbstractHandler implements IHandler {

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
	 */
	public Object execute(final ExecutionEvent event) throws ExecutionException {
		final FilteredItemsSelectionDialog dialog = new TLAFilteredItemsSelectionDialog(HandlerUtil.getActiveShell(event));
		dialog.open();
		
		final Object[] result = dialog.getResult();
		if (result != null && result.length == 1) {
			final Map<String, String> parameters = new HashMap<String, String>();
			if (result[0] instanceof Module && ((Module) result[0]).isRoot()) {
				parameters.put(OpenSpecHandler.PARAM_SPEC, ((Module) result[0]).getModuleName());
				UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
			} else if (result[0] instanceof Module) {
				parameters.put(OpenModuleHandler.PARAM_MODULE, ((Module) result[0]).getModuleName());
				UIHelper.runCommand(OpenModuleHandler.COMMAND_ID, parameters);
			} else if (result[0] instanceof Model) {
				parameters.put(OpenModelHandler.PARAM_MODEL_NAME, ((Model) result[0]).getName());
				UIHelper.runCommand(OpenModelHandler.COMMAND_ID, parameters);
			} else if (result[0] instanceof Spec) {
				parameters.put(OpenSpecHandler.PARAM_SPEC, ((Spec) result[0]).getName());
				UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
			}
		}
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/preference/ColorPredicateFieldEditor.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.tool.prover.ui.preference;

import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.widgets.Composite;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ColorPredicate;

/**
 * @author lamport
 *
 */
public class ColorPredicateFieldEditor extends StringFieldEditor
{
    public ColorPredicateFieldEditor(String name, String label, Composite parent)
    {
        super(name, label, StringFieldEditor.UNLIMITED, StringFieldEditor.VALIDATE_ON_KEY_STROKE , parent);
    }

    public boolean doCheckState()
    {
        String value = this.getStringValue();
        value = value.trim();
        if (value.startsWith("leaf"))
        {

//            showErrorMessage("should not begin with `leaf'");
            return false;
        }
        try
        {
            new ColorPredicate(value);
        } catch (Exception e)
        {
            return false;
        }
        return true;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/RandomEnumerableValues.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME> - added support for fingerprint stack trace
 ******************************************************************************/

package tlc2.value;

import java.util.Random;

import tlc2.TLCGlobals;
import tlc2.tool.ModelChecker;
import tlc2.tool.TLCState;
import tlc2.util.IdThread;

public abstract class RandomEnumerableValues {
	
	/* Randomization for sets */
		
	private static long randomSeed; 
	
	public static long getSeed() {
		return randomSeed;
	}
	
	/**
	 * Initialize Random with the given seed value.
	 **/
	public static void setSeed(final long seed) {
		randomSeed = seed;
		reset();
	}
	
	/**
	 * Re-Initialize Random with the recorded seed value.
	 * 
	 * @return The previously used Random instance that can later be re-activate
	 *         with {@link RandomEnumerableValues#set(Random)}.
	 **/
	public static Random reset() {
		final Random random = get();
		RANDOMS.remove();
		return random;
	}

	public static Random set(Random random) {
		final Random old = get();
		RANDOMS.set(random);
		return old;
	}
	
	public static Random get() {
		return RANDOMS.get();
	}
	
	private static final ThreadLocal<Random> RANDOMS = new ThreadLocal<Random>() {
		@Override
		protected Random initialValue() {
			if (TLCGlobals.mainChecker != null && ModelChecker.class.equals(TLCGlobals.mainChecker.getClass())) {
				// In order to recreate the error trace in BFS mode - which essentially
				// corresponds to rerunning state exploration following a given path - we have
				// to recreate the same random values too. Otherwise, TLC will fail to recreate
				// the trace because the recreated TLCState does not match the fingerprint in
				// the error trace/path. Therefore, we maintain one RNG per IdThread (IWorker)
				// which - for the initial states - is seeded with enumFractionSeed and - in the
				// scope of next-state - gets seeded with the fingerprint of the predecessor
				// state.
				return new TLCStateRandom(randomSeed);
			} else {
				// DFS or Simulation need no special handling because:
				// - DFS does not re-create the error trace (just prints the current trace).
				// - Simulation mode is intended to allow users to gather statistics on
				// behaviors generated with specified probabilities of different transitions.
				// (For example, to find the expected time for a message to be delivered with
				// retransmission as a function of the probability of message loss). For this,
				// it's important that the random choice have no correlation with the state in
				// which the choice is made.
				return new DefaultRandom(randomSeed);
			}
		}

		@Override
		public Random get() {
			// Hook to re-initialize random (no-op for DFS and simulation).
			return ((EnumerableValueRandom) super.get()).initialize();
		}
	};
		
	private interface EnumerableValueRandom {
		Random initialize();
	}

	@SuppressWarnings("serial")
	private static final class DefaultRandom extends Random implements EnumerableValueRandom {
		public DefaultRandom(long randomSeed) {
			super(randomSeed);
		}

		@Override
		public final Random initialize() {
			// Noop
			return this;
		}
	}

	@SuppressWarnings("serial")
	private static final class TLCStateRandom extends Random implements EnumerableValueRandom {

		private TLCState state;

		public TLCStateRandom(long randomSeed) {
			super(randomSeed);
		}

		private void initializedFor(final TLCState state) {
			// XOR the state's fingerprint with the initial randomSeed value. This is done
			// so that two identical states (same fingerprint) of two different
			// specifications do not produce the same random value.
			final long seed = state.fingerPrint() ^ randomSeed;
			this.setSeed(seed);
			this.state = state;
		}

		private boolean isInitializedFor(final TLCState another) {
			return state == another;
		}

		@Override
		public Random initialize() {
			final TLCState state = IdThread.getCurrentState();
			// state is null during the generation of initial states and non-null in the
			// scope of the next-state relation (however, state can be an initial state).
			// Thus, an RNG is seeded with randomSeed during the generation of initial
			// states and seeded with randomSeed ^ predecessor's fingerprint during the
			// generation of next states.
			// Do not re-initialize random for the same TLCState twice to produce two
			// distinct values with high probability with a next-state such as:
			// Next == x' = RandomElement(0..2) /\ y' = RandomElement(0..2)
			// If random was to be re-initialized/re-seeded, RandomElement(0..2) for x' and y'
			// would be identical values (also see tlc2.tool.RandomElementXandYTest).
			if (state != null && !isInitializedFor(state)) {
				initializedFor(state);
			}
			return this;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/TraceExpressionModelWriter.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.model;

import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.PlatformUI;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tlc2.output.SpecTraceExpressionWriter;

public class TraceExpressionModelWriter extends SpecTraceExpressionWriter {
    /**
     * {@inheritDoc}
     */
	@Override
    protected String getTLAModuleClosingTag() {
        final StringBuilder sb = ResourceHelper.getModuleClosingTag();
    	
    	return sb.toString();
    }
	
    /**
     * Write the content to files
     * @param tlaFile
     * @param cfgFile
     * @param monitor
     * @throws CoreException
     */
	public void writeFiles(final IFile tlaFile, final IFile cfgFile, final IProgressMonitor monitor) throws CoreException {
		final ContentWriter cw = (inputStream, forTLAFile) -> {
			final IFile file = forTLAFile ? tlaFile : cfgFile;
			
			if (file.exists()) {
				try {
					file.setContents(inputStream, IResource.FORCE, monitor);
				} catch (final CoreException ce) {
					throw new IOException("Exception writing file " + ce.getMessage(), ce);
				}
			} else {
				throw new IOException("Expected file " + file.getName() + " has been removed externally.");
			}
		};
		
		try {
			super.writeFiles(cw);
		} catch (final IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.ERROR,
									"Exception encountered attempting to write modules for the model checking.", e));
		}
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/BufferedDataInputStream.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Wed Oct 17 15:23:57 PDT 2001 by yuanyu
package util;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import tlc2.output.EC;

/** A <code>BufferedDataInputStream</code> is an optimized
    combination of a <code>java.io.BufferedInputStream</code>
    and a <code>java.io.DataInputStream</code>. It also provides
    an <code>atEOF</code> method for detecting end-of-file.<P>
   
    For efficiency, <code>BufferedDataInputStream</code>s are
    unmonitored. Hence, it is the client's responsibility to lock 
    the stream before using it. This requirement is denoted in 
    the comments of this class by the specification 
    <TT>REQUIRES LL = SELF</TT>. */

public final class BufferedDataInputStream extends FilterInputStream implements IDataInputStream {
    /* protected by SELF */
    private byte[] buff;    /* buffer of bytes to read */
    private int len;        /* number of valid bytes in "buff" */
    private int curr;       /* position of next byte to return */
    private byte[] temp;    /* temporary array used by various methods */

    /* Object invariants:
       this.out == null <==> ``stream is closed''
       this.buff != null && 0 < this.buff.length
       this.len != 0
       this.len > 0 <==> 0 <= this.curr < this.len <= this.buff.length
       this.len < 0 <==> ``read EOF from underlying stream''
       this.temp != null && this.temp.length >= 8
    */

    /** Initialize this input stream. The stream will be closed
        initially; use the <code>open</code> method below to
        open it on an underlying <code>InputStream</code>. */
    public BufferedDataInputStream() {
        super(null);
        this.initFields();
    }

    /** Open this input stream on the underlying stream <code>is</code>. */
    public BufferedDataInputStream(InputStream is) throws IOException {
        super(is);
        this.initFields();
        this.len = this.in.read(this.buff);
        Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
    }
    
    /** Open this input stream on the underlying input stream
        <code>new FileInputStream(name)</code>. */
    public BufferedDataInputStream(String name) throws IOException {
        this(new FileInputStream(name));
    }
    
    /** Open this input stream on the underlying input stream
        <code>new FileOutputStream(file)</code>. */
    public BufferedDataInputStream(File file) throws IOException {
        this(new FileInputStream(file));
    }

    private void initFields() {
        this.buff = new byte[8192];
        this.curr = 0;
        this.temp = new byte[8];
    }
    
    /** REQUIRES LL = SELF */
    /** Re-open this input stream on <code>is</code>. This method need
        not be called on a newly initialized stream, but it can be called
        after the stream has been closed to re-open the stream on a
        different underlying stream without requiring internal resources
        to be re-allocated. */
    public void open(InputStream is) throws IOException {
        Assert.check(this.in == null, EC.SYSTEM_STREAM_EMPTY);
        this.in = is;
        this.len = this.in.read(this.buff);
        Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
    }
    
    /** Equivalent to <code>this.open(new FileInputStream(name))</code>. */
    public void open(String name) throws IOException {
        this.open(new FileInputStream(name));
    }

    /** REQUIRES LL = SELF */
    /** Closes this stream and its underlying stream. */
    public void close() throws IOException {
        this.in.close();
        this.in = null;
    }
    
    /** REQUIRES LL = SELF */
    /** Returns <code>true</code> iff the stream is exhausted. */
    public final boolean atEOF() {
        return (this.len < 0);
    }
    
    /** REQUIRES LL = SELF */
    /** Reads up to <code>b.length</code> bytes into <code>b</code>, 
        and returns the number of bytes read, or -1 if the stream is 
        exhausted on entry. */
    public final int read(byte[] b) throws IOException {
        return this.read(b, 0, b.length);
    }
    
    /** REQUIRES LL = SELF */
    /** Reads up to <code>n</code> bytes into <code>b</code> starting
        at position <code>off</code>, and returns the number of bytes
        read, or -1 if the stream is exhausted on entry. */
    public final int read(byte[] b, int off, int n) throws IOException {
        if (this.len < 0) return -1;
        int offInit = off;
        while (n > 0 && this.len > 0) {
            int toCopy = Math.min(n, this.len - this.curr);
            System.arraycopy(this.buff, this.curr, b, off, toCopy);
            this.curr += toCopy; off += toCopy; n -= toCopy;
            if (this.curr == this.len) {
                // refill buffer from underlying input stream
                this.len = this.in.read(this.buff);
                Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
                this.curr = 0;
            }
        }
        return off - offInit;
    }
    
    /** REQUIRES LL = SELF */
    /** Reads <code>b.length</code> bytes into <code>b</code>, or
        throws <code>EOFException</code> if the stream contains fewer
        than <code>b.length</code> bytes. */
    public final void readFully(byte[] b) throws IOException, EOFException {
        this.readFully(b, 0, b.length);
    }
    
    /** REQUIRES LL = SELF */
    /** Reads <code>n</code> bytes into <code>b</code> starting at
        position <code>off</code>, or throws <code>EOFException</code>
        if the stream contains fewer than <code>n</code> bytes. */
    public final void readFully(byte[] b, int off, int n)
      throws IOException, EOFException {
        while (n > 0) {
            int numRead = this.read(b, off, n);
            if (numRead < 0) throw new EOFException();
            off += numRead; n -= numRead;
        }
    }
    
    /** REQUIRES LL = SELF */
    /** Reads and returns the next byte of this stream, or throws
        <code>EOFException</code> if the stream is exhausted. */
    public final byte readByte() throws IOException, EOFException {
        if (this.len < 0) throw new EOFException();
        byte res = this.buff[this.curr++];
        if (this.curr == this.len) {
            // refill buffer from underlying input stream
            this.len = this.in.read(this.buff);
            Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
            this.curr = 0;
        }
        return res;
    }
    
    /** REQUIRES LL = SELF */
    /** Reads and returns the next <code>boolean</code> value
        encoded in the next byte of this stream, or
        throws <code>EOFException</code> if the stream is
        exhausted. */
    public final boolean readBoolean() throws IOException, EOFException {
        return (this.readByte() != 0);
    }
    
    /** REQUIRES LL = SELF */
    /** Read and return the next <code>short</code> value
        encoded in the next two bytes of this stream, or
        throw <code>EOFException</code> if the stream contains
        fewer than two bytes. */
    public final short readShort() throws IOException, EOFException {
        this.readFully(this.temp, 0, 2);
        return (short) ((temp[0] << 8) | (temp[1] & 0xff));
    }
        
    /** REQUIRES LL = SELF */
    /** Reads and returns the next <code>int</code> value
        encoded in the next four bytes of this stream, or
        throws <code>EOFException</code> if the stream contains
        fewer than four bytes. */
    public final int readInt() throws IOException, EOFException {
        this.readFully(this.temp, 0, 4);
        int res = temp[0];
        res <<= 8; res |= (temp[1] & 0xff);
        res <<= 8; res |= (temp[2] & 0xff);
        res <<= 8; res |= (temp[3] & 0xff);
        return res;
    }
    
    /** REQUIRES LL = SELF */
    /** Reads and returns the next <code>long</code> value
        encoded in the next eight bytes of this stream, or
        throws <code>EOFException</code> if the stream contains
        fewer than eight bytes. */
    public final long readLong() throws IOException, EOFException {
        this.readFully(this.temp, 0, 8);
        long res = temp[0];
        res <<= 8; res |= (temp[1] & 0xff);
        res <<= 8; res |= (temp[2] & 0xff);
        res <<= 8; res |= (temp[3] & 0xff);
        res <<= 8; res |= (temp[4] & 0xff);
        res <<= 8; res |= (temp[5] & 0xff);
        res <<= 8; res |= (temp[6] & 0xff);
        res <<= 8; res |= (temp[7] & 0xff);
        return res;
    }
    
    /** REQUIRES LL = SELF */
    /** Reads and returns the next line of text from this stream, or
        <code>null</code> if the stream is exhausted. Any end-of-line
        character(s) are not included in the result. A line is termined
        by a carriage return character (<code>'\r'</code>), a newline 
        character (<code>'\n'</code>), a carriage return immediately 
        followed by a newline, or by the end of the stream. */
    public final String readLine() throws IOException {
        String res = null;
        while (this.len > 0) {
            for (int i = this.curr; i < this.len; i++) {
                if (this.buff[i] == (byte)'\n' || this.buff[i] == (byte)'\r') {
                    // remember EOL character
                    byte eol = this.buff[i];
                    
                    // create new substring
                    String s = new String(this.buff, /*offset=*/ this.curr,
					  /*count=*/ i - this.curr);
                    if (res == null) res = s; else res += s;
                    
                    // skip over bytes in stream
                    this.skip(i + 1 - this.curr);
                    
                    // skip '\n' if it follows '\r'
                    if (eol == (byte)'\r' && this.len > 0
                        && this.buff[this.curr] == (byte)'\n') {
                        this.readByte();
                    }
                    return res;
                }
            }
            // hit end of buffer -- append rest of buffer to "res"
            String s = new String(this.buff, /*offset=*/ this.curr,
				  /*count=*/ this.len - this.curr);
            if (res == null) res = s; else res += s;
            
            // skip over bytes in stream
            this.skip(this.len - this.curr);
        }
        // hit EOF without seeing EOL chars
        return res;
    }

    public final String readString(int n) throws IOException {
      char[] b = new char[n];
      int off = 0;
      while (n > 0) {
	if (this.len < 0) throw new EOFException();
	int offInit = off;
	while (n > 0 && this.len > 0) {
	  int toCopy = Math.min(n, this.len - this.curr);
	  for (int i = 0; i < toCopy; i++) {
	    b[off+i] = (char)this.buff[this.curr+i];
	  }
	  this.curr += toCopy; off += toCopy; n -= toCopy;
	  if (this.curr == this.len) {
	    // refill buffer from underlying input stream
	    this.len = this.in.read(this.buff);
	    Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
	    this.curr = 0;
	  }
	}
	int numRead = off - offInit;
	off += numRead; n -= numRead;
      }
      return new String(b);
    }
  
    /** REQUIRES LL = SELF */
    /** Skips over the next <code>n</code> bytes in this stream,
        or throws <code>EOFException</code> if it contains fewer
        than <code>n</code> bytes. */
    public final void skip(int n) throws IOException, EOFException {
        while (this.len > 0 && this.curr + n >= this.len) {
            n -= (this.len - this.curr);
            // refill buffer from underlying input stream
            this.len = this.in.read(this.buff);
            Assert.check(this.len != 0, EC.SYSTEM_STREAM_EMPTY);
            this.curr = 0;
        }
        if (n > 0 && this.len < 0) throw new EOFException();
        this.curr += n;
        Assert.check(this.len < 0 || this.curr < this.len, EC.SYSTEM_INDEX_ERROR);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/util/SimpleFilenameToStreamTest.java<|end_filename|>
package util;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.File;

import org.junit.Test;

public class SimpleFilenameToStreamTest {

	/**
	 * Try to load a standard module
	 */
	@Test
	public void testResolveStandardModule() {
		final SimpleFilenameToStream sfts = new SimpleFilenameToStream();
		final File file = sfts.resolve("TLC.tla", true);
		
		assertNotNull(file);
		assertTrue(file.getAbsolutePath() + " does not exist!", file.exists());
	}
	
	/**
	 * Test whether the fix for #424 still works
	 */
	@Test
	public void testWindowsTLAFileCreation() {
		if (System.getProperty("os.name").toLowerCase().indexOf("win") > -1) {
			final String driveLetter = "X:";
			final String parentDirectory = driveLetter + "\\Develop\\myspecs\\DecentSpec\\";
			final String child = parentDirectory + "Fromage.tla";
			final FilenameToStream.TLAFile file = new FilenameToStream.TLAFile(parentDirectory, child, null);
			final int driveLetterCount = file.getAbsolutePath().split(driveLetter).length - 1;
			
			assertTrue("There should be 1 drive letter in the child's absolute path, but there are " + driveLetterCount,
					   (1 == driveLetterCount));
		}
	}
	
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/util/ChangedSpecModulesGatheringDeltaVisitor.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.util;

import java.util.List;
import java.util.Vector;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * Visitor to find out what modules in the root file's directory have changed
 */

public abstract class ChangedSpecModulesGatheringDeltaVisitor implements IResourceDeltaVisitor
{

    private final IContainer rootFileParent;
    private Vector<IResource> modules = new Vector<IResource>();
    private IResource model = null;
    private boolean checkpointsChanged = false;
    private final IFolder modelDir;

    public ChangedSpecModulesGatheringDeltaVisitor(Model model)
    {
    	modelDir = model.getTargetDirectory();
        rootFileParent = Activator.getSpecManager().getSpecLoaded().getRootFile().getParent();
    }

    /**
     * If the delta points to a module in the currently loaded spec, it adds that resource to
     * the list modules.
     * If the delta points to the file of the configuration, then it sets model equal to 
     * that file.
     * If the delta points to a resouce that is the model directory for the configuration in
     * the constructor, then sets checkpointsChanged to true.
     * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
     */
    /* (non-Javadoc)
     * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
     */
    public boolean visit(IResourceDelta delta) throws CoreException
    {
        final IResource resource = delta.getResource();
        // TLCActivator.getDefault().logDebug("resource = " + resource.getFullPath().toString());
        if (IResource.FILE == resource.getType())
        {

            // add the file only if it's parent is the root file's parent.
            if (ResourceHelper.isModule(resource) && (resource.getParent().equals(rootFileParent)))
            {
                // TLCActivator.getDefault().logDebug("module resource added");
                modules.add(resource);
            } else

            // The first conjunct of the following test should probably be ((delta.getFlags() & IResourceDelta.MARKERS)
            // == IResourceDelta.MARKERS),
            // but it doesn't hurt to remove that test and risk unnecessarily removing and resetting markers.
            if (/* delta.getFlags() == IResourceDelta.MARKERS && */(getModel() != null) && getModel().equals(resource))
            {
                // TLCActivator.getDefault().logDebug("model set to resource");

                model = resource;
                return false;
            }
        } else if (IResource.FOLDER == resource.getType())
        {
            if ((modelDir != null) && (modelDir.exists()) && (modelDir.equals(resource)))
            {
                checkpointsChanged = true;
                return false;
            }
        }
        // TODO: we don't really want the visitor to visit the whole tree, do we?
        return true;
    }

    /**
     * Retrieves found modules, or an empty list, if nothing found
     * @return a list with found modules
     */
    public List<IResource> getModules()
    {
        return modules;
    }

    /**
     * This method must be provided, in order to supply the model of interest 
     * @return the resource storing the model
     */
    public abstract IResource getModel();

    /**
     * Returns if the resource delta contained a marker modifications of the model file
     */
    public boolean isModelChanged()
    {
        return this.model != null;
    }

    /**
     * Returns true if the visitor has found a change to the directory
     * containing the checkpoints, so a checkpoint might have changed.
     * @return
     */
    public boolean getCheckpointChanged()
    {

        return checkpointsChanged;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/other/CurrentDir.java<|end_filename|>
/***************************************************************************
* How to get the current directory.                                        *
*                                                                          *
* Also, all the java (version 1.5) properties.                             *
***************************************************************************/
package tlc2.tool.other;

import java.io.File;

/**
 * Simple printing utility
 * @deprecated is likely not used (SZ February 19, 2009)
 */
public class CurrentDir
{
    public static void main(String args[])
    {
        for (int i = 0; i < args.length; i++)
        {
            System.out.println("args[" + i + "] = '" + args[i] + "'");
        }
        ;

        File dir1 = new File(".");
        File dir2 = new File("..");
        try
        {
            System.out.println("Current dir : " + dir1.getCanonicalPath());
            System.out.println("Parent  dir : " + dir2.getCanonicalPath());
            System.out.println("HOME: " + System.getenv("HOME"));
            // System.out.println("user.home: " + System.getProperty("user.home")) ;
            System.out.println("java.version : " + System.getProperty("java.version"));
            System.out.println("java.vendor : " + System.getProperty("java.vendor"));
            System.out.println("java.vendor.url : " + System.getProperty("java.vendor.url"));
            System.out.println("java.home : " + System.getProperty("java.home"));
            System.out
                    .println("java.vm.specification.version : " + System.getProperty("java.vm.specification.version"));
            System.out.println("java.vm.specification.vendor : " + System.getProperty("java.vm.specification.vendor"));
            System.out.println("java.vm.specification.name : " + System.getProperty("java.vm.specification.name"));
            System.out.println("java.vm.version : " + System.getProperty("java.vm.version"));
            System.out.println("java.vm.vendor : " + System.getProperty("java.vm.vendor"));
            System.out.println("java.vm.name : " + System.getProperty("java.vm.name"));
            System.out.println("java.specification.version : " + System.getProperty("java.specification.version"));
            System.out.println("java.specification.vendor : " + System.getProperty("java.specification.vendor"));
            System.out.println("java.specification.name : " + System.getProperty("java.specification.name"));
            System.out.println("java.class.version : " + System.getProperty("java.class.version"));
            System.out.println("java.class.path : " + System.getProperty("java.class.path"));
            System.out.println("java.library.path : " + System.getProperty("java.library.path"));
            System.out.println("java.io.tmpdir : " + System.getProperty("java.io.tmpdir"));
            System.out.println("java.compiler : " + System.getProperty("java.compiler"));
            System.out.println("java.ext.dirs : " + System.getProperty("java.ext.dirs"));
            System.out.println("os.name : " + System.getProperty("os.name"));
            System.out.println("os.arch : " + System.getProperty("os.arch"));
            System.out.println("os.version : " + System.getProperty("os.version"));
            System.out.println("file.separator : " + System.getProperty("file.separator"));
            System.out.println("path.separator : " + System.getProperty("path.separator"));
            System.out.println("line.separator : " + System.getProperty("line.separator"));
            System.out.println("user.name : " + System.getProperty("user.name"));
            System.out.println("user.home : " + System.getProperty("user.home"));
            System.out.println("user.dir : " + System.getProperty("user.dir"));

            System.out.println("Setting current directory to c:\\users\\lamport");
            System.setProperty("user.dir", "c:\\users\\lamport");
            System.out.println("user.dir : " + System.getProperty("user.dir"));
            System.out.println("Current dir : " + dir1.getCanonicalPath());

        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCVariable.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TLCVariable
{
	private static final Comparator<TLCVariable> comparator = new Comparator<TLCVariable>() {
		public int compare(TLCVariable v1, TLCVariable v2) {
			if (v1.isTraceExplorerVar() && v2.isTraceExplorerVar()) {
				// both are variables. Compare the vars alphabetically.
				return v1.getName().compareTo(v2.getName());
			}
			if (v1.isTraceExplorerVar()) {
				return -1;
			}
			if (v2.isTraceExplorerVar()) {
				return 1;
			}
			return v1.getName().compareTo(v2.getName());
		}
	};
	
	// "^/\ ": Optional conjunct delimiting variables (not present for a state with a single variable).
	// lhs: Match any valid TLA+ variable name (any letter, digit or underscore, see http://lamport.azurewebsites.net/tla/TLAPlus2Grammar.tla).
	// " = ": delimiter
	// rhs: Match any characters including newlines up to the next "/\".
	private static final Pattern pattern = Pattern.compile("^(\\/\\\\ )?(?<lhs>\\w+) = (?<rhs>.[^\\/\\\\]*)",
			// Match over multiple lines and dot matches newline character.
			Pattern.MULTILINE | Pattern.DOTALL);

	public static List<TLCVariable> parseVariables(final String variablesText) {
		final List<TLCVariable> vars = new ArrayList<TLCVariable>();

		final Matcher matcher = pattern.matcher(variablesText);
		while (matcher.find()) {
			final String lhs = matcher.group("lhs");
			final String rhs = matcher.group("rhs").trim(); // Trim dangling newlines.
			
			vars.add(new TLCVariable(lhs, TLCVariableValue.parseValue(rhs)));
		}
		
		Collections.sort(vars, comparator);
		return vars;
	}
	
    private String name;
    private TLCVariableValue value;
    private boolean isTraceExplorerVar;

    private TLCVariable(String name, TLCVariableValue value)
    {
        this.name = name;
        this.value = value;
        this.isTraceExplorerVar = false;

    }

    public String getName()
    {
        return name;
    }

    public TLCVariableValue getValue()
    {
        return value;
    }

    public String toString()
    {
        return value == null ? "" : value.toString();
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public void setValue(TLCVariableValue value)
    {
        this.value = value;
    }

    /**
     * Returns whether or not this variable represents
     * a trace explorer expression. See {@link TLCVariable#setTraceExplorerVar(boolean)}
     * for setting the value returned by this method. By default, it is false.
     * @return
     */
    public boolean isTraceExplorerVar()
    {
        return isTraceExplorerVar;
    }

    /**
     * Returns the name this variable in a single line String.
     * 
     * The name could be multiple lines if this represents a trace explorer
     * expression.
     * 
     * @return
     */
    public String getSingleLineName()
    {
        return name.replaceAll("\n", "").replaceAll("\r", "");    }

    /**
     * Sets the status of this variable as representing or not
     * representing a trace explorer expression. By default, it
     * is not.
     * 
     * @param isTraceExplorerVar whether or not this variable
     * represents a trace explorer expression.
     */
    public void setTraceExplorerVar(boolean isTraceExplorerVar)
    {
        this.isTraceExplorerVar = isTraceExplorerVar;
    }
	
	public int getChildCount() {
		return value.getChildCount();
	}
	
	public final boolean isChanged() {
		return value.isAdded() || value.isDeleted() || value.isChanged();
	}
	
	/**
	 * This compares against name and the value of {@code isTraceExplorerVar}
	 */
	public boolean representsTheSameAs(final TLCVariable other) {
		return (isTraceExplorerVar == other.isTraceExplorerVar) && Objects.equals(name, other.name);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/ParseResult.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

import java.util.Vector;

import org.eclipse.core.resources.IResource;
import org.lamport.tla.toolbox.tool.IParseResult;
import org.lamport.tla.toolbox.util.TLAMarkerInformationHolder;

import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.Errors;

/**
 * A holder for status SpecObj and the resource, and the parse status
 * @author <NAME>
 * @version $Id$
 */
public class ParseResult implements IParseResult
{
    private int status = IParseConstants.UNPARSED;
    private SpecObj specObj;
    private IResource parsedResource;
    private Errors parseErrors;
    private Errors semanticErrors;
    private Vector<TLAMarkerInformationHolder> detectedErrors;
    /**
     * Time stamp for when the parser
     * was called that eventually produced this result
     * as returned by {@link System#currentTimeMillis()}.
     */
    private long parserCalled;

    /**
     * Constructs the parse status object 
     * @param status one of the {@link IParseConstants} values
     * @param specObj current specObject or null
     */
    public ParseResult(int status, SpecObj specObj, IResource parsedResource, Errors parseErrors,
            Errors semanticErrors, long parserCalled)
    {
        this.status = status;
        this.specObj = specObj;
        this.parsedResource = parsedResource;
        this.parseErrors = parseErrors;
        this.semanticErrors = semanticErrors;
        this.detectedErrors = new Vector<TLAMarkerInformationHolder>();
        this.parserCalled = parserCalled;
    }

    /**
     * @param specObj the specObj to set
     */
    public void setSpecObj(SpecObj specObj)
    {
        this.specObj = specObj;
    }

    /**
     * @return the specObj
     */
    public SpecObj getSpecObj()
    {
        return specObj;
    }

    /**
     * @param status the status to set
     * 
     * According to Eclipse, this method is never called.
     */
    public void setStatus(int status)
    {
        this.status = status;
    }

    /**
     * @return the status
     */
    public int getStatus()
    {
        return status;
    }

    public IResource getParsedResource()
    {
        return parsedResource;
    }

    public void setParsedResource(IResource parsedResource)
    {
        this.parsedResource = parsedResource;
    }

    public Errors getParseErrors()
    {
        return parseErrors;
    }

    public Errors getSemanticErrors()
    {
        return semanticErrors;
    }

    public Vector<TLAMarkerInformationHolder> getDetectedErrors()
    {
        return detectedErrors;
    }

    /**
     * Add an error to the error list
     * @param error marker information holder
     */
    public void addMarker(TLAMarkerInformationHolder error)
    {
        detectedErrors.add(error);
    }

    /**
     * Time stamp for when the parser
     * was called that eventually produced this result
     * as returned by {@link System#currentTimeMillis()}
     * 
     * @return the time when the parser was called to produce
     * this result
     */
    public long getParserCalled()
    {
        return parserCalled;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ExecuteNextCommandHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.keys.IBindingService;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.util.UIHelper;

public class ExecuteNextCommandHandler extends AbstractHandler implements IHandler, VerifyKeyListener, FocusListener
{

    private TLAEditor editor;
    private IDocument doc ;                          // The document being edited.
    private ISelectionProvider selectionProvider ;   // 
    private TextSelection selection ;                // The current selection.
    private int offset ;                             // The current offset.
    private IRegion lineInfo ;                       // The lineInfo for the current offset.

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        editor = EditorUtil.getTLAEditorWithFocus();
        String cmd = event.getCommand().getId();
        if (editor != null)
        {
            install();
        }

        return null;
    }

    /**
     * Listens for the first key to be pressed. If it is a digit, it
     * finds the word currently containing the caret and repeats that word
     * the number of times equal to the digit pressed. If the key pressed
     * is not a digit, this does nothing to the document and
     * removes itself from subsequent key events.
     */
    public void verifyKey(VerifyEvent event)
    {
        try
        {
            // no other listeners should respond to this event
            event.doit = false;
System.out.println("Heard keystroke.");
            
            IBindingService ibindingService = (IBindingService) 
                                  UIHelper.getActivePage().getActivePart().getSite().getService(IBindingService.class) ;
            KeyStroke keyStroke = SWTKeySupport.convertAcceleratorToKeyStroke(SWTKeySupport.convertEventToUnmodifiedAccelerator(event));
            Binding binding = ibindingService.getPerfectMatch(KeySequence.getInstance(keyStroke) );
            ParameterizedCommand pcommand = binding.getParameterizedCommand();
            IHandlerService ihandlerService = (IHandlerService) 
                        UIHelper.getActivePage().getActivePart().getSite().getService(IHandlerService.class) ;
            ihandlerService.executeCommand(pcommand, null);
        } catch (ExecutionException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NotDefinedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NotEnabledException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NotHandledException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally
        {

            uninstall();
        }
    }

    /**
     * This should never be called. The handler
     * should only be listening if there already is focus
     * and should be removed as a listener when focus
     * is lost.
     */
    public void focusGained(FocusEvent e)
    {
        // TODO Auto-generated method stub

    }

    /**
     * Uninstalls the handler.
     */
    public void focusLost(FocusEvent e)
    {
        uninstall();
    }

    /**
     * Should be called when the handler starts listening
     * for key strokes.
     * 
     * Adds this as a key stroke listener, adds to focus listeners
     * of the underlying text widget of the editor, and sets the
     * status line.
     * 
     * This is added as a focus listener so that it can uninstall()
     * itself if focus is lost.
     */
    private void install()
    {
 System.out.println("Start install.");
        editor.getViewer().prependVerifyKeyListener(this);
        editor.getViewer().getTextWidget().addFocusListener(this);
        editor.setStatusMessage("Example command.");
        System.out.println("End install.");
   }

    /**
     * Should be called when the handler is done listening for
     * key strokes.
     * 
     * Removes itself as a key stroke listener, a focus listener, and sets
     * the status line to the empty string.
     */
    private void uninstall()
    {
System.out.println("Start uninstall");
        // do not listen to any other key strokes
        editor.getViewer().removeVerifyKeyListener(this);

        editor.getViewer().getTextWidget().removeFocusListener(this);

        editor.setStatusMessage("");
        System.out.println("End uninstall");

    }


}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/EvalExceptionLivenessTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class EvalExceptionLivenessTest extends ModelCheckerTestCase {
    public EvalExceptionLivenessTest() {
        super("DistBakery3aAuxMC", new String[] { "-config", "DistBakery3aAuxMC.tla" }, EC.ExitStatus.ERROR);
    }

    @Override
	protected boolean doCoverage() {
		return false;
	}

	@Test
    public void testSpec() {
        assertTrue(recorder.recorded(EC.TLC_FINISHED));
        assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "950", "555", "89"));

        // Error: The first argument of <= should be an integer, but instead it is:
        // (-1 :> 0)
		assertTrue(recorder.recordedWithStringValues(EC.GENERAL,
				"TLC threw an unexpected exception.\n"
				+ "This was probably caused by an error in the spec or model.\n"
				+ "See the User Output or TLC Console for clues to what happened.\n"
				+ "The exception was a java.lang.RuntimeException\n"
				+ ": Attempted to check equality of the function <<-2>> with the value:\n"
				+ "-2"));

		final List<String> expectedTrace = new ArrayList<String>(15);
		// 1
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> TRUE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"ncs\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"ncs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"M1s\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 2
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> TRUE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"L1\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"L1\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"M1s\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 3
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"M1s\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"M1\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"M1s\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 4
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 2 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"M1s\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"M1\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 5
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"enter\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"M1\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 6
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 0 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"wait\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = ( -2 :> (-2 :> <<>> @@ -1 :> <<[num |-> 1, type |-> \"write\"]>>) @@\n"
				+ "  -1 :> (-2 :> <<>> @@ -1 :> <<>>) )\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 7
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"wait\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = ( -2 :> (-2 :> <<>> @@ -1 :> <<>>) @@\n"
				+ "  -1 :> (-2 :> <<[type |-> \"ack\"]>> @@ -1 :> <<>>) )\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 8
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"wait\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 9
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"L2\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L2\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 10 (9)
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 2 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"L2\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L3\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 11 (10)
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"L3\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"L3\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 12
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> TRUE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 2 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"L3\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"pcs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"scs\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 13
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> TRUE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"cs\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"cs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"scs\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 14
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> FALSE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"exit\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {-1} @@ -1 :> {})\n"
				+ "/\\ net = (-2 :> (-2 :> <<>> @@ -1 :> <<>>) @@ -1 :> (-2 :> <<>> @@ -1 :> <<>>))\n"
				+ "/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"ncs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"scs\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		// 15
		expectedTrace.add("/\\ rnum = (-2 :> (-2 :> 0 @@ -1 :> 0) @@ -1 :> (-2 :> 1 @@ -1 :> 0))\n"
				+ "/\\ msgStop = (-2 :> FALSE @@ -1 :> FALSE)\n"
				+ "/\\ mustRdBar = (<<-2, -1>> :> FALSE @@ <<-1, -2>> :> FALSE)\n"
				+ "/\\ j = (-2 :> 1 @@ -1 :> 1)\n"
				+ "/\\ pc = (-2 :> \"scs\" @@ -1 :> \"ncs\" @@ 12 :> \"a\" @@ 21 :> \"a\")\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ net = ( -2 :> (-2 :> <<>> @@ -1 :> <<[num |-> 0, type |-> \"write\"]>>) @@\n"
				+ "  -1 :> (-2 :> <<>> @@ -1 :> <<>>) )\n"
				+ "/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ numBar = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ tempBar = (<<-2, -1>> :> 0 @@ <<-1, -2>> :> 0)\n"
				+ "/\\ pcBar = ( <<-2>> :> \"ncs\" @@\n"
				+ "  <<-1>> :> \"ncs\" @@\n"
				+ "  <<-2, -1>> :> \"scs\" @@\n"
				+ "  <<-1, -2>> :> \"M1s\" @@\n"
				+ "  <<-2, -1, \"wr0\">> :> \"wr0\" @@\n"
				+ "  <<-1, -2, \"wr0\">> :> \"wr0\" )");
		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/explorer/ExploreNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.explorer;
import java.util.Hashtable;

/**
 * implemented by the following classes (as well as various abstract and  superclasses):
 *
 *        AssumeNode, AtNode, Context, DecimalNode, FormalParamNode, LetInNode, NumeralNode, 
 *        OpApplNode, OpArgNode, OpDeclNode, OpDefNode, StringNode, Subst, SubstInNode, TheoremNode
 */

public interface ExploreNode {

  public String toString(int depth);
    /***********************************************************************
    * This displays the node as a string.  Apparently, the string should   *
    * begin with "\n" to start a new line.  The depth parameter is         *
    * apparently used to control the limit on the depth being displayed.   *
    * Apparently, the method should return "" if depth <= 0, and I         *
    * imagine it should call foo.toString(depth-1) to print each           *
    * descendant foo.                                                      *
    ***********************************************************************/
  public String levelDataToString();

  public void   walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, final ExplorerVisitor visitor);
    /***********************************************************************
    * This method is apparently supposed to insert an entry in             *
    * semNodesTable for itself and every descendant in the semantic tree   *
    * by executing                                                         *
    *                                                                      *
    *     Integer uid = Integer.valueOf(myUID);                                *
    *     if (semNodesTable.get(uid) != null) return;                      *
    *     semNodesTable.put(uid, this);                                    *
    *                                                                      *
    * and then calling child.walkGraph(semNodesTable) for every            *
    * descendant.                                                          *
    ***********************************************************************/
    
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TLACompletionProcessor.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContextInformation;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Point;
import org.lamport.tla.toolbox.editor.basic.ToolboxCompletionProcessor;
import org.lamport.tla.toolbox.editor.basic.pcal.IPCalReservedWords;

/**
 * Syntactic auto-completion processor
 * @author <NAME>
 */
public class TLACompletionProcessor extends ToolboxCompletionProcessor implements IContentAssistProcessor
{
    public TLACompletionProcessor() {
    	final List<String> asList = Arrays.asList(ITLAReserveredWords.ALL_WORDS_ARRAY);
    	for (String string : asList) {
    		final List<CompletionProposalTemplate> proposal = new ArrayList<CompletionProposalTemplate>(1);
    		proposal.add(new CompletionProposalTemplate(string + " "));
			proposals.put(string, proposal);
		}
    	
		// Define PCal "algorithm" here because the PCalCompletionProcessor is only
		// active inside an algorithm definition (chicken or egg problem).
		final List<CompletionProposalTemplate> l = new ArrayList<CompletionProposalTemplate>(1);
		l.add(new CompletionProposalTemplate(
				"(***************************************************************************\r\n"
						+ "--algorithm AlgorithmName {\r\n}\r\n"
						+ "***************************************************************************)\r\n",
				IPCalReservedWords.ALGORITHM, IPCalReservedWords.ALGORITHM_HELP));
		proposals.put(ITLAReserveredWords.ALGORITHM, l);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int)
     */
	public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
		// Retrieve selected range
		final Point selectedRange = viewer.getSelectedRange();
		if (selectedRange.y > 0) {
			// Text is selected. Create a context information array.
			final IContextInformation[] contextInfos = new ContextInformation[ITLAReserveredWords.ALL_WORDS_ARRAY.length];

			// Create one context information item for each style
			for (int i = 0; i < ITLAReserveredWords.ALL_WORDS_ARRAY.length; i++) {
				contextInfos[i] = new ContextInformation(null, ITLAReserveredWords.ALL_WORDS_ARRAY[i] + " Style");
			}
			return contextInfos;
		}
		return new ContextInformation[0];
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/job/ITLAPMOptions.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.job;

/**
 * This interface contains constants for
 * all options that can be used to launch the prover.
 * 
 * The description of each option is copied from the tlapm-toolbox
 * interface spec.
 * 
 * @author <NAME>
 *
 */
public interface ITLAPMOptions
{

    /**
     * --toolbox <bl> <el> [options] FILE
     * 
     * <bl> and <el> are both integers that give the begin line and end line of the part of the 
     * file to be considered by the prover. If the arguments are both equal to 0, the entire module 
     * will be considered.
     */
    public static final String TOOLBOX = "--toolbox";
    /**
     * --meth
     * 
     * Changes the default method for proving 
     * (the default is zenon with 10 second time-out and isabelle auto fallback)
     */
    public static final String METH = "--method";
    /**
     * --solver
     * 
     * Which smt solver to use.
     */
    public static final String SOLVER = "--solver";
    /**
     * --paranoid
     * 
     * Asks isabelle to check trivial obligations
     */
    public static final String PARANOID = "--paranoid";
    /**
     * --isaprove
     * 
     * Sends obligations to isabelle to be proved as soon as zenon fails 
     * or when isabelle is called by a pragma.
     */
    public static final String ISAPROVE = "--isaprove";

    /**
     * --cleanfp : Erase fingerprint file
     */
    public static final String FORGET_ALL = "--cleanfp";

    /**
     * --nofp : Erase fingerprints from currently selected proof region.
     */
    public static final String FORGET_CURRENT = "--nofp";

    /**
     * -C
     * 
     * Tells tlapm to call Isabelle to check Zenon proofs.
     */
    public static final String ISACHECK = "-C";
    /**
     * --noproving
     * 
     * Does not send any obligations to backends. Checks if an obligation is 
     * trivial or not and considers previous results in the fingerprint files. 
     * If an obligation is not trivial and does not appear in the fingerprints 
     * file, then the only message sent to the toolbox has a status "to be proved".
     */
    public static final String NOPROVING = "--noproving";
    /**
     * --threads <num>
     * 
     * Num is an integer giving the number of worker backend threads used. 
     * Default is the number of cores.
     */
    public static final String THREADS = "--threads";
    /**
     * -C
     * 
     * Sends all obligations to isabelle for checking except trivial obligations 
     * (if --paranoid is not called), already checked obligations, and obligations 
     * on which isabelle has already failed or succeeded.
     */
    public static final String CHECK = "-C";
    /**
     * --wait <t>
     * 
     * t is an integer. After sending an obligation to a backend, the pm waits 
     * t seconds. If the backend has not finished on that obligation after those 
     * t seconds, the pm sends an obligation message with status "being proved" 
     * to the toolbox for that obligation. The default value is 3.
     */
    public static final String WAIT = "--wait";
    /**
     * --cleanfp
     * 
     * Erase the fingerprint file before processing the module. Adds new fingerprints.
     */
    public static final String CLEANFP = "--cleanfp";
    /**
     * --nofp
     * 
     * Erase fingerprints of obligations considered by the present launch of 
     * the toolbox (i.e. located between bl and el). Adds new fingerprints.
     */
    public static final String NOFP = "--nofp";
    /**
     * --nofpl b e
     * 
     * Erase fingerprints of obligations both (considered by the present launch of 
     * the toolbox) and (located between lines b and e). Adds new fingerprints.
     */
    public static final String NOFPL = "--nofpl";
    /**
     * --fpdir <dir>
     * 
     * Sets to dir the directory from which the fingerprints file is loaded and to 
     * which it is saved. (accepts both complete and relative pathnames)
     */
    public static final String FPDIR = "--fpdir";
    /**
     * --safefp
     * 
     * Checks isabelle and zenon versions before loading fingerprints. Only uses 
     * fingerprints whose zenon and isabelle versions equal the zenon and isabelle 
     * versions currently used by tlapm.
     */
    public static final String SAFEFP = "--safefp";
    /**
     * --help
     * 
     * Show the help message and exit.
     */
    public static final String HELP = "--help";
    /**
     * --version
     * 
     * Show version number and exit.
     */
    public static final String VERSION = "--version";
    /**
     * --verbose
     * 
     * Produce verbose messages.
     */
    public static final String VERBOSE = "--verbose";
    /**
     * --where
     * 
     * Show location of standard library and exit.
     */
    public static final String WHERE = "--where";
    /**
     * --config
     * 
     * Show configuration and exit.
     */
    public static final String CONFIG = "--config";
    /**
     * --summary
     * 
     * Show summary of theorems (implies -N and not -C).
     */
    public static final String SUMMARY = "--summary";
    /**
     * --timing
     * 
     * Show runtime statistics.
     */
    public static final String TIMING = "--timing";
    /**
     * -I <dir>
     * 
     * Add <dir> to search path.
     */
    public static final String ADD_DIR = "-I";
    /**
     * -d <dir>
     * 
     * Send generated output to <dir>.
     */
    public static final String SEND_DIR = "-d";
    /**
     * -k
     * 
     * Keep going on backend failures.
     */
    public static final String KEEP_GOING = "-k";
    /**
     * -N
     * 
     * Do not run any backend verifiers.
     * (-> similar to --noproving)
     */
    public static final String NO_BACKEND = "-N";
    /**
     * --trust {[-]<backend>}
     * 
     * Enable/disable trust on backends (see --trust list).
     */
    public static final String TRUST = "--trust";
    /**
     * --noflatten
     * 
     * Do not flatten obligations.
     */
    public static final String NO_FLATTEN = "--noflatten";
    /**
     * --nonormal
     * 
     * Do not normalize obligations before printing.
     */
    public static final String NO_NORMAL = "--nonormal";
    /**
     * --debug {[-]<flag>}
     * 
     * Enable/disable debugging flags.
     */
    public static final String DEBUG = "--debug";

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/NewSymbNode.java<|end_filename|>
// Copyright (c) 2007 Microsoft Corporation.  All rights reserved.

// last modified on Fri 23 Nov 2007 at 17:21:52 PST by lamport
/***************************************************************************
* The NewSymbNode constructor is invoked in semantic/Generator.java to     *
* construct the nodes corresponding to a NewSymb syntactic node in an      *
* AssumeProve.  The NewSymb node represents a declaration in an ASSUME,    *
* such as "ASSUME CONSTANT x \in S ".                                      *
*                                                                          *
* The node has two descendants in the semantic tree, returned              *
* by these methods:                                                        *
*   OpDeclNode getOpDeclNode()                                             *
*     An OpDeclNode for the declaration.                                   *
*                                                                          *
*   ExprNode getSet()                                                      *
*     If the node represents a declaration such as "CONSTANT x \in S",     *
*     then this returns the ExprNode for S. Otherwise, it returns null.    *
***************************************************************************/

package tla2sany.semantic;

import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.xml.SymbolContext;

public class NewSymbNode extends LevelNode {

  /*************************************************************************
  * Fields.                                                                *
  *************************************************************************/
  private OpDeclNode opDeclNode = null;
    /***********************************************************************
    * The OpDeclNode for the declaration represented by the NewSymbNode    *
    * object.                                                              *
    ***********************************************************************/
  private ExprNode  set         = null;
    /***********************************************************************
    * The ExprNode for expression S in "CONSTANT id \in S".                *
    ***********************************************************************/
// There's now a level field for all LevelNode subclasses, and this.levelChecked
// indicates if levelCheck has been callsed
//  private int       level = -1;
//    /***********************************************************************
//    * The level.  The value of -1 indicates that levelCheck has not yet    *
//    * been called.                                                         *
//    ***********************************************************************/

// Role subsumed by this.levelCorrect
//  private boolean  theLevelCheck = true ;
//    /***********************************************************************
//    * Set by this.levelCheck to the value to be returned on subsequent     *
//    * calls.                                                               *
//    ***********************************************************************/

  /*************************************************************************
  * The Constructor.                                                       *
  *************************************************************************/
  public NewSymbNode(
           OpDeclNode   opDeclNode, // The OpDeclNode for the declaration.
           ExprNode     set,        // Expression S in "CONSTANT x \in S",
                                    //   null for other kinds of declaration.
           TreeNode stn             // The syntax node.
          ) {
    super(NewSymbKind, stn) ;
    this.set        = set;
    this.opDeclNode = opDeclNode ;
  }


  /*************************************************************************
  * Methods particular to the NewSymb node.                                *
  *************************************************************************/
  public final ExprNode   getSet()         {return set;}
  public final OpDeclNode getOpDeclNode() {return opDeclNode;}

  /*************************************************************************
  * The implementation of the LevelNode abstract methods.                  *
  *                                                                        *
  * The level of the node is the maximum of opDeclNode's level and the     *
  * level of the `set' expression, if it's non-null.  Any other level      *
  * information comes from the `set' expression.                           *
  *************************************************************************/
  @Override
  public boolean levelCheck(int iter)       {

    if (levelChecked < iter) {
      /*********************************************************************
      * This is the first call of levelCheck, so the level information     *
      * must be computed.  Actually, with the current implementation,      *
      * there's no need to call opDeclNode.levelCheck, since that just     *
      * returns true.  However, we do it anyway in case the OpDeclNode     *
      * class is changed to make levelCheck do something.                  *
      *********************************************************************/
      levelChecked = iter ;
      boolean opDeclLevelCheck = opDeclNode.levelCheck(iter) ;
      level = opDeclNode.getLevel() ;
      if (set != null) {
        levelCorrect = set.levelCheck(iter) ;
        level = Math.max(set.getLevel(), level);
        if (level == TemporalLevel) {
          levelCorrect = false;
          errors.addError(this.stn.getLocation(),
                          "Level error:\n" +
                          "Temporal formula used as set.");
          }
       }  ;
      levelCorrect = levelCorrect && opDeclLevelCheck;
      if (set != null) {
        levelParams = set.getLevelParams();
        allParams = set.getAllParams();
        levelConstraints = set.getLevelConstraints();
        argLevelConstraints = set.getArgLevelConstraints();
        argLevelParams      = set.getArgLevelParams();
       }; // if (set != null)
      }; // if (levelChecked < iter)
    return levelCorrect;
   }

//  public int getLevel()             {return this.level; }
//
//  public HashSet getLevelParams()   {
//    if (set == null) {return EmptySet;}
//    else return set.getLevelParams();
//   }
//
//  public SetOfLevelConstraints getLevelConstraints() {
//    if (set == null) {return EmptyLC;}
//    else return set.getLevelConstraints();
//   }
//
//  public SetOfArgLevelConstraints getArgLevelConstraints() {
//    if (set == null) {return EmptyALC;}
//    else return set.getArgLevelConstraints();
//   }
//
//  public HashSet getArgLevelParams() {
//    if (set == null) {return EmptySet;}
//    else return set.getArgLevelParams();
//   }

  /**
   * toString, levelDataToString and walkGraph methods to implement
   * ExploreNode interface
   */
//  public final String levelDataToString() {
//    return "Level: "               + this.level                    + "\n" +
//           "LevelParameters: "     + this.getLevelParams()         + "\n" +
//           "LevelConstraints: "    + this.getLevelConstraints()    + "\n" +
//           "ArgLevelConstraints: " + this.getArgLevelConstraints() + "\n" +
//           "ArgLevelParams: "      + this.getArgLevelParams()      + "\n";
//  }

  /**
   * The body is the node's only child.
   */

  @Override
  public SemanticNode[] getChildren() {
    if (this.set == null) {
        return null;
    } else {
      return new SemanticNode[] {this.set};
    }
  }

  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    if (set != null) { set.walkGraph(semNodesTable, visitor); } ;
    visitor.postVisit(this);
   }

  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";
    String setString = "" ;
    if (this.set != null) {
      setString = Strings.indent(2,
                   "\nSet:" + Strings.indent(2, this.set.toString(depth-1)));
     }
    return "\n*NewSymbNode: " +
	    "  " + super.toString(depth) +
             Strings.indent(2, "\nKind: " + this.getKind() +
                          "\nopDeclNode:" + Strings.indent(2,
                                this.opDeclNode.toString(depth-1)) +
             setString);
   }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
    Element e = doc.createElement("NewSymbNode");
    e.appendChild(getOpDeclNode().export(doc,context));
    if (getSet() != null) {
      e.appendChild(getSet().export(doc,context));
    }
    return e;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/preference/ModelEditorPreferenceInitializer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.preference;

import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

public class ModelEditorPreferenceInitializer  extends AbstractPreferenceInitializer {
	public void initializeDefaultPreferences() {
		final IPreferenceStore uiPreferencesStore = TLCUIActivator.getDefault().getPreferenceStore();

        uiPreferencesStore.setDefault(IModelEditorPreferenceConstants.I_MODEL_EDITOR_SHOW_ECE_AS_TAB, false);
        uiPreferencesStore.setDefault(IModelEditorPreferenceConstants.I_OVERRIDDEN_DEFINITION_STYLE,
        		IModelEditorPreferenceConstants.I_OVERRIDDEN_DEFINITION_STYLE_MODULE_NAME);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/impl/SetOfRcrdValueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.IntStream;

import org.junit.BeforeClass;
import org.junit.Test;

import tlc2.util.FP64;
import tlc2.value.impl.SetOfRcdsValue.SubsetEnumerator;
import util.UniqueString;

public class SetOfRcrdValueTest {

	private static final int a = 97;

	private static final Value[] getValue(final int n, String str) {
		final Value[] values = new Value[n];
		for (int i = 0; i < n; i++) {
			values[i] = new StringValue(str + i);
		}
		return values;
	}

	private static final Value[] getValue(int n, String... strs) {
		final Value[] values = new Value[strs.length];
		for (int i = 0; i < values.length; i++) {
			values[i] = new SetEnumValue(getValue(n, strs[i]), false);
		}
		return values;
	}

	private static final Value[] getValue(int n, UniqueString[] names) {
		// a,b,c,d,e,...
		return getValue(n, IntStream.range(a, a + names.length).mapToObj(ascii -> Character.toString((char) ascii))
				.toArray(String[]::new));
	}

	private static final UniqueString[] getNames(final int n) {
		final UniqueString[] names = new UniqueString[n];
		for (int i = 0; i < names.length; i++) {
			names[i] = UniqueString.uniqueStringOf("N" + i);
		}
		return names;
	}

	@BeforeClass
	public static void setup() {
		FP64.Init();
	}

	@Test
	public void testSimple() {
		final UniqueString[] names = getNames(3);
		
		final Value[] values = new Value[3];
		values[0] = new SetEnumValue(getValue(7, "a"), true);
		values[1] = new IntervalValue(1, 2);
		values[2] = new IntervalValue(1, 4);
		
		final SetOfRcdsValue setOfRcrdValue = new SetOfRcdsValue(names, values, true);

		checkElements(names, values, setOfRcrdValue, (SubsetEnumerator) setOfRcrdValue.elements(setOfRcrdValue.size()));
	}

	private static void checkElements(final UniqueString[] names, final Value[] values, final SetOfRcdsValue set,
			final SubsetEnumerator rcds) {
		for (int i = 0; i < set.size(); i++) {
			// Check names are stable.
			final RecordValue rcd = rcds.elementAt(i);
			assertArrayEquals(names, rcd.names);
			// Check values are from correct range.
			final Value[] rcdValues = rcd.values;
			for (int j = 0; j < rcdValues.length; j++) {
				assertTrue(values[j].member(rcdValues[j]));
			}
		}
	}
	
	@Test
	public void testRangeSubsetValue() {
		final UniqueString[] names = getNames(4);
		final SetOfRcdsValue setOfRcrdValue = new SetOfRcdsValue(names, getValue(2, names), true);

		final Set<Value> actual = new HashSet<>(setOfRcrdValue.elements(setOfRcrdValue.size()).all());
		assertEquals(setOfRcrdValue.size(), actual.size());

		final Set<Value> expected = new HashSet<>(setOfRcrdValue.elements().all());
		assertEquals(expected, actual);
	}

	@Test
	public void testRandomSubset() {
		final UniqueString[] names = getNames(4);
		final SetOfRcdsValue setOfRcrdValue = new SetOfRcdsValue(names, getValue(3, names), true);

		final int size = 27;
		final Enumerable randomSubset = setOfRcrdValue.getRandomSubset(size);
		final Set<RecordValue> randomsubsetValues = new HashSet<>(size);

		final ValueEnumeration enumerator = randomSubset.elements();
		RecordValue rcd;
		while ((rcd = (RecordValue) enumerator.nextElement()) != null) {
			assertEquals(names.length, rcd.names.length);
			assertEquals(names.length, rcd.values.length);
			randomsubsetValues.add(rcd);
			// Check element is in the original SetOfFcnsValue.
			assertTrue(setOfRcrdValue.member(rcd));
		}

		assertEquals(size, randomsubsetValues.size());
	}

	@Test
	public void testRandomSubsetVaryingParameters() {
		for (int n = 1; n < 7; n++) {
			final UniqueString[] names = getNames(n);
			for (int m = 1; m < 5; m++) {
				final SetOfRcdsValue setOfRcrdValue = new SetOfRcdsValue(names, getValue(m, names), true);
				final Set<RecordValue> randomsubsetValues = new HashSet<>();
				for (int kOutOfN = 0; kOutOfN < setOfRcrdValue.size(); kOutOfN++) {
					final Enumerable randomSubset = setOfRcrdValue.getRandomSubset(kOutOfN);

					final ValueEnumeration enumerator = randomSubset.elements();
					RecordValue rcd;
					while ((rcd = (RecordValue) enumerator.nextElement()) != null) {
						assertEquals(names.length, rcd.names.length);
						assertEquals(names.length, rcd.values.length);
						randomsubsetValues.add(rcd);
						// Check element is in the original SetOfFcnsValue.
						assertTrue(setOfRcrdValue.member(rcd));
					}

					assertEquals(kOutOfN, randomsubsetValues.size());
					randomsubsetValues.clear();
				}
			}
		}
	}

	@Test
	public void testRandomSubsetAstronomically() {
		//	RandomSubset(10000, [a1 : {k : k \in 1..50}, a2 : {k : k \in 1..50}, a3 : {k : k \in 1..50},
		//                       a4 : {k : k \in 1..50}, a5 : {k : k \in 1..50}, a6 : {k : k \in 1..50},
		//                       a7 : {k : k \in 1..50}, a8 : {k : k \in 1..50}, a9 : {k : k \in 1..50},
		//                      a10 : {k : k \in 1..50}])
		final UniqueString[] names = getNames(10);
		final SetOfRcdsValue setOfRcrdValue = new SetOfRcdsValue(names, getValue(50, names), true);

		final int k = 10000;
		final Enumerable randomSubset = setOfRcrdValue.getRandomSubset(k);
		final Set<RecordValue> randomsubsetValues = new HashSet<>(k);

		final ValueEnumeration enumerator = randomSubset.elements();
		RecordValue rcd;
		while ((rcd = (RecordValue) enumerator.nextElement()) != null) {
			assertEquals(names.length, rcd.names.length);
			assertEquals(names.length, rcd.values.length);
			randomsubsetValues.add(rcd);
			// Check element is in the original SetOfFcnsValue.
			assertTrue(setOfRcrdValue.member(rcd));
		}

		assertEquals(k, randomsubsetValues.size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/LiveExprNodeTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.util.Context;

public class LiveExprNodeTest {

	@Test
	public void testLNBool() {
		// Rewriting rules page 452.
		final LiveExprNode p = new LNBool(true);
		final LiveExprNode q = new LNBool(true);
		
		// ~~T -> T
		LiveExprNode tf = new LNNeg(new LNNeg(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(p.equals(tf.toDNF()));

		// ~<>T -> []F
		tf = new LNNeg(new LNEven(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNAll(new LNBool(false)).equals(tf.toDNF()));

		// ~[]T -> <>F
		tf = new LNNeg(new LNAll(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNEven(new LNBool(false)).equals(tf.toDNF()));

		// ~()T -> ()F
		//TODO: pushNeg causes a StackOverflow, see LiveExprNode#pushNeg
		tf = new LNNeg(new LNNext(p));
		assertFalse(tf.isPositiveForm());
//		assertTrue(tf.pushNeg().isPositiveForm());
//		assertTrue(new LNNext(new LNBool(false)).equals(tf.toDNF()));

		// ~(T /\ T) -> F \/ F
		//TODO: Rewrite F\/F to F in toDNF? Probably not worth it.
		tf = new LNNeg(new LNConj(p, q));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNDisj(new LNBool(false), new LNBool(false)).equals(tf.toDNF()));

		// ~(T \/ T) -> F /\ F
		//TODO: Rewrite F/\F to F in toDNF? Probably not worth it.
		tf = new LNNeg(new LNDisj(p, q));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNConj(new LNBool(false), new LNBool(false)).equals(tf.toDNF()));
	}

	@Test
	public void testLNState() {
		final LiveExprNode p = new LNStateAST(new TBParTest.DummyOpApplNode("p"), Context.Empty);
		final LiveExprNode q = new LNStateAST(new TBParTest.DummyOpApplNode("q"), Context.Empty);

		// ~~p -> p
		LiveExprNode tf = new LNNeg(new LNNeg(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(p.equals(tf.toDNF()));

		// ~<>p -> []~p
		tf = new LNNeg(new LNEven(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNAll(new LNNeg(p)).equals(tf.toDNF()));

		// ~[]p -> <>~p
		tf = new LNNeg(new LNAll(p));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNEven(new LNNeg(p)).equals(tf.toDNF()));

		// ~()p -> ()~p
		//TODO: pushNeg causes a StackOverflow, see LiveExprNode#pushNeg
		tf = new LNNeg(new LNNext(p));
		assertFalse(tf.isPositiveForm());
//		assertTrue(tf.pushNeg().isPositiveForm());
//		assertTrue(new LNNext(new LNNeg(p)).equals(tf.toDNF()));

		// ~(p /\ q) -> ~p \/ ~q
		tf = new LNNeg(new LNConj(p, q));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNDisj(new LNNeg(p), new LNNeg(q)).equals(tf.toDNF()));

		// ~(p \/ q) -> ~p /\ ~q
		tf = new LNNeg(new LNDisj(p, q));
		assertFalse(tf.isPositiveForm());
		assertTrue(tf.pushNeg().isPositiveForm());
		assertTrue(new LNConj(new LNNeg(p), new LNNeg(q)).equals(tf.toDNF()));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/console/ConsoleFactory.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.console;

import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleFactory;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A TLC console
 * @author <NAME>
 */
public class ConsoleFactory implements IConsoleFactory
{
    private static final String TLC_ID = "TLC-Console";

    public void openConsole()
    {
        IWorkbenchPage activePage = UIHelper.getActivePage();
        if (activePage != null)
        {
            try
            {
                activePage.showView(IConsoleConstants.ID_CONSOLE_VIEW, TLC_ID, IWorkbenchPage.VIEW_ACTIVATE);
            } catch (PartInitException e)
            {
                ConsolePlugin.log(e);
            }
        }
    }

    public static IOConsole getTLCConsole()
    {
    	IOConsole console = findConsole(TLC_ID);

        return console;
    }

    /**
     * Fins the console with a given name
     * @param name, name of the console
     * @return
     */
    private static IOConsole findConsole(String name)
    {
        if (name == null)
        {
            throw new IllegalArgumentException("Console name must be not null");
        }
        IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();

        IConsole[] existing = consoleManager.getConsoles();
        // try to find existing
        for (int i = 0; i < existing.length; i++)
        {
            if (name.equals(existing[i].getName()))
            {
                return (IOConsole) existing[i];
            }
        }

        // no console found, create a new one
        IOConsole myConsole = new IOConsole(name, null);
        consoleManager.addConsoles(new IConsole[] { myConsole });
        return myConsole;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/TLCPerspective.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

/**
 * Perspective for TLC tool
 * @author <NAME>
 * @version $Id$
 */
public class TLCPerspective implements IPerspectiveFactory
{

    /**
     * Perspective ID
     */
    public static final String ID = "org.lamport.tla.toolbox.tool.perspective.tlc";

    public void createInitialLayout(IPageLayout layout)
    {
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LNNeg.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:39 PST by lamport
//      modified on Sat Jul 28 00:35:57 PDT 2001 by yuanyu

package tlc2.tool.liveness;

import tlc2.tool.ITool;
import tlc2.tool.TLCState;

public class LNNeg extends LiveExprNode {
	private final LiveExprNode body;

	public LNNeg(LiveExprNode body) {
		this.body = body;
	}

	public final LiveExprNode getBody() {
		return this.body;
	}

	public final int getLevel() {
		return this.body.getLevel();
	}

	public final boolean containAction() {
		return this.body.containAction();
	}
	
	@Override
	public final boolean isPositiveForm() {
		if (this.body instanceof LNBool || this.body instanceof LNState) {
			return true;
		}
		return false;
	}

	public final boolean eval(ITool tool, TLCState s1, TLCState s2) {
		return !this.body.eval(tool, s1, s2);
	}

	public final void toString(StringBuffer sb, String padding) {
		sb.append("-");
		this.getBody().toString(sb, padding + " ");
	}

	public void extractPromises(TBPar promises) {
		getBody().extractPromises(promises);
	}

	public int tagExpr(int tag) {
		return getBody().tagExpr(tag);
	}

	public final LiveExprNode makeBinary() {
		return new LNNeg(getBody().makeBinary());
	}

	public LiveExprNode flattenSingleJunctions() {
		LiveExprNode ln1 = getBody();
		if (ln1 instanceof LNNeg) {
			return ((LNNeg) ln1).getBody().flattenSingleJunctions();
		}
		return new LNNeg(ln1.flattenSingleJunctions());
	}

	public final LiveExprNode toDNF() {
		LiveExprNode body = getBody();
		if ((body instanceof LNState) || (body instanceof LNAction)) {
			return this;
		}
		return body.pushNeg().toDNF();
	}

	public LiveExprNode simplify() {
		LiveExprNode body1 = getBody().simplify();
		if (body1 instanceof LNBool) {
			return new LNBool(!((LNBool) body1).b);
		}
		return new LNNeg(body1);
	}

	public boolean isGeneralTF() {
		return getBody().isGeneralTF();
	}

	public LiveExprNode pushNeg() {
		return getBody();
	}

	public LiveExprNode pushNeg(boolean hasNeg) {
		LiveExprNode lexpr = getBody();
		return lexpr.pushNeg(!hasNeg);
	}

	/**
	 * This method returns true or false for whether two LiveExprNodes are
	 * syntactically equal.
	 */
	public boolean equals(LiveExprNode exp) {
		if (exp instanceof LNNeg) {
			return getBody().equals(((LNNeg) exp).getBody());
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.LiveExprNode#toDotViz()
	 */
	public String toDotViz() {
		return "-" + getBody().toDotViz();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/MissingBodyInWhileTest.java<|end_filename|>
package pcal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.tool.CommonTestCase;
import util.ToolIO;

public class MissingBodyInWhileTest extends PCalTest {
	
	@Test
	public void test() {
		assertEquals(trans.STATUS_EXIT_WITH_ERRORS,
				trans.runMe(new String[] {"-nocfg", CommonTestCase.BASE_PATH + "MissingBodyInWhile.tla"}));
		
		final String[] messages = ToolIO.getAllMessages();
		assertTrue(messages.length == 1);
		
		final String msg = messages[0];
		assertEquals("Unrecoverable error:\n" + 
				" -- Missing body of while statement at\n" + 
				"    line 6, column 14.", msg.trim());
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/handler/ProducePDFHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.handler;

import java.io.File;
import java.util.Vector;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.lamport.tla.toolbox.tool.tla2tex.TLA2TeXActivator;
import org.lamport.tla.toolbox.tool.tla2tex.preference.ITLA2TeXPreferenceConstants;
import org.lamport.tla.toolbox.ui.handler.SaveDirtyEditorAbstractHandler;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2tex.TLA;
import tla2tex.TLA2TexException;

/**
 * This handler will attempt to run TLA2TeX on a module if a
 * TLAEditorAndPDFViewer is currently selected. It will load the pdf file in the
 * second tab of the viewer.
 * 
 * @author <NAME>
 */
public class ProducePDFHandler extends SaveDirtyEditorAbstractHandler {

	private final String TLA2TeX_Output_Extension = "pdf";

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands
	 * .ExecutionEvent)
	 */
	public Object execute(final ExecutionEvent event) {
		if (!saveDirtyEditor(event)) {
			return null;
		}

		final IPreferenceStore preferenceStore = TLA2TeXActivator.getDefault().getPreferenceStore();
		final boolean useEmbeddedViewer = preferenceStore.getBoolean(ITLA2TeXPreferenceConstants.EMBEDDED_VIEWER);
		final boolean osHandlesPDF = preferenceStore.getBoolean(ITLA2TeXPreferenceConstants.HAVE_OS_OPEN_PDF);
		
		final IEditorInput editorInput = activeEditor.getEditorInput();
		if (editorInput instanceof IFileEditorInput) {
			final IResource fileToTranslate = ((IFileEditorInput) editorInput).getFile();
			if ((fileToTranslate != null) && ResourceHelper.isModule(fileToTranslate)) {
				final AbstractPDFViewerRunnable pdfViewer;
				
				if (osHandlesPDF) {
					pdfViewer = new OperatingSystemPDFRunnable(this, activeEditor.getSite(), fileToTranslate);
				} else if (useEmbeddedViewer) {
					pdfViewer = new EmbeddedPDFViewerRunnable(this, activeEditor.getSite(), fileToTranslate);
				} else {
					pdfViewer = new StandalonePDFViewerRunnable(this, activeEditor.getSite(), fileToTranslate);
				}
				
				runPDFJob(pdfViewer, fileToTranslate);
			}
		}

		return null;
	}

	/**
	 * This method schedules a long running job that runs tla2tex on the file to
	 * translate and loads it in the browser that is part of the second tab of
	 * the tlaEditorAndPDFViewer.
	 * 
	 * It is done as a long running job so that the UI thread is not locked
	 * while tla2tex runs.
	 * 
	 * This handles any unrecoverable error in tla2tex translation and presents
	 * it to the user as an error message.
	 * 
	 * If the user has the pdf file in the .toolbox directory open in another
	 * program, then the toolbox will show a warning stating that the new pdf
	 * file could not be created. It will display the old, unmodified pdf file
	 * to the user.
	 * 
	 * @param tlaEditorAndPDFViewer
	 * @param fileToTranslate
	 */
	void runPDFJob(final AbstractPDFViewerRunnable runnable, final IResource fileToTranslate) {
		Job tla2TexJob = new WorkspaceJob("Produce PDF") {
			public IStatus runInWorkspace(final IProgressMonitor monitor) {
				try {
					final Vector<String> tla2texArgs = new Vector<String>();
					final IPreferenceStore preferenceStore = TLA2TeXActivator.getDefault().getPreferenceStore();

					if (preferenceStore
							.getBoolean(ITLA2TeXPreferenceConstants.SHADE_COMMENTS)) {
						tla2texArgs.add("-shade");
						tla2texArgs.add("-nops"); // The -nops switch added by
													// LL on 7 Apr 2010
					}

					if (preferenceStore
                            .getBoolean(ITLA2TeXPreferenceConstants.NO_PCAL_SHADE)) {
                        tla2texArgs.add("-noPcalShade");  
                    }

					if (preferenceStore
							.getBoolean(ITLA2TeXPreferenceConstants.NUMBER_LINES)) {
						tla2texArgs.add("-number");
					}

					tla2texArgs.add("-latexCommand");
					String latexCommand = preferenceStore
							.getString(ITLA2TeXPreferenceConstants.LATEX_COMMAND);
					tla2texArgs.add(latexCommand);

					tla2texArgs.add("-grayLevel");
					tla2texArgs
							.add(Double.toString(preferenceStore
									.getDouble(ITLA2TeXPreferenceConstants.GRAY_LEVEL)));

					tla2texArgs.add("-latexOutputExt");
					tla2texArgs.add(TLA2TeX_Output_Extension);
					tla2texArgs.add("-metadir");
					tla2texArgs.add(fileToTranslate.getProject().getLocation()
							.toOSString());
					tla2texArgs.add(fileToTranslate.getLocation().toOSString());

					// the two units of work are running
					// the translation and opening the pdf file
					// in the browser
					monitor.beginTask("Producing PDF", 2);
					monitor.subTask("Translating Module");

					TLA.runTranslation((String[]) tla2texArgs
							.toArray(new String[tla2texArgs.size()]));

					// Refresh the Eclipse workspace after a file has been
					// created outside of the Eclipse Resource realm. This makes
					// sure that the Eclipse resource layer sees the newly
					// created (PDF) file.
					// Without an explicit refresh, one might see the symptoms
					// outlined in Bug #317 in general/bugzilla/index.html
					// (org.eclipse.core.internal.resources.ResourceException:
					// Resource '/Test/Test.pdf' does not exist.)
					fileToTranslate.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);

					monitor.worked(1);

					final String outputFileName = fileToTranslate.getProject()
							.getLocation().toOSString()
							+ File.separator
							+ ResourceHelper.getModuleName(fileToTranslate)
							+ "." + TLA2TeX_Output_Extension;
					
					final File outputFile = new File(outputFileName);
					if (outputFile.exists()) {
						
						runnable.setFile(outputFileName);
						runnable.setMonitor(monitor);
						
						// Open the file if it exists.
						// If it has not been modified, this is
						// most likely because it is open in an
						// external program, so display this information
						// to the user.
						UIHelper.runUISync(runnable);
					} else {
						final Runnable r = () -> {
							MessageDialog.openError(UIHelper.getShellProvider().getShell(), "PDF file not found",
									"Could not locate a pdf file for the module.");
						};
						
						UIHelper.runUIAsync(r);
					}
				} catch (final TLA2TexException | CoreException e) {
					handleJobException(e);
				}
				return Status.OK_STATUS;
			}
		};

		// setUser(false) to not popup a modal dialog on each PDF generation.
		tla2TexJob.setUser(false);
		tla2TexJob.setPriority(Job.LONG);
		tla2TexJob.schedule();
	}
	
	private void handleJobException(final Exception e) {
		TLA2TeXActivator.getDefault().logError("Error while producing pdf file: " + e.getMessage(), e);

		final Runnable r = () -> {
			final Shell s = PlatformUI.getWorkbench().getDisplay().getActiveShell();
			final int response = MessageDialog.open(MessageDialog.ERROR, s, "PDF Production Problem",
					"The following error was encountered while attempting to generate the PDF - perhaps you "
						+ "have not set a full path to pdflatex in the preferences?\n\n" + e.getMessage(),
					SWT.NONE, "Open Preferences", "Ok");
			
			if (response == 0) {
				final PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(s, 
						"toolbox.tool.tla2tex.preference.TLA2TeXPreferencePage",
						new String[] { "toolbox.tool.tla2tex.preference.TLA2TeXPreferencePage" }, null);
				dialog.open();
			}
		};
		
		UIHelper.runUIAsync(r);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.uitest/src/org/lamport/tla/toolbox/ui/handler/SpecEditorOpenCondition.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.ui.IEditorPart;
import org.lamport.tla.toolbox.editor.basic.TLAEditorAndPDFViewer;
import org.lamport.tla.toolbox.util.UIHelper;

public class SpecEditorOpenCondition extends DefaultCondition {

	private String prefix = "";
	
	public SpecEditorOpenCondition(final String aPrefix) {
		prefix = aPrefix;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#test()
	 */
	public boolean test() throws Exception {
		IEditorPart activeEditor = UIHelper.getActiveEditor();
		if(activeEditor instanceof TLAEditorAndPDFViewer) {
			final String aTitle = activeEditor.getTitle();
			return aTitle.startsWith(prefix);
		} 
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swtbot.swt.finder.waits.ICondition#getFailureMessage()
	 */
	public String getFailureMessage() {
		return String.format("Timed out waiting for editor with %s to open", prefix);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/DecomposeProofHandler.java<|end_filename|>
/**
 * BUG DISCOVERED in March 2019 by LL
 *   If an INSTANCE statement implicitly instantiates a module parameter with the identifier
 *   of the same name (by not specifying an instantiation for it), the Decompose Proof command
 *   expands definitions from the instantiated module by replacing the parameter by
 *   the text of the INSTANCE statement.  The problem is manifest in a bad argument
 *   passed to substInNodeToInstanceSub, and that manifestation is explained in comments
 *   starting around line 5342.  (Search for "22 March 2019".)  There are also comments containing 
 *   and explaining an unsuccessful attempt to fix the problem.
 * 
 * CHANGE MADE BY LL on 18 March 2019
 *   At some point, this class was modified by first creating a new version called
 *   NewDecomposeProofHandler and then renaming it to be the current version.  A lot
 *   of references to NewDecomposeProofHandler remained, including ones pointing to
 *   an error at a certain line number of NewDecomposeProofHandler.  I changed almost
 *   all mentions of NewDecompose... to Decompose..., and updated the line numbers of
 *   the error.  I left a couple of NewDecompose... in comments that seemed to accompany
 *   commented-out code from that file.
 *     
 * BUG DISCOVERED in August 2019 
 *   If a definition in an instantiated module contains an expression like 2 ++ 2
 *   and the command expands that definition, it produces an expansion that might
 *   contain the expression 2 I!++ 2 which is illegal, instead of the correct
 *   expansion I++(2, 2).  This may be difficult to fix.  However, it shouldn't
 *   be hard to fix what will probably be the most common case:  If the expression
 *   is 2 + 2, where + is the operator imported from the Standard Module Integers or
 *   Naturals, and that same + is imported into the current module, then I!+ is
 *   equivalent to +, so the current 2 I!+ 2 can be changed to 2 + 2.
 * 
 * IN MIDDLE OF
 * Fixing bug on line 428 of Test.tla.  Will try the approach of adding
 * a global Renaming to the decomposition state to keep track of all renaming in
 * all formulas.  This should obviate the need for any other renamings in the state, but
 * now just using it to get renamings that are missed.  It's been added to getCurrentName,
 * though I don't know if that's necessary.  The renamings needed to fix the bug on 
 * line 428 of Test.tla are the
 * ones being returned by ResourceHelper.getBoundIdentifiers in addSymbolsDeclaredLater.
 * That method returns the original names, but should return the new names of any
 * identifiers that have been renamed.  This requires copying that method into
 * this module and rewriting it appropriately.
 * 
 *  
 *  
 * THINGS TO DO:
 *  - Check that what I've done so far works with definition expansion.
 *  
 *  - Figure out how to control displaying of context assumptions once some assumption
 *    has been decomposed.  Perhaps the easiest thing to do is, once a context assumption has
 *    been \E-decomposed, remove it's NodeRepresentations from  assumeReps and put its 
 *    decomposition in the ASSUME section.  Once a CASE-decomposition is made, all context
 *    assumptions should be removed from assumeReps and the decomposition should be moved
 *    to the ASSUME section if it came from a context assumption.  What should be done
 *    on /\ decompositions?  Should all other decompositions be disabled/removed?  Should
 *    it depend on whether the /\ decomposition came from a \E.
 *    
 *  - Should original ASSUMEs that haven't been decomposed be removed from assumeReps
 *    once they can no longer be decomposed?
 *    
 *  - Fix proof generation so it adds the necessary BY steps and DEF names.
 *  
 *  - Handle substitutions of multi-line formulas.
 *  
 *  - Handle decompositions of formulas that come from other modules.
 *    
 * 
 * NEW Decompose Proof Handler Command
 *   This class is the development version of the new Decompose Proof Handler
 *   command.  If I could get Eclipse/Git to work, I would be building it in
 *   a different branch rather than in the master branch.
 * 
 * ENHANCEMENTS 
 * 
 * - Allow case splits and introduction of Skolem constants on usable assumptions--
 *   that is, assumption from relevant ASSUME or SUFFICES ASSUME clauses.
 *   I originally thought there are too many of them to display, but I no longer
 *   think this will be the case--although it would be distracting to display
 *   them when the user just wants to decompose the current assumptions.
 *   
 *   THIS WILL BE DONE AS FOLLOWS:
 *    - There will be a switch to determine whether potential decompositions
 *      from assumptions in the environment should be displayed.
 *    - The state of that switch will be remembered between invocations.
 *    - Clicking on the switch shows or hides the relevant assumptions
 *      immediately.
 *    - Only assumptions that have a possible decomposition (possibly
 *      within deeper conjunctions and definition expansions) are shown.
 *    To make this less cumbersome, once one assumption or conjunct of an
 *    assumption is chosen for decomposition, others are no longer shown.
 *      
 *   
 * CURRENT BUGS AND MISSING FEATURES:
 * 
 *  - Bug reported 16 Jan 2014 by Jael, fixed on 23 Aug 2014 by LL. 
 *    STILL FIXED IN NEW VERSION
 *    Decomposing
 *  
 *       THEOREM \A x, y : x /\ y => TRUE
 *       
 *    with \A then => then /\ puts the menu in a state in which P is not enabled.
 *    
 *    This may not be a bug, since there decomposing the /\ accomplished nothing.
 *    However, decomposing the /\ and then the \E in
 *    
 *       THEOREM ASSUME (\E x : TRUE) /\ FALSE
 *       PROVE   TRUE
 *       
 *    Leaves the Prove button disabled
 *    
 *  - Bug discovered 19 Aug 2014 by LL.  FIXED IN NEW VERSION
 *    Decomposing
 *    
 *       <1>3. ASSUME (\E x : D) /\ (A \/ D)
 *             PROVE  FALSE
 *             
 *    by /\ then \E then \/ does not add the necessary assumption <1>3 to
 *    the BY of the SUFFICES (or QED if USE SUFFICES not chosen).
 *    
 *    
 *  - Bug discovered 23 Aug 2014 by LL:  
 *    FIXED IN NEW VERSION by not allowing a \A decomposition after 
 *    a \/ decomposition,
 *    The following produces a parse error on decomposition by \/ 
 *    then \A then Prove.
 *    Note especially what happens with USE SUFFICES option, where
 *    a NEW declaration is moved before a previous assumption in the
 *    proof.  (Without the SUFFICES option, the problem can be solved
 *    by preserving the original order of the assumptions.)
 *    
 *      S1b == A \/ ({y_1 \in {44} : y_1 > 0} = {x \in {44} : x > 0})
 *      THEOREM ASSUME NEW x , NEW y_1, S1b  
 *              PROVE  \A x_1 : FALSE   
 *      <1>3. ASSUME (\E x : D) /\ (A \/ D)
 *            PROVE  FALSE
 *            
 *    
 *  - The command does renaming of bound variables when necessary to avoid
 *    name clashes, but not of symbols defined in a LET.
 *    
 *    
 *  - The implementation contains code written to implement a "use Subexpression Names"
 *    feature that allowed the user to specify that decomposition that involved 
 *    expanding definitions was to be done by using subexpression names rather
 *    than actually expanding the definition in the proof text.  This feature
 *    was abandoned because the initial implementation did not allow renaming of
 *    identifiers to avoid name clashes in the subexpression names.  However, the
 *    code that was written remains; only the button for choosing the feature
 *    was made invisible.  This means that there is a lot of dead code 
 *    that was executed only when the option was chosen.
 *    THE DEAD CODE IS BEING LEFT IN JUST IN CASE SOMEONE WANTS TO IMPLEMENT
 *    THAT FEATURE.
 *
 *
 *  - If decomposition requires expanding a definition, the decomposition will be
 *    performed only if each argument of the defined operator appears on a 
 *    single line of the source text.  (Different arguments may appear on 
 *    different lines.)
 *    
 *    Also, expanding of definitions obtained by instantiation will be performed
 *    only if the expressions substituted for the parameters of the instantiated
 *    module are single-line expressions.
 *    
 *    THESE RESTRICTIONS MAY SOME DAY BE REMOVED.  See MODULE Substitution,
 *    appended below, for a spec of the necessary code.
 * 
 *  - Decomposition will not be performed if it requires expanding the definition of
 *    an operator instantiated with parametrized renaming--that is, an operator
 *    whose name is something like Foo(x+y,z)!Bar.  (The definition of an operator
 *    named Foo!Bar can be expanded.)  The problem is that from the semantic tree,
 *    it is impossible whether an operator application is written Foo(x+y,z)!Bar(42)
 *    or Foo!Bar(x+y,z,42).  Fixing this will require modifying SANY to add the
 *    necessary disambiguating information to the semantic tree.
 *  
 *  - Decomposition will never be performed on any decomposable formula that
 *    appears as an operator argument.  For example, in
 *    
 *      F(a, b) == a \/ b
 *      THEOREM F(G \/ H, I) => K
 *    then decomposition into the two cases G \/ H and I will be performed, but
 *    decomposition into the subcases G and H will not.
 *    THIS RESTRICTION WILL PROBABLY REMAIN.  IT DOESN'T SEEM LIKELY TO OCCUR OFTEN.
 *    
 *  - When definitions obtained by instantiation are expanded, operator names
 *    may need to be changed--e.g., replacing Op with Foo!Bar!Op.  This will
 *    not be done if Op is used as an operator argument, and a warning will
 *    be raised if an operator that might need renaming is encountered.
 *  
 *  - It would be useful to have the option of expanding an assumption or goal
 *    that is a LET formula.  This would create an initial DEFINE step in the proof.
 *    THIS RESTRICTION WILL PROBABLY REMAIN.  IT DOESN'T SEEM LIKELY TO OCCUR OFTEN.
 *    
 *  - Renaming of identifiers to avoid name clashes when expanding definitions doesn't do
 *    all the renaming it should.  In particular, it does not rename operators defined in
 *    a LET clause or their definition parameters.  See ResourceHelper.getBoundIdentifiers
 *    to get a start on fixing this.
 *    
 *  - Bug discovered by LL on 28 October 2014 
 *    If an operator argument contains a bound variable, as in Op(\E x : F(x)), and
 *    a decomposition is performed that expands the definition of Op, then decomposing
 *    other formulas can produce a decomposition that doesn't parse because of name
 *    conflicts with x in the expression \E x : F(x).  Fixing this would require
 *    major changes to the code, since the design is based on the assumption that
 *    substitutions will never have to be done in an expression that is substituted
 *    for some identifier.  One way to fix this would be to make a NodeRepresentation
 *    maintain with its NodeText the information about all substitutions that have
 *    been done in NodeText.  But that's just a vague idea and it's not clear how
 *    easy it would be to do it, if it's even possible.
 *    
 *  - Bug discovered by LL on 1 December 2014
 *    Renaming of bound identifiers can be done in an /\ decomposition of an assumption
 *    before it's necessary.  Repeated /\ decompositions can yield an expression
 *    like \E x_2_2_1 : exp(x_2_2_1) .   When such an expression is decomposed, the
 *    quantifier bound is given a reasonable name like x_2, but the instances of
 *    that bound keep their silly name, so this expression can yield the assumption
 *    clauses:  NEW x_2, exp(x_2_2_1) .  
 *    
 *    As a concrete example, consider:
 *    
 *      THEOREM ASSUME ( (\E x : x \subseteq x) /\ ((\E x : x = {x}) 
 *                         /\ ((\E x : x \ {x} = {})) /\ (A \/ \A x : x = <<x>>))),
 *                      NEW x
 *              PROVE  FALSE
 *          
 *    As of 1 December 2014, the decomposition of this theorem can
 *    produce:
 *    
 *       <1> SUFFICES ASSUME NEW x_1,
 *                           x_1_1 \subseteq x_1_1,
 *                           NEW x_2,
 *                           x_2_2_1 = {x_2_2_1}
 *                    PROVE  FALSE
 *         OBVIOUS
 *       <1> QED  
 *    
 *    Note: => decomposition doesn't seem to have this problem.
 *    
 * 
 * HOW THE COMMAND WORKS
 * 
 * A single object of this class is created and attached to the command.  Multiple
 * executions of the command use the same object, so data can be stored as (non-static)
 * fields of the object between executions of the command.
 * 
 * The structure of the methods is as follows.  Executing the command calls the
 * execute() method, which does some stuff and then calls realExecute() in a
 * Runnable.  That method initializes the state and calls raiseWindow to draw the
 * window, creating the buttons and their listeners.  Each formula shown in the
 * command's window is described by a NodeRepresentation object.
 * 
 * Clicking a button calls the widgetSelected method of the 
 * DecomposeProofButtonListener subclass.  This calls the appropriate one of the 
 * following methods to handle the click:
 * 
 *   andAction     (splitting an /\ assumption and producing an /\-split proof)
 *   forAllAction  (splitting a \A goal)
 *   existsAction  (splitting a \E assumption)
 *   impliesAction (splitting a => goal)
 *   orAction      (splitting a \/ assumption)
 *   sqsubAction   (splitting a [N]_v assumption)
 *   caseAction    (producing a case-split proof)
 *   
 *   A NodeRepresentation object is created for a formula in the window by
 *   calling the subNodeRep method of the NodeRepresentation method, which calls
 *   the decompose method to set the object's decomposition field that describes
 *   how that the proof can be split on that formula.  
 *   
 *   When a formula with NodeRepresentation nrep is split, the resulting formulas 
 *   have NodeRepresentation objects constructed by calling the 
 *   decompositionChildToNodeRep method (which calls the nrep.subNodeRep method).
 *   
 *   The value of state.assumeReps is initially set to the sequence of 
 *   decomposable context assumptions and all non-context assumptions.
 *   When an assumption is decomposed by anything other than an /\ decomposition,
 *   the newly created assumption is put in the section of state.assumeReps
 *   that begins at position state.firstAddedAssumption.  The order of created
 *   assumptions in that section is the same as the order of the original
 *   assumptions from which they came, except that the NodeRepresentation created 
 *   by \/ decomposition is always the last assumption.  An assumption added
 *   as a result of decomposing the goal is made the last assumption in
 *   state.assumeReps except for a node created by \/ decomposition.  (This
 *   ordering is implemented using NodeRepresentation.initialPosition.)
 *   
 *   IMPLEMENTATION NOTE: substitution
 *   - When something is substituted for an operator argument, the substitution
 *     is done at the level of strings.  Therefore, any identifiers that appear
 *     in the substituting expression will never be found when looking for name
 *     clashes.  This should not cause any problem because any substitution needed
 *     in the operator argument should be performed before the operator's 
 *     definition is expanded.   
 *     
 *   - To eliminate name clashes, new identifiers are substituted for existing
 *     bound identifiers.  These new identifiers clash with nothing when they
 *     are introduced.  To keep them from clashing with identifiers introduced
 *     or revealed later, these names are remembered in the renaming field of the 
 *     Decomposition object.
 */

/***************************************************************************
            A SPEC OF DECOMPOSITION

The following decompositions are provided.

   => decomposition:
     The goal A => B is changed to the goal B by adding assumption A
  
   \A decomposition:
      The goal \A x \in S : G is changed to the goal G by adding assumption
      NEW x \in S.  (Unbounded \A is transformed similarly.)
  
   \E decomposition:
       The assumption \E x \in S : A is changed to the two assumptions
       NEW x \in S, A .  (A change of variable may occur to prevent name
       clash.)
  
   \/ decomposition:
        The assumption A_1 \/ ... \/ A_n is decomposed into n cases,
        in each of which one A_i is assumed.  Only a single 
        \/ decomposition of an assumption may be performed.  However,
        a case may be further decomposed by \/ or \E decomposition.      
  
   /\ assumption decomposition:
       The assumption A_1 /\ ... /\ A_n is replaced by the n separate
       assumptions A_1, ... , A_n
  
   /\ goal decomposition:
       The goal A_1 /\ ... /\ A_n produces a decomposition of the proof 
       into separate proofs of the A_i.  This is a final step that
       produces the proof.

Each of these decompositions can be performed if the goal or assumption
has the indicated form, or if it consists of a single operator whose
definition has that form.

After an \/ decomposition has been performed, no further \/
decomposition may be performed.

An /\ decomposition can be performed only if it, or further /\
decompositions of the assumptions it produces can lead to 
  - a \E decomposition or 
  - a \/ decomposition when no \/ decomposition has yet been
    performed.

Context assumptions that are not decomposible should not be shown.

POSSIBLE OPTION: Whether or not non-decomposible assumptions from
the statement being decomposed (either ASSUME clauses or a CASE
assumption) should be shown.  Current choice: do not show.

All case assumptions produced by \/ decomposition and any assumption
created by =>, \A, or \E decomposition should be shown.  All of these
assumptions will appear explicitly, in the appropriate ASSUME or CASE
clauses, as assumptions in the proof that is generated.

POSSIBLE OPTION: Whether or not non-decomposible assumptions produced
by /\ decomposition should be shown.  This might depend on whether
or not the decomposed assumption was a context assumption.  Current
choice: not to show.

POSSIBLE OPTION: Whether or not non-decomposed assumptions produced by
/\ decomposition should appear as explicit assumptions in the
generated proof.  They are not logically necessary because they are
implied by assumptions in the generated proof's context (which
includes the ASSUME clauses of the decomposed step).  Current choice
(preferred by Damien, Stephan, and LL): not to appear.
**************************************************************************/

 
/*************************************************
 A SPEC OF PROOF GENERATION

 The |= Notation
 ---------------
 I will write A |= P as an abbreviation for ASSUME A PROVE P, for
 A a list of assumptions and P a formula.

 A formula P is equivalent to |= P (the case of A the empty list).

 Define A_1 |= (A_2 |= P) to be A_1, A2 |= P , where I use "," to mean
 concatenation of lists of assumptions.

 I will also allow assumptions of the form A_1 \/ ... \/ A_n
 where the A_i are sequents of the form  A |= P .  I hope its meaning
 is obvious.  It obeys the rule that

 A, (B_1 \/ ... \/ B_n), C |= P

 is equivalent to

 (A, B_1, C |= P) /\ ... /\ (A, B_n, C |= P)

 CASE
 ----
 If the A_i are formulas and P is the current goal, then the step

 <i>j. A_1, ... , A_n |= P 

 can be written 

 <i>j. CASE A_1 /\ ... /\ A_n


 Proofs with and without SUFFICES
 --------------------------------
 Any proof of the form

 <i> SUFFICES A |= P
 BY DEF D_1, ... , D_k
 <i>1. S_1
 ...
 <i>n. S_n
 <i> QED
 BY <i>1, ... , <i>n DEF P

 is equivalent to

 <i>1. A |= S_1
 ...
 <i>n. A |= S_n
 <i> QED
 BY <i>1, ... , <i>n DEF D_1, ... , D_k, P

 I will therefore only consider proofs with SUFFICES.


 Proof by Conjunction Splitting
 -----------------------------
 Suppose an obligation A |= P is transformed into the obligation 
 A, H |= C by expanding definitions D_1, ...  , D_k, where 
 C == C_1 /\ ...  /\ C_n.  Then A |= P has the proof:

 <i> SUFFICES  H |= C
 BY DEF D_1, ... , D_k
 <i>1. C_1
 ...
 <i>n. C_n
 <1> QED
 BY <i>1, ... , <i>n DEF C

 If C is equal to C_1 /\ ... /\ C_n (rather than equal after the
 definition of C is expanded, then the DEF C is eliminated.


 Proof by Disjunction Splitting
 -------------------------------
 Suppose an obligation A |= P is transformed into the obligation 
 A, H |= C by expanding definitions D_1, ... , D_k.

 Suppose that A, H |= C is then transformed to the equivalent
 obligation  J, K, L |= C by expanding definitions E_1, ... , E_m,
 and K == K_1 \/ ... \/ K_n.  Then A |= P has the
 proof

 <i> SUFFICES H, J, K, L |= C
 BY DEF D_1, ... , D_k, E_1, ... , E_m
 <i>1. K_1 |= C
 ...
 <i>n. K_n |= C
 <1> QED
 BY <i>1, ... , <i>n DEF K

 (The DEF K can be eliminated if K equals 

 The transformation of A, H |= C to J, K, L |= C will be done in
 two steps:

 1. Splitting conjunctions into separate assumptions.

 2. Performing the transformations:

 \E x : S   ->  NEW x, S .

 NEW x, S_1 \/ ... \/ S_n  ->  
 (NEW x |= S_1) \/ ... \/ (NEW x |= S_n)

 **************************************************************************/

/*
 * To figure out how to lay out a nice popup, see 
 *    
 *    http://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html
 *    
 * to find out how to use GridLayout, and see ObligationsView.updateItem 
 * to see how to add things to a Composite nested inside other things.  
 * See also the ScrolledComposite method, which with luck will just be
 * a composite with scrollbars when needed.
 */

package org.lamport.tla.toolbox.editor.basic.handlers;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.spec.parser.ModuleParserLauncher;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.util.HelpButton;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.StringSet;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.AssumeProveNode;
import tla2sany.semantic.DefStepNode;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.InstanceNode;
import tla2sany.semantic.LeafProofNode;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.NewSymbNode;
import tla2sany.semantic.NonLeafProofNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpArgNode;
import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.ProofNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.Subst;
import tla2sany.semantic.SubstInNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.TheoremNode;
import tla2sany.st.Location;
import util.StringHelper;
import util.TLAConstants;
import util.UniqueString;

public class DecomposeProofHandler extends AbstractHandler implements
        IHandler {

    /***************************************************************
     * Fields holding information about the module, its source text, the
     * selected text, the selected step, and the theorem in which it appears.
     ****************************************************************/
    /**
     * The document being edited.
     */
    private IDocument doc;

    /**
     * A mapping from module names to IDocuments, containing IDocuments for
     * all modules that have been encountered in the course of expanding
     * imported definitions.
     * 
     */
    private Hashtable<String, IDocument> moduleNameToDoc ;
    
    /**
     * Some Eclipse thingee that seems to be needed.
     */
    private ISelectionProvider selectionProvider;

    /**
     * The current selection.
     */
    private TextSelection selection;

    /**
     * The current offset.
     */
    private int offset;

    /**
     * The module being edited.
     */
    private ModuleNode moduleNode;

    /**
     * The theorem containing the selected step
     */
    private TheoremNode theorem;

    /**
     * The step being decomposed.
     */
    private TheoremNode step;

    /**
     * The step's node representation.
     */
    private NodeRepresentation stepRep;

    /**
     * The step's proof which should be either null or a LeafProofNode.
     */
    private ProofNode proof;

    /**
     * If the step being proved is numbered <2>3, then this equals 2.
     */
    private int proofLevel;

    /**
     * The proofLevel converted to a string like "<2>", except that a level of 0
     * or -1 (which are possible) is converted to 1.
     */
    private String proofLevelString;

    /**
     * If the step is number <2>3, then this is "<2>3". If the step is
     * unnumbered, as in <2>, or if it is the entire theorem, then this string
     * is null.
     * 
     * Note that the SANY parser appears to replace <+> or <*> by <n> for the
     * appropriate number n, so the Toolbox doesn't have to deal with <+> or
     * <*>.
     */
    private String stepNumber;

    /**
     * The column in which the step begins.
     */
    private int stepColumn;

    /**
     * PREFERENCES
     * 
     * The following fields are constants, some of which should perhaps be set
     * as preferences.
     */
    /**
     * The default value of showContextValue
     */
    private static final boolean SHOW_CONTEXT_DEFAULT = true;
    
    /**
     * The default value of useSufficesValue ;
     */
    private static final boolean USE_SUFFICES_DEFAULT = true;

    /**
     * The default value of useCaseValue ;
     */
    private static final boolean USE_CASE_DEFAULT = true;

    /**
     * The default value of subexpressionValue.
     */
    private static final boolean SUBEXPRESSION_DEFAULT = false;

    /**
     * The number of columns to the right of stepColumn to which the created
     * proof is to be indented.
     */
    private static final int PROOF_INDENT = 2;

    /**
     * Whether or not to leave a blank line between the created proof steps.
     */
    private static final boolean BLANK_LINE_BETWEEN_STEPS = false;

    /**
     * True iff an "obvious" proof should be written "PROOF OBVIOUS" rather than
     * just "OBVIOUS".
     */
    private static final boolean OBVIOUS_HAS_PROOF = false;

    /**
     * True iff the QED step of the new proof should have a number rather than
     * just a level.
     */
    private static final boolean NUMBER_QED_STEP = true;

    /**
     * The string that should follow a step number like <2>7 in proofs
     * constructed by decomposition.
     */
    private static final String STEP_NUMBER_PUNCTUATION = ".";

    /**
     * When renaming identifiers to avoid name conflicts, an identifier id is
     * renamed to id + RENAMING_SUFFIX + i for some number i. Any identifier
     * that has this form is considered to be a renamed identifier, and it will
     * be renamed by changing i.
     * 
     * If the value of RENAMING_SUFFIX is "", everything will work but the
     * renaming will be a little weird for identifiers whose original name ends
     * in a digit, or if an identifier that gets renamed with i > 9 gets
     * re-renamed.
     */
    private static final String RENAMING_SUFFIX = "_";

    /*************************************************************************
     * Fields that contain the current assumptions and goal.
     * 
     * The data for the current assumptions are kept in vectors, the i-th
     * element containing data for the i-th assumption. This is done to make it
     * easy to replace one assumption by several. Other objects contain pointers
     * to these vectors, so once the vectors are constructed by
     * DecomposeProofHandler.execute, they can be modified but must not be
     * replaced by new vectors.
     *************************************************************************/

    /**
     * The NodeRepresentation objects for the current assumptions.
     */
    // private Vector<NodeRepresentation> assumeReps; // moved to state

    /**
     * The NodeRepresentation object for the current goal.
     */
    // private NodeRepresentation goalRep; // moved to state

    // Fields for displaying the Decompose Proof window.
    private Shell windowShell; // The shell of the Decompose Proof window
    private Point location = null; // The location at which window should open.
    private TLAEditor editor; // The editor from which window was raised.
    private IFile editorIFile; // The IFile of the editor, used for making
                               // it read-only.

    /**
     * Holds the current state of the decomposition. It will be cloned when the
     * state is changed, the clone modified and its previousState field set to
     * the current value of state, and state set to the new DecompositionState.
     */
    private DecompositionState state = null;

    /* *
     * MANY OF THE FOLLOWING FIELDS WILL BE PUT INTO THE state
     * DecompositionState OBJECT
     */

    /**
     * If the user has done an OR split on an assumption, then this is the index
     * of the assumption in assumes and state.assumeReps. Otherwise, it equals
     * -1.
     */
    // int chosenSplit; // MOVED TO DecompositionState (not sure IF STILL
    // NEEDED)

    /**
     * True if the proof of a SUFFICES step (or of the QED step if there is no
     * SUFFICES step) needs the name of the step being decomposed in the BY
     * clause if that step has a name. I believe this is the case iff an
     * \E-split has been done on an assumption that was not moved from the goal.
     * 
     * 
     */
    // boolean needsStepNumber; // TO BE MOVED TO DecompositionState

    /**
     * The original DecomposeProofHandler documentation said:
     * 
     *   True iff the step/theorem being decomposed is an ASSUME/PROVE. This is
     *   relevant for setting state.needsStepNumber.
     *   
     * To try to maintain the meaning of this field, it is set true iff the step
     * being decomposed is an ASSUME/PROOF (or CASE) that has an assumption other
     * than a NEW.
     * 
     */
    boolean hasAssumes;

// UP-DOWN ARROWS REMOVED
//    /**
//     * Once the user has performed an AND split on an assumption, then another
//     * AND split can be performed only on one of the results of that split. The
//     * indices of the nodes in <code>assumes</code> and
//     * <code>state.assumeReps</code> resulting from AND splits range from
//     * andSplitBegin through (including) andSplitEnd. If no AND split has been
//     * performed, then andSplitBegin and andSplitEnd equal -1.
//     * 
//     */
    // int andSplitBegin; // moved to state
    // int andSplitEnd; // moved to state
    // private HashSet<String> goalDefinitions; // MOVED TO state
    // private HashSet<String> assumpDefinitions; // MOVED TO state

    /**
     * The set of all user-definable identifiers that are declared or defined
     * before the theorem or step being decomposed. It consists of the
     * following:
     * 
     * - CONSTANTS and VARIABLES of the current module declared before the step.
     * These are obtained from moduleNode.getConstantDecls() and
     * moduleNode.getVariableDecls(). (See ShowDeclarationsHandler.setList.)
     * 
     * - Operators and Theorem/Assumption name defined before the current step.
     * These are obtained from moduleNode.getOpDefs() and
     * moduleNode.getThmOrAssDefs(). To do this, we first find the names of all
     * modules whose definitions are imported by INSTANCE statements that occur
     * before the step. We do this from moduleNode.getInstances() to find all
     * unnamed INSTANCE statements occurring before the step, and then follow
     * the getInstances() pointers to find them. To determine if the identifier
     * defined by an OpDefNode or ThmOrAssumpDefNode node n occurs before the
     * step, we examine n.getSource() and if its not moduleNode, we see if it's
     * a member of the set of relevant instantiated modules.
     * 
     * - Identifiers used in named instantiations (e.g., the I in I == INSTANCE
     * ...). They are obtained from moduleNode.getInstances().
     * 
     * - Identifiers declared by NEW clauses in ASSUME/PROVE or SUFFICES
     * ASSUME/PROVE statements in whose scope the step lies.
     * 
     * - Definitions in DEFINE steps (represented by DefStepNode objects) in
     * whose scope the step lies.
     */
    private  StringSet declaredIdentifiers;
    
    /*
     * If the command requires expanding a definition obtained through implicit
     * instantiation of a module parameter (that is, without an explicit WITH
     * substitution), then a bug in the renaming code could incorrectly expand
     * that definition.  When this is first encountered, a warning is raised.
     * However, since most of the time the renaming will be performed correctly,
     * it will be a nuisance to raise the warning over and over again.  So,
     * the warning is raised only once for every launch of the Toolbox.  The
     * raiseImplicitRenamingWarning flag is used to control this.
     * Added by LL on 22 March 2019.
     */
    private static String lastModuleWithImplicitRenamingWarning = "" ;
    
    /********************************************************************
     * METHODS INVOLVED IN RENAMING
     *********************************************************************/
    /**
     * Returns the current name of the FormalParamNode `node'. If it has been
     * renamed, then this name is found in rename.newNames. Otherwise, it is the
     * original name.
     * 
     * Added 3 Dec 2014.  If not found in rename, then look for it in state.renaming.
     * 
     * @param node
     * @param rename
     * @return
     */
    private String getCurrentName(FormalParamNode node, Renaming rename) {
        String newName = null;
        int i = 0;
        while ((i < rename.identifiers.size()) && (newName == null)) {
            if (rename.identifiers.elementAt(i) == node) {
                newName = rename.newNames.elementAt(i);
            }
            i++;
        }
        if (newName == null) {
            while ((i < state.renaming.identifiers.size()) && (newName == null)) {
                if (state.renaming.identifiers.elementAt(i) == node) {
                    newName = state.renaming.newNames.elementAt(i);
                }
                i++;
            }
        }
        if (newName == null) {
            return node.getName().toString();
        } else {
            return newName;
        }
    }

    /**
     * Modifies the Renaming object rename to indicate that the current name of
     * `node' is `name'. If the current name of `node' is its original name,
     * then do nothing.
     * 
     * @param node
     * @param name
     * @param rename
     */
    private void addCurrentName(FormalParamNode node, String name,
            Renaming rename) {
        // If node is in rename.identifiers, then set i to its index.
        // Otherwise, set i to rename.identiers.size().
        int i = 0;
        while ((i < rename.identifiers.size())
                && (rename.identifiers.elementAt(i) != node)) {
            i++;
        }

        // Either replace the current renaming of `name' in `rename'
        // if there is one, otherwise add the renaming iff it's not
        // the same as its original name.
        if (i < rename.identifiers.size()) {
            rename.newNames.remove(i);
            rename.newNames.insertElementAt(name, i);
        } else {
            if (!name.equals(node.getName().toString())) {
                rename.identifiers.add(node);
                rename.newNames.add(name);
            }
        }
    }

    /**
     * Returns a new name for `node' that is different from any of the names in
     * the set currentlyDeclared of names . If getCurrentName(node, rename) is
     * not in currentlyDeclared, then that's the name returned. Otherwise, if
     * there's a node n with the same original name as `node' that is being
     * renamed by `rename', and getCurrentName(n, rename) not in
     * currentlyDeclared, then the methods return getCurrentName(n, rename).
     * Otherwise, it returns the string nm + RENAMING_SUFFIX + i where nm is the
     * original name of `node', and i is the smallest positive integer such that
     * this string is not in currentlyDeclared.
     * 
     * @param node
     * @param currentlyDeclared
     * @param rename
     * @return
     */
    private String getNewName(FormalParamNode node,
            StringSet currentlyDeclared, Renaming rename) {

        String curName = getCurrentName(node, rename);
        if (!currentlyDeclared.contains(curName)) {
            return curName;
        }

        String oldName = getNewNamePrefix(node.getName().toString());
        int i = 1;
        while (currentlyDeclared.contains(oldName + i)) {
            i++;
        }

        return oldName + i;
    }

    /**
     * The return value is the string str such that if the identifier with name
     * oldname is to be renamed, its new name should have the form str+i for
     * some positive integer i. See RENAMING_SUFFIX.
     * 
     * The method assumes that oldname is a string containing at least one
     * character.
     * 
     * @param oldname
     * @return
     */
    private String getNewNamePrefix(String oldname) {

        // Return oldname unless it has a single character or doesn't end with a
        // digit.
        if ((oldname.length() < 2)
                || !Character.isDigit(oldname.charAt(oldname.length() - 1))) {
            return oldname + RENAMING_SUFFIX;
        }

        // Set newname to oldname minus the last digit.
        String newname = oldname.substring(0, oldname.length() - 1);

        // Keep removing digits from the end of newname until it ends with
        // RENAMING_SUFFIX or gets too short.
        while ((newname.length() > RENAMING_SUFFIX.length())
                && Character.isDigit(newname.charAt(newname.length() - 1))
                && !newname.endsWith(RENAMING_SUFFIX)) {
            newname = newname.substring(0, newname.length() - 1);
        }

        if (newname.endsWith(RENAMING_SUFFIX)) {
            return newname;
        } else {
            return oldname + RENAMING_SUFFIX;
        }
    }
    
    // 
    /**
     * Returns the index in state.assumeReps at which to put the new nodes
     * obtained by decomposing a top-level node.  If the node being decomposed was in state.assumeReps,
     * then we assume that it was at position oldIndex, has been removed, but state.firstAddedAssumption
     * has not been changed.  In that case, state.firstAddedAssumption is updated appropriately.
     * Otherwise, oldIndex should be set to -1 -- for example if the new nodes are obtained by
     * decomposing the goal.
     * 
     * @param oldIndex
     * @param initPos
     * @return
     */
    private int newAssumeRepsIndex(int oldIndex, int initPos ) {
        if (oldIndex >= state.firstAddedAssumption) {
            return oldIndex ;
        }
        if (oldIndex != -1) {
          state.firstAddedAssumption-- ;
        }
        int i = state.firstAddedAssumption ;
        while (   (i < state.assumeReps.size() ) 
               && (initPos >= state.assumeReps.elementAt(i).initialPosition) ) {
            i++ ;
        }
        
        return i;
    }

    /****************************************
     * THE TOP MENU BUTTONS.
     *****************************************/
    // NOT CLEAR IF THESE BUTTON VALUES SHOULD BE PUT IN DecompositionState
    // OR IF PERHAPS EVEN THE BUTTONS SHOULD BE PUT THERE.
    
    /**
     * The showContextButton is true iff decomposible assumptions coming 
     * from the context should be displayed.
     */
    private boolean showContextValue = SHOW_CONTEXT_DEFAULT;
    private Button showContextButton;
    
    /**
     * The useSufficesButton determines whether the created proof will use an
     * initial SUFFICES step to declare the newly created assumptions, or if
     * those assumptions will be put on each step of the proof in an
     * ASSUME/PROVE.
     */
    private boolean useSufficesValue = USE_SUFFICES_DEFAULT;
    private Button useSufficesButton; //

    /**
     * The useSufficesButton determines whether the created proof will use an
     * initial SUFFICES step to declare the newly created assumptions, or if
     * those assumptions will be put on each step of the proof in an
     * ASSUME/PROVE.
     */
    private boolean useCaseValue = USE_CASE_DEFAULT;
    private Button useCaseButton; //

    /**
     * The subexpressionButton determines if an occurrence of a user-defined
     * operator should be expanded by replacing it with its definition, or by
     * using subexpression names like Op(43)!2. In the initial implementation,
     * definitions that come from a different module are always expanded by
     * using subexpression names.
     */
    private boolean subexpressionValue = SUBEXPRESSION_DEFAULT;
    private Button subexpressionButton;

    /**
     * Record the state of the top menu's check buttons.
     */
    private void readButtons() {
        showContextValue = showContextButton.getSelection();
        useSufficesValue = useSufficesButton.getSelection();
        useCaseValue = useCaseButton.getSelection();
        subexpressionValue = subexpressionButton.getSelection();
    }

    /**
     * THE REAL EXECUTE METHOD
     * 
     * This method is called by a synchronous job launched in the execute method
     * to do most of the work of executing the Decompose Proof command.
     * 
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.
     *      ExecutionEvent)
     * 
     * @return
     * @throws ExecutionException
     */
    public Object realExecute() throws ExecutionException {
        // Activator.getDefault().logDebug("Decompose Proof Called");
         /**
         * Is set to the set of ASSUMEs of the selected step/theorem,
         * excluding inner ASSUME/PROVE assumptions.
         */
        Vector<SemanticNode> assumes = new Vector<SemanticNode>();

        /**
         * Is set to the goal of the selected step or theorem, which
         * may come from the context.  It is set to null if the goal
         * cannot be handled.
         */
        SemanticNode  goal = null ;  
        
        /**
         * The step from which the goal comes.
         */
        
        LevelNode goalStep = null ;
        /**
         * If goal is set to null, this describes why not in an error
         * message saying "Step has goal that comes from" + nullReason + "step".
         */
        String nullReason = "[This string should never be displayed]";
        
        /**
         * Is set to all prior facts asserted by the theorem or its steps
         * that could be used in proving the selected step.  (Empty if the
         * theorem itself is selected.)  It does not contain inner
         * ASSUME/PROVE assumptions
         */
        Vector <SemanticNode> contextAssumptions = new Vector<SemanticNode>() ;
        
        /**
         * For each assumption in contextAssumptions, the following two vectors
         * give the step from which the assumption comes and its name, which is
         * "" if it comes from  an unnamed step or the theorem itself.
         */     
        Vector <LevelNode> contextSteps = new Vector<LevelNode>() ;
        Vector <String> contextSources = new Vector<String> () ;
        // String[] blankLine = new String[] { "" };
        // String[] oneline = new String[] { "1" };
        
        
        /******************************************************************
         * Perform various checks to see if the command should be executed, and
         * possibly raise an error warning if it shouldn't.
         *******************************************************************/
        // Do nothing if already executing command.
        if (this.windowShell != null) {
            if (!this.windowShell.isDisposed()) {
                System.out.println("Command called when being executed.");
                return null;
            }
        }

        // Report an error if there are dirty modules.
        // This should not happen
        if (existDirtyModules()) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command", "There is an unsaved module.");
            return null;
        }

        // Pop up an error if the spec is not parsed.
        Spec spec = Activator.getSpecManager().getSpecLoaded();
        if (spec == null || spec.getStatus() != IParseConstants.PARSED) {
            MessageDialog
                    .openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "The spec status must be \"parsed\" to execute this command.");
            return null;
        }

        /*
         * The following text for finding the editor, document, selection, and
         * module is copied from other commands.
         */
        // The following should be a no-op, because the editor was already
        // found to be non-null.
        if (editor == null) {
            Activator.getDefault().logDebug(
                    "2nd call of getTLAEditorWithFocus returned null");
            return null;
        }
        editorIFile = ((FileEditorInput) editor.getEditorInput()).getFile();

        // The editor should not be dirty, so the following should be a no-op.
        if (editor.isDirty()) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "The module is dirty; this should not happen.");
            return null;
        }

        /**********************************************
         * Initialize the state of the decomposition.
         **********************************************/
        this.state = new DecompositionState();
        state.hasChanged = false;
        // state.chosenSplit = -1;
        // state.needsStepNumber = false;
        state.goalDefinitions = new StringSet();
        state.assumpDefinitions = new HashSet<String>();

        // selectedLocation is Location of selected region.
        Location selectedLocation = EditorUtil.getLocationAt(doc, offset,
                selection.getLength());

        /****************************************************
         * Set the `theorem' field.
         *****************************************************/
        TheoremNode[] allTheorems = moduleNode.getTheorems();
        theorem = null;
        int i = 0;
        String moduleFile = moduleNode.stn.getFilename();
        while ((theorem == null) & (i < allTheorems.length)) {
            if (allTheorems[i].stn.getFilename().equals(moduleFile)
                    && EditorUtil.lineLocationContainment(selectedLocation,
                            allTheorems[i].stn.getLocation())) {
                theorem = allTheorems[i];
            }
            i++;
        }

        if (theorem == null) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "The cursor is not in a theorem.");
            return null;
        }

        /****************************************************************
         * Initialize goal to the theorem's goal
         ****************************************************************/
        goal = theorem.getTheorem() ;
        if (goal instanceof AssumeProveNode) {
            goal = ((AssumeProveNode) goal).getProve();            
        }
        goalStep = theorem ;
        
        // Set declaredIdentifiers to all the defined or declared symbols
        // whose scope contains `theorem'
        this.declaredIdentifiers = 
                ResourceHelper.declaredSymbolsInScopeSet(
                this.moduleNode, theorem.stn.getLocation());

        
        /********************************************************************
         * Set the following fields: step,  proofLevel, proof. Add the necessary
         * declarations to this.declaredIdentifiers.  Also compute the following
         * two values.
         *********************************************************************/
        // ExprNode goal = null ;
        
        step = theorem;
        boolean notDone = true;
        /*
         * proofLevel is set to the level of the current proof, if there is one;
         * otherwise it is set to -1. This is tricky because for a proof node
         * that is a DefStepNode (which comes from a DEFINE step or a step of
         * the form Foo == INSTANCE...) or an InstanceNode (which comes from a
         * step that is a simple INSTANCE statement) from an unnumbered step,
         * the level number is nowhere in the semantic (or syntax) tree. So, we
         * have to keep checking proof steps until we find a step whose node is
         * not a DefStepNode or InstanceNode. If we don't find one, proofLevel
         * is set to -1. Fortunately, the chosen step can't be decomposed in
         * that case, so an error should be raised before any use is made of
         * proofLevel.
         * 
         * This represents a change made by LL on 8 Mar 2013. Before then,
         * stepLevel was called on pfsteps[0], causing a bug if pfsteps[0] was a
         * DefStepNode or InstanceNode.
         */
        proofLevel = -1;
        proof = step.getProof();
        while (notDone && (proof != null)
                && (proof instanceof NonLeafProofNode)) {
            LevelNode[] pfsteps = ((NonLeafProofNode) proof).getSteps();
            LevelNode foundLevelNode = null;
            i = 0;
            // The following step added by LL on 24 April 2013. Without
            // it, the added steps get the level number of 1 plus the
            // highest-level of the proof.
            proofLevel = -1;
            while ((foundLevelNode == null) && (i < pfsteps.length)) {
                if (    (proofLevel == -1) 
                    && !(pfsteps[i] instanceof DefStepNode)
                    && !(pfsteps[i] instanceof InstanceNode)) {
                   proofLevel = stepLevel(pfsteps[i]);
                }
                // Set currStepName to name of the current step.
                String currStepName = null ;
                if (pfsteps[i] instanceof TheoremNode) {
                  currStepName = getStepName((TheoremNode) pfsteps[i]) ;
                }

                if (EditorUtil.lineLocationContainment(selectedLocation,
                        pfsteps[i].stn.getLocation())) {
                    foundLevelNode = pfsteps[i];
                    

                    // pfsteps[i] is either the selected step
                    // or a step whose proof contains the selected step.
                    // Here's what must be done:
                    //   For a non-SUFFICES step:  
                    //     IF it's an ASSUME/PROVE:
                    //      - Add its NEW declarations to declaredIdentifiers.
                    //      - Add its other assumptions to either assumes or
                    //        context assumptions, depending on whether this is the
                    //        selected step.
                    //      - set goal to its PROVE formula
                    //     IF it's not an assume prove:
                    //       IF it's a CASE, add its formula to assumes or contextAssumptions.
                    //       IF it's a PICK, set goal to null.
                    //       IF it's a QED step, do nothing.
                    //       IF it's an ordinary formula, set goal to it.
                    //   For a SUFFICES step:
                    //       Set goal to null.
                    if (pfsteps[i] instanceof TheoremNode) {
                       TheoremNode thmNode = (TheoremNode) pfsteps[i];
                       ProofNode pfNode =  thmNode.getProof() ;
                       // Set isChosenStep true if pfsteps[i] has no proof.
                       // If pfsteps[i] is the chosen step, then either isChosenStep is true, 
                       // or else the user has chosen a step with a proof and an error will
                       // later be raised.
                       boolean isChosenStep = (pfNode == null) || (pfNode instanceof LeafProofNode) ;
                       if (!thmNode.isSuffices()) {
                           if (thmNode.getTheorem() instanceof AssumeProveNode) {
                              // ordinary ASSUME/PROVE
                              SemanticNode[] assumptions = ((AssumeProveNode) thmNode
                                      .getTheorem()).getAssumes();
                              for (int j = 0; j < assumptions.length; j++) {
                                  if (assumptions[j] instanceof NewSymbNode) {
                                      declaredIdentifiers
                                              .add(((NewSymbNode) assumptions[j])
                                                      .getOpDeclNode().getName()
                                                      .toString());
                                  } else {
                                      if (! (assumptions[j] instanceof AssumeProveNode)) {
                                        if (isChosenStep) {
                                            assumes.addElement(assumptions[j]) ;
                                        } else {
                                            contextAssumptions.addElement(assumptions[j]);
                                            contextSteps.addElement(thmNode) ;
                                            contextSources.addElement(currStepName);
                                        }
                                      }
                                  }
                              }
                              goal = ((AssumeProveNode) thmNode.getTheorem()).getProve();
                              goalStep = thmNode ;
                          } else {
                            // not SUFFICES or ASSUME/PROVE
                              SemanticNode newGoalSemNode = thmNode.getTheorem() ;
                              if (newGoalSemNode instanceof OpApplNode) {
                                  OpApplNode newGoal = (OpApplNode) newGoalSemNode ;
                                  UniqueString goalOpName = newGoal.getOperator().getName();
                                  if (goalOpName == ASTConstants.OP_pfcase) {
                                      if (isChosenStep) {
                                          assumes.addElement(newGoal.getArgs()[0]) ;
                                      } else {
                                          contextAssumptions.addElement(newGoal.getArgs()[0]);
                                          contextSteps.addElement(thmNode) ;
                                          contextSources.addElement(currStepName);
                                      }
                                  } else if (goalOpName == ASTConstants.OP_pick) {
                                      goal = null;
                                      nullReason = "PICK";
                                  } else if (goalOpName == ASTConstants.OP_have) {
                                      goal = null;
                                      nullReason = "HAVE";
                                  }else if (goalOpName == ASTConstants.OP_take) {
                                      goal = null;
                                      nullReason = "TAKE";
                                  }else if (goalOpName == null) {
                                      // I don't know what this is, so it must be weird.
                                      goal = null;
                                      nullReason = "weird";
                                  } else if (goalOpName == ASTConstants.OP_qed) {
                                      // do nothing
                                  }
                                  else {
                                      // an ordinary formula
                                      goal = newGoal ; 
                                      goalStep = thmNode ;
                                  }                           
                              } else {
                                  // Not an OpApplNode, so it's something weird.
                                  goal = null;
                                  nullReason = "weird";
                              }
                           }                        
                       } else {
                           // A SUFFICES step.
                           goal = null;
                           nullReason = "SUFFICES";
                         }
                    } // end of if (pfsteps[i] instanceof TheoremNode)
                    else { goal = null;
                           nullReason = "weird" ;
                    }
                } else {
                    // Selected step must come after this step.  Have the
                    // following cases:
                    // For a SUFFICES step:
                    //   If it's an ASSUME/PROVE then:
                    //     - Add its ASSUMEs to contextAssumptions
                    //     - Add its NEW declarations to declaredIdentifiers.
                    //     - Set goal to its PROVE formula
                    //   If it's not a SUFFICES step:
                    //     - Set goal to its formula.
                    //  For a non-SUFFICES step:
                    //    If it's a PICK step, then:
                    //      - Add its declared formulas to declaredIdentifiers.
                    //      - Add its body to contextAssumptions
                    //    If it's a TAKE step, then:
                    //      - Add its declared formulas to declaredIdentifiers.
                    //      - Set goal to null.
                    //    If it's a HAVE step, then:
                    //      - Add its formula to contextAssumptions
                    //      - Set goal to null.
                    //    If it's a WITNESS step, then set goal to null.
                    //    If it's just a plain formula, add it to contextAssumptions.
                    //    If it's a DEFINE or INSTANCE step, then add its definitions
                    //      to declaredIdentifiers.
                    // 
                    // Bug fixed by LL on 24 June 2014: Failed to add PICK step's
                    // introduced identifiers to declaredIdentifiers.
                    // 
                    if (pfsteps[i] instanceof TheoremNode) {
                        TheoremNode node = (TheoremNode) pfsteps[i];
                        if (node.isSuffices()) {
                           // For SUFFICES, must set goal to this node's goal
                           // and add any non-NEW assumptions to contextAssumptions.                           
                           if (node.getTheorem() instanceof AssumeProveNode) {
                                 goal = ((AssumeProveNode) node.getTheorem()).getProve() ;
                                 goalStep = node ;
                                 SemanticNode[] assumptions = ((AssumeProveNode) node
                                         .getTheorem()).getAssumes();
                                 for (int j = 0; j < assumptions.length; j++) {
                                     if (assumptions[j] instanceof NewSymbNode) {
                                         declaredIdentifiers
                                                 .add(((NewSymbNode) assumptions[j])
                                                         .getOpDeclNode().getName()
                                                         .toString());
                                     } else {
                                         // Non-NEW assumptions added to contextAssumptions.
                                         if (! (assumptions[j] instanceof AssumeProveNode)) {
                                           contextAssumptions.addElement(assumptions[j]) ;
                                           contextSteps.addElement(node) ;
                                           contextSources.addElement(currStepName) ;
                                         }
                                     }
                                 }
                           } else {
                               goal = (SemanticNode) node.getTheorem();
                               goalStep = node ;
                               if (! (goal instanceof OpApplNode)){
                                   goal = null ;
                                   nullReason = "weird";
                               }
                           }
                        } else if (node.getTheorem() instanceof OpApplNode) {
                            // Check if it's a $Pick step and if it is, add declared
                            // identifiers and add body to contextAssumptions.
                            OpApplNode oanode = (OpApplNode) node.getTheorem();
                            String operatorName = oanode.getOperator().getName().toString();

                            if (   operatorName.equals("$Pick")
                                || operatorName.equals("$Witness")
                                || operatorName.equals("$Take")) {
                                FormalParamNode[] fp = oanode
                                        .getUnbdedQuantSymbols();
                                
                                // Add body of PICK to contextAssumptions
                                if (operatorName.equals("$Pick")) {
                                    contextAssumptions.addElement(oanode.getArgs()[0]) ;
                                    contextSteps.addElement(node) ;
                                    contextSources.addElement(currStepName) ;
                                }
                                if (! operatorName.equals("$Witness")) {
                                    // add to declaredIdentifiers
                                    if (fp != null) {
                                        // This is an unbounded PICK or TAKE -- 
                                        //  e.g., PICK  x, y : exp
                                        for (int j = 0; j < fp.length; j++) {
                                            declaredIdentifiers.add(fp[j].getName()
                                                    .toString());
                                        }
                                    } else {
                                        // This is a bounded PICK or TAKE -- e.g., 
                                        // PICK x, y \in S, z \in T : exp
                                        FormalParamNode[][] fpn = oanode
                                                .getBdedQuantSymbolLists();
                                        for (int j = 0; j < fpn.length; j++) {
                                            for (int k = 0; k < fpn[j].length; k++) {
                                                declaredIdentifiers.add(fpn[j][k]
                                                        .getName().toString());
                                            }
                                        }
                                    }
                                    
                                    if (operatorName.equals("$Take")) {
                                        goal = null ;
                                        nullReason = "TAKE" ;
                                    }
                                } else {
                                    goal = null ;
                                    nullReason = "WITNESS" ;
                                }
                                

                            } else if (operatorName.equals("$Have")) {
                                goal = null ;
                                nullReason = "HAVE" ;
                                contextAssumptions.addElement(oanode.getArgs()[0]) ;
                                contextSteps.addElement(node) ;
                                contextSources.addElement(currStepName) ;           
                            } else if (! operatorName.equals("$Pfcase"))  {
                                // I think the only possibility left is for this to be 
                                // an ordinary formula.
                                contextAssumptions.addElement(oanode) ;
                                contextSteps.addElement(node) ;
                                contextSources.addElement(currStepName) ;
                            }
                        }
                    }

                    // It it's a DEFINE step, must add the defined
                    // operator names to declaredIdentifiers.
                    if (pfsteps[i] instanceof DefStepNode) {
                        OpDefNode[] defs = ((DefStepNode) pfsteps[i]).getDefs();
                        for (int j = 0; j < defs.length; j++) {
                            declaredIdentifiers.add(defs[j].getName()
                                    .toString());
                        }
                    }
                    // If its an INSTANCE step, must add the instantiated
                    // module's definitions.
                    if (pfsteps[i] instanceof InstanceNode) {
                        ResourceHelper.addDeclaredSymbolsInScopeSet(
                                declaredIdentifiers,
                                ((InstanceNode) pfsteps[i]).getModule(),
                                ResourceHelper.infiniteLoc);
                    }
                }

                i++;
            }
            if (foundLevelNode == null) {
                notDone = false;
            } else if (!(foundLevelNode instanceof TheoremNode)) {
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "The cursor is in a non-provable step.");
                return null;
            } else {
                step = (TheoremNode) foundLevelNode;
                proof = step.getProof();
            }
        }
        
        /**************************************************************
         * Check that the step has either no proof or a leaf proof.
         *************************************************************/
        if ((proof != null) && !(proof instanceof LeafProofNode)) {
            MessageDialog
                    .openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "You have selected a step that already has a non-leaf proof.");
            return null;
        }

        /**
         * Because of the poor organization of the code, there are two
         * edge cases not handled properly and must be handled here
         * as special cases.  The first is the case of the statement of
         * the theorem being the decomposed step.  The code for this case  
         * was cloned from the code executed above within the body 
         * of the
         * 
         *    if (!step.isSuffices())
         *    
         * statement which handles setting goal and assumes for a
         * decomposed step.
         * 
         * The second case not handled properly is that of the theorem 
         * statement being an ASSUME/PROVE and is not itself being 
         * decomposed.  In this cases, the theorem's ASSUMES must be 
         * prepended to contextAssumptions.
         */
        if (step == theorem) {
            if (step.getTheorem() instanceof AssumeProveNode) {
                // ordinary ASSUME/PROVE
                SemanticNode[] assumptions = ((AssumeProveNode) step
                        .getTheorem()).getAssumes();
                for (int j = 0; j < assumptions.length; j++) {
                    if (assumptions[j] instanceof NewSymbNode) {
                        declaredIdentifiers
                                .add(((NewSymbNode) assumptions[j])
                                        .getOpDeclNode().getName()
                                        .toString());
                        assumes.addElement(assumptions[j]) ;
                    } else {
                        if (! (assumptions[j] instanceof AssumeProveNode)) {
                         assumes.addElement(assumptions[j]) ;
                        }
                    }
                }
                goal = ((AssumeProveNode) step .getTheorem()).getProve();
                goalStep = step ;

           } else {
            // not  ASSUME/PROVE
            SemanticNode newGoalSemNode = step.getTheorem() ;
             if (newGoalSemNode instanceof OpApplNode) {
                OpApplNode newGoal = (OpApplNode) newGoalSemNode ;
                UniqueString goalOpName = newGoal.getOperator().getName();
                if (goalOpName == ASTConstants.OP_pfcase) {
                    goal = newGoal.getArgs()[0] ;
                } else if (goalOpName == ASTConstants.OP_pick) {
                    goal = null;
                    nullReason = "PICK";
                } else if (goalOpName == null) {
                    // I don't know what this is, so it must be weird.
                    goal = null;
                    nullReason = "weird";
                } else if (goalOpName == ASTConstants.OP_qed) {
                    // do nothing
                }
                else {
                    // an ordinary formula
                    goal = newGoal ; 
                    goalStep = step ;
                }                           
             } else {
                // Not an OpApplNode, so it's something weird.
                goal = null;
                nullReason = "weird";
             }
           }
        } else { // step != theorem
            if (theorem.getTheorem() instanceof AssumeProveNode) {
                SemanticNode[] thmAssumps = 
                    ((AssumeProveNode) theorem.getTheorem()).getAssumes() ;
                // assumption inserted as the k-th assumption in contextAssumptions
                int k = 0 ;
                for (int j = 0; j < thmAssumps.length; j++) {
                    if (thmAssumps[j] instanceof NewSymbNode) {
                        declaredIdentifiers
                                .add(((NewSymbNode) thmAssumps[j])
                                        .getOpDeclNode().getName()
                                        .toString());
                    } else {
                        contextAssumptions.insertElementAt(thmAssumps[j], k) ;  
                        contextSteps.insertElementAt(theorem.getTheorem(), k) ;
                        contextSources.insertElementAt(null, k) ;
                        k++ ;
                    }                    
                }
            }
        }
        /**
         * Found the and processed step. Raise an error if the step's goal can't 
         * be handled.
         */
        if (goal == null) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "Cannot decompose because goal is from a " + nullReason + " step.");
            return null;
        }
        /*
         * set proofLevelString
         */
        int level = this.proofLevel;
        if (level < 0) {
            level = 0;
        }
        proofLevelString = "<" + (level + 1) + ">";

        /*************************************************************
         * Set stepNumber and stepColumn.  
         * 
         * Most of this code has been cloned to implement the
         * getStepName method.  It should be replaced by a call
         * to that method, but if it ain't broke, why fix it?
         ************************************************************/
        SyntaxTreeNode nd = (SyntaxTreeNode) step.stn;
        if (step == theorem) {
            stepNumber = null;
        } else {
            stepNumber = nd.getHeirs()[0].image.toString();
            if (stepNumber.indexOf('>') == stepNumber.length() - 1) {
                stepNumber = null;
            } else {
                // Need to remove punctuation after the number:
                i = stepNumber.indexOf('>') + 1;
                while ((i < stepNumber.length() && (Character
                        .isLetterOrDigit(stepNumber.charAt(i)) || (stepNumber
                        .charAt(i) == '_')))) {
                    i++;
                }
                if (i < stepNumber.length()) {
                    stepNumber = stepNumber.substring(0, i);
                }
            }
        }
        stepColumn = nd.getLocation().beginColumn();


        /**************************************************************
         * Set stepRep
         *************************************************************/
        try {
            stepRep = new NodeRepresentation(doc, step);
        } catch (BadLocationException e) {
            e.printStackTrace();
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "An error that should not happen has occurred in "
                            + "line 1678 of DecomposeProofHandler.");
            return null;
        }

        // MOVED THE SETTING OF assumes, goal to the main loop above.
        /**************************************************************
         * Set state.assumeReps,  and state.goalRep
         *************************************************************/
            state.assumeReps = new Vector<NodeRepresentation>();

            // Add to state.assumeReps the decomposable context assumptions.
            for (i = 0; i < contextAssumptions.size(); i++) {
                NodeRepresentation contextStepRep = null ;
                try {
                    contextStepRep = new NodeRepresentation(doc, contextSteps.elementAt(i));
                } catch (BadLocationException e) {
                    e.printStackTrace();
                    MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "An error that should not happen has occurred in "
                                    + "line 1698 of DecomposeProofHandler.");
                    return null;
                }
                NodeRepresentation nodeRep = contextStepRep.subNodeRep(contextAssumptions.elementAt(i),
                        state.assumeReps, null, null, null, true);
                nodeRep.contextStepName = contextSources.elementAt(i) ;
                if ((nodeRep.decomposition != null) 
                        && (nodeRep.nodeSubtype != NodeRepresentation.IMPLIES_TYPE)
                        // Following conjunct added 9 Dec 2014
                        && (nodeRep.nodeSubtype != NodeRepresentation.FORALL_TYPE)) {
                    nodeRep.initialPosition = state.assumeReps.size() ;
                    state.assumeReps.addElement(nodeRep);
                    state.numberOfContextAssumptions++;                  
                }
            }

            // Add to state.assumeReps the assumptions in assumes,
            // which come from the step being decomposed that is either
            // an ASSUME/PROVE or a CASE step.  Set hasAssumes true
            // iff there is such an assumption
            hasAssumes = false;
            if (assumes.size() > 0) {
                hasAssumes = true ;
            }
            for (i = 0; i < assumes.size(); i++) {
                NodeRepresentation nodeRep = stepRep.subNodeRep(assumes.elementAt(i),
                        state.assumeReps, null, null, null, true);
                nodeRep.contextStepName = this.stepNumber ;
// I THINK THE FOLLOWING COMMENT IS OBSOLETE:
// If we want to add an option not to show non-decomposible assumptions, here's
// the code to implement it. 
//                if (nodeRep.decomposition != null) {
                    nodeRep.initialPosition = state.assumeReps.size() ;
                    state.assumeReps.addElement(nodeRep);                  
//                }
            }
            // Initially there are no added assumptions, so state.firstAddedAssumption
            // points to the position after the end of state.assumeReps.
            state.firstAddedAssumption = state.assumeReps.size();
            
           // Similarly to the handling of contextAssumptions, we create the NodeRepresentation
           // of the current goal from the NodeRepresentation of goalStep.
           NodeRepresentation goalStepRep = null;
        try {
            goalStepRep = new NodeRepresentation(doc, goalStep);
        } catch (BadLocationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "An error that should not happen has occurred in "
                            + "line 1749 of DecomposeProofHandler.");
            return null;
        }
           state.goalRep = goalStepRep.subNodeRep(goal, null, null, null, null, false);
           state.goalRep.initialPosition = Integer.MAX_VALUE - 42;
           state.goalRep.fromGoal = true ;
         // END OF SETTING state.assumeReps and state.goalRep

        /***************************************************************************
         * Make the editor read-only.
         ***************************************************************************/
        // The following method is deprecated because it is actually possible to
        // use it, so it has been replaced by something that requires a PhD in
        // Eclipse to figure out how to use. The command
        //
        // EditorUtil.setReadOnly(editorIFile, true);
        //
        // that has worked in other places in the Toolbox code seems to work
        // here only occasionally. This being modern 21st century code, I have
        // the choice of reading 10^6 lines of code to figure out what is going
        // on, or doing what seems to work.
        editorIFile.setReadOnly(true);
        raiseWindow();
        // Activator.getDefault().logDebug(
        // "Finished Decompose Proof Handler execute");

//NodeTextRep ntr = state.goalRep.toNodeTextRep() ;
//OpApplNode oan = (OpApplNode) state.goalRep.semanticNode.getChildren()[0] ;
//ntr = prependToOpName(ntr, state.goalRep.semanticNode, 
//        oan, "Foo!Bar!") ;
//System.out.println(ntr.toString()) ;

//NodeTextRep ntr = state.goalRep.toNodeTextRep() ;
//OpDeclNode[] formalParams = new OpDeclNode[] 
//   { (OpDeclNode) ((OpApplNode)
//         state.goalRep.semanticNode.getChildren()[0]).getOperator()  };
//String[] arguments = new String[] {"SubForA_x"};  
//ExprNode sn = (ExprNode) state.goalRep.semanticNode ;
//SemanticNode[] argNodes = new SemanticNode[] { null };
//NodeTextRep newNtr = instantiateInNodeText(
//   formalParams, arguments, argNodes, sn, ntr) ;
//System.out.println(newNtr.toString());

//SemanticNode sn = state.goalRep.semanticNode;
//ExprOrOpArgNode[] ean = ResourceHelper.getUsesOfUserDefinedOps(sn);
        
 // String[] s = DefPrefixes("foo!bar!") ;
 
//NodeTextRep ntr = state.goalRep.toNodeTextRep() ;
//OpApplNode oan = (OpApplNode) state.goalRep.semanticNode ;
//ntr = renameInNodeText (oan, ntr, "", "foo!bar!" ) ;
//System.out.println(ntr.toString()) ;

//String[] ss = "foo".split("!") ;
        return null;
    }

    /**
     * Returns the name of a proof step, or null if it has no name (but only
     * a level).  Thus for the step
     * 
     *     <3>4ax. 1+1=2
     *     
     * it returns "<3>4ax", but returns null for the step:
     * 
     *     <3> 2+2=5
     *     
     * This code cloned from the code that sets the stepNumber and
     * stepColumn fields.  That code should be replaced by a call
     * of this method.
     * @param step
     * @return
     */
    static String getStepName (TheoremNode step) {
        SyntaxTreeNode nd = (SyntaxTreeNode) step.stn;
        String result = nd.getHeirs()[0].image.toString();
        if (result.indexOf('>') == result.length() - 1) {
            result = null;
        } else {
            // Need to remove punctuation after the number:
            int i = result.indexOf('>') + 1;
            while ((i < result.length() && (Character
                    .isLetterOrDigit(result.charAt(i)) || (result
                    .charAt(i) == '_')))) {
                i++;
            }
            if (i < result.length()) {
                result = result.substring(0, i);
            }
        }
        return result ;
    }
    /**
     * This method is called when the user issues a the Decompose Proof command.
     * It launches a synchronous task that calls realExecute() to do most of the
     * work. However, before doing that, it sets various fields of the
     * DecomposeProofHandler object that can't be set from the separate
     * thread.
     * 
     * This running of a separate task was done to allow the command to ask the
     * user if he wants to save and parse dirty modules, and to not run the code
     * in realExecute() before those modules were actually saved and parsed. I
     * tried all sorts of things until coming up with this code, which seems to
     * work. However, previous versions seemed to work until bugs
     * appeared--perhaps because the weather changed in Bangladesh. So, I have
     * no idea if it will still work when the monsoons come.
     * 
     * Apparently the monsoons came, and the race condition re-appeared.
     * However, so far, its only effect seems to be a race between two
     * executions of the parser, which can make the command fail and may produce
     * a bogus parsing error. Of course, when the monsoons stop, some other
     * failure mode may appear.
     * 
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.
     *      ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {
        /*******************************************************************
         * Set the following fields: doc, text, selectionProvider, selection,
         * offset, moduleNode.
         ******************************************************************/
        this.editor = EditorUtil.getTLAEditorWithFocus();
        this.doc = editor.getDocumentProvider().getDocument(
                editor.getEditorInput());
        this.selectionProvider = editor.getSelectionProvider();
        this.selection = (TextSelection) selectionProvider.getSelection();
        this.offset = selection.getOffset();

        // Get the module.
        String moduleName = editor.getModuleName();
        this.moduleNode = ResourceHelper.getModuleNode(moduleName);

        // Initialize moduleNameToDoc
        moduleNameToDoc = new Hashtable<String, IDocument>() ;
        moduleNameToDoc.put(this.moduleNode.getName().toString(), this.doc) ;

        /**
         * The Following code copied from ProverHelper.
         */

        boolean proceed = UIHelper.promptUserForDirtyModules();
        if (!proceed) {
            // the user cancelled
            return null;
        }

        if (editor == null) {
            Activator.getDefault().logDebug(
                    "getTLAEditorWithFocus returned null");
            return null;
        }
        editorIFile = ((FileEditorInput) editor.getEditorInput()).getFile();

        ParseResult parseResult = ResourceHelper
                .getValidParseResult(editorIFile);

        if (parseResult == null) {
            /*
             * The following comments taken from ProverJob.initializeFields,
             * from which the code here was cloned.
             * 
             * Its necessary to call this parsing within the job's run method.
             * Its a bad idea to have two calls to SANY executing at the same
             * time, and its possible for a launch of the prover to trigger
             * background parsing. For example, the user might have dirty
             * editors open when launching the prover. He will be prompted to
             * save them. This could trigger background parsing. The run method
             * will not be executed while the background parsing completes. This
             * ensures that the following parsing will not occur while the
             * background parsing executes.
             */
            parseResult = new ModuleParserLauncher().parseModule(editorIFile,
                    new NullProgressMonitor());
        }

        /**
         * ProverHelper at this point schedules a new job. I couldn't get that
         * to work right, so I tried a runnable.
         */
        DecomposeProofRunnable runnable = new DecomposeProofRunnable(this);

        UIHelper.runUISync(runnable);
        return null;
    }

    /**
     * Enabled state is based upon whether the spec has been parsed. (https://github.com/tlaplus/tlaplus/issues/243)
     */
    @Override
	public void setEnabled(Object context) {
		final Spec spec = Activator.getSpecManager().getSpecLoaded();

		setBaseEnabled(spec.getStatus() == IParseConstants.PARSED);
	}

    /**
     * The Runnable class extension for running the realExecute() method.
     * 
     * @author lamport
     * 
     */
    public class DecomposeProofRunnable implements java.lang.Runnable {
        DecomposeProofHandler handler;

        DecomposeProofRunnable(DecomposeProofHandler h) {
            handler = h;
        }

        public void run() {
            try {
                handler.editor = EditorUtil.getTLAEditorWithFocus();
                handler.doc = editor.getDocumentProvider().getDocument(
                        editor.getEditorInput());
                handler.selectionProvider = editor.getSelectionProvider();
                handler.selection = (TextSelection) selectionProvider
                        .getSelection();
                handler.offset = selection.getOffset();

                // Get the module.
                String moduleName = editor.getModuleName();
                handler.moduleNode = ResourceHelper.getModuleNode(moduleName);

                handler.realExecute();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * METHODS FOR DISPLAYING THE COMMAND'S WINDOW
     */

    // Note: Experimentation seems to show that horizontalSpan doesn't apply to
    // a Label or a Button, so I've been putting the Label or Button inside a
    // composite to do that.
    private void raiseWindow() {
//if ((state.numberOfContextAssumptions > state.assumeReps.size())) {
//    return ;
//}
        if ((windowShell != null) && (!windowShell.isDisposed())) {
            location = windowShell.getLocation();
            windowShell.close();
            windowShell.dispose();
        }
        Shell topshell = UIHelper.getShellProvider().getShell();

        // Since minimizing the window does something weird--namely,
        // makes it contain just the top bar and puts it in a corner
        // of the screen--we create a resizable window with only a
        // close button.
        windowShell = new Shell(topshell, SWT.CLOSE | SWT.TITLE | SWT.RESIZE);
        windowShell.setText("Decompose Proof");
        windowShell.addDisposeListener(new WindowDisposeListener(this));
        Composite shell = new Composite(windowShell, SWT.NONE);
        GridLayout gridLayout = new GridLayout(3, false);
        shell.setLayout(gridLayout);
        /**
         * Display the top-line window
         */
        // topMenu is a composite containing the stuff on the menu line.
        Composite topMenu = new Composite(shell, SWT.NONE);
        gridLayout = new GridLayout(7, false); 
           // was 5 then 6.  Needs to be 7 because of invisible subexpressionButton.
        gridLayout.marginBottom = 0;
        topMenu.setLayout(gridLayout);
        GridData gridData = new GridData();
        gridData.horizontalSpan = 3;
        topMenu.setLayoutData(gridData);

        // Display "Back Button"
        Button backButton = new Button(topMenu, SWT.PUSH);
        setupMenuButton(backButton, BACK_BUTTON, "\u2190");
        backButton.setFont(JFaceResources.getFontRegistry().get(
                JFaceResources.HEADER_FONT));
        backButton.setEnabled(state.previousState != null);

        // Display "Replace Step" button
        // The enabling condition for the button was changed by LL on 23 Aug
        // 2014
        // to the following: This button is enabled iff the following are all
        // true
        //
        // - some change has been made
        // - A Case split has not been chosen. (If it has, then
        // it has an enabled P button.
        // - The last decomposition action (as opposed to a Back
        // action or movement of an assumption up or down) was
        // NOT clicking on an /\ decomposition button
        // (of an assumption).
        //
        // One should click on an /\ decomposition button
        // only to reveal a \E or \/ decomposition. The third
        // condition doesn't insure this, since the user could
        // perform two separate /\ decomposition and only
        // do a further decomposition on one of the results. But,
        // it approximates that condition.
        Button replaceButton = new Button(topMenu, SWT.PUSH);
        setupMenuButton(replaceButton, PROVE_BUTTON, "P");
        replaceButton.setFont(JFaceResources.getFontRegistry().get(
                JFaceResources.HEADER_FONT));
        replaceButton.setEnabled(state.hasChanged && (! state.splitChosen())
        /* && (state.andSplitEnd == -1) removed with 23 Aug 2014 changes. */
        );

        
        // Display "Show Context" checkbox.
        showContextButton = new Button(topMenu, SWT.CHECK);
        setupCheckButton(showContextButton, "Show Context");
        showContextButton.setSelection(showContextValue);
        // This checkbox needs a listener to toggle the display of the
        // context assumptions.
        showContextButton.addSelectionListener(new DecomposeProofButtonListener(this,
                new Integer(SHOW_CONTEXT_BUTTON), MENU));


        // Display "Use SUFFICES" checkbox.
        useSufficesButton = new Button(topMenu, SWT.CHECK);
        setupCheckButton(useSufficesButton, "Use SUFFICES");
        useSufficesButton.setSelection(useSufficesValue);

        // Display "Use CASE" checkbox.
        useCaseButton = new Button(topMenu, SWT.CHECK);
        setupCheckButton(useCaseButton, "Use CASE");
        useCaseButton.setSelection(useCaseValue);

        // Display checkbox to choose whether to expand definitions with
        // subexpression names.
        subexpressionButton = new Button(topMenu, SWT.CHECK);
        setupCheckButton(subexpressionButton, "Use subexpression names");
        subexpressionButton.setSelection(subexpressionValue);
        gridData = new GridData();
        gridData.horizontalAlignment = GridData.FILL;
        gridData.grabExcessHorizontalSpace = true;
        subexpressionButton.setLayoutData(gridData);
        // Hide the option. See comments at beginning of file.
        subexpressionButton.setVisible(false);

        // Display Help button that should raise help page for this
        // dialog window. I wish I knew how to move the button to
        // the right edge of the window. But it's been a mere 36
        // years since Knuth invented the idea of expandable glue,
        // so we can't expect the Eclipse people to have heard of it
        // yet.  However, this seems to produce a reasonable approximation.
        Button helpButton = HelpButton.helpButton(topMenu,
                "prover/decompose.html");
        gridData = new GridData();
        gridData.horizontalIndent = 20;
        helpButton.setLayoutData(gridData);

        /**************************************************************
         * Display the ASSUME Section
         **************************************************************/
        // Display the "ASSUME", which must be put in a
        // composite because it spans multiple rows, and it appears
        // that a Label can't do that.
        Label assumeLabel ;
//        gridData = new GridData();
//        gridData.horizontalSpan = 3;
//        Label assumeLabel = new Label(shell, SWT.NONE);
//        assumeLabel.setText("ASSUME");
//        assumeLabel.setFont(JFaceResources.getFontRegistry().get(
//                JFaceResources.HEADER_FONT));
//        assumeLabel.setLayoutData(gridData);
        if (state.assumeReps != null) {
            addAssumptionsToComposite(state.assumeReps, shell);
        }

        /**********************************************************
         * Display the Goal
         **********************************************************/
        // Display the "PROVE", which must be put in a
        // composite because it spans multiple rows, and it appeared
        // that a Label can't do that. However, for some reason it
        // now appears that a label can do that.
        gridData = new GridData();
        gridData.horizontalSpan = 3;
        assumeLabel = new Label(shell, SWT.NONE);
        assumeLabel.setLayoutData(gridData);
        assumeLabel.setText("PROVE");
        assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                JFaceResources.HEADER_FONT));
        String labelText = null;

        // isProver = true means clicking on the button produces the proof.
        boolean isProver = false;
        // Set disable to disable the button, which should be done iff
        // decomposition of an assumption has been started and this is
        // an AND node.
        boolean disable = false;
        switch (state.goalRep.nodeSubtype) {
        case NodeRepresentation.AND_TYPE:
            labelText = "/\\";
            isProver = true;
            disable = (state.splitChosen()) ;
            break;
        case NodeRepresentation.FORALL_TYPE:
            labelText = "\\A";
            // We disable \A decomposition when an OR-split has been 
            // made because it will produce a name conflict if one of 
            // the \A variables occurs (bound) in the OR-split.  This 
            // could be avoided by making the forAllAction() method 
            // smart enough to do the necessary renaming.  A simpler 
            // thing to implement would be to add code here that sets 
            // disable true only if there actually is such a name conflict.
            disable = state.splitChosen() ;
            break;
        case NodeRepresentation.IMPLIES_TYPE:
            labelText = "=>";
            break;
        default:
            labelText = null;
        }
        if (labelText != null) {
            Button goalButton = new Button(shell, SWT.PUSH);
            setupActionButton(goalButton, state.goalRep, labelText);
            goalButton.setEnabled(!disable);
        } else {
            assumeLabel = new Label(shell, SWT.NONE);
            assumeLabel.setText("  ");
        }

        // Add a spacer between the button and the formula
        Composite comp;
        comp = new Composite(shell, SWT.NONE);
        gridLayout = new GridLayout(1, false);
        comp.setLayout(gridLayout);
        if (isProver && !disable) {
            assumeLabel = new Label(comp, SWT.NONE);
            assumeLabel.setText("P");
            assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                    JFaceResources.HEADER_FONT));
        }
        comp.setSize(0, 5);

        assumeLabel = new Label(shell, SWT.NONE);
        assumeLabel
                .setText(stringArrayToString(state.goalRep.primedNodeText()));
        gridData = new GridData();
        gridData.verticalAlignment = SWT.TOP;
        assumeLabel.setLayoutData(gridData);

        // The following sets the font to be the Toolbox editor's text font.
        assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                JFaceResources.TEXT_FONT));
        shell.pack();
        // Point shellSize = shell.getSize();
        windowShell.pack();
        windowShell.update();
        if (this.location != null) {
            windowShell.setLocation(this.location);
        }
        windowShell.open();

        /***************************************************************************
         * For some reason, reraising the window seems to cause the editor to
         * become writable, so we make it read-only again.
         ***************************************************************************/
        // See the comments on the following command where it is used in the
        // execute method.
        editorIFile.setReadOnly(true);
    }

    /**
     * This method assumes that `composite' is a composite with a gridlayout
     * having 3 columns. It populates it with the buttons and stuff for an
     * assumptions list to go in the Decompose Proof window. It is called only
     * by RaiseWindow to produce the top-level list of assumptions, with
     * nodeRepVector equal to assume
     * 
     * @param nodeRepVector
     * @param composite
     */
    void addAssumptionsToComposite(Vector<NodeRepresentation> nodeRepVector,
            Composite composite) {

        // This code was moved from a place in which the following variables
        // were declared. Their original values are irrelevant here.
        Composite comp;
        GridData gridData;
        GridLayout gridLayout;
        Label assumeLabel;

        /*************************************************************
         * Displaying the assumptions.
         * 
         * First, Set assumeWidth to the number of characters in the widest line
         * among all the lines in the assumptions.
         **************************************************************/
        int assumeWidth = 0;
        for (int i = 0; i < nodeRepVector.size(); i++) {
            for (int j = 0; j < nodeRepVector.elementAt(i).nodeText.length; j++) {
                assumeWidth = Math.max(assumeWidth,
                        nodeRepVector.elementAt(i).nodeText[j].length());
            }
        }

        
         /**
         * Add the assumptions to the composite.
         */
        
         // We first set haveContextAssumpsToDisplay to true
         // iff there is at least one context assumption to be
         // displayed, and then add the "CONTEXT ASSUMPTIONS" heading
         // iff it is true.
         boolean haveContextAssumpsToDisplay = false ;
         for (int i = 0; i < state.numberOfContextAssumptions; i++) {
             if (displayContextAssump(nodeRepVector.elementAt(i), i)) {
                 haveContextAssumpsToDisplay = true ;
             }
         }
         
         if (haveContextAssumpsToDisplay) {
           gridData = new GridData();
           gridData.horizontalSpan = 3;
           assumeLabel = new Label(composite, SWT.NONE);
           assumeLabel.setText("CONTEXT ASSUMPTIONS");
           assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                   JFaceResources.HEADER_FONT));
           assumeLabel.setLayoutData(gridData);
         }
        
        for (int i = 0; i < nodeRepVector.size(); i++) {               
            if (i == state.numberOfContextAssumptions) {
                // ADD "ASSUME" heading
                gridData = new GridData();
                gridData.horizontalSpan = 3;
                assumeLabel = new Label(composite, SWT.NONE);
                assumeLabel.setText("ASSUME");
                assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                        JFaceResources.HEADER_FONT));
                assumeLabel.setLayoutData(gridData);
            }   
            if (i == state.firstAddedAssumption) {
                // ADD ----- splitting added assumptions from original ones.
                gridData = new GridData();
                gridData.horizontalSpan = 3;
                assumeLabel = new Label(composite, SWT.NONE);
                assumeLabel.setText("    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
                assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                        JFaceResources.HEADER_FONT));
                assumeLabel.setLayoutData(gridData);
             }
            
            NodeRepresentation aRep = nodeRepVector.elementAt(i);

            // We display aRep iff it is non-context assumption that
            // should be displayed (which is a complicated decision)
            // or it is a context assumption that should be displayed
            // (which is simple because most of the context assumptions
            // that shouldn't be displayed don't appear in nodeRepVector)
            if (  ((i >= state.numberOfContextAssumptions) 
                       && displayNonContextAssump(aRep, i))
                || ((i < state.numberOfContextAssumptions) 
                       && displayContextAssump(aRep, i))) {
              // We should display aRep  
              //
              if (aRep.nodeType != NodeRepresentation.OR_DECOMP) {
                  // This is an ordinary assumption (and Expression or NEW
                  // node).
                  // assumeLabel = new Label(comp, SWT.NONE);
                  /*************************************************************
                   * Add the button or blank area to the first column.
                   *************************************************************/
                  String labelText = null;
                  
                  // set false if button to be disabled
                  boolean enable = true ;
                  // The null test is because created NEW nodes have null
                  // semanticNode fields.
                  if ((aRep.semanticNode != null)
                          && (aRep.semanticNode.getKind() == ASTConstants.OpApplKind)) {
                      switch (aRep.nodeSubtype) {
                      case NodeRepresentation.AND_TYPE:
                          labelText = "/\\";
                          
                          // In an attempt to allow /\ decompositions to occur for
                          // \E after a case-split had been chosen, the following
                          // statement was originally
                          //    enabled == conjIsDecomposable((OpApplNode) aRep.semanticNode) ;
                          // However, this didn't work because conjIsDecomposible assumes
                          // that its input is a conjunction and not an occurrence of
                          // a defined operator whose definition is a conjunction,
                          // which may be the case here.  So, we just disable
                          // /\-decomposition after a case-split is chosen.  The user
                          // can just do the /\-decomposition before the case split.
                          //
                          enable = ! state.splitChosen() ;
                  
                           break;
                      case NodeRepresentation.OR_TYPE:
                      case NodeRepresentation.SQSUB_TYPE:
                          labelText = "\\/";
                          enable = ! state.splitChosen() ;
                          break;
                      case NodeRepresentation.EXISTS_TYPE:
                          labelText = "\\E";
                          break;
                      default:
                          labelText = null;
                      }
                  }
                  if (labelText != null) {
                      /*************************************************************
                       * Add a button
                       *************************************************************/
                      Button button = new Button(composite, SWT.PUSH);
                      setupActionButton(button, nodeRepVector.elementAt(i),
                              labelText);
                      if (!enable) { 
                          button.setEnabled(false);
                      }
                  } else {
                      /*************************************************************
                       * Add a blank area.
                       *************************************************************/
                      comp = new Composite(composite, SWT.NONE);
                      gridLayout = new GridLayout(1, false);
                      comp.setLayout(gridLayout);
                      assumeLabel = new Label(comp, SWT.NONE);
                      assumeLabel.setText("  ");
                      gridData = new GridData();
                      gridData.horizontalIndent = 25;
                      comp.setLayoutData(gridData);
                  }
                  comp = new Composite(composite, SWT.NONE);
                  gridLayout = new GridLayout(1, false);
                  comp.setLayout(gridLayout);
                  comp.setSize(0, 5);
              
                  /********************************************************************
                   * Add the text of the clause, preceded by appropriate up/down
                   * arrows for a node that comes from an AND-SPLIT. Combine it
                   * with the next node if its onSameLineAsNext field is true
                   * (which implies it and the next node are NEW nodes.
                   ********************************************************************/
                  comp = new Composite(composite, SWT.NONE);
                  gridLayout = new GridLayout(3, false);
                  comp.setLayout(gridLayout);
                  // Add arrow buttons if necessary
// UP-DOWN ARROWS REMOVED
//                  if ((state.chosenSplit == -1) && (state.andSplitBegin <= i)
//                          && (i <= state.andSplitEnd)) {
//                      Button arrowButton = new Button(comp, SWT.ARROW | SWT.UP);
//                      arrowButton
//                              .addSelectionListener(new ArrowSelectionListener(i,
//                                      SWT.UP, this));
//                      gridData = new GridData();
//                      gridData.verticalAlignment = SWT.TOP;
//                      arrowButton.setLayoutData(gridData);
//                      if (i == state.andSplitBegin) {
//                          arrowButton.setEnabled(false);
//                      }
//                      arrowButton = new Button(comp, SWT.ARROW | SWT.DOWN);
//                      arrowButton
//                              .addSelectionListener(new ArrowSelectionListener(i,
//                                      SWT.DOWN, this));
//              
//                      gridData = new GridData();
//                      gridData.verticalAlignment = SWT.TOP;
//                      arrowButton.setLayoutData(gridData);
//                      if (i == state.andSplitEnd) {
//                          arrowButton.setEnabled(false);
//                      }
//                  }
              
                  assumeLabel = new Label(comp, SWT.BORDER); // SWT.NONE);
                  String text = stringArrayToString(nodeRepVector.elementAt(i)
                          .primedNodeText());
                  // Combine this with following NEW nodes if necessary
                  while (nodeRepVector.elementAt(i).onSameLineAsNext) {
                      i++;
                      text = text
                              + ", "
                              + stringArrayToString(nodeRepVector.elementAt(i).nodeText);
              
                  }
                  assumeLabel.setText(text);
                  // Set the font to be the editors main text font.
                  assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                          JFaceResources.TEXT_FONT));
                  gridData = new GridData();
                  // I have no idea why (undoubtedly a feature that no one has
                  // ever bothered to document), but the following statement did
                  // not have any effect before I added the new composite between
                  // the
                  // button and it. Now it can be used to add positive or negative
                  // space
                  // to the left of the label.
                  gridData.horizontalIndent = 0;
                  gridData.verticalAlignment = SWT.TOP;
                  gridData.horizontalAlignment = SWT.LEFT;
                  assumeLabel.setLayoutData(gridData);
              } else {
                  // This is an OR_DECOMP node.
                  // Add a P button and a P
                  //
                  Button goalButton = new Button(composite, SWT.PUSH);
                  setupActionButton(goalButton, aRep, "P");
                  gridData = new GridData();
                  gridData.horizontalIndent = 15;
                  goalButton.setLayoutData(gridData);
              
                  goalButton.setFont(JFaceResources.getFontRegistry().get(
                          JFaceResources.HEADER_FONT));
              
                  // Add a spacer between the button and the cases
                  comp = new Composite(composite, SWT.NONE);
                  gridLayout = new GridLayout(1, false);
                  comp.setLayout(gridLayout);
              
                  // inner is the composite that contains the CASEs
                  Composite inner = new Composite(composite, SWT.NONE);
                  gridLayout = new GridLayout(2, false);
                  inner.setLayout(gridLayout);
              
                  for (int j = 0; j < aRep.children.size(); j++) {
                      assumeLabel = new Label(inner, SWT.NONE);
                      assumeLabel.setText("CASE");
                      assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                              JFaceResources.TEXT_FONT));
                      Composite caseComp = new Composite(inner, SWT.BORDER); // SWT.NONE)
                                                                             // ;
                      gridLayout = new GridLayout(3, false);
                      caseComp.setLayout(gridLayout);
                      addCaseToComposite(aRep.children.elementAt(j), caseComp);
                      gridData = new GridData();
                      gridData.verticalAlignment = SWT.TOP;
                      caseComp.setLayoutData(gridData);
              
                  }
              }
         } // end if (this should be displayed)
        }
    }
    
    /**
     * This returns true iff we should display a context assumption 
     * rep = state.assumeReps(i).  It equals:
     *
     *   \/ i = chosenSplit
     *   \/ rep.isCreated = true
     *   \/ /\ state.chosenSplit =  -1
     *      /\ 
     *      /\ showContextValue = true
     *      
     * Note that any of the first three disjunctions can be true when 
     * showContextValue is false because it was set to false after 
     * a context assumption was decomposed.
     * @param rep
     * @param i
     * @return
     */
    boolean displayContextAssump(NodeRepresentation rep, int i) {
        return   //  (i == state.chosenSplit) ||
                   rep.isCreated
// UP-DOWN ARROWS REMOVED
//                || (    (state.andSplitBegin <= i)
//                     && (i <= state.andSplitEnd) )
                || (    (! state.splitChosen())
//                     && (state.andSplitBegin == -1)
                     && showContextValue ) ;
    }
    
    /**
     * This returns true iff we should display an assumption 
     * rep = state.assumeReps(i) from the selected step.  Unlike for
     * context assumptions, we display not only an assumption that
     * is now decomposable, but also one that would be decomposable
     * if an OR-decomposition had not already been chosen.  It equals:
     * 
     *   \/ rep.isCreated
     *   \/ rep.nodeType = OR_DECOMP
     *   \/ rep.nodeType = EXISTS_TYPE
     *   \/ /\ rep.nodeType = AND_TYPE
     *      /\ rep.nodeSubtype != OTHER_TYPE
     *  
     * @param rep
     * @param i
     * @return
     */
    boolean displayNonContextAssump(NodeRepresentation rep, int i) {
        return    rep.isCreated
               || (rep.nodeType == NodeRepresentation.OR_DECOMP)
               || (rep.nodeType == NodeRepresentation.EXISTS_TYPE)
               || (   (rep.nodeType == NodeRepresentation.AND_TYPE)
                    && (rep.nodeSubtype != NodeRepresentation.OTHER_TYPE)  ) ;
    }
    /**
     * This method assumes that `composite' is a composite with a gridlayout
     * having 3 columns. It populates it with the buttons and stuff for an
     * assumptions list to go in the Decompose Proof window. It is called to
     * produce the contents of a CASE decomposition in the window. It is called
     * by addAssumptionsToComposite and by itself.
     * 
     * @param nodeRepVector
     * @param composite
     */
    void addCaseToComposite(Vector<NodeRepresentation> nodeRepVector,
            Composite composite) {
        Composite comp;
        GridData gridData;
        GridLayout gridLayout;
        Label assumeLabel;

        for (int i = 0; i < nodeRepVector.size(); i++) {
            NodeRepresentation aRep = nodeRepVector.elementAt(i);

            if ((aRep.nodeType == NodeRepresentation.NEW_NODE)
                    || (aRep.nodeType == NodeRepresentation.OTHER_NODE)
                    || ((aRep.nodeType == NodeRepresentation.EXPR_NODE)
                            && (aRep.nodeSubtype != NodeRepresentation.OR_TYPE)
                            && (aRep.nodeSubtype != NodeRepresentation.EXISTS_TYPE) && (aRep.nodeSubtype != NodeRepresentation.SQSUB_TYPE))) {
                /**
                 * For a CASE decomposition, these nodes are not split. We
                 * therefore put the text of the the assumption all the way on
                 * the left, filling its line.
                 */

                // For a New node, combine it with following NEW nodes if
                // necessary.
                String text = stringArrayToString(nodeRepVector.elementAt(i)
                        .primedNodeText());
                while (nodeRepVector.elementAt(i).onSameLineAsNext) {
                    i++;
                    text = text
                            + ", "
                            + stringArrayToString(nodeRepVector.elementAt(i)
                                    .primedNodeText());
                }
                assumeLabel = new Label(composite, SWT.NONE);
                assumeLabel.setText(text);
                assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                        JFaceResources.TEXT_FONT));
                gridData = new GridData();
                gridData.horizontalSpan = 3;
                assumeLabel.setLayoutData(gridData);
            } else if (aRep.nodeType != NodeRepresentation.OR_DECOMP) {
                // This is an ordinary assumption (an Expression or NEW node).
                /*************************************************************
                 * Add the button or blank area to the first column.
                 *************************************************************/
                String labelText = null;
                // The null test was originally added because created NEW nodes
                // have null
                // semanticNode fields. However, NEW nodes are no longer
                // processed
                // by this code. However, it seems harmless to keep it and I may
                // have forgotten some case in which a NodeRepresentation with a
                // null semanticNode field is created.
                if ((aRep.semanticNode != null)
                        && (aRep.semanticNode.getKind() == ASTConstants.OpApplKind)) {
                    switch (aRep.nodeSubtype) {
                    case NodeRepresentation.AND_TYPE:
                        labelText = null;
                        break;
                    case NodeRepresentation.OR_TYPE:
                    case NodeRepresentation.SQSUB_TYPE:
                        labelText = "\\/";
                        break;
                    case NodeRepresentation.EXISTS_TYPE:
                        labelText = "\\E";
                        break;
                    default:
                        labelText = null;
                    }
                }
                if (labelText != null) {
                    /*************************************************************
                     * Add a button
                     *************************************************************/
                    Button button = new Button(composite, SWT.PUSH);
                    setupActionButton(button, nodeRepVector.elementAt(i),
                            labelText);
                    if ((aRep.nodeSubtype == NodeRepresentation.AND_TYPE)
                            || (aRep.nodeSubtype == NodeRepresentation.FORALL_TYPE)) {
                        button.setEnabled(false);
                    }
                } else {
                    /*************************************************************
                     * Add a blank area.
                     *************************************************************/
                    comp = new Composite(composite, SWT.NONE);
                    gridLayout = new GridLayout(1, false);
                    comp.setLayout(gridLayout);
                    assumeLabel = new Label(comp, SWT.NONE);
                    assumeLabel.setText("  ");
                    gridData = new GridData();
                    gridData.horizontalIndent = 25;
                    comp.setLayoutData(gridData);
                }

                // Add a spacer between the button and the formula
                comp = new Composite(composite, SWT.NONE);
                gridLayout = new GridLayout(1, false);
                comp.setLayout(gridLayout);
                comp.setSize(0, 5);

                /********************************************************************
                 * Add the text of the clause, preceded by appropriate up/down
                 * arrows for a node that comes from an AND-SPLIT.
                 ********************************************************************/
                comp = new Composite(composite, SWT.NONE);
                gridLayout = new GridLayout(3, false);
                comp.setLayout(gridLayout);
             // UP-DOWN ARROWS REMOVED
                // Add arrow buttons if necessary
//                if ((state.chosenSplit == -1) && (state.andSplitBegin <= i)
//                        && (i <= state.andSplitEnd)) {
//                    Button arrowButton = new Button(comp, SWT.ARROW | SWT.UP);
//                    arrowButton
//                            .addSelectionListener(new ArrowSelectionListener(i,
//                                    SWT.UP, this));
//                    gridData = new GridData();
//                    gridData.verticalAlignment = SWT.TOP;
//                    arrowButton.setLayoutData(gridData);
//                    if (i == state.andSplitBegin) {
//                        arrowButton.setEnabled(false);
//                    }
//                    arrowButton = new Button(comp, SWT.ARROW | SWT.DOWN);
//                    arrowButton
//                            .addSelectionListener(new ArrowSelectionListener(i,
//                                    SWT.DOWN, this));
//
//                    gridData = new GridData();
//                    gridData.verticalAlignment = SWT.TOP;
//                    arrowButton.setLayoutData(gridData);
//                    if (i == state.andSplitEnd) {
//                        arrowButton.setEnabled(false);
//                    }
//                }

                assumeLabel = new Label(comp, SWT.NONE);
                String text = stringArrayToString(nodeRepVector.elementAt(i)
                        .primedNodeText());
                assumeLabel.setText(text);
                // Set the font to be the editors main text font.
                assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                        JFaceResources.TEXT_FONT));
                gridData = new GridData();
                // I don't think the following setting of the gridData fields
                // has any effect, but it doesn't seem to hurt.
                gridData.horizontalIndent = 0;
                gridData.verticalAlignment = SWT.TOP;
                gridData.horizontalAlignment = SWT.LEFT;
                assumeLabel.setLayoutData(gridData);

            } else {
                // This is an OR_DECOMP node.
                {
                    // Add a blank label
                    assumeLabel = new Label(composite, SWT.NONE);
                    assumeLabel.setText("  ");
                    comp = new Composite(composite, SWT.NONE);
                    gridLayout = new GridLayout(1, false);
                    comp.setLayout(gridLayout);
                }

                // Add a spacer between the button and the cases
                comp = new Composite(composite, SWT.NONE);
                gridLayout = new GridLayout(1, false);
                comp.setLayout(gridLayout);

                // inner is the composite that contains the CASEs
                Composite inner = new Composite(composite, SWT.NONE);
                // The following commands were an effort to remove
                // excess height above the Composite inner. They failed.
                // ((GridLayout) composite.getLayout()).marginHeight = 0;
                // ((GridLayout) composite.getLayout()).marginTop = 0;
                gridLayout = new GridLayout(2, false);
                // The following commands tried to remove excess vertical
                // space above the Composite inner. They failed.
                // gridLayout.marginHeight = 0;
                // gridLayout.marginTop = 0;
                inner.setLayout(gridLayout);

                for (int j = 0; j < aRep.children.size(); j++) {
                    assumeLabel = new Label(inner, SWT.NONE);
                    assumeLabel.setText("CASE");
                    assumeLabel.setFont(JFaceResources.getFontRegistry().get(
                            JFaceResources.TEXT_FONT));
                    Composite caseComp = new Composite(inner, SWT.BORDER); // SWT.NONE)
                                                                           // ;
                    gridLayout = new GridLayout(3, false);
                    caseComp.setLayout(gridLayout);
                    addCaseToComposite(aRep.children.elementAt(j), caseComp);
                    gridData = new GridData();
                    gridData.verticalAlignment = SWT.TOP;
                    caseComp.setLayoutData(gridData);
                }
            }
        }
    }

    /***************************************************************************
     * The action-button handlers
     ****************************************************************************/
    /**
     * The /\ action, both for a goal (which generates the proof) and for an
     * assumption (which splits the assumption).  This action will only be
     * enabled if the conjunction contains within it, or within one of its
     * conjuncts, a \/ or \E formula.
     * 
     * Note that nodeRep must be either the goal or else a top-level assumption
     * of state.assumeReps.
     * 
     * @param nodeRep
     */
    void andAction(NodeRepresentation nodeRep) {
        if (nodeRep.getParentVector() == null) {
            /**
             * This is a "prove by AND-split" operation.
             */
            makeProof(nodeRep, true, false);
        } else {
            /**
             * This is an AND-SPLIT of an assumption, so nodeRep equals
             * state.assumeReps(i) for some i and parentNode = null.
             * We set idx to i, and we set decomp to the Decomposition
             * object.
             * 
             */
            int idx = nodeRep.getParentIndex();
            Decomposition decomp = nodeRep.decomposition;

            // Modify state.hasChanged, assumeHasChanged, and
            // state.goalDefinitions.
            state.hasChanged = false; // Changed from true to false by LL on 23
                                      // Aug 2014. See
                                      // comments on hasChanged's declaration.
            // assumeHasChanged = true;
            if (decomp.definedOp != null) {
                // Modified by LL on 4 Feb 2013 to change
                // state.assumpDefinitions
                // instead of state.goalDefinitions to fix a bug. But I'm not
                // sure that this is always the correct thing to do.
                // state.goalDefinitions.add(decomp.definedOp);
                state.assumpDefinitions.add(decomp.definedOp);
            }

            // Remove this assumption and insert the split nodes in its place.
            // Set newSemanticNodes to the vector of new assumptions. However,
            // the call to decompositionChildToNodeRep calls
            // decompSubstituteInNodeText,
            // which requires nodeRep to still be in state.assumeReps.
            // Therefore, we
            // accumulate the NodeRepresentation objects for the children and
            // replace nodeRep afterwards.
            Vector<SemanticNode> addedAssumps = decomp.children;
            Vector<NodeRepresentation> addedToAssumeReps = new Vector<NodeRepresentation>();
            for (int i = 0; i < addedAssumps.size(); i++) {
                // Call decompositionChildToNodeRep to construct the child's
                // NodeRepresentation.
                NodeRepresentation rep = decompositionChildToNodeRep(nodeRep,
                        i, this.state.assumeReps, null);
                rep.initialPosition = nodeRep.initialPosition ;
                rep.isCreated = false;  // changed from true by LL on 8 Oct 2014
                addedToAssumeReps.add(rep);
            }
            this.state.assumeReps.remove(idx);
            for (int i = 0; i < addedToAssumeReps.size(); i++) {
                this.state.assumeReps.add(idx + i,
                        addedToAssumeReps.elementAt(i));
            }
//         // UP-DOWN ARROWS REMOVED
//            // Update state.andSplitBegin & state.andSplitEnd. Recall the
//            // precondition.
//            if (state.andSplitBegin == -1) {
//                state.andSplitBegin = idx;
//                state.andSplitEnd = idx + addedAssumps.size() - 1;
//            } else {
//                state.andSplitEnd = state.andSplitEnd + addedAssumps.size() - 1;
//            }
            
            // Update state.numberOfContextAssumptions
            if (idx < state.numberOfContextAssumptions) {
                state.numberOfContextAssumptions = 
                        state.numberOfContextAssumptions + (addedAssumps.size()-1) ;
            }
            if (idx < state.firstAddedAssumption) {
                state.firstAddedAssumption = state.firstAddedAssumption + (addedAssumps.size()-1) ;
            }
            raiseWindow();
            return ;
        }
    }

    /**
     * Execute a \A split of the goal.
     * 
     * @param nodeRep
     */
    void forAllAction(NodeRepresentation nodeRep) {
        QuantifierDecomposition qdc = decomposeQuantifier(nodeRep, true);

        // abort operation if decomposeQuantifier call failed.
        if (qdc != null) {
            Decomposition decomp = nodeRep.decomposition;
            state.hasChanged = true;
            if (decomp.definedOp != null) {
                state.assumpDefinitions.add(decomp.definedOp);
            }

            this.state.goalRep = qdc.body;
            // I think that, once we start decomposing things, goal
            // may be used in calling primingNeedsParens
            // this.goal = qdc.body.semanticNode ;

            int newIdx = newAssumeRepsIndex(-1, nodeRep.initialPosition) ;
            for (int i = 0; i < qdc.news.size(); i++) {
                this.state.assumeReps.add(newIdx+i, qdc.news.elementAt(i));
                // this.assumes.add(qdc.news.elementAt(i).semanticNode) ;
            } 
        }
        raiseWindow();
    }

    /**
     * Executes an \E split of an assumption. If this is a top-level assumption,
     * then the NEW variables may have to be changed to avoid a name clash with
     * NEW variables or other bound variables of later assumptions or of the
     * goal.
     * 
     * Also, for a top-level assumption , if an AND-split has been performed,
     * then this has to increment state.andSplitEnd because it adds an
     * assumption to the AND-split region.
     * 
     * @param nodeRep
     */
    void existsAction(NodeRepresentation nodeRep) {
        // Set decomp to nodeRep's decomposition and idx
        // and parentVec so that nodeRep = parentVec.elementAt(idx).

        int idx = nodeRep.getParentIndex();
        Vector<NodeRepresentation> parentVec = nodeRep.getParentVector();

        Decomposition decomp = nodeRep.decomposition;
        state.hasChanged = true;
        if (decomp.definedOp != null) {
            if (parentVec == state.assumeReps) {
                // Note that it doesn't seem to matter what values are put into assumpDefinitions.
                // See comment on this field.
                state.assumpDefinitions.add(nodeRep.instantiationSubstitutions.prefix + decomp.definedOp);
            } else {
                // I think this assignment does nothing because an \E decomposition
                // doesn't appear in the goal.  However, I'm not at all sure of this.
                state.goalDefinitions.add(nodeRep.instantiationSubstitutions.prefix + decomp.definedOp);
            }
        }

        // Set state.needsStepNumber if necessary. (See that field's
        // documentation.)
        //
        // Bug discovered by LL 19 Aug 2014. The spec of isCreated indicates
        // that nodeRep.isCreated is true if this exists was created by an
        // AND-split on an assumption, in which case the documentation of
        // state.needsStepNumber implies that state.needsStepNumber should be
        // set true.
        //
        // This bug was apparently fixed in the new version.
        // Removed this code on 3 Dec 2014
//        if (!nodeRep.isCreated && this.hasAssumes) {
//            state.needsStepNumber = true;
//        }

        QuantifierDecomposition qdc = decomposeQuantifier(nodeRep, false);

        // Abort operation if qdc is null
        if (qdc != null) {
            // This added by LL on 11 Feb 2013
            qdc.body.isCreated = true;
            
            qdc.body.fromExists = true ;

            parentVec.remove(idx);

            // If this is a top-level context assumption, then
            // decrement state.numberOfContextAssumptions, and set idx to the appropriate
            // place to put the new assumptions
            if (parentVec == state.assumeReps) {
                // Was 
                //   int newIdx =  newAssumeRepsIndex(idx, nodeRep.initialPosition) ; 
                // Changed on 3 Dec 2014 to the following code so new top-level NEWs
                // are added to the end of the created assumptions.  This should make
                // it unnecessary to worry about renamings required because of bound
                // variables in the bounding exprssions (if any) of NEW variables 
                // being added.  
                int newIdx = idx ;
                if (idx < state.firstAddedAssumption) {
                    state.firstAddedAssumption-- ;
                    newIdx = state.firstAddedAssumption ;
                }
                if (idx < state.numberOfContextAssumptions) {
                   state.numberOfContextAssumptions = state.numberOfContextAssumptions-1  ;
                }

                idx = newIdx ;
            }
            for (int i = 0; i < qdc.news.size(); i++) {
                parentVec.add(idx + i, qdc.news.elementAt(i));
                // parentVec.add(idx + i, qdc.news.elementAt(i).semanticNode) ;
            }
            parentVec.add(idx + qdc.news.size(), qdc.body);
            // parentVec.add(idx + qdc.news.size(), qdc.body.semanticNode) ;

        }
        raiseWindow();
    }

    /**
     * Execute an IMPLIES split.
     * 
     * @param nodeRep
     */
    void impliesAction(NodeRepresentation nodeRep) {
        Decomposition decomp = nodeRep.decomposition;
        state.hasChanged = true;
        if (decomp.definedOp != null) {
            state.assumpDefinitions.add(decomp.definedOp);
        }

        // If this is within the subexpression-name expansion of a definition,
        // set NodeTextRep to the NodeTextRep that is the name of the formula
        // represented by nodeRep.
        NodeTextRep newNodeText = null;
        if ((decomp.definedOp != null) && (subexpressionButton.getSelection())) {
            newNodeText = decomp.definedOpRep;
        } else if (nodeRep.isSubexpressionName) {
            newNodeText = new NodeTextRep(nodeRep.nodeText, nodeRep.mapping);
        }

        NodeRepresentation nrep = decompositionChildToNodeRep(nodeRep, 0,
                this.state.assumeReps, nodeRep.parentNode);

        nrep.isCreated = true;
        nrep.isPrimed = nrep.isPrimed || decomp.primed;
        int newIdx = newAssumeRepsIndex(-1, nodeRep.initialPosition) ;
        this.state.assumeReps.add(newIdx, nrep);
        nrep = decompositionChildToNodeRep(nodeRep, 1,
                nodeRep.getParentVector(), nodeRep.parentNode);
        nrep.isCreated = true;
        this.state.goalRep = nrep;

        raiseWindow();
    }

    /**
     * Perform an or-split action. This turns nodeRep to an OR_DECOMP type node.
     * 
     * @param nodeRep
     */
    void orAction(NodeRepresentation nodeRep) {
        
        // Set decomp to nodeRep's decomposition and idx
        // and parentVec so that nodeRep = parentVec.elementAt(idx).
        // to the value such that
        int idx = nodeRep.getParentIndex();
        Vector<NodeRepresentation> parentVec = nodeRep.getParentVector();
        // If this is an OR-split of a top-level assumption, then
        // set state.chosenSplit to idx (NO LONGER NEEDED) and
        // move the node to the end of assumeReps
        if (parentVec == this.state.assumeReps) {
           int oldIdx = nodeRep.getParentIndex() ;
           if (oldIdx < state.numberOfContextAssumptions) {
               state.numberOfContextAssumptions-- ;
           }
           if (oldIdx < state.firstAddedAssumption) {
               state.firstAddedAssumption-- ;
           }
           state.assumeReps.remove(oldIdx) ;
           // this.state.chosenSplit = state.assumeReps.size() ;
           state.assumeReps.add(nodeRep) ;
        }

        Decomposition decomp = nodeRep.decomposition;
        state.hasChanged = true;
        if (decomp.definedOp != null) {
            state.goalDefinitions.add(nodeRep.instantiationSubstitutions.prefix + decomp.definedOp);
        }

        nodeRep.nodeType = NodeRepresentation.OR_DECOMP;
        nodeRep.nodeSubtype = NodeRepresentation.OTHER_TYPE;
        nodeRep.children = new Vector<Vector<NodeRepresentation>>();
        nodeRep.initialPosition = Integer.MAX_VALUE ;

        for (int i = 0; i < decomp.children.size(); i++) {
            Vector<NodeRepresentation> repVec = new Vector<NodeRepresentation>();
            nodeRep.children.add(repVec);
            NodeRepresentation rep = decompositionChildToNodeRep(nodeRep, i,
                    repVec, nodeRep);
            repVec.add(rep);
        }
        raiseWindow();
    }

    /**
     * Perform the or-split for a [N]_v formula.
     * 
     * @param nodeRep
     */
    void sqsubAction(NodeRepresentation nodeRep) {
        // Set decomp to nodeRep's decomposition and idx
        // and parentVec so that nodeRep = parentVec.elementAt(idx).
        // to the value such that
        int idx = nodeRep.getParentIndex();
        Vector<NodeRepresentation> parentVec = nodeRep.getParentVector();
        // If this is an OR-split of a top-level assumption, then
        // set state.chosenSplit to idx. (NO LONGER NEEDED)
        // and move the node to the end of state.assumeReps.
        if (parentVec == this.state.assumeReps) {
         
            
            nodeRep.initialPosition = Integer.MAX_VALUE;
            // this.state.chosenSplit = idx;
            int oldIdx = nodeRep.getParentIndex() ;
            if (oldIdx < state.numberOfContextAssumptions) {
                state.numberOfContextAssumptions-- ;
            }
            if (oldIdx < state.firstAddedAssumption) {
                state.firstAddedAssumption-- ;
            }
            state.assumeReps.remove(oldIdx) ;
            state.assumeReps.add(nodeRep) ;
        }

        Decomposition decomp = nodeRep.decomposition;
        state.hasChanged = true;
        if (decomp.definedOp != null) {
            state.goalDefinitions.add(nodeRep.instantiationSubstitutions.prefix + decomp.definedOp);
        }

        nodeRep.nodeType = NodeRepresentation.OR_DECOMP;
        nodeRep.nodeSubtype = NodeRepresentation.OTHER_TYPE;
        nodeRep.children = new Vector<Vector<NodeRepresentation>>();

        for (int i = 0; i < decomp.children.size(); i++) {
            Vector<NodeRepresentation> repVec = new Vector<NodeRepresentation>();
            nodeRep.children.add(repVec);
            NodeRepresentation rep = decompositionChildToNodeRep(nodeRep, i,
                    repVec, nodeRep);
            if (i == 1) {
                // Have to fix the UNCHANGED node. We prepend the "UNCHANGED"
                // to nodeText and set it to be a node of type OTHER, which
                // means it
                // will never be split.
                rep.nodeType = NodeRepresentation.OTHER_NODE;
                rep.nodeSubtype = NodeRepresentation.OTHER_TYPE;
                rep.nodeText = prependToStringArray(rep.nodeText, "UNCHANGED ");

            }
            repVec.add(rep);
        }
        raiseWindow();
    }

    /**
     * Create the proof for a case-split.
     * 
     * @param nodeRep
     */
    void caseAction(NodeRepresentation nodeRep) {
        makeProof(nodeRep, false, false);
    }

    /**
     * makeProof(nodeRep, isAndProof, sufficesOnly) creates the proof.  
     * It is called three ways:
     * 
     *  - isAndProof = true /\ sufficesOnly = false
     *      The user has selected /\ decomposition
     *      
     *  - isAndProof = false /\ sufficesOnly = true
     *      The user has selected the top "P" button, which
     *      is enabled if only \E decompositions and/or =>
     *      decompositions have been chosen.
     *      
     *  - isAndProof =  sufficesOnly = false
     *      The user has chosen a case split.
     *      
     * Here is how (I think) a proof should be constructed. 
     *  
     *  userProof = a BY proof of the decomposed step, with BY and DEF clauses
     *              userProof.BY and userProof.DEF.  (Obvious representations if
     *              either or both of those clauses are empty--e.g. OBVIOUS if
     *              both are empty.)
     *              
     *  createdAssumps = Sequence of all new assumptions added by decomposition,
     *                   except for assumption on which case split is being done (if any)
     *                   
     *  caseSplitAssump = Disjunction on which case split being done, or null if none.
     *   
     *  createdAssumps.defs = 
     *    Sequence of names of operators expanded to obtain assumptions
     *    in createdAssumps, including assumptions that were originally
     *    part of the goal.
     * 
     *  createdAssumps.stepNames =
     *    Sequence of names of all named steps from which assumptions
     *    in createdAssumps were obtained, excluding ones from assumptions
     *    that were originally part of the goal (but including the decomposed
     *    step's name for assumptions coming from its assumptions).
     * 
     *  caseSplitAssump.defs (implemented by the case-split nodes fromDefs) = 
     *    Sequence of names of operators expanded to obtain the top-level caseSplitAssump
     * 
     *  caseSplitDefs (implemented as state.goalDefinitions) =
     *     Sequence of names of operators expanded to obtain all the case splits from
     *     caseSplitAssump.
     *     
     *  caseSplitAssump.stepName =
     *    Sequence containing name of step from which 
     *    caseSplitAssump came, or empty seq if either: 
     *        - caseSplitAssump = null 
     *        - that step is unnamed
     *        - the case split formula came from the original goal.
     *    
     *  decompGoal = The goal created by the decomposition.
     *  
     * Here are the proofs created for different cases (assuming a level <1> statement):
     *    
     * CASE 1: \/ sufficesOnly = true         \* CASE 1a
     *         \/ /\ isAndProof = true        \* CASE 1b
     *            /\ "Use SUFFICES" chosen ->
     * 
     *   <2> SUFFICES ASSUME createdAssumps
     *                PROVE  decompGoal
     *      BY createdAssumps.stepNames DEF createdAssumps.defs
     *      [NOTE: IF createdAssumps is empty, then the SUFFICES
     *             step is eliminated.  This can 
     *             be the case only if sufficesOnly = false.]
     *   IF isAndProof = true 
     *      THEN ... 
     *           <2>i. conjunct i of decompGoal
     *             BY userProof
     *           ...
     * 
     *   <2>n. QED
     *     IF sufficesOnly = true
     *       THEN userProof
     *       ELSE BY <2>1, ... , <2>n-1, createdAssumps.stepNames 
     *          \o IF there is no SUFFICES 
     *               THEN DEF decompGoal.fromDefs
     *           \o IF is a defined op THEN <<the operator name>>
     *                                 ELSE << >>
     * 
     * CASE 2: /\ isAndProof = true
     *         /\ "Use SUFFICES" not chosen ->
     * 
     *   ...
     *   <2>i. ASSUME createdAssumps
     *         PROVE  conjunct i of decompGoal
     *     BY userProof.BY, <2>i DEF userProof.DEF
     *   ...
     * 
     *   <2>n. QED
     *     BY <2>1, ... , <2>n-1, createdAssumps.stepNames
     *     DEF createdAssump.defs \o
     *           IF decompGoal is a defined op THEN <<the operator name>>
     *                                         ELSE << >>
     *           \o createdAssumps.defs
     *  
     * CASE 3: /\ isAndProof = sufficesOnly = FALSE
     *         /\ "Use SUFFICES" chosen  -> 
     * 
     *   <2> SUFFICES ASSUME createdAssumps \o
     *                       IF case-split came from original goal or was in the body of a \E
     *                         THEN , top-level caseSplitAssump formula (possibly an operator name)
     *                PROVE  decompGoal
     *      BY createdAssumps.stepNames 
     *      DEF createdAssumps.defs \o IF case-split came from original goal
     *                                   THEN , caseSplitAssump.defs
     *      NOTE: IF the ASSUMES is empty, then SUFFICES step is eliminated and 
     *            the BY and DEF clauses are made part of the QED step's proof.
     *            (However, in that case BY clause should be empty.)
     *   ...
     *   <2>i. ASSUME case i of caseSplitAssump
     *         PROVE  decompGoal
     *              [This ASSUME/PROVE should be replaced by a CASE
     *               statement if "Use CASE" chosen and all of the ASSUME
     *               clauses are formulas.]
     *           BY userProof.BY, <2>i DEF userProof.DEF
     *   ...
     *   <2>n. QED
     *     BY <2>1, ... , <2>n-1, caseSplitAssump.stepNames 
     *     DEF caseSplitDefs \o  IF case-split not from original goal 
     *                              and not from the body of a \E
     *                             THEN caseSplitAssump.defs
     * 
     * CASE 4: /\ isAndProof = sufficesOnly = FALSE
     *         /\ "Use SUFFICES" not chosen   ->
     * 
     *   ...
     *   <2>i. ASSUME case i of caseSplitAssump
     *         PROVE  decompGoal
     *               [This ASSUME/PROVE should be replaced by a CASE
     *                statement if "Use CASE" chosen and all of the ASSUME
     *                clauses are formulas.]
     *           BY userProof.BY, <2>i,  DEF userProof.DEF
     *   ...
     *   <2>n. QED
     *     BY <2>1, ... , <2>n-1, createdAssumps.stepNames, caseSplitAssump.stepName 
     *     DEF createdAssumps.defs, caseSplitAssump.defs, caseSplitDefs
     * 
     * @param nodeRep
     * @param isAndProof
     * @param sufficesOnly
     */
    void makeProof(NodeRepresentation nodeRep, boolean isAndProof,
            boolean sufficesOnly) {

        /**
         * Set proofIndent to the amount to indent both the new proof and the
         * proofs of its steps. We may want to do something clever about
         * inferring what the user wants from the indentation he used if the
         * step has a leaf proof. However, this can be complicated because some
         * people put the proof on the last line of the obligation. So for now,
         * we just set it to PROOF_INDENT.
         * 
         * We also set proofIndentString to a string of that number of spaces.
         */
        // StringSet aaTestSet = new StringSet();
        // addDeclaredSymbols(aaTestSet, state.goalRep);

        // Compute createdAssumps, createdAssumps.defs and createdAssump.stepNames, 
        // defined in the spec above.  Also, set createdAssumpsNodeTexts to
        // the vector of the String arrays representing createdAssumps.
        
        Vector<NodeRepresentation> createdAssumps = new Vector<NodeRepresentation>();
        StringSet createdAssumpsDefs = new StringSet();
        StringSet createdAssumpStepNames = new StringSet();
        for (int i=state.firstAddedAssumption; i < state.assumeReps.size() ; i++) {
           NodeRepresentation rep = state.assumeReps.elementAt(i);
           if (rep.nodeType != NodeRepresentation.OR_DECOMP) {
               createdAssumps.add(rep) ;
               if ((rep.contextStepName != null) && ! rep.fromGoal) {
                   createdAssumpStepNames.add(rep.contextStepName);           
               }
               createdAssumpsDefs.addAll(rep.fromDefs) ;
           }  
           else {
               if (rep != nodeRep) {
                   MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                           "Decompose Proof Command",
                           "Something unexpected is going on at "
                                   + "line 3285 of DecomposeProofHandler.");
               }

           }
         }
        
        Vector<String[]> createdAssumpsNodeTexts = new Vector<String[]>() ;
        for (int i =0; i < createdAssumps.size(); i++) {
            createdAssumpsNodeTexts.add(createdAssumps.elementAt(i).nodeText) ;
        }
        
        // Sanity check
        if (sufficesOnly && (createdAssumps.size() == 0)) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "Sanity check failed at "
                            + "line 3301 of DecomposeProofHandler.");
        }
        
        
        int proofIndent = PROOF_INDENT;
        String proofIndentString = StringHelper.copyString(" ", proofIndent);

        // Set assumptionsText to a string array such that applying 
        // stringArrayToString to it produces the text of the list of 
        // assumptions in createdAssumps.
        String[] assumptionsText = createdAssumptions();
        
        // If createdAssumps contains only formulas (and no NEW assumptions),
        // then set assumptionsAsConjText to a string array such that applying 
        // stringArrayToString to it produces the text of the conjunction of
        // all the assumptions in createdAssumps.  Otherwise, assumptionsAsConjText
        // is set to null.
        
        String[] assumptionsAsConjText = new String[createdAssumps.size()] ;
        
        int k = 0 ;
        while ((assumptionsAsConjText) != null && (k < createdAssumps.size())){
            NodeRepresentation rep = createdAssumps.elementAt(k) ;
            if (rep.nodeType == NodeRepresentation.NEW_NODE){
                assumptionsAsConjText = null ;
            }
            else {
                if (createdAssumps.size() > 1) {
                    assumptionsAsConjText[k] = 
                      stringArrayToString(prependToStringArray(rep.nodeText, "/\\ ")) ;
                }
                else {
                    assumptionsAsConjText[k] = stringArrayToString(rep.nodeText) ;
                }
            }
            k++ ;
        }
            
            
        // If there is a proof, set proofText to its string array
        // representation, with indentation prepended to it, and delete it.
        // Set proofBY and proofDEF to the sets of BY and DEF elements.
        String[] proofText = null;
        StringSet proofBY = null;
        StringSet proofDEF = null ;
        if (this.proof != null) {
            proofText = this.stepRep.subNodeText(this.proof).nodeText;
            proofText = prependToStringArray(proofText, proofIndentString);
            try {
                IRegion proofRegion = EditorUtil.getRegionOf(this.doc,
                        ((SyntaxTreeNode) this.proof.stn).getLocation());
                this.doc.replace(proofRegion.getOffset(),
                        proofRegion.getLength(), "");
            } catch (BadLocationException e) {
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "An error that should not happen has occurred in "
                                + "line 3358 of DecomposeProofHandler.");
                e.printStackTrace();
            }
            proofBY = new StringSet();
            proofDEF = new StringSet();
            
            
            // Set proofBY and proofDEF
            // line = current line in proofText, trimmed
            // lineNum = line number of line
            // idx = current index in current line
            String line = "";
            int lineNum = 0;
            int idx = 0;
            boolean notfound = true ;
            // find "BY" 
            while (notfound && lineNum < proofText.length) {
               line = proofText[lineNum].trim();
               if (line.startsWith("BY")) {
                   idx = proofText[lineNum].indexOf("BY") + 2;
                   notfound = false;
               }
               else if (line.equals("")){
                   lineNum++ ;
               }
               else {
                   // Must be an OBVIOUS proof
                   lineNum = Integer.MAX_VALUE ;
               }  
            }
            
            if (!notfound) {
                // Do nothing if there is no BY step.  
                // Otherwise, first set stringBY to comma separated list of BY clauses
                // and set notfound false if there is a DEF 
                String stringBY = "" ;
                boolean defNotfound = true ;
                while (defNotfound && lineNum < proofText.length) {
                    line = proofText[lineNum].substring(idx, proofText[lineNum].length()) ;
                    // If line contains "DEF"
                    //   THEN set defIdx to its index and notfound to false
                    //   ELSE set defIdx to line.length()
                    int defIdx = 0 ;
                    while ((defIdx < line.length()) && defNotfound) {
                       defIdx = line.indexOf("DEF", defIdx) ; 
                       if (defIdx == -1) {
                            defIdx = line.length() ;
                       }
                       else if (   ((defIdx == 0) || 
                                            Character.isWhitespace(line.charAt(defIdx-1)))
                                    && ((defIdx+3 == line.length()) || 
                                            Character.isWhitespace(line.charAt(defIdx+3)))
                              ) {
                          defNotfound = false ;
                         // defIdx = defIdx;
                       }
                       else {
                           defIdx = defIdx+3 ;
                       }
                    }
                    
                    stringBY = stringBY + line.substring(0, defIdx) ; 
                    
                   if (defNotfound) {
                       lineNum ++;
                       idx = 0;
                   }
                   else {
                       idx = idx + defIdx+3 ;
                   }
                }
                
                proofBY.addAll(StringSet.CommaSeparatedListToStringSet(stringBY)) ;
                

                if (!defNotfound) {
                    // A DEF was found, so we have to add everything after it to
                    // proofDEF
                    String stringDEF = "" ;
                    while (lineNum < proofText.length) {
                        line = proofText[lineNum].substring(idx, proofText[lineNum].length()) ;
                        stringDEF = stringDEF + line ;
                        lineNum++ ;
                        idx = 0 ;
                    }
                    proofDEF.addAll(StringSet.CommaSeparatedListToStringSet(stringDEF)) ;  
                }
            }
        }

        
        // Set addStepNumber true iff we need to add the step number to the
        // BY clause of a SUFFICES step or of the QED step.  This should not
        // be needed any more, but it has one use and it seems safest to just
        // let sleeping code lie.
        // Removed it on 3 Dec 2014
        // boolean addStepNumber = (stepNumber != null)
        //        && this.state.needsStepNumber;

        // Set sufficesStep to the string array of the suffices step,
        // or null if there is none. There is a suffices step iff either
        //  - the user has selected the Use SUFFICES option, and the
        //    decomposition of the goal has created an assumption, or
        //  - sufficesOnly = true
        String[] sufficesStep = null;
        boolean hasSufficesStep = 
                       (useSufficesButton.getSelection() && (createdAssumps.size() != 0))
                    || sufficesOnly ;
        if (hasSufficesStep) {           
            // CASE 1 or CASE 3
            String sufficesProof = null;

//            String[] sufficesAssumeText = new String[0] ;
//            
//            for (int i = 0; i < createdAssumpsNodeTexts.size(); i++) {
//                sufficesAssumeText = concatStringArrays
//                                       (sufficesAssumeText, 
//                                        createdAssumpsNodeTexts.elementAt(i));
//                if (i != createdAssumpsNodeTexts.size() - 1) {
//                    sufficesAssumeText = appendToStringArray(sufficesAssumeText, ",") ;
//                }
//            }
                    
            StringSet sufficesDEF = createdAssumpsDefs.clone();

            if (    (nodeRep != null)
                 && (nodeRep.nodeType == NodeRepresentation.OR_DECOMP) 
                 && (nodeRep.fromGoal || nodeRep.fromExists) ) {
                // CASE 3 with case-split from original goal
                if (createdAssumps.size() != 0) {
                    assumptionsText = appendToStringArray(assumptionsText, ",") ;
                }
                assumptionsText = concatStringArrays(assumptionsText, nodeRep.nodeText);
                
                sufficesDEF.addAll(nodeRep.fromDefs) ;
            }
            
            String[] suffices = prependToStringArray(
                    concatStringArrays(
                            prependToStringArray(assumptionsText, "ASSUME "),
                            prependToStringArray(
                                    this.state.goalRep.primedNodeText(),
                                    "PROVE  ")), proofLevelString
                            + " SUFFICES ");

            // The following is the only use of addStepNumber
            // it should probably be replaced by something else.
            // See comments for declaration of addStepNumber.
            // LL-XXXXX:  On 29 Nov 2014, LL tried just commenting it out,
            // hoping that any step numbers now needed are added
            // using the contextStepName field of the NodeRepresentation 
            // objects.  That caused a bug to appear.  However, that bug
            // was actually orthogonal and this use of addStepNumber
            // just fixed it in one case.  The root cause was fixed
            // on 1 Dec 2014 by adding the createdAssumpStepNames.isEmpty()
            // clause, and the use of addStepNumber remains commented out.
            if (state.assumpDefinitions.isEmpty() 
                    && createdAssumpStepNames.isEmpty()
                    /* && !addStepNumber */) {
                // No goal definitions were expanded; the proof is obvious.
                if (OBVIOUS_HAS_PROOF) {
                    sufficesProof = "PROOF OBVIOUS";
                } else {
                    sufficesProof = "OBVIOUS";
                }
            } else {
                // Need a BY proof, with a DEF if there are expanded
                // definitions
                sufficesProof = "BY ";
                
                if (!createdAssumpStepNames.isEmpty()) {
                    sufficesProof = sufficesProof + 
                                     createdAssumpStepNames.toCommaSeparatedString() + " ";
                }
                
                if (!sufficesDEF.isEmpty()) {
                    sufficesProof = sufficesProof + "DEF " + sufficesDEF.toCommaSeparatedString();
                }
                
                // The following code was commented out.  However, it produced an empty BY
                // because we were here and shouldn't have been.  However, the reason for
                // being here have been fixed on 1 Dec 2014.
//                if (addStepNumber) {
//                    sufficesProof = sufficesProof + this.stepNumber + " ";
//                }
//                if (!state.assumpDefinitions.isEmpty()) {
//                    sufficesProof = sufficesProof + "DEF "
//                            + setOfStringsToList(state.assumpDefinitions);
//                }
            }

            sufficesStep = concatStringArrays(suffices,
                    new String[] { proofIndentString + sufficesProof });
        }

        
        // Set
        // - mainProofSteps to be an array of string arrays for the
        //   steps of the proof other than the SUFFICES and QED steps. ,
        // - numberOfSteps to the number of those steps (which
        //   should equal mainProofSteps.length;
        // - proofDef to be the name of the operator whose definition
        //   is the current goal, if this is an and-split proof.
        //   It is null otherwise.

        String[][] mainProofSteps = null;
        int numberOfSteps = 0;
        
        // For /\ proof whose conjunction comes from
        // a defined operator, proofDef equals that operator.
        // otherwise it equals null ;
        String proofDef = null;

        if (!sufficesOnly) {

            if (isAndProof) {
                /**
                 * This is an and-decomposition proof (CASES 1b and 2)
                 */
                Decomposition decomp = nodeRep.decomposition;
                numberOfSteps = decomp.children.size();
                mainProofSteps = new String[numberOfSteps][];
                proofDef = decomp.definedOp;

                for (int i = 0; i < numberOfSteps; i++) {
                    // Set goalArray to the String array of the goal.
                    NodeRepresentation stepGoalRep = decompositionChildToNodeRep(
                            nodeRep, i, null, null);
                    String[] goalArray = stepGoalRep.primedNodeText();
                    

                    // Set step to step number + the step's obligation.
                    String[] step;

                    // Set isAssumeProve to indicate if this is an ASSUME/PROVE
                    // step, rather than an ordinary assertion.
                    boolean isAssumeProve = false;
                    // If there is no SUFFICES step but the goal decomposition
                    // created new ASSUME clauses, then they must be the ASSUME
                    // of an ASSUME / PROVE
                    if ((sufficesStep == null && createdAssumps.size() != 0)) {
                        step = concatStringArrays(
                                prependToStringArray(assumptionsText, "ASSUME "),
                                prependToStringArray(goalArray, "PROVE  "));
                        isAssumeProve = true;

                    } else {
                        // Just a simple step, no ASSUME/PROVE.
                        step = goalArray;
                    }
                    // Set stepNum to the step number--e.g. "<2>3"
                    String stepNum = proofLevelString + (i + 1);

                    step = prependToStringArray(step, stepNum
                            + STEP_NUMBER_PUNCTUATION + " ");

                    // Add the proof to step, if there is one.
                    if (proofText != null) {
                        String[] newProofText = proofText.clone();
                        if (isAssumeProve) {
                            // Need to add step number to the BY part;
                            addStepNumToProof(stepNum, newProofText);
                        }
                        step = concatStringArrays(step, newProofText);
                    }

                    // Set the i-th conjunctStep to step
                    mainProofSteps[i] = step;
                }
            } else {
                /**
                 * This is a case-split proof.
                 * Note that caseSplitAssumpDefs = nodeRep.fromDefs()
                 * caseSplitDefs = state.goalDefinitions = 
                 *   union of nd.fromDefs() for all descendant nodes 
                 *   (via the child field) nd of nodeRep.
                 * 
                 */
                // Set pfStepVec to a Vector of proof steps.
                Vector<String[]> pfStepVec = new Vector<String[]>();
                for (int i = 0; i < nodeRep.children.size(); i++) {
                    Vector<NodeRepresentation> childVec = nodeRep.children
                            .elementAt(i);
                    String[] assumpArray;
                    if (!hasSufficesStep) {
                        assumpArray = new String[assumptionsText.length];
                        for (int j = 0; j < assumptionsText.length; j++) {
                            assumpArray[j] = assumptionsText[j];
                        }
                    } else {
                        assumpArray = new String[0];
                        assumptionsAsConjText = new String[0] ;
                    }
                    
                    boolean assumpArrayOnlyFormulas = true ;
                    for (int j = 0; j < createdAssumps.size(); j++) {
                        assumpArrayOnlyFormulas = 
                          assumpArrayOnlyFormulas && 
                            (createdAssumps.elementAt(j).nodeType != NodeRepresentation.NEW_NODE) ;
               
                    }
                    addCaseProofs(pfStepVec, childVec, assumpArray,
                            proofText, assumptionsAsConjText);
                }

                // turn pfStepVec into the array mainProofSteps
                mainProofSteps = new String[pfStepVec.size()][];
                for (int i = 0; i < mainProofSteps.length; i++) {
                    mainProofSteps[i] = pfStepVec.elementAt(i);
                }
                numberOfSteps = mainProofSteps.length;
            }
        }
        
        // Set qedStep to the QED step (with its step number and proof).
        String[] qedStep = new String[2];
        qedStep[0] = proofLevelString;
        if (NUMBER_QED_STEP && (numberOfSteps != 0)) {
            qedStep[0] = qedStep[0] + (numberOfSteps + 1)
                    + STEP_NUMBER_PUNCTUATION;
        }
        qedStep[0] = qedStep[0] + " QED";
        
        if (sufficesOnly) {
            // CASE 1a
            if (proofText != null) {
                qedStep[1] = stringArrayToString(proofText) ;
            } 
            else {
                qedStep = new String[] {qedStep[0]} ;
            }

        }
        else {
            // not CASE 1a
            // Set qedBY and qedDEF to the BY and DEF clauses
            StringSet qedBY = new StringSet() ;
            StringSet qedDEF = new StringSet() ;
            
            // Add the names of mainProofSteps to qedBY
            for (int i = 1; i <= numberOfSteps; i++) {
                qedBY.add(proofLevelString + i) ;
            }
            
            if (isAndProof) {
                // CASES 1b and 2
                qedBY.addAll(createdAssumpStepNames) ;
                if (proofDef != null) {
                    qedDEF.add(proofDef) ;
                }
                if (! hasSufficesStep) {
                    qedDEF.addAll(nodeRep.fromDefs) ;
                    qedDEF.addAll(createdAssumpsDefs) ;
                }
            }
            else {
                // CASES 3 and 4
                if (useSufficesButton.getSelection()) {
                    // CASE 3
                    if (nodeRep.contextStepName != null) {
                        qedBY.add(nodeRep.contextStepName) ;
                    }
                    
                    qedDEF.addAll(state.goalDefinitions) ;
                    
                    if (!hasSufficesStep && nodeRep.fromGoal) {
                        qedDEF.addAll(nodeRep.fromDefs) ;
                    }
                    
                }
                else {
                    // CASE 4
                    qedBY.addAll(createdAssumpStepNames) ;
                    if (nodeRep.contextStepName != null) {
                        qedBY.add(nodeRep.contextStepName) ;
                    }
                    qedDEF.addAll(createdAssumpsDefs) ;
                    qedDEF.addAll(nodeRep.fromDefs) ;
                    qedDEF.addAll(state.goalDefinitions) ;
                }
            }
            
            qedStep[1] = proofIndentString + "BY "
                    + qedBY.toCommaSeparatedString() ;
            if (! qedDEF.isEmpty()) {
                qedStep[1] = qedStep[1] + " DEF " 
                    + qedDEF.toCommaSeparatedString() ;
            }
        }
        
        
        
        
//        /*
//         * The following is much too complicated in the sufficesOnly case. In
//         * that case, hasGoalDefs and hasAssumeDefs will all be set to false, so
//         */
//                
//        qedStep[1] = proofIndentString + "BY "   
//                + ((numberOfSteps > 0) ? (proofLevelString + 1) : "");
//        for (int i = 2; i <= numberOfSteps; i++) {
//            qedStep[1] = qedStep[1] + ", " + proofLevelString + i;
//        }
//        // Add step number if necessary.
//        if ((sufficesStep == null) && state.needsStepNumber
//                && (this.stepNumber != null)) {
//            qedStep[1] = qedStep[1] + ", " + this.stepNumber;
//        }
//
//        boolean hasGoalDefs = (!this.state.assumpDefinitions.isEmpty())
//                && (sufficesStep == null);
//        boolean hasAssumeDefs = !this.state.goalDefinitions.isEmpty();
//
//        String goalAndAssumeDefs = (hasGoalDefs ? setOfStringsToList(this.state.assumpDefinitions)
//                : "")
//                + ((hasGoalDefs && hasAssumeDefs) ? ", " : "")
//                + (hasAssumeDefs ? this.state.goalDefinitions.toCommaSeparatedString()
//                        : "");
//        if (sufficesOnly) {
//            if (this.proof != null) {
//                qedStep = concatStringArrays(new String[] { qedStep[0] },
//                        prependToStringArray(proofText, proofIndentString));
//            } else {
//                qedStep[1] = "";
//            }
//        } else {
//            // Either not a suffices only proof, or proof = null. In
//            // either case, can construct the QED step as if it
//            boolean hasDEF = false;
//            if (hasGoalDefs || hasAssumeDefs) {
//                hasDEF = true;
//                qedStep[1] = qedStep[1] + " DEF " + goalAndAssumeDefs;
//            }
//            if (proofDef != null) {
//                if (hasDEF) {
//                    qedStep[1] = qedStep[1] + ", " + proofDef;
//                } else {
//                    qedStep[1] = qedStep[1] + " DEF " + proofDef;
//                }
//            }
//        }
// Here's where we can stop changing things (I hope) 
        String[] blankLine = new String[] { "" };
        String[] completeProof = new String[0];
        if (sufficesStep != null) {
            if (BLANK_LINE_BETWEEN_STEPS) {
                completeProof = concatStringArrays(sufficesStep, blankLine);
            } else {
                completeProof = sufficesStep;
            }
        }

        if (mainProofSteps != null) {
            completeProof = concatStringArrays(completeProof, mainProofSteps[0]);
            for (int i = 1; i < mainProofSteps.length; i++) {
                if (BLANK_LINE_BETWEEN_STEPS) {
                    completeProof = concatStringArrays(completeProof,
                            concatStringArrays(blankLine, mainProofSteps[i]));
                } else {
                    completeProof = concatStringArrays(completeProof,
                            mainProofSteps[i]);
                }
            }

            if (BLANK_LINE_BETWEEN_STEPS) {
                completeProof = concatStringArrays(completeProof, blankLine);
            }
        }
        completeProof = concatStringArrays(completeProof, qedStep);

        // we indent the proof.
        completeProof = prependToStringArray(
                completeProof,
                StringHelper.copyString(" ", this.step.getLocation()
                        .beginColumn() - 1 + proofIndent));

        // we now add the proof to the module. We put it on the line
        // after the last line of the theorem.
        try {
            int nextLineOffset = doc.getLineInformation(
                    this.step.getTheorem().getLocation().endLine()).getOffset();
            this.doc.replace(nextLineOffset, 0,
                    stringArrayToString(completeProof) + "\n");
        } catch (BadLocationException e) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "An error that should not happen has occurred in "
                            + "line 3845 of DecomposeProofHandler.");
            e.printStackTrace();
        }

        // We dispose of the window. The disposal listener will do
        // everythingthat's supposed to happen when the window is
        // removed.
        this.windowShell.dispose();
        return;
    }

    /**
     * Adds the proof steps for a CASE decomposition.
     * 
     * @param pfStepVec
     *            The vector to which proof steps should be added.
     * @param childVec
     *            The vector of CASE assumptions' NodeRepresentation objects,
     *            which may include OR_DECOMP nodes.
     * @param assumpArray
     *            The assumptions that must be prepended to each case.
     * @param proofText
     *            The user's proof, or null if none.
     *            
     * @param assumpArrayAsFormula
     *            Non-null iff all the assumptions in assumpArray are formulas,
     *            (so none are NEW declarations), in which case it is assumpArray
     *            written as a single formula (which is a conjunction if assumpArray
     *            has length > 1).
     */
    void addCaseProofs(Vector<String[]> pfStepVec,
            Vector<NodeRepresentation> childVec, String[] assumpArray,
            String[] proofText, String[] assumpArrayAsFormula) {

        // Set newAssumpArray to the concatenation of assumpArray and
        // the NEW assumptions of childVec --- which must be all the elements of
        // childVec except the last.
        // First set newAssumpCount to the length of newAssumpArray. Note that
        // it includes the last element of childVec iff that element is not an
        // OR_DECOMP
        // node.
        int newAssumpCount = assumpArray.length;

        String[] newAssumpArrayAsFormula = assumpArrayAsFormula ;
                if (childVec.elementAt(0).nodeType == NodeRepresentation.NEW_NODE){
                    newAssumpArrayAsFormula = null ;
                }
                else {
                    newAssumpArrayAsFormula = new String[0] ;
                }

        NodeRepresentation lastChildNode = childVec
                .elementAt(childVec.size() - 1);

        // The assumptions to be added to newAssumpArray the elements 0 through
        // lenOfChildAssumps - 1.
        int lenOfChildAssumps = childVec.size();
        if (lastChildNode.nodeType == NodeRepresentation.OR_DECOMP) {
            lenOfChildAssumps--;
        }

        for (int i = 0; i < lenOfChildAssumps; i++) {
            newAssumpCount = newAssumpCount
                    + childVec.elementAt(i).primedNodeText().length;
            
        }
        String[] newAssumpArray = new String[newAssumpCount];
        for (int i = 0; i < assumpArray.length; i++) {
            newAssumpArray[i] = assumpArray[i];
        }
        if (lenOfChildAssumps > 0) {
            if (assumpArray.length > 0) {
                newAssumpArray[assumpArray.length - 1] = newAssumpArray[assumpArray.length - 1]
                        + ",";
            }
            int idx = assumpArray.length;
            for (int i = 0; i < lenOfChildAssumps; i++) {
                String[] assump = childVec.elementAt(i).primedNodeText();
                for (int j = 0; j < assump.length; j++) {
                    newAssumpArray[idx] = assump[j];
                    idx++;
                }
                if (i != lenOfChildAssumps - 1) {
                    newAssumpArray[idx - 1] = newAssumpArray[idx - 1] + ",";
                }
            }
        }

        if (lastChildNode.nodeType == NodeRepresentation.OR_DECOMP) {
            // Need to recurse through the children
            for (int i = 0; i < lastChildNode.children.size(); i++) {
                addCaseProofs(pfStepVec, lastChildNode.children.elementAt(i),
                        newAssumpArray, proofText, newAssumpArrayAsFormula);
            }
        } else {
            // This is a terminal node. Construct the proof step.
            // Set step to the step's obligation.
            String[] step;
            // We use a CASE step if there's just a single new assumption,
            //  assumpArrayAsFormula != false, and "use CASE" is selected.

            if ((assumpArrayAsFormula != null) && useCaseButton.getSelection() && (childVec.size() == 1)) {
                // This is a CASE step.
                if (assumpArrayAsFormula.length == 0) {
                   // There are no assumptions to add.
                   step = prependToStringArray(lastChildNode.primedNodeText(),
                           "CASE ");
                } 
                else {
                  // Bug fixed 16 Nov 2014: Forgot that we need to prepend
                  // /\ to assumpArrayAsFormula if it is not a conjunction list.
                  // Rather than looking to see if we can just modify asssumpArrayAsFormula
                  // outside the loop, we re-add the /\ if necessary for each
                  // proof step.
                    String[] aarrayAsForm = assumpArrayAsFormula.clone() ;
                    if (assumpArrayAsFormula.length == 1) {
                        aarrayAsForm[0] = "/\\ " + aarrayAsForm[0] ;
                    }
                    step = prependToStringArray(
                            concatStringArrays(aarrayAsForm, 
                                               prependToStringArray(
                                                     lastChildNode.primedNodeText(),
                                                     "/\\ "))  ,
                            "CASE ");
                }
            } else {
                // This is an ASSUME/PROVE step.
                step = concatStringArrays(
                        prependToStringArray(newAssumpArray, "ASSUME "),
                        prependToStringArray(
                                this.state.goalRep.primedNodeText(), "PROVE  "));
            }

            String stepNum = proofLevelString + (pfStepVec.size() + 1);
            step = prependToStringArray(step, stepNum + STEP_NUMBER_PUNCTUATION
                    + " ");
            // Add the proof to step, if there is one. Since this is always
            // either
            // a CASE or an ASSUME/PROVE, if there is a proof, then we must add
            // the step
            // number to the proof's BY facts.
            if (proofText != null) {
                String[] newProofText = proofText.clone();
                addStepNumToProof(stepNum, newProofText);
                step = concatStringArrays(step, newProofText);
            }
            pfStepVec.add(step);
        }

    }

    /**
     * Adds the stepNum as a fact to the BY part of the leaf proof represented
     * by proofText--unless the proof is "OMITTED", in which case it does
     * nothing.
     * 
     * @param stepNum
     *            A step number such as "<2>3"
     * @param proofText
     *            A leaf proof as a string array of the proof of the step being
     *            decomposed, which is assumed to be non-null.
     */
    private void addStepNumToProof(String stepNum, String[] proofText) {
        LeafProofNode pfNode = (LeafProofNode) this.proof;

        if (pfNode.getOmitted()) {
            return;
        }

        if (((pfNode.getFacts() == null) || (pfNode.getFacts().length == 0))
                && ((pfNode.getDefs() == null) || (pfNode.getDefs().length == 0))) {
            // This is an "OBVIOUS" proof. Must replace the "OBVIOUS"
            // by "BY " + stepNum
            int i = 0;
            boolean notDone = true;
            while (notDone && (i < proofText.length)) {
                int idx = proofText[i].indexOf("OBVIOUS");
                if (idx != -1) {
                    proofText[i] = proofText[i].replaceFirst("OBVIOUS", "BY "
                            + stepNum);
                    notDone = false;
                }
                i++;
            }
        } else {
            // There is a "BY". Set comesAfter to either "BY"
            // or "ONLY", depending on whether there is not or there
            // is not a "BY ONLY"
            String comesAfter = "BY";
            if (pfNode.getOnlyFlag()) {
                comesAfter = "ONLY";
            }

            // Have to add a "," after stepNum if there already are BY
            // facts.
            String stepNumAdded = stepNum;
            if ((pfNode.getFacts() != null) && (pfNode.getFacts().length > 0)) {
                stepNumAdded = stepNum + ",";
            }
            int i = 0;
            boolean notDone = true;
            while (notDone && (i < proofText.length)) {
                int idx = proofText[i].indexOf(comesAfter);
                if (idx != -1) {
                    proofText[i] = proofText[i].replaceFirst(comesAfter,
                            comesAfter + " " + stepNumAdded);
                    notDone = false;
                }
                i++;
            }
        }
    }

    /**
     * Returns the NodeRepresentation for a child in nodeRep's decomposition
     * when nodeRep's formula is decomposed. It is called when processing an
     * AND-split, => Split, or OR split action.  It assumes that the result
     * is the goal iff vec = null ;
     * 
     * @param nodeRep
     *            The NodeRepresentation whose decomposition child's
     *            representation is returned.
     * @param i
     *            The index of the child in nodeRep's decomposition's children
     *            vector.
     * @param vec
     *            The result's parentVector field.
     * @param father
     *            The result's parentNode field.
     * @return
     */
    /**
     * @param nodeRep
     * @param i
     * @param vec
     * @param father
     * @return
     */
    /**
     * @param nodeRep
     * @param i
     * @param vec
     * @param father
     * @return
     */
    NodeRepresentation decompositionChildToNodeRep(NodeRepresentation nodeRep,
            int i, Vector<NodeRepresentation> vec, NodeRepresentation father) {
        // decomp is the nodeRep's decomposition
        Decomposition decomp = nodeRep.decomposition;

        // Set newNodeText to be null if the result's nodeText is to be obtained
        // from nodeText's semantic node. Otherwise, set it to the appropriate
        // subexpression name.
        NodeTextRep newNodeText = null;
        if ((decomp.definedOp != null)
                && this.subexpressionButton.getSelection()) {
            newNodeText = appendToNodeText(decomp.definedOpRep,
                    decomp.namePath.elementAt(i));
        } else if (nodeRep.isSubexpressionName) {
            newNodeText = appendToNodeText(new NodeTextRep(nodeRep.nodeText,
                    nodeRep.mapping), decomp.namePath.elementAt(i));
        }

        // Set childDoc to the IDocument in which the children are to
        // be found. 
        IDocument childDoc = this.doc;
        String moduleName = this.moduleNode.getName().toString() ;
        if (decomp.moduleName != null) {
            childDoc = moduleNameToIDocument(decomp.moduleName) ;
        }

        // Set result to the node representation.
        NodeRepresentation result;
        
        if ((decomp.definedOp != null) && (newNodeText == null)) {
            // Have to expand nodeRep's definition node.
            try {
                // this.doc replaced by childDoc by LL 15 Aug 2014:
                NodeRepresentation res = new NodeRepresentation(childDoc,
                        decomp.children.elementAt(i));
                NodeTextRep ntext = decompSubstituteInNodeText(nodeRep,
                        (ExprNode) decomp.children.elementAt(i),
                        new NodeTextRep(res.nodeText, res.mapping), nodeRep);
                res.nodeText = ntext.nodeText;
                res.mapping = ntext.mapping;
                // Following added 2 Dec 2014
                if (res.decomposition != null) {
                    res.decomposition.renaming = ntext.renaming;
                }
                res.instantiationSubstitutions = decomp.instantiationSubstitutions.clone();

                // This is a hack, calling subNodeRep for the subnode of
                // the definition body consisting of the entire definition body.
                // But a little thought reveals that this does what needs to be
                // done.
                result = res.subNodeRep(decomp.children.elementAt(i), vec,
                        father, null, decomp, vec != null);
                result.isPrimed = nodeRep.isPrimed;
                if (result.decomposition != null) { // null test added 4 Dec 2014
                    result.decomposition.renaming = 
                            result.decomposition.renaming.addAll(ntext.renaming);  
                }
                
                if (!(decomp.children.elementAt(i) instanceof ExprNode)) {
                    MessageDialog.openError(UIHelper.getShellProvider()
                            .getShell(), "Decompose Proof Command",
                            "An error that should not happen has occurred in "
                                    + "line 4152 of DecomposeProofHandler.");
                }
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "An error that should not happen has occurred in "
                                + "line 4160 of DecomposeProofHandler.");
                return null;
            }
            // We now perform the substitutions in result
            // based on its instantiationSubstitutions field.
            // If it's not an OpApplNode, then there should be
            // not substitutions to be made.  (This can happen
            // if it's something weird like a number.  I don't
            // know if there are any non-weird cases.)
            if (result.semanticNode instanceof OpApplNode) {
                NodeTextRep ntr = result.toNodeTextRep() ;
                ntr = instantiateInNodeText(
                        OpDeclNodeVectorToArray(decomp.instantiationSubstitutions.params), 
                        StringVectorToArray(decomp.instantiationSubstitutions.substs), 
                        (OpApplNode) result.semanticNode, 
                        ntr);
                ntr = renameInNodeText((OpApplNode) result.semanticNode, 
                                       ntr, decomp.instantiationSubstitutions.prefix, 
                                       "") ;
                if (ntr == null) {
                    return null ;
                }
                result.nodeText = ntr.nodeText ;
                result.mapping = ntr.mapping ;    
            }
   

        } else {
            // Call subNodeRep to construct the result.
            result = nodeRep.subNodeRep(decomp.children.elementAt(i), vec,
                  father, newNodeText, decomp, vec != null);
            NodeTextRep ntext = decompSubstituteInNodeText(nodeRep,
                    (ExprNode) decomp.children.elementAt(i),
                    new NodeTextRep(result.nodeText, result.mapping), nodeRep);
            result.nodeText = ntext.nodeText;
            result.mapping = ntext.mapping;
            // Following added 2 Dec 2014
            if (result.decomposition != null) {
                result.decomposition.renaming = ntext.renaming;
            }
             
            
        }
        // Set various fields whose values can be inferred from nodeRep and
        // decomp.
        // Don't set rep.isCreated because don't want it set for an
        // AND-split of an assumption, unless that assumption came from
        // a split of the goal.
        result.isPrimed = result.isPrimed || decomp.primed;
        result.isSubexpressionName = nodeRep.isSubexpressionName
                || newNodeText != null;
        result.initialPosition = nodeRep.initialPosition ;
        result.contextStepName = nodeRep.contextStepName ;
        result.fromGoal = nodeRep.fromGoal ;
        result.fromExists = nodeRep.fromExists ;
        result.fromDefs = nodeRep.fromDefs.clone();
        result.instantiationSubstitutions = decomp.instantiationSubstitutions ;
        if (decomp.definedOp != null) {
            result.fromDefs.add(nodeRep.instantiationSubstitutions.prefix + decomp.definedOp) ;
        }
        return result;
    }
    
    // The following code was copied from the jumpToLocation
    // method in UIHelper.java
    IDocument moduleNameToIDocument(String moduleName) {
        IDocument result = this.moduleNameToDoc.get(moduleName) ;
        if (result == null ) {
            IFile moduleIFile = (IFile) ResourceHelper
                    .getResourceByModuleName(moduleName);
            FileEditorInput fileEditorInput = new FileEditorInput(moduleIFile);
            FileDocumentProvider moduleFileDocProvider = new FileDocumentProvider();

            try {
                moduleFileDocProvider.connect(fileEditorInput);
            } catch (CoreException e1) { // I don't know what to do here
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "An error that should not happen has occurred in "
                                + "line 4239 of DecomposeProofHandler.");
            }
            result = moduleFileDocProvider.getDocument(fileEditorInput);
        }
        return result ;
    }

    /**
     * Since Java doesn't allow structs, this is a class whose sole purpose is
     * to provide a return type for the following method. Its fields are a
     * vector of NodeRepresentations that will be a vector of NEW nodes obtained
     * from a quantified expression, and a NodeRepresentation obtained from the
     * body of that expression.
     */
    static class QuantifierDecomposition {
        Vector<NodeRepresentation> news;
        NodeRepresentation body;
    }

    /**
     * Returns the NodeRepresentations of the nodes forming the decomposition
     * for a \A or \E split. It assumes that the decomposition is a \A or \E
     * decomposition, so its quantIds field is not null. The NodeRepresentations
     * for the NEW assumptions are given a null semanticNode field, since I
     * don't think that field is ever used once decomposition begins. The
     * isForAll argument is used to determine whether the body's created field
     * should be set true.
     * 
     * If this is a top-level \E split, then the NEW variables may have to be
     * changed to avoid name clashes with NEW variables or other bound variables
     * of later assumptions or of the goal. This is not a problem for a \A split
     * because, since the \A formula is the goal, there are no later items to
     * clash with.  THE LATTER IS NO LONGER VALID WITH THE NEW METHOD FOR ORDERING
     * ASSUMPTIONS.  IT LED TO BUGS IN THE OLD VERSION BECAUSE THE \A SPLIT NEW
     * ASSUMPTION COULD APPEAR BEFORE CASE-SPLIT ASSUMPTIONS.
     * 
     * If the node cannot be decomposed--for example, if an operator is
     * instantiated with a multi-line expression--then null is returned.
     * 
     * 
     * @param nodeRepArg
     *            The node being decomposed.
     * @param isForAll
     *            True iff this is called for a \A split
     * @return
     */
    QuantifierDecomposition decomposeQuantifier(NodeRepresentation nodeRepArg,
            boolean isForAll) {
        QuantifierDecomposition result = new QuantifierDecomposition();
        result.news = new Vector<NodeRepresentation>();
        NodeRepresentation nodeRep = nodeRepArg;
        Decomposition decomp = nodeRep.decomposition;

        // If this is within the subexpression-name expansion of a definition,
        // set NodeTextRep to the NodeTextRep that is the name of the formula
        // represented by nodeRep.
        NodeTextRep newNodeText = null;
        if ((decomp.definedOp != null) && (subexpressionButton.getSelection())) {
            newNodeText = decomp.definedOpRep;
        } else if (nodeRep.isSubexpressionName) {
            newNodeText = new NodeTextRep(nodeRep.nodeText, nodeRep.mapping);
        } else if (decomp.definedOp != null) {
            // Must expand the definition. We do this by creating a new
            // NodeRepresentation whose semanticNode, nodeText, and mapping
            // fields are what they should be for the definition body,
            // and creating a decomposition field for it.
            try {
                // NEED TO SUBSTITUTE FOR DEFINITION'S FORMAL PARAMETERS

                // Strip prime from nodeRepArg.semanticNode if it has one.
                if (!(nodeRepArg.semanticNode instanceof OpApplNode)) {
                    MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "Something unexpected is going on at "
                                    + "line 4313 of DecomposeProofHandler.");
                    return null;
                }
                OpApplNode oan = (OpApplNode) nodeRepArg.semanticNode;
                if (oan.getOperator().getName() == ASTConstants.OP_prime) {
                    oan = (OpApplNode) oan.getArgs()[0];
                }
                              
                // Set instSubs to the new InstanceSubstitution for the decomposition 
                // nodes and sn to the (OpArgNode) at the bottom of the SubstInNode chain.
                InstanceSubstitution instSubs = decomp.instantiationSubstitutions.clone(); 
                ExprNode sn = ((OpDefNode) oan.getOperator()).getBody();
                while (sn instanceof SubstInNode) {
                    sn = ((SubstInNode)sn).getBody() ; 
                }

                // Need to create the NodeRepresentation using the
                // module in which the definition occurs.  
                String moduleName = sn.getLocation().source() ;
                IDocument idoc = moduleNameToIDocument(moduleName);
                NodeRepresentation res = new NodeRepresentation(idoc, sn);
                // This is a hack, calling subNodeRep for the subnode of
                // the definition body consisting of the entire definition body.
                // But a little thought reveals that this does what needs to be 
                // done. 
                // Note: I don't know if the last argument of the subNodeRep call
                // matters.  But it may affect whether the resulting assumption
                // is displayed.
                nodeRep = res.subNodeRep(sn, nodeRepArg.getParentVector(),
                        nodeRepArg.parentNode, null, decomp, !isForAll);
                nodeRep.isPrimed = nodeRepArg.isPrimed;
                nodeRep.fromGoal = nodeRepArg.fromGoal ;
                nodeRep.fromExists = nodeRepArg.fromExists ;
                nodeRep.fromDefs = nodeRepArg.fromDefs.clone() ;
                nodeRep.instantiationSubstitutions = instSubs ;
                if (decomp.definedOp != null) {
                    nodeRep.fromDefs.add(
                        nodeRepArg.instantiationSubstitutions.prefix + decomp.definedOp) ;
                }
                

                // We now perform the substitutions in nodeRep
                // based on its instantiationSubstitutions field.
                NodeTextRep ntr = nodeRep.toNodeTextRep() ;
                ntr = instantiateInNodeText(
                        OpDeclNodeVectorToArray(nodeRep.instantiationSubstitutions.params), 
                        StringVectorToArray(nodeRep.instantiationSubstitutions.substs), 
                        (OpApplNode) nodeRep.semanticNode, 
                        ntr);
                ntr = renameInNodeText((OpApplNode) nodeRep.semanticNode, 
                                       ntr, nodeRep.instantiationSubstitutions.prefix, 
                                       "") ;
                if (ntr == null) {
                    return null ;
                }
                nodeRep.nodeText = ntr.nodeText ;
                nodeRep.mapping = ntr.mapping ;
                
                nodeRep.decomposition.formalParams = nodeRepArg.decomposition.formalParams;
                nodeRep.decomposition.arguments = nodeRepArg.decomposition.arguments;
                nodeRep.decomposition.argNodes = nodeRepArg.decomposition.argNodes;

                NodeTextRep ntext = decompSubstituteInNodeText(nodeRep, sn,
                        new NodeTextRep(nodeRep.nodeText, nodeRep.mapping),
                        nodeRepArg);
                nodeRep.nodeText = ntext.nodeText;
                nodeRep.mapping = ntext.mapping;
                // Following added 2 Dec 2014
                if (nodeRep.decomposition != null) {
                   nodeRep.decomposition.renaming = ntext.renaming;
                }
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "An error that should not happen has occurred in "
                                + "line 4390 of DecomposeProofHandler.");
                return null;
            }
        }

        // At this point, for a \E decomposition, we must perform any needed
        // substitutions in nodeRep for the \E's bound identifiers that can
        // cause a clash with bound identifiers or NEW declarations that occur
        // after this assumption.

        // Set idsToRename to the vector of NEW identifiers to be renamed,
        // and set idNewNames to the vector of their new names. These will be
        // empty vectors for a \A decomposition.
        Vector<FormalParamNode> idsToRename = new Vector<FormalParamNode>();
        Vector<String> idNewNames = new Vector<String>();

        if (!isForAll) {
            // Set prevDeclared to the set of all identifiers declared or
            // defined at the location of nodeRepArg.
            // Bug discovered 2 Dec 2014: need also add to prevDeclared
            // all later uses of bound identifiers that could cause a conflict
            // that requires renaming of the NEW declaration(s) to be added.
            StringSet prevDeclared = this.declaredIdentifiers.clone();
            addDeclaredSymbols(prevDeclared, nodeRepArg);

            addSymbolsDeclaredLater(prevDeclared, nodeRepArg, true);

            // set idsToRename to the vector of NEW identifiers to be renamed,
            // and set idNewNames to the vector of their new names.
            // nrenaming is the renaming field of nodeRep, which will have
            // changed if the
            for (int i = 0; i < decomp.quantIds.size(); i++) {
                FormalParamNode id = decomp.quantIds.elementAt(i);
                if (prevDeclared.contains(getCurrentName(id, decomp.renaming))) {
                    idsToRename.add(id);
                    idNewNames
                            .add(getNewName(id, prevDeclared, decomp.renaming));
                }
            }

            // Call substituteInNode to do the renamings in nodeRep.
            FormalParamNode[] formalParams = new FormalParamNode[idsToRename
                    .size()];
            String[] arguments = new String[idsToRename.size()];
            boolean[] isBoundedIdRenaming = new boolean[idsToRename.size()];
            SemanticNode[] argNodes = new SemanticNode[idsToRename.size()];
            for (int i = 0; i < idsToRename.size(); i++) {
                formalParams[i] = idsToRename.elementAt(i);
                arguments[i] = idNewNames.elementAt(i);
                isBoundedIdRenaming[i] = true;
                argNodes[i] = null;
            }

            NodeTextRep nText = substituteInNodeText(formalParams, arguments,
                    isBoundedIdRenaming, argNodes,
                    (ExprNode) nodeRep.semanticNode, new NodeTextRep(
                            nodeRep.nodeText, nodeRep.mapping),
                    nodeRep.decomposition);
            nodeRep.nodeText = nText.nodeText;
            nodeRep.mapping = nText.mapping;
            for (int i = 0; i < idsToRename.size(); i++) {
                addCurrentName(idsToRename.elementAt(i),
                        idNewNames.elementAt(i), nodeRep.decomposition.renaming);
                addCurrentName(idsToRename.elementAt(i),
                        idNewNames.elementAt(i), state.renaming); // added 3 Dec 2014
            }
        }

        int lastLine = -1;
        for (int i = 0; i < decomp.quantIds.size(); i++) {
            // Loop invariant:
            // lastRow != -1 iff
            // /\ i > 0
            // /\ \/ this is an unbounded quantifier
            //    \/ the i-1st NEW fits entirely on line lastLine
            NodeRepresentation rep = new NodeRepresentation();
            rep.initialPosition = nodeRepArg.initialPosition ;
            rep.semanticNode = null;
            rep.nodeType = NodeRepresentation.NEW_NODE;
            rep.newId = getCurrentName(decomp.quantIds.elementAt(i),
                    nodeRep.decomposition.renaming);
            rep.isCreated = true;
            rep.parentNode = nodeRep.parentNode;
            if (nodeRep.getParentVector() != null) {
                rep.setParentVector(nodeRep.getParentVector());
            } else {
                // nodeRep is the current goal and so the NEW assumptions
                // will become top-level assumptions and rep.parentVector
                // should be set to the DecomposeProofHandler's assumeRep
                // vector.
                rep.setParentVector(this.state.assumeReps);
            }

            // set id to "NEW" plus the bound identifier
            NodeTextRep ntrep = new NodeTextRep();
            String id = "NEW " + rep.newId;
            // + decomp.quantIds.elementAt(i).getName().toString();

            // beginLine is set to the line containing the source if there is
            // no quantifier bound or the quantifier bound occupies a single
            // line. Otherwise, it is set to -1.
            int beginLine = ((SyntaxTreeNode) decomp.quantIds.elementAt(i).stn)
                    .getLocation().beginLine();
            if (decomp.quantBounds == null) {
                // Set ntrep to a trivial NodeTextRep representing a
                // 1-line string with a standard mapping that should never
                // be used.
                ntrep.nodeText = new String[1];
                ntrep.nodeText[0] = id;
                ntrep.mapping = new Vector[1];
                ntrep.mapping[0] = new Vector<MappingPair>();
                ntrep.mapping[0].addElement(new MappingPair(1, -1));
            } else {
                // Set ntrep to be a NodeTextRep for the quantifier bound,
                // primed if decomp.primed or nodeRep.isPrimed is = true.
                if (newNodeText == null) {
                    // The bound is not a subexpression name.
                    ntrep = nodeRep
                            .subNodeText(decomp.quantBounds.elementAt(i));
                    if (decomp.primed || nodeRep.isPrimed) {
                        if (primingNeedsParens(decomp.quantBounds.elementAt(i))) {
                            ntrep = prependToNodeText(
                                    appendToNodeText(ntrep, ")'"), "(");
                        } else {
                            ntrep = appendToNodeText(ntrep, "'");
                        }
                    }
                } else {
                    // The bound is a subexpression name.
                    String str = decomp.quantBoundsubexpNames.elementAt(i);
                    if (decomp.primed) {
                        str = str + "'";
                    }
                    ntrep = appendToNodeText(newNodeText, str);
                }
                ntrep = prependToNodeText(ntrep, " \\in ");
                if (ntrep.nodeText.length > 1) {
                    beginLine = -1;
                }
            }

            if (decomp.quantBounds != null) {
                ntrep = prependToNodeText(ntrep, id);
                // Following added 3 Dec 2014
                rep.semanticNode = decomp.quantBounds.elementAt(i) ;
            }
            rep.nodeText = ntrep.nodeText;
            rep.mapping = ntrep.mapping;
            
            // Set node's contextStepName to be that of nodeRepArg
            rep.contextStepName = nodeRepArg.contextStepName ;
            rep.fromGoal = nodeRepArg.fromGoal ;
            // nodeRep.fromDefs = 
            // IF nodeRep obtained from nodeRepArg  by expanding def of Op
            //   THEN nodeRepArg.fromDefs \cup {Op}
            //   ELSE nodeRepArg.fromDefs
            rep.fromDefs = nodeRep.fromDefs ;

            result.news.add(rep) ;
            if ((beginLine != -1) && (beginLine == lastLine)) {
                result.news.elementAt(i - 1).onSameLineAsNext = true;
            }
            lastLine = beginLine;
        }

        // We next compute the NodeRepresentation for the body of the quantified
        // expression.
        if (newNodeText != null) {
            // We are using subexpression names, so we append to newNodeText
            // the "!(id1, ... , idn)" needed to form the subexpression name
            // of the body.
            String str = "!(";
            for (int i = 0; i < decomp.quantIds.size(); i++) {
                if (i != 0) {
                    str = str + ", ";
                }
                str = str + decomp.quantIds.elementAt(i).getName().toString();
            }
            str = str + ")";
            newNodeText = appendToNodeText(newNodeText, str);
        }
        result.body = nodeRep.subNodeRep(decomp.children.elementAt(0),
                nodeRep.getParentVector(), nodeRep.parentNode, newNodeText,
                nodeRep.decomposition, !isForAll);
        result.body.isCreated = true ; // changed to true from isForAll by LL on 8 Oct 2014
        result.body.isPrimed = result.body.isPrimed || decomp.primed;
        result.body.isSubexpressionName = nodeRep.isSubexpressionName
                || (newNodeText != null);
        result.body.initialPosition = nodeRepArg.initialPosition ;
        // set contextStepName for the body.
        result.body.contextStepName = nodeRepArg.contextStepName ;
        result.body.fromGoal = nodeRep.fromGoal ;
        result.body.fromExists = nodeRep.fromExists ;
        result.body.fromDefs = nodeRep.fromDefs.clone() ;
        return result;
    }

    /**
     * Returns string array such that applying stringArrayToString to it
     * produces the text of the list of assumptions in createdAssumps of
     * the spec of MakeProof.
     */
    String[] createdAssumptions() {
        /**
         * Sets vec to a vector of string arrays such that applying
         * stringArrayToString to each of them produces the text of an
         * assumption in this.state.assumeReps for which the isCreated field
         * equals true--except that multiple one-line NEW assumptions are
         * combined into a single 1-line string array.
         */
        Boolean sufficesSelected = useSufficesButton.getSelection();
        Vector<String[]> vec = new Vector<String[]>();
        
        // Set lastAddedAssump so that state.firstAddedAssumption .. lastAddedAssump-1
        // are the added non-case-split assumptions of state.assumeReps.
        int lastAddedAssump = state.assumeReps.size() ;
        if (state.splitChosen()) {
            lastAddedAssump--;
        }
        
        for (int i = state.firstAddedAssumption; i < lastAddedAssump; i++) {
            NodeRepresentation rep = state.assumeReps.elementAt(i);
                String newDecls = null;
                while (rep.onSameLineAsNext) {
                    if (newDecls != null) {
                        newDecls = newDecls + ", ";
                    } else {
                        newDecls = "";
                    }
                    newDecls = newDecls + rep.nodeText[0];
                    i++;
                    rep = state.assumeReps.elementAt(i);
                }
                if (newDecls == null) {
                    vec.add(rep.primedNodeText());
                } else {
                    vec.add(new String[] { newDecls + ", " + rep.nodeText[0] });
                }
//            }
        }

        /**
         * Sets resVec to a single vector obtained by combining the elements of
         * vec, putting commas between them.
         */
        Vector<String> resVec = new Vector<String>();
        for (int i = 0; i < vec.size(); i++) {
            String[] strArray = vec.elementAt(i);
            for (int j = 0; j < strArray.length; j++) {
                String str = strArray[j];
                if ((j == strArray.length - 1) && (i != vec.size() - 1)) {
                    str = str + ",";
                }
                resVec.add(str);
            }
        }

        // Convert resVec to the array result and return it.
        String[] result = new String[resVec.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = resVec.elementAt(i);
        }
        return result;
    }

    /**
     * The following bug fixed by LL on 3 July 2014: Decomposing
     * 
     * foo(p) == \A x : p <=> A \/ B 
     * THEOREM foo(\/ C')
     * 
     * produces the new goal
     * 
     * ASSUME NEW x PROVE \/ C' <=> A \/ B 
     * --------- 
     * Assumes that nodeTextRep is
     * the NodeTextRep for the ExprNode sn (possibly after some substitutions
     * have been made). It returns the NodeTextRep object representing sn after
     * substituting arguments[i] for formalParams[i], for each i. It assumes
     * that argNodes[i] is the semantic node whose string representation is
     * arguments[i]. That string representation must be a single-line string (no
     * line breaks).
     * 
     * Note: this assumes that none of the substitutions made before this one
     * have added any of the formal parameter symbols being substituted for. We
     * also assume that the node sn is being used as a complete assume clause or
     * goal.
     * 
     * @param formalParams
     *            The formal parameters to be substituted for.
     * @param arguments
     *            The String representations of argNodes, which must be a
     *            single-line expression.
     * @param isBoundedIdRenaming
     *            An array whose i-th element is true iff formalParams[i] is the
     *            FormalParamNode of a bound identifier in sn that is being
     *            renamed to arguments[i].
     * @param argNodes
     *            The semantic nodes of the expressions to be substituted,
     *            except that argNodes[i] is not used and may be null if
     *            isBoundedIdRenaming[i] = true.
     * @param sn
     *            SemanticNode in which the substitutions are being made.
     * @param nodeTextRep
     *            Representation of sn (perhaps after other substitutions).
     * @param decomp
     *            A decomposition from which to find renamings of identifiers.
     * @return
     */
    NodeTextRep substituteInNodeText(FormalParamNode[] formalParams,
            String[] arguments, boolean[] isBoundedIdRenaming,
            SemanticNode[] argNodes, ExprNode sn, NodeTextRep nodeTextRep,
            Decomposition decomp) {
        NodeTextRep result = nodeTextRep.clone();

        int numOfLines = result.nodeText.length;

        // We set inserts to an array of Insertion vectors that describe the
        // modification made
        // to nodeTextRep to get result. This is used to call adjustIndentation
        // to fix the
        // indentation of result.
        Vector<Insertion>[] inserts = new Vector[numOfLines];
        for (int i = 0; i < numOfLines; i++) {
            inserts[i] = new Vector();
        }
        // Line of first token of sn, used to translate from Location line
        // numbers to
        // indices in noteTextRep.nodeText.
        int beginLine = sn.stn.getLocation().beginLine();

        for (int i = 0; i < arguments.length; i++) {
            SemanticNode[] uses = ResourceHelper.getUsesOfSymbol(
                    formalParams[i], sn);

            String replacementText = arguments[i];

            // NOTE: If we were substituting for a formal parameter for which a
            // different identifier had been substituted, we have to use as
            // sourceTextLength the length of the new identifier.
            int sourceTextLength = getCurrentName(formalParams[i],
                    decomp.renaming).length();
            // Set mayNeedParens true if replacementText doesn't end in ' and
            // would
            // need parentheses around it in order to prime it.
            boolean mayNeedParens = false;
            if (primingNeedsParens(argNodes[i])
                    && ((replacementText.charAt(replacementText.length() - 1) != '\'')
                            // Following disjuncts added on 3 July 2014 to fix
                            // bug
                            // described above.
                            || replacementText.startsWith("\\/") || replacementText
                                .startsWith("/\\"))) {
                mayNeedParens = true;
            }
            for (int j = 0; j < uses.length; j++) {
                if (!(uses[j] instanceof OpApplNode)) {
                    MessageDialog.openError(UIHelper.getShellProvider()
                            .getShell(), "Decompose Proof Command",
                            "An error that should not happen has occurred in "
                                    + "line 4750 of DecomposeProofHandler.");
                    return result;
                }
                // Note: the following code outside the if (mayNeedParens) has
                // been cloned below for renaming the FormalParamNode
                // declaration
                // if isBoundedIdRenaming[i] is true.
                Location useLocation = uses[j].stn.getLocation();
                int useIdx = useLocation.beginLine() - beginLine;
                int offset = colToLoc(useLocation.beginColumn(),
                        result.mapping[useIdx]);
                String thisReplaceText = replacementText;
                if (mayNeedParens) {
                    // Define text that, if it surrounds the replaced text, implies
                    // that no parentheses are needed.
                    String[] precedingSafe = new String[] { "(", "[", "{", ",",
                            "<<", "->", ":" };
                    String[] followingSafe = new String[] { ")", "]", "}", ",",
                            ">>", "->", "~>" };

                    // Because we assume that the formula we're substituting
                    // into is a complete assumption or goal, the end of the 
                    // formula is also a safe preceding or following "string".
                    String testString = result.nodeText[useIdx].substring(0,
                            offset).trim();
                    int line = useIdx;
                    while (testString.equals("") && line > 0) {
                        line--;
                        testString = result.nodeText[line];
                    }
                    boolean terminated = testString.equals("");
                    int k = 0;
                    while (!terminated && k < precedingSafe.length) {
                        terminated = testString.endsWith(precedingSafe[k]);
                        k++;
                    }
                    if (terminated) {
                        testString = result.nodeText[useIdx].substring(
                                offset + sourceTextLength).trim();
                        line = useIdx;
                        while (testString.equals("")
                                && line < result.nodeText.length - 1) {
                            line++;
                            testString = result.nodeText[line];
                        }
                        terminated = testString.equals("");
                        k = 0;
                        while (!terminated && k < precedingSafe.length) {
                            terminated = testString
                                    .startsWith(followingSafe[k]);
                            k++;
                        }
                    }
                    if (!terminated) {
                        thisReplaceText = "(" + replacementText + ")";
                    }
                }
                result.nodeText[useIdx] = result.nodeText[useIdx].substring(0,
                        offset)
                        + thisReplaceText
                        + result.nodeText[useIdx].substring(offset
                                + sourceTextLength);
                adjustMappingPairVector(useLocation.beginColumn() + 1 // +1 added 28 Nov 2014
                        // LL-XXXXX I believe the "+ sourceTextLength"
                        // in the next line should be removed.
                        /* + sourceTextLength */, thisReplaceText.length()
                        - sourceTextLength, result.mapping[useIdx]);

                // Update inserts
                inserts[useIdx].add(new Insertion(offset, sourceTextLength,
                        thisReplaceText.length()));
            }

            // if isBoundedIdRenaming[i] is true, then rename the occurrence of
            // the FormalParamNode. The code was cloned for the code above that
            // renames uses.
            //
            // This can be called with decomp.renaming containing renamings for
            // bounded identifiers that occur in a different part of the spec
            // because we're now inside an expanded definition. We therefore
            // have to not try to do the renaming in that case.
            if (isBoundedIdRenaming[i]) {
                Location useLocation = formalParams[i].stn.getLocation();
                // We do this replacement iff the identifier declaration is
                // contained
                // in the location in which the renaming is being performed.
                if (EditorUtil.locationContainment(useLocation,
                        sn.stn.getLocation())) {
                    int useIdx = useLocation.beginLine() - beginLine;
                    int offset = colToLoc(useLocation.beginColumn(),
                            result.mapping[useIdx]);
                    result.nodeText[useIdx] = result.nodeText[useIdx]
                            .substring(0, offset)
                            + replacementText
                            + result.nodeText[useIdx].substring(offset
                                    + sourceTextLength);
                    adjustMappingPairVector(useLocation.beginColumn() + 1 // +1 added 28 Nov 2014
                            // LL-XXXXX commented out "+ sourceTextLength"
                            // because it looks funny
                            /* + sourceTextLength */, replacementText.length()
                            - sourceTextLength, result.mapping[useIdx]);

                    // Update inserts
                    inserts[useIdx].add(new Insertion(offset, sourceTextLength,
                            replacementText.length()));
                }
            }

        }

        // Adjust the indentation.
        adjustIndentation(nodeTextRep, result, inserts);

        return result;
    }
    
    
    /**
     * This method is a clone of substituteInNodeText.
     * 
     * Assumes that nodeTextRep is
     * the NodeTextRep for the ExprNode sn (possibly after some substitutions
     * have been made). It returns the NodeTextRep object representing sn after
     * substituting arguments[i] for formalParams[i], for each i. It assumes
     * that argNodes[i] is the semantic node whose string representation is
     * arguments[i]. That string representation must be a single-line string (no
     * line breaks).
     * 
     * The code being cloned has this note:
     *   This assumes that none of the substitutions made before this one
     *   have added any of the formal parameter symbols being substituted for.
     * I don't understand why, or if this applies to this method which is
     * to be used to substitute in the expressions in SubstInNodes--but only
     * under the assumption that they are single-line expressions. 
     * 
     * @param formalParams
     *            The formal parameters to be substituted for.
     * @param arguments
     *            The Strings to be substituted for the formalParams.
     * @param argNodes
     *            The semantic nodes of the expressions to be substituted.
     * @param sn
     *            SemanticNode in which the substitutions are being made.
     * @param nodeTextRep
     *            Representation of sn (perhaps after other substitutions).
     * @return
     */
    NodeTextRep  instantiateInNodeText(OpDeclNode[] formalParams,
            String[] arguments, ExprOrOpArgNode sn, NodeTextRep nodeTextRep) {
        NodeTextRep result = nodeTextRep.clone();

        int numOfLines = result.nodeText.length;

        // We set inserts to an array of Insertion vectors that describe the modification made
        // to nodeTextRep to get result.  This is used to call adjustIndentation to fix the
        // indentation of result.
        Vector<Insertion>[] inserts = new Vector[numOfLines];
        for (int i = 0; i < numOfLines; i++) {
            inserts[i] = new Vector();
        }
        // Line of first token of sn, used to translate from Location line numbers to
        // indices in noteTextRep.nodeText.
        int beginLine = sn.stn.getLocation().beginLine();

        for (int i = 0; i < arguments.length; i++) {
            SemanticNode[] uses = ResourceHelper.getUsesOfSymbol(
                    formalParams[i], sn);

            String replacementText = arguments[i];

            // NOTE: If we were substituting for a formal parameter for which a
            // different identifier had been substituted, we have to use as
            // sourceTextLength the length of the new identifier.
            int sourceTextLength = formalParams[i].getName().toString().length();
            // Set mayNeedParens true if replacementText doesn't end in ' and
            // would need parentheses around it in order to prime it.
            boolean mayNeedParens = false;
            if (primingNeedsParens(formalParams[i])
                    && ((replacementText.charAt(replacementText.length() - 1) != '\'')
                            // Following disjuncts added on 3 July 2014 to fix
                            // bug
                            // described above.
                            || replacementText.startsWith("\\/") || replacementText
                                .startsWith("/\\"))) {
                mayNeedParens = true;
            }
            for (int j = 0; j < uses.length; j++) {
            	// "|| (uses[j] instanceof OpArgNode)" added by LL 18 March 2019
                if (!((uses[j] instanceof OpApplNode) || (uses[j] instanceof OpArgNode))) {
                    MessageDialog.openError(UIHelper.getShellProvider()
                            .getShell(), "Decompose Proof Command",
                            "An error that should not happen has occurred in "
                                    + "line 4941 of DecomposeProofHandler.");
                    return result;
                }
                // Note: the following code outside the if (mayNeedParens) has
                // been cloned below for renaming the FormalParamNode
                // declaration  if isBoundedIdRenaming[i] is true.
                Location useLocation = uses[j].stn.getLocation();
                int useIdx = useLocation.beginLine() - beginLine;
                int offset = colToLoc(useLocation.beginColumn(),
                        result.mapping[useIdx]);
                String thisReplaceText = replacementText;
                if (mayNeedParens) {
                    // Define text that, if it surrounds the replaced text, implies
                    // that no parentheses are needed.
                    String[] precedingSafe = new String[] { "(", "[", "{", ",",
                            "<<", "->", ":" };
                    String[] followingSafe = new String[] { ")", "]", "}", ",",
                            ">>", "->", "~>" };

                    // Because we assume that the formula we're substituting
                    // into is a complete assumption or goal, the end of the 
                    // formula is also a safe preceding or following "string".
                    String testString = result.nodeText[useIdx].substring(0,
                            offset).trim();
                    int line = useIdx;
                    while (testString.equals("") && line > 0) {
                        line--;
                        testString = result.nodeText[line];
                    }
                    boolean terminated = testString.equals("");
                    int k = 0;
                    while (!terminated && k < precedingSafe.length) {
                        terminated = testString.endsWith(precedingSafe[k]);
                        k++;
                    }
                    if (terminated) {
                        testString = result.nodeText[useIdx].substring(
                                offset + sourceTextLength).trim();
                        line = useIdx;
                        while (testString.equals("")
                                && line < result.nodeText.length - 1) {
                            line++;
                            testString = result.nodeText[line];
                        }
                        terminated = testString.equals("");
                        k = 0;
                        while (!terminated && k < precedingSafe.length) {
                            terminated = testString
                                    .startsWith(followingSafe[k]);
                            k++;
                        }
                    }
                    if (!terminated) {
                        thisReplaceText = "(" + replacementText + ")";
                    }
                }
                result.nodeText[useIdx] = result.nodeText[useIdx].substring(0,
                        offset)
                        + thisReplaceText
                        + result.nodeText[useIdx].substring(offset
                                + sourceTextLength);
                adjustMappingPairVector(useLocation.beginColumn() +1 // +1 added 28 Nov 2014
                   /* + sourceTextLength */, thisReplaceText.length()
                        - sourceTextLength, result.mapping[useIdx]);

                // Update inserts
                inserts[useIdx].add(new Insertion(offset, sourceTextLength,
                        thisReplaceText.length()));
            }
        }

        // Adjust the indentation.
        adjustIndentation(nodeTextRep, result, inserts);

        return result;
    }
    
    /**
     * Assumes that noteTextRep is a representation of sn, possibly after substitutions.
     * It assumes that prefix and postPrefix have the form [id!]* where id is an 
     * identifier.  For example, suppose prefix = "Foo!Bar" and postPrefix = "X!Y!Z!".
     * Then for each instance of a user-defined operator Op in sn, the method looks 
     * for operator Op in the current module under the names Foo!Bar!Op, Foo!Bar!X!Op,
     * Foo!Bar!X!Y!Op, Foo!Bar!X!Y!Z!Op.  It then substitutes for Op in that instance in 
     * nodeTextRep the name under which it was found.  I think the name should always
     * be found in any case, and I don't know what to do if it isn't--so, I'll raise
     * an error window once.
     * 
     *  
     * @param sn
     * @param nodeTextRep
     * @param prefix
     * @param postPrefix
     */
    NodeTextRep renameInNodeText (ExprOrOpArgNode sn, NodeTextRep nodeTextRep, 
                           String prefix, String postPrefix) {
        
        NodeTextRep result = nodeTextRep ;
        
        // If there's nothing to append, then there's nothing to do.  In
        // addition to this being an optimization of the normal case, it
        // simplifies matters because any operators we're renaming have to
        // be globally defined in their module, so they can be found in
        // that module's list of definitions.  That's not true for defined
        // operators in the current module, which can use locally defined
        // operators.
        if (prefix.equals("") && postPrefix.equals("")) {
            return result ;
        }
        
        // errorFound is set true when a user error is raised.
        boolean errorFound = false ;
               
        String [] trialPrefixes = DefPrefixes(postPrefix) ;
        for (int i=0 ; i < trialPrefixes.length; i++) {
            trialPrefixes[i] = prefix + trialPrefixes[i] ;
        }
        
        ExprOrOpArgNode[] opUses = ResourceHelper.getUsesOfUserDefinedOps(sn) ;
        
        for (int i = 0; i < opUses.length; i++) {
            if (opUses[i] instanceof OpApplNode) {
                OpDefNode opDef = (OpDefNode) ((OpApplNode) opUses[i]).getOperator() ;
                String opDefName = opDef.getName().toString() ;
                ExprNode opDefBody = opDef.getBody() ;
                boolean notFound = true ;
                
                // Set j such that trialPrefixes[j]+opDefName is the correct operator name.
                int j = 0 ;
                while (notFound && j < trialPrefixes.length ) {
                    OpDefNode symNode = stringToOpDef(trialPrefixes[j]+opDefName) ; 
                    if (symNode != null) {
                         // Have to check if foundOpDef is really an instantiation
                         // of opDef.  To do that, we see if the definition of opDef
                         // is the same node as the definition of foundOpDef after
                         // peeling off some number of SubstInNodes
                        ExprNode foundOpDefBody = symNode.getBody() ;  
                        ExprNode body = opDefBody ;
                        while (notFound && (foundOpDefBody instanceof SubstInNode)) {
                            notFound = body != foundOpDefBody ;
                            foundOpDefBody = ((SubstInNode) foundOpDefBody).getBody() ;
                        }
                        if (notFound) {
                            notFound = body != foundOpDefBody ;
                        }
                    } 
                    
                    if (notFound) {
                        j++ ;
                    }
                }
                
                if (notFound) {
                    if (!errorFound) {
                        MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                                "Decompose Proof Command",
                                "Something that should not happen has occurred in "
                                        + "line 5099 of DecomposeProofHandler.");
                        errorFound = true ;
                    }
                }
                else {
                    result = prependToOpName(result, sn, (OpApplNode) opUses[i], trialPrefixes[j]) ;
                }
                    
                
            }
            
            else if ((opUses[i] instanceof OpArgNode) && (trialPrefixes.length > 1)) {
                MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                        "Decompose Proof Command",
                        "A use of " + ((OpArgNode) opUses[i]).getName() + 
                        " as an operator name may require manual renaming.");
            }
            
            else {
                if (!errorFound) {
                    MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "Something that should not happen has occurred in "
                                    + "line 5122 of DecomposeProofHandler.");
                    errorFound = true ;
                }
            }             
        }
       // 
        return result ;  
    }
    
    /**
     * Looks up a user-defined operator with name str in the current module and 
     * returns its OpDef node, else null if the operator isn't defined.
     */
    OpDefNode stringToOpDef(String str) {
        OpDefNode result = null ;
        OpDefNode[] allDefs = moduleNode.getOpDefs() ;
        int i = 0 ;
        while ((result == null) && (i < allDefs.length) ) {
            if (str.equals(allDefs[i].getName().toString())) {
                result = allDefs[i];
            }
            i++ ;
        }
        return result ;
    }
    /**
     * If prefix = "Foo!Bar!", then it returns the three-element array 
     * ["", "Foo!", "Foo!Bar!"] .
     * 
     * @param prefix
     * @return
     */
    static String[] DefPrefixes(String prefix) { 
        if (prefix.equals("")) {
            return new String[] {""} ;
        }
        String[] split = prefix.split("!") ;
        String[] result = new String[split.length+1] ;
        for (int i=0 ; i < result.length; i++) {
            if (i == 0) {
                result[i] = "" ;
             }
             else {
                 result[i] = result[i-1] + split[i-1] ;
             }
            if (i != 0) {
                result[i] = result[i] + "!" ;
             }
        }
        return result ;
    }

    
    

    /**
     * Calls substituteInNodeText to perform the substitution of arguments for
     * formal parameters in a decomposition that is the expansion of a
     * definition, as well as for bound identifiers that must be renamed because
     * of name clashes with declarations and definitions occurring earlier in
     * the module.
     * 
     * @param nodeRep
     *            NodeRepresentation being decomposed.
     * @param sn
     * @param nodeTextRep
     * @param originalNodeRep
     *            NodeRepresentation that is currently in the state.assumeReps /
     *            state.goalRep data structure at the place where nodeRep will
     *            go.
     * 
     * @return
     */
    NodeTextRep decompSubstituteInNodeText(NodeRepresentation nodeRep,
            ExprNode sn, NodeTextRep nodeTextRep,
            NodeRepresentation originalNodeRep) {
        Decomposition decomp = nodeRep.decomposition;

        // Set prevDeclared to the set of all identifiers declared or defined at
        // the location of nodeRep.
        StringSet prevDeclared =  this.declaredIdentifiers.clone();
        addDeclaredSymbols(prevDeclared, originalNodeRep);

        // Added by LL on 10 Feb 2013 because formulas that are being decomposed
        // may wind up added in the scope of later NEW declarations.
        addSymbolsDeclaredLater(prevDeclared, originalNodeRep, false);

        // Set rename to a new Renaming object containing the renamings
        // in decomp.renamings together with all additional renamings
        // necessary to avoid name conflicts with names in prevDeclared.
        Renaming rename = decomp.renaming.clone();

        addToRenaming(rename, prevDeclared, sn);

        // Compile the arguments for calling substituteInNodeText.
        // Set decompParamsLen to the number of formal parameters, which is 0
        // if decomp.formalParams = null
        int decompParamsLen = 0;
        if (decomp.formalParams != null) {
            decompParamsLen = decomp.formalParams.length;
        }
        FormalParamNode[] formalParams = new FormalParamNode[decompParamsLen
                + rename.identifiers.size()];
        String[] arguments = new String[formalParams.length];

        boolean[] isBoundedIdRenaming = new boolean[formalParams.length];
        SemanticNode[] argNodes = new SemanticNode[formalParams.length];

        for (int i = 0; i < decompParamsLen; i++) {
            formalParams[i] = decomp.formalParams[i];
            arguments[i] = decomp.arguments[i];
            isBoundedIdRenaming[i] = false;
            argNodes[i] = decomp.argNodes[i];
        }

        // Save the new names chosen for the identifiers in renameIdentifiers
        // in the vector renameIdentifiersNames. They must be added
        // to renamedIdentifiers and newIdentifierNames after the call
        // to substituteInNode because, if an identifier gets re-renamed,
        // then substituteInNode needs to know the name of the
        // identifier (actually, its length) before the re-renaming.
        for (int i = 0; i < rename.identifiers.size(); i++) {
            formalParams[i + decompParamsLen] = rename.identifiers.elementAt(i);
            arguments[i + decompParamsLen] = rename.newNames.elementAt(i);
            isBoundedIdRenaming[i + decompParamsLen] = true;
            argNodes[i + decompParamsLen] = null;
        }

        NodeTextRep result = substituteInNodeText(formalParams, arguments,
                isBoundedIdRenaming, argNodes, sn, nodeTextRep, decomp);
        // The following commented out by LL on 8 Feb 2013 because it seems
        // wrong.
        // The renamings for decomp are for the expression that is the use
        // of the operator in whose definition we are performing the
        // substitutions.
        // Add the renamings to decomp.renaming
        // On 10 Feb 2013, LL realized that seems to be wrong, because some
        // bounded id renaming is getting lost.
        // On 2 Dec 2014 LL realized that things are getting screwed up
        // because it should be the NodeText that's keeping track of
        // these renamings.
        // decomp.renaming = rename;
        result.renaming = rename;
        // Have to add the renamings just done to state.renaming.  Must do
        // it here, after substituteInNodeText has been called to do those
        // renamings.
        addToRenaming(this.state.renaming, prevDeclared, sn) ; // added 4 Dec 2014

        return result;
    }
    

    /**
     * Assume that we are decomposing a use of a user-defined operator
     * named opName in a context with isub the InstanceSubstitution, and 
     * subIn is a SubstInNode which begins the definition of opName.
     * Then this returns a new InstanceSubstitution obtained by appending
     * to isub the substitutions for the parameters being renamed by subIn.
     * Note that if opName is something like Foo!Bar!Op, then user-defined
     * operators in the expressions being substituted for parameters by subIn
     * will have to have their names prepended by isub.prefix and perhaps
     * also with "Foo!" or "Foo!Bar!".
     * 
     * In case of error, returns null.
     * @param isub
     * @param opName
     * @param subIn
     * @return
     */
    InstanceSubstitution substInNodeToInstanceSub(
            InstanceSubstitution isub,
            String opName,
            SubstInNode subIn
            ) {
        InstanceSubstitution result = isub.clone() ;
        int lastBang = opName.lastIndexOf('!') ;
        String postPrefix = "";
        if (lastBang != -1) {
            postPrefix = opName.substring(0, lastBang + 1) ;
        }
        // Set doc to the document of the SubstInNode's module
        IDocument doc = moduleNameToIDocument(subIn.getLocation().source()) ;
        
        Subst[] substitutes = subIn.getSubsts() ;
        OpDeclNode[] paramsArray = OpDeclNodeVectorToArray(isub.params) ;
        String[] subsArray = StringVectorToArray(isub.substs) ;
        for (int i = 0; i < substitutes.length; i++) {
			Subst subst = substitutes[i];
			/*
			 * The following if / else was added by LL on 22 March 2019 to partially fix the
			 * bug in expanding definitions imported by instantiations with implicit
			 * instantiation of one or more module parameters.  It simply does no substitution
			 * for an implicitly instantiated module parameter.  This is always OK if this
			 * is a top-level instantiation--that is, if this substitution is creating
			 * an expression of the same module as the definition the Decompose Proof
			 * command is expanding.  If this is not the case, and a warning has not
			 * already been produced for the current module, then a warning is given.
			 * The one safe case that will produce the warning is if this is not a top-level
			 * instantiation, but the parameter is also implicitly substituted for in
			 * all higher-level instantiations.  This is likely to be the case for
			 * instantiations of instantiated definitions--for example, if a low-level
			 * spec instantiates a middle-level spec which instantiates a high-level
			 * spec.  It's likely that there is some CONSTANT parameter that is the
			 * same in all three specs and will be instantiated implicitly in both
			 * INSTANCE statements.  This could be checked for by dynamically keeping track 
			 * of all implicit instantiations in all modules examined.  But that's
			 * complicated enough that it would probably be better to fix the entire
			 * algorithm for expanding instantiated definitions so it gets things right
			 * even in cases that it now doesn't, as in failing to do proper renaming
			 * for defined operators.
			 */
			if (!subst.isImplicit()) { 				
				result.params.add(subst.getOp());
				NodeRepresentation nodeRep;
				try {
					/*
					 * The following comments were added by LL on 18 March 2019.  They may
					 * be useful if someone wants to really fix the problem.
					 * 
					 * The following code was an attempt to fix the bug in the Decompose Proof
					 * command that causes it to replace implicitly instantiated module parameters
					 * with the text of the INSTANCE statement. There seemed to be two problems that
					 * are finessed by the rix. The first is that when the current method is called and the i-th
					 * module parameter is implicitly instantiated with a parameter of the current module, 
					 * then subIn.substs[i].expr is an ExprOrOpDefNode with its op field identifying that
					 * parameter, but with its stn field pointing to the text of the INSTANCE
					 * statement. Except, if that parameter came from an EXTENDed module, that stn
					 * field points to the parameter's declaration in the instantiated module. In
					 * the first case, the text of the instantiated parameter was replaced by the
					 * text of the INSTANCE statement. In the second case, it was replaced by the
					 * text from the current module that's at the location of the parameter's
					 * declaration in the EXTENDed module.
					 * 
					 * Another bug whose effect I don't understand in the current code is that if
					 * the current module instantiates module A, which instantiates module B, if a
					 * parameter P in module B is implicitly instantiated by a parameter in module
					 * A, the instantiation of parameter P in module A is marked as implicit in
					 * subIn.substs[...].implicit.
					 * 
					 * In the following code, if subIn.substs[i].implicit is true,
					 * subIn.substs[i].expr.stn is effectively changed to point to the declaration
					 * of the parameter in the instantiated module. However, that doesn't work
					 * because, as in the exceptional case above, the parameter gets replaced by the
					 * text in the current module at the location of the parameter's declaration in
					 * the instantiated module.
					 * 
					 * To fix the bug, one must first understand the complete method of performing
					 * substitutions in expanding a definition. This will take more time than I
					 * have.
					 * 
					 * 
					 */
//            	ExprOrOpArgNode substExpr = subst.getExpr() ;            	
//            	if (subst.isImplicit()) {
//            		// set subst.expr.stn to a clone of its current value
//            		// except with its location set to a location whose beginning
//            		// is the location of subst.op.stn and its ending location
//            		// is that location with its column equal to
//            		// its starting column + length(subst.op.name) - 1
//            		// (That's so it doesn't include the "(...)" that's
//            		// included if this is an operator with arguments.
//                	OpDeclNode substOp = subst.getOp() ;
//                	Location opLocation = substOp.getLocation() ;
//                	String substOpName = substOp.getName().toString() ;
//                	String opLocationSourceString = opLocation.source() ;
//                	UniqueString opLocationSource = UniqueString.uniqueStringOf(opLocationSourceString)  ;
//           		    Location exprLocation = substExpr.stn.getLocation() ;
//           		    Token t = Token.newToken(substExpr.stn.getKind()) ;
//           		    t.image = substExpr.stn.getImage() ;
//           		    t.beginLine = opLocation.beginLine() ;
//           		    t.endLine = opLocation.endLine() ;
//           		    t.beginColumn = opLocation.beginColumn() ;
//           		    t.endColumn = t.beginColumn + substOpName.length() - 1 ;
//           		    substExpr.stn = new SyntaxTreeNode(
//           		    		UniqueString.uniqueStringOf(substOp.stn.getFilename()),
//           		    		   substExpr.stn.getKind(), t) ;
//            	}
//            	nodeRep = new NodeRepresentation(doc, substExpr) ;
//                 /*
//                  * END OF FIX.  The following line is the old code being
//                  * replaced by the fix.
//                  */

					nodeRep = new NodeRepresentation(doc, subst.getExpr());
				} catch (BadLocationException e) {
					MessageDialog.openError(UIHelper.getShellProvider().getShell(), "Decompose Proof Command",
							"Something unexpected is going on at " + "line 5356 of DecomposeProofHandler.");
					return null;
				}

				if (nodeRep.nodeText.length != 1) {
					MessageDialog.openError(UIHelper.getShellProvider().getShell(), "Decompose Proof Command",
							"Cannot handle instantiation of module parameter\n " + "with multi-line formula.");
					return null;
				}

				NodeTextRep ntRep = nodeRep.toNodeTextRep();

				ntRep = instantiateInNodeText(paramsArray, subsArray, subst.getExpr(), ntRep);
				ntRep = renameInNodeText(subst.getExpr(), ntRep, isub.prefix, postPrefix);
				if (ntRep == null) {
					return null;
				}
				result.substs.add(ntRep.nodeText[0]);
			}
			else if ( /* This is an implicit instantiation.  The following generates a warning 
			           *  if a warning has not already been generated for this module and this 
			           *  is not a top-level implicit instantiation.
			          */
					  (!this.moduleNode.getName().toString().equals(lastModuleWithImplicitRenamingWarning))
					  && (!this.moduleNode.getName().toString().equals(
							  subst.getExpr().getTreeNode().getFilename()))) { 
					MessageDialog.openError(UIHelper.getShellProvider().getShell(), 
				      "Decompose Proof Command",
					  "The implicit instantiation of one or more module parameters in an INSTANCE"
				        + "\nstatement in an instantiated module may cause the incorrect expansion of"
				        + "\ndefinitions imported by instantiation.  This can be avoided by using"
				        + "\nWITH clauses to make instantiations explicit."
						+ "\n\nThis warning will probably not be repeated for this module.");
					this.lastModuleWithImplicitRenamingWarning = this.moduleNode.getName().toString();
				} // End of if/else statement added by LL on 22 March 2019
		}
        return result ;
    }
    /**
     * The NodeTextRep obtained by performing the substitutions indicated by
     * isub in the nodeText and mapping fields of nodeRep.  The expression
     * nodeRep.semanticNode comes from a module that is imported into the
     * current module with renaming described that contains isub.prefix as
     * a prefix and is a prefix of isub.prefix + newPrefix.
     * 
     * @param isub
     * @param newPrefix
     * @param nodeRep
     * @return
     */
     NodeTextRep instanceSubstitute(
            InstanceSubstitution isub, String newPrefix, NodeRepresentation nodeRep) {
        NodeTextRep result = (new NodeTextRep(nodeRep.nodeText, nodeRep.mapping)).clone() ;
        
        return result ;
    }
    
    /**
     * Adds to `renaming' all the renamings to bound identifiers in expr that
     * are necessary to eliminate clashes with names in the set prevDeclared.
     * 
     * This code was obtained by modifying the implementation of
     * ResourceHelper.innerGetBoundIdentifiers.
     * 
     * @param rename
     * @param prevDeclared
     * @param expr
     * @return
     */
    private void addToRenaming(Renaming renaming, StringSet prevDeclared,
            ExprNode expr) {
        if (!(expr instanceof OpApplNode)) {
            return;
        }

        StringSet newDeclared =  prevDeclared.clone();

        OpApplNode node = (OpApplNode) expr;
        if (node.getUnbdedQuantSymbols() != null) {
            for (int i = 0; i < node.getUnbdedQuantSymbols().length; i++) {
                FormalParamNode id = node.getUnbdedQuantSymbols()[i];
                if (newDeclared.contains(getCurrentName(id, renaming))) {
                    String newname = getNewName(id, newDeclared, renaming);
                    newDeclared.add(newname);
                    addCurrentName(id, newname, renaming);
                    // addCurrentName(id, newname, state.renaming) ; // added 3 Dec 2014
                }
            }
        }

        if (node.getBdedQuantSymbolLists() != null) {
            for (int i = 0; i < node.getBdedQuantSymbolLists().length; i++) {
                addToRenaming(renaming, prevDeclared,
                        node.getBdedQuantBounds()[i]);
                FormalParamNode[] nodeList = node.getBdedQuantSymbolLists()[i];
                for (int j = 0; j < nodeList.length; j++) {
                    FormalParamNode id = nodeList[j];
                    if (newDeclared.contains(getCurrentName(id, renaming))) {
                        String newname = getNewName(id, newDeclared, renaming);
                        newDeclared.add(newname);
                        addCurrentName(id, newname, renaming);
                        // addCurrentName(id, newname, state.renaming) ; // added 3 Dec 2014
                    }
                }
            }
        }

        for (int i = 0; i < node.getArgs().length; i++) {
            if (node.getArgs()[i] instanceof ExprNode) {
                addToRenaming(renaming, newDeclared,
                        (ExprNode) node.getArgs()[i]);
            }
        }

    }

    /**
     * A DecompositionState describes the current state of the decomposition,
     * and determines what is shown in the command's popup window. There will be
     * a chain of such objects to support the "Back" option.
     */
    private class DecompositionState {
        /**
         * previousState is the decomposition state to which the "Back" button
         * goes. It should be null only for the initial state.
         */
        DecompositionState previousState = null;

        /**
         * The hasChanged field is (I believe) used only to determine if the
         * replaceButton on the command's window raised by raiseWindow() is
         * enabled. For reasons explained in the comments describing that
         * button, hasChanged is set true by any decomposition action except
         * clicking on an /\ decomposition, which sets it false.
         */
        boolean hasChanged;

        /*************************************************************************
         * Fields that contain the current assumptions and goal.
         * 
         * The data for the current assumptions are kept in vectors, the i-th
         * element containing data for the i-th assumption. This is done to make
         * it easy to replace one assumption by several. Other objects contain
         * pointers to these vectors, so once the vectors are constructed by
         * DecomposeProofHandler.execute, they can be modified but must not
         * be replaced by new vectors.
         *************************************************************************/
        /**
         * The NodeRepresentation objects for the current assumptions.
         */
        private Vector<NodeRepresentation> assumeReps;

        /**
         * The NodeRepresentation object for the current goal.
         */
        private NodeRepresentation goalRep;

        /**
         * The number of assumptions in assumeReps that are context assumptions.
         */
        private int numberOfContextAssumptions ;
        
        /**
         * state.assumeReps.elementAt(firstAddedAssumption) through
         * state.assumeReps.elementAt(state.assumeReps.size()-1) are
         * all the added assumptions that must appear as assumptions in
         * the decomposed proof.
         *   
         */
        private int firstAddedAssumption ;
        
        /**
         * On 15 Oct 2014 the field chosenSplit was removed.  It contained
         * the index of an OR-split entry in assumeReps, if there is one.
         * Now, such an OR-split entry must be the last one in assumeReps,
         * so the splitChosen() method replaces it.
         */
        boolean splitChosen() {
            return    (assumeReps.size() > 0)
                   && (assumeReps.elementAt(assumeReps.size()-1).nodeType 
                           == NodeRepresentation.OR_DECOMP) ;
        }

        /**
         * True if the proof of a SUFFICES step (or of the QED step if there is
         * no SUFFICES step) needs the name of the step being decomposed in the
         * BY clause if that step has a name. I believe this is the case iff an
         * \E-split has been done on an assumption that was not moved from the
         * goal.
         * Removed 3 Dec 2014
         */
        // boolean needsStepNumber;

        /**
         * Once the user has performed an AND split on an assumption, then
         * another AND split can be performed only on one of the results of that
         * split. The indices of the nodes in <code>assumes</code> and
         * <code>state.assumeReps</code> resulting from AND splits range from
         * state.andSplitBegin through (including) state.andSplitEnd. If no AND
         * split has been performed, then state.andSplitBegin and
         * state.andSplitEnd equal -1.
         * 
         */
// UP-DOWN ARROWS REMOVED
//        int andSplitBegin; // NOT CLEAR IF THESE WILL BE USED IN NEW VERSION.
//        int andSplitEnd; // NOT CLEAR IF THESE WILL BE USED IN NEW VERSION.

        /**
         * The set of Ids of user-defined operations that must appear in the DEF
         * clause of the QED step's proof. They are definitions that were
         * expanded in decomposing non-top level \E and/or \/ assumptions.
         */
        private StringSet goalDefinitions;

        // It appears that the only use made of assumpDefinitions is to
        // test whether or not it is empty.
        private HashSet<String> assumpDefinitions;

        // PERHAPS CAN BE COMBINED WITH goalDefinitions
        
        /**
         * The set of renamings made in all the assumptions
         * and in the goal.  This should be used to replace the
         * renaming fields in the Decomposition and NodeTextRep objects.
         * But that would require work.  Instead, this is being used to
         * find renamings that are currently being missed.  In particular,
         * it's only used to 
         *  Added 3 Dec 2014
         */
        Renaming renaming = new Renaming() ;

        public DecompositionState clone() {
            DecompositionState result = new DecompositionState();

            result.hasChanged = hasChanged;
            result.assumeReps = new Vector<NodeRepresentation>();
            for (int i = 0; i < assumeReps.size(); i++) {
                result.assumeReps.addElement(assumeReps.elementAt(i).deepClone(
                        null, result.assumeReps));
            }

            result.goalRep = goalRep.deepClone(null, null);
            result.numberOfContextAssumptions = numberOfContextAssumptions ;
            result.firstAddedAssumption = firstAddedAssumption ;
            // result.chosenSplit = chosenSplit;
            // result.needsStepNumber = needsStepNumber;
// UP-DOWN ARROWS REMOVED
//            result.andSplitBegin = andSplitBegin;
//            result.andSplitEnd = andSplitEnd;
            result.goalDefinitions = goalDefinitions.clone();
            result.assumpDefinitions = (HashSet<String>) assumpDefinitions
                    .clone();
            result.renaming = renaming.clone(); // added 3 Dec 2014

            return result;
        }
    }

    /**
     * A NodeRepresentation object describes the TLA+ source text that produced
     * a SemanticNode, after substitutions have been performed for some
     * identifiers. It contains the following information:
     * <ul>
     * <li>The SemanticNode <code>node</code>.
     * 
     * <li>A String[] object <code>nodeText</code> that describes the source
     * text after substitutions have been performed.
     * 
     * <li>A mapping from <line, column> coordinates occurring in locations in
     * the syntax tree of <code>node</code> to the corresponding positions in
     * <code>nodeText</code>.
     * </ul>
     * Substitutions are performed for an identifier for two reasons:
     * <ul>
     * <li>The formal parameter of a definition is replaced by an argument when
     * expanding the definition. To simplify the implementation, such an
     * expansion is performed only when all the arguments consist of text
     * occurring on a single line.
     * 
     * <li>A bound identifier has been renamed to avoid a name conflict.
     * </ul>
     * A substitution cannot be performed for any occurrence that was added by a
     * substitution. Hence, an identifier introduced by renaming cannot be
     * renamed.
     * 
     * An OR-decomposition node represents an assumption that has been
     * decomposed into a disjunction for a proof by cases. Such a node has a
     * vector of children, which can include OR-decomposition nodes.
     * 
     * 
     * @author lamport
     * 
     */
    public class NodeRepresentation {
        /**
         * The original semantic node
         */
        SemanticNode semanticNode;

        /**
         * We represent the text of a TLA+ syntactic unit as a String array,
         * each element representing one line of the text with no end-of-line
         * characters.
         * 
         * The text from the module that represents <code>node</code>,
         * represented by the array nodeText of strings as follows. Let S be the
         * region of the module that produces the node. If S lies entirely on
         * one line, then nodeText has length 1 and nodeText[0] = S. Otherwise,
         * suppose S lies on N lines. Let B be the array with B[0] containing
         * the beginning of S up until the end of the first line, with B[1], ...
         * , B[n-1] containing the next n-2 lines of S, and with B[n] containing
         * the rest of S. Then nodeText is the array obtained from B by possibly
         * adding spaces to the beginning of B[0] and possibly removing spaces
         * from the beginning of B[1], ... , B[n] so that there is at least one
         * line of nodeText that does not begin with a space and the formatting
         * of the original text is maintained in nodeText.
         * 
         * This is not quite accurate.
         * 
         * @param document
         * @param semanticNode
         * @return
         */
        String[] nodeText;

        // mapping defines the mapping from <line, column> coordinates
        // within the syntax tree of `node' to positions in nodeText,
        // where <ln, c> is mapped into the position mapping[j](c) in
        // string nodeText[j], where j = ln - node.stn.beginLine()
        // (node.stn.beginLine() is the number of the line on which the
        // source text of `node' begins. (See the comments on the
        // MappingPair class for a definition of mapping[j](c).
        Vector<MappingPair>[] mapping;

        
        /**
         * Returns just the NodeTextRep part of this NodeRepresentation object.
         * Note that there is no cloning involved.
         * 
         * @return
         */
        NodeTextRep toNodeTextRep() {
            NodeTextRep result = new NodeTextRep(nodeText, mapping) ;
            if (decomposition != null) {
                result.renaming = decomposition.renaming ;
            }
            return result ;
        }
        
        // Suppose that we are decomposing a proof in module M, and 
        // this NodeRepresentation nr represents an expression in module N.
        // Thus, nr.semanticNode is a node in the semantic tree of N,
        // so the name op and definition expr of a defined operator used in 
        // nr are expressions that make sense in module N, not in the
        // proof's module M.  Then operator op is known in module m
        // by the name instantiatedNamePrefix + op, and the definition
        // expr is imported into M by performing the substitutions
        // instantiationSubstitutions in expr.  Example:
        //
        //   MODULE M contains  IP == INSTANCE P WITH CP <- expM
        //                      ... ASSUME IP!POp(argM), ...
        //   MODULE P contains  IN == INSTANCE N WITH CN <- expP
        //                      POp(a) == ... \/ IN!NOp(a, argP) 
        //   MODULE N contains  NOp(b, c) == expr(b, c)
        //   
        // Then decomposing IP!Pop(argM) produces the following
        // assumption, where exp WITH C <- sub means with the expression
        // sub for all instances of the node C with the expr sub.
        //      
        //   ... \/ IN!NOp(argM, argP WITH CP <- expM)
        //
        // Decomposing that disjunction produces a case
        //
        //   expr(argM, argP WITH CP <- expM)  
        //                    WITH   CN <- (expP WITH CP <- expM)
        //
        // Note that argM is equivalent to argM WITH CP <- expM
        // which is equivalent to (argM WITH CP <- expM) WITH CN <- expP
        // because neither CP (which is declared in module P) nor
        // CN (which is declared in module N) can occur in argM (which
        // is an expression module M.  Note that CP and CN denote semantic
        // nodes, not the strings that represent those nodes (which
        // could be the same string for both of them).
        //
        InstanceSubstitution instantiationSubstitutions = new InstanceSubstitution() ;
        
        // The nodeType is the type of node.
        private static final int EXPR_NODE = 0; // An OpApplNode
        private static final int NEW_NODE = 1; // A NewSymbNode
        private static final int OR_DECOMP = 2;
        // A node representing a decomposition into the disjunction of its
        // children.
        private static final int PROOF_NODE = 4;
        // The LeafProofNode of the step. This may not be needed.
        private static final int OTHER_NODE = 5;
        private int nodeType = 0;

        // An EXPR_NODE has a subtype, indicating what
        // decomposition can be applied.
        // Subtypes for decomposing a goal:
        private static final int AND_TYPE = 0; // A conjunction
        private static final int IMPLIES_TYPE = 2; // An implication
        private static final int FORALL_TYPE = 3; // A \A
        // Subtypes for decomposing an assumption
        private static final int OR_TYPE = 1; // A disjunction
        private static final int EXISTS_TYPE = 4; // An \E
        private static final int SQSUB_TYPE = 5; // An [A]_v expression
//        private static final int MULTI_TYPE = 6;
        // An assumption that is the conjunction of formulas, two or more
        // of which can be decomposed.
        // Subtype for something that can't be decomposed
        private static final int OTHER_TYPE = 99; // anything else

        public int nodeSubtype = OTHER_TYPE;

        /**
         * If this NodeRepresentation object is of type NEW_NODE, then this is
         * the NEW identifier.
         */
        public String newId = null;
        
        /**
         * This NodeRepresentation object either was or was obtained from the
         * assumption that was originally state.assumeReps.elementAt(initialPosition),
         * except that initialPosition equals approximately Integer.MAX_VALUE - 42
         * if it came from the goal and equals Integer.MAX_VALUE if it is the
         * (only) object of type OR_DECOMP in state.assumeReps.
         */
        int initialPosition = -1 ;  // -1 indicates that value not set.

        /********************************************************************
         * An OR-Split operation can be performed on a node of type EXPR_NODE
         * and subtype OR_TYPE. This operation replaces the node with one of
         * type OR_DECOMP, whose children field is a vector with one element for
         * each disjunct of the semanticNode's disjuncts, where
         * children.elementAt(i) is a vector of length 1 containing a node of
         * type EXPR_NODE for that disjunct. Further operations on that node can
         * turn children.elementAt(i) into a vector consisting of a sequence of
         * NEW_NODE NodeRepresentation objects followed by an EXPR_NODE or
         * OR_DECOMP node. The `children' field is null for a node of type other
         * than OR_DECOMP.
         *********************************************************************/
        Vector<Vector<NodeRepresentation>> children = null;

        /********************************************************************
         * If this node has parentNode # null, then it equals
         * n.children.elementAt(i).elementAt(j) for an OR_DECOMP node n, where
         * parentNode = n and parentVector = n.children.elementAt(i). In this
         * case, the node is of type EXPR_NODE, NEW_NODE, or OR_DECOMP.
         * 
         * If parentNode = null, then there are two cases:
         * 
         * - The node is either an element of state.assumeReps. In that case, it
         * equals h.state.assumeReps.elementAt(j) for the
         * DecomposeProofHandler object h, and parentVector =
         * state.assumeReps.
         * 
         * - the node is state.goalRep and parentVector = null .
         ********************************************************************/
        NodeRepresentation parentNode = null;
        private Vector<NodeRepresentation> parentVector = null;

        Vector<NodeRepresentation> getParentVector() {
            return this.parentVector;
        }

        void setParentVector(Vector<NodeRepresentation> parentVector) {
            this.parentVector = parentVector;
        }

        /**
         * The two methods NodeRepresentation.nodeRepPath and
         * DecomposeProofHandler.pathToNodeRep() provide a means of
         * describing a NodeRepresentation object that identifies the "same"
         * object described by a DecompositionState or by a clone of it. They
         * are defined as follows:
         * 
         * The set NS of all NodeRepresentation objects is defined by:
         * 
         * - state.goal \in NS - \A i, j : state.assumeReps.elementAt(i) \in NS
         * - \A ns \in NS : \A i : ns.children.elementAt(i).elementAt(j) \in NS
         * 
         * For any ns \in NS, ns.nodePath() is a vector <<v0, ... , v2N>> of
         * Integers (for N >= 0) such that
         * 
         * ns = root.children.elementAt(vN-1).elementAt(vN-2)
         * .children.elementAt(vN-3).elementAt(vN-4) ...
         * .children.elementAt(1).elementAt(0)
         * 
         * where root == IF vN = -1 THEN this.goalRep ELSE
         * this.assumeReps.elementAt(vN)
         * 
         * For any vector V of Integers, there exists ns \in NS such that V =
         * ns.nodeRepPath(), then pathToNodeRep(V) = ns.
         * 
         * nodeRepPath is defined below. pathToNodeRep is a method in the outer
         * DecomposeProofHandler class.
         * 
         * @return
         */
        Vector<Integer> nodeRepPath() {
            Vector<Integer> result = new Vector<Integer>();
            NodeRepresentation currNR = this;
            while (currNR.parentNode != null) {
                int idx1 = currNR.getParentIndex();
                result.addElement(new Integer(idx1));
                Vector<NodeRepresentation> parVec = currNR.getParentVector();
                currNR = currNR.parentNode;
                Vector<Vector<NodeRepresentation>> childs = currNR.children;
                boolean notFound = true;
                int idx2 = 0;
                while (notFound && (idx2 < childs.size())) {
                    if (childs.elementAt(idx2) == parVec) {
                        notFound = false;
                    } else {
                        idx2++;
                    }
                }

                if (notFound) {
                    MessageDialog.openError(UIHelper.getShellProvider()
                            .getShell(), "Decompose Proof Command",
                            "An error that should not happen has occurred in "
                                    + "line 5865 of DecomposeProofHandler.");
                    return null;
                }

                result.addElement(new Integer(idx2));

            }

            if (currNR.getParentVector() == null) {
                result.addElement(new Integer(-1));
            } else {
                result.addElement(new Integer(currNR.getParentIndex()));
            }

            return result;
        }

        /**
         * If parentVector is non-null, then the current node equals
         * parentVector.elementAt(getParentIndex()). If parentVector is null,
         * then getParentIndex() equals -l.
         * 
         * @return
         */
        int getParentIndex() {
            if (getParentVector() == null) {
                return -1;
            }
            for (int i = 0; i < getParentVector().size(); i++) {
                if (this == getParentVector().elementAt(i)) {
                    return i;
                }
            }
            return -2; // this shouldn't happen
        }

           // State information about this clause.

        /**
         * True iff this is a NEW assumption that was not in the original
         * obligation, or it is an ExprNode that was created by splitting the
         * goal or by doing an AND-split on an assumption.  Its only function
         * in the displayContextAssump() method, where it causes a node
         * created by an /\ split to be displayed even if the user has
         * unchecked the "Show Context" option.
         */
        boolean isCreated = false;
        
        /**
         * Despite the name, this is the step name of the assumption from
         * which this assumption came, whether it is a context assumption
         * or an assumption from the step being decomposed.  However,
         * it is null if this NodeRepresentation is the goal, or an assumption
         * that came by decomposing the node.  It is also null if it comes from
         * an unnamed step (one with only a level number).
         */
        String contextStepName ;
        
        /**
         * True iff this NodeRepresentation came from a (sub)formula of the goal.
         */
        boolean fromGoal = false ;
        
        /**
         * True iff this NodeRepresentation came from decomposing a \E .
         */
        boolean fromExists = false ;
        /**
         * The names of operators whose definitions were expanded to produce this
         * NodeRepresentation.
         */
        StringSet fromDefs = new StringSet();
        
        /**
         * True iff this is a NEW node that is to be displayed on the same line
         * as the next node, which is also a NEW node. For nodes that come from
         * the step, this is true iff this and the next node are NEW nodes that
         * all appear entirely on the same line. For added NEW nodes, it will be
         * true iff:
         * 
         * - The NEW statement fits on a single line (meaning that it is NOT of
         * the form NEW x \in S where S is a multi-line formula)
         * 
         * - It and the next node come from the same \A or \E, as in the NEW x
         * and NEW y from \A x, y : ...
         * 
         * A sequence of same-line NEWs will not all be put on the same line in
         * the proof if its width plus proofIndent is greater than the
         * module-editor right margin preference, which is obtained with
         * 
         * Activator.getDefault().getPreferenceStore().getInt(
         * EditorPreferencePage.EDITOR_RIGHT_MARGIN);
         */
        boolean onSameLineAsNext = false;

        /**
         * True iff the formula represented by this node has an implicit prime
         * that does not appear in the semanticNode or nodeText fields.
         */
        boolean isPrimed = false;

        /**
         * If this is true, then the semanticNode field represents the expansion
         * of the subexpression name that appears in the nodeText field. This
         * means that the node has been obtained by decomposing another node by
         * expanding a definition, so no further decomposition by expanding a
         * definition is possible. (Using a subexpression name, it's impossible
         * to name the result of expanding a definition unless it's a LET
         * definition inside the current definition. I'm not sure what should be
         * done with LET definitions inside assumptions or goals.)
         */
        boolean isSubexpressionName = false;

        /**
         * Non-null iff the node can be decomposed as indicated by the
         * Decomposition object.
         */
        Decomposition decomposition = null;

        /**
         * Create a NodeRepresentation for a subnode of this node.
         * 
         * @param sn
         *            The subnode
         * @param vec
         *            The result's parentVector field.
         * @param father
         *            The result's parentNode field.
         * @param setNodeText
         *            If non-null, then the result's nodeText field is to be set
         *            to this rather than the NodeTextRep representation of the
         *            semanticNode field. It will be non-null if the nodeText is
         *            to be set to a subexpression name, so set
         *            isSubexpressionName field true in that case.
         * @param decomp
         *            The Decomposition from which the identifier renamings for
         *            the result's decomposition field are to be obtained.
         * 
         * @param isAssumption
         *            True iff this is an assumption, rather than the goal,
         *            whose NodeRepresentation is being constructed.
         *            
         * @return
         */
        NodeRepresentation subNodeRep(SemanticNode sn,
                Vector<NodeRepresentation> vec, NodeRepresentation father,
                NodeTextRep setNodeText, Decomposition decomp, boolean isAssumption) {

            NodeRepresentation result = new NodeRepresentation();
            result.parentNode = father;
            result.setParentVector(vec);
            result.semanticNode = sn;

            // Set the fields of the result that are inherited from the node
            // it's a subnode of.
            result.isPrimed = this.isPrimed;
            result.isSubexpressionName = this.isSubexpressionName;

            // If the original node came from splitting the
            // goal, then this node also came from splitting the
            // goal.
            result.isCreated = this.isCreated;

            NodeTextRep nodeTextRep = setNodeText;
            if (nodeTextRep == null) {
                nodeTextRep = this.subNodeText(sn);
            } else {
                result.isSubexpressionName = true;
            }
            result.nodeText = nodeTextRep.nodeText;
            result.mapping = nodeTextRep.mapping;
            
            result.instantiationSubstitutions = this.instantiationSubstitutions;

            /*
             * Compute the type, subType, and decomposition fields.
             */
            switch (sn.getKind()) {
            case ASTConstants.OpApplKind:
                result.nodeType = EXPR_NODE;

                result.decomposition = decompose(result, decomp, isAssumption);
                if (result.decomposition == null) {
                    result.nodeSubtype = OTHER_TYPE;
                } else {
                    result.nodeSubtype = result.decomposition.type;
                }
                break;
            case ASTConstants.NewSymbKind:
                result.nodeType = NEW_NODE;
                NewSymbNode newNode = (NewSymbNode) sn;
                result.newId = newNode.getOpDeclNode().getName().toString();
                break;
            case ASTConstants.LeafProofKind:
                result.nodeType = PROOF_NODE;
                break;
            default:
                result.nodeType = OTHER_NODE;
            }

            return result;
        }

        /**
         * This is like subNodeRep except it returns only the fields contained
         * in a NodeText. It is called by subNodeRep to set those fields.
         * 
         * @param sn
         * @return
         */
        NodeTextRep subNodeText(SemanticNode sn) {
            NodeTextRep result = new NodeTextRep();
            // result.semanticNode = sn ;
            // set beginIdx to be the index in this.nodeText representing the
            // first line of the source of SemanticNode node sn.
            int beginIdx = getBeginLine(sn) - getBeginLine(this.semanticNode);
            result.nodeText = new String[getEndLine(sn) - getBeginLine(sn) + 1];
            result.mapping = new Vector[result.nodeText.length];
            // Set beginCol to the column of the first token of sn.
            // Set beginPos to the position of the first token of sn in the
            // string
            // this.result.nodeText[beginLine - 1] containing its text.
            int beginCol = sn.stn.getLocation().beginColumn();
            int beginPos = colToLoc(beginCol, this.mapping[beginIdx]);

            /*
             * Set the nodeText and mapping fields.
             */
            // Set result.nodeText[0] to the string containing the first
            // token and everything to its right in this.nodeText[...].
            // Set result.mapping[0] to the MappingVector obtained by
            // subtracting beginPos from all increments.
            result.nodeText[0] = this.nodeText[beginIdx].substring(beginPos);
            Vector<MappingPair> mv = cloneMappingPairVector(this.mapping[beginIdx]);
            // Since we just removed beginPos characters to the left of
            // beginCol, we should execute
            adjustMappingPairVector(beginCol, -beginPos, mv);

            result.mapping[0] = mv;

            // Set result.nodeText[i] to a copy of this.nodeText[i+...]
            // and result.mapping[i] to a copy of this.mapping[i] for
            // all other lines of the subnode's text.
            // Set minPos = the minimum of beginPos and the smallest number
            // of leading spaces of any subsequent line of result.nodeText.
            // However, we need to ignore lines consisting of only spaces.
            int minPos = beginPos;
            for (int i = 1; i < result.mapping.length; i++) {
                result.nodeText[i] = this.nodeText[i + beginIdx];
                if (!StringHelper.onlySpaces(result.nodeText[i])) {
                    minPos = Math.min(minPos,
                            StringHelper.leadingSpaces(result.nodeText[i]));
                }
                result.mapping[i] = new Vector<MappingPair>();
                for (int j = 0; j < this.mapping[i + beginIdx].size(); j++) {
                    result.mapping[i].add(this.mapping[i + beginIdx].elementAt(
                            j).clone());
                }
            }

            // Remove the part of the last line of result.nodeText that doesn't
            // belong to the subnode
            result.nodeText[result.nodeText.length - 1] = result.nodeText[result.nodeText.length - 1]
                    .substring(
                            0,
                            colToLoc(sn.stn.getLocation().endColumn() + 1,
                                    result.mapping[result.mapping.length - 1]));

            // Add any necessary space at the beginning of result.nodeText[0]
            int spacesAddedToFirstLine = beginPos - minPos;
            result.nodeText[0] = StringHelper.copyString(" ",
                    spacesAddedToFirstLine) + result.nodeText[0];
            // Since we now have added spacesAddedToFirstLine, we execute
            adjustMappingPairVector(beginCol, spacesAddedToFirstLine,
                    result.mapping[0]);

            // Trim any necessary space from the beginning of result.nodeText[i]
            // for i > 0.
            for (int i = 1; i < result.nodeText.length; i++) {
                if (!StringHelper.onlySpaces(result.nodeText[i])) {
                    result.nodeText[i] = result.nodeText[i].substring(minPos);
                    adjustMappingPairVector(1, -minPos, result.mapping[i]);
                }
            }
            return result;
        }

        /**
         * If this.isPrimed is false, it just returns this.nodeText. Otherwise,
         * it returns the primed version of this.nodeText. It tries to be clever
         * and not put parentheses around the text if they're not needed.
         * Parentheses are not needed if isSubexpressionName is true, or if
         * primingNeedsParens(...) says they're not needed.
         */
        String[] primedNodeText() {
            if (!this.isPrimed) {
                return this.nodeText;
            }

            boolean needsParens = (!this.isSubexpressionName)
                    && primingNeedsParens(this.semanticNode);

            String[] result = this.nodeText.clone();
            if (needsParens) {
                result = prependToStringArray(result, "(");
                result[result.length - 1] = StringHelper
                        .trimEnd(result[result.length - 1]) + ")'";
            } else {
                result[result.length - 1] = StringHelper
                        .trimEnd(result[result.length - 1]) + "'";
            }
            return result;
        }

        /**
         * This constructor is used to construct a NodeRepresentation object for
         * the entire selected step and its leaf proof (if any), and for an
         * expanded definition body. It just sets the semanticNode, nodeText and
         * mapping fields.
         * 
         * @param document
         *            The document of the editor
         * @param node
         * @throws BadLocationException
         */
        NodeRepresentation(IDocument document, SemanticNode node)
                throws BadLocationException {
            this.semanticNode = node;
            Location location = node.stn.getLocation();
            nodeText = new String[location.endLine() - location.beginLine() + 1];
            mapping = new Vector[nodeText.length];
            for (int i = 0; i < mapping.length; i++) {
                mapping[i] = new Vector<MappingPair>();
                mapping[i].add(new MappingPair(1, -node.stn.getLocation()
                        .beginColumn()));
            }
            if (location.beginLine() == location.endLine()) {
                IRegion thmregion = EditorUtil.getRegionOf(document,
                        node.stn.getLocation());
                String str = document.get(thmregion.getOffset(),
                        thmregion.getLength());
                nodeText[0] = str;
                return;
            }

            IRegion region = document
                    .getLineInformation(location.beginLine() - 1);
            nodeText[0] = document.get(
                    region.getOffset() + location.beginColumn() - 1,
                    region.getLength() - location.beginColumn() + 1);
            // minCol is the min of the beginning column of the first line (with
            // the first column numbered 0) and the smallest number of leading
            // spaces of any later line. However, lines with no text
            // should be ignored.
            int minCol = location.beginColumn() - 1;
            for (int i = 1; i < nodeText.length; i++) {
                region = document.getLineInformation(location.beginLine() - 1
                        + i);
                nodeText[i] = document.get(region.getOffset(),
                        region.getLength());
                if (!StringHelper.onlySpaces(nodeText[i])) {
                    minCol = Math.min(minCol,
                            StringHelper.leadingSpaces(nodeText[i]));
                }
            }

            // remove the rest of the last line that's not part of the token's
            // text
            nodeText[nodeText.length - 1] = nodeText[nodeText.length - 1]
                    .substring(0, location.endColumn());

            // Add any necessary space at the beginning of nodeText[0]
            int spacesAddedToFirstLine = location.beginColumn() - minCol - 1;
            nodeText[0] = StringHelper.copyString(" ", spacesAddedToFirstLine)
                    + nodeText[0];
            mapping[0].elementAt(0).inc = -minCol - 1;

            // Trim any necessary space from the beginning of nodeText[i] for i
            // > 0. However, must check for the case of an empty line.
            for (int i = 1; i < nodeText.length; i++) {
                if (!StringHelper.onlySpaces(nodeText[i])) {
                    nodeText[i] = nodeText[i].substring(minCol);
                    mapping[i].elementAt(0).inc = -1 - minCol;
                }
            }
            return;
        }

        /**
         * Constructs an empty object
         */
        public NodeRepresentation() {
            // TODO Auto-generated constructor stub
        }

        /**
         * Make a deep clone of this NodeRepresentation object, with given
         * parent fields.
         * 
         * @param parNode
         *            The parentNode field of the cloned object.
         * @param parVector
         *            The parentVector field of the cloned object
         * @return
         */
        protected NodeRepresentation deepClone(NodeRepresentation parNode,
                Vector<NodeRepresentation> parVector) {
            NodeRepresentation result = new NodeRepresentation();

            result.semanticNode = this.semanticNode;

            // clone the nodeText field
            result.nodeText = new String[this.nodeText.length];
            for (int i = 0; i < result.nodeText.length; i++) {
                result.nodeText[i] = this.nodeText[i];
            }

            // clone the mapping field
            result.mapping = null;
            if (this.mapping != null) {
                result.mapping = this.mapping.clone();
                for (int i = 0; i < result.mapping.length; i++) {
                    result.mapping[i] = new Vector<MappingPair>();
                    for (int j = 0; j < this.mapping[i].size(); j++) {
                        result.mapping[i].add(this.mapping[i].elementAt(j).clone());
                    }
                }
            }

            // recursively clone the children
            result.children = null;
            if (this.children != null) {
                result.children = new Vector<Vector<NodeRepresentation>>();
                for (int i = 0; i < this.children.size(); i++) {
                    Vector<NodeRepresentation> oldParVec = this.children
                            .elementAt(i);
                    Vector<NodeRepresentation> newParVec = new Vector<NodeRepresentation>();
                    for (int j = 0; j < oldParVec.size(); j++) {
                        newParVec.addElement(oldParVec.elementAt(j).deepClone(
                                result, newParVec));
                    }
                    result.children.addElement(newParVec);
                }
            }

            result.instantiationSubstitutions = this.instantiationSubstitutions.clone() ;
            // result.instantiatedNamePrefix = this.instantiatedNamePrefix ;
            result.nodeType = this.nodeType;
            result.nodeSubtype = this.nodeSubtype;
            // result.stepName = this.stepName ;
            result.newId = this.newId;
            result.initialPosition = this.initialPosition;
            result.contextStepName = this.contextStepName;
            result.fromGoal = this.fromGoal;
            result.fromExists = this.fromExists ;
            result.parentNode = parNode;
            result.parentVector = parVector;
            result.isCreated = this.isCreated;
            result.onSameLineAsNext = this.onSameLineAsNext;
            result.isPrimed = this.isPrimed;
            result.isSubexpressionName = this.isSubexpressionName;

            result.fromDefs = this.fromDefs.clone() ;
            result.decomposition = null;
            if (this.decomposition != null) {
                result.decomposition = this.decomposition.clone();
            }

            // The following was added for testing. It should no longer be
            // necessary.
            // But if it fails, there's a serious bug, so we might as well keep
            // it.
            if (result.children != null) {
                for (int i = 0; i < result.children.size(); i++) {
                    Vector<NodeRepresentation> pvec = result.children
                            .elementAt(i);
                    for (int j = 0; j < pvec.size(); j++) {
                        NodeRepresentation nr = pvec.elementAt(j);
                        if (nr.parentNode != result || nr.parentVector != pvec) {
                            MessageDialog.openError(UIHelper.getShellProvider()
                                    .getShell(), "Decompose Proof Command",
                                    "An error that should not happen has occurred in "
                                            + "line 6347 of DecomposeProofHandler.");
                        }
                    }
                }
            }

            return result;
        }

        public String toString() {
            String val = "";
            // if (originalOperator != null) {
            // val = "Original Operator: " + originalOperator + "\n" ;
            // }
            val = val + "nodeText: |=\n" + stringArrayToString(nodeText) + "=|";
            for (int i = 0; i < mapping.length; i++) {
                val = val + "\n" + i + ":";
                for (int j = 0; j < mapping[i].size(); j++) {
                    val = val + "  " + mapping[i].elementAt(j).toString();
                }
            }

            return val;
        }

    }

    /**
     * This is the "inverse" of the method NodeRepresentation.nodeRepPath(). See
     * the comments for that method to understand what pathToNodeRep is doing.
     * 
     * @param vec
     *            Should be the result produced by a call of nodeRepPath().
     * @return Should be a NodeRepresentation nr such that nr.nodeRepPath() =
     *         vec.
     */
    NodeRepresentation pathToNodeRep(Vector<Integer> vec) {
        NodeRepresentation result = null;
        int i = vec.size() - 1;
        int idx = vec.elementAt(i).intValue();
        if (idx == -1) {
            return state.goalRep;
        }
        ;
        result = state.assumeReps.elementAt(idx);
        i--;
        while (i >= 0) {
            int idx1 = vec.elementAt(i).intValue();
            i--;
            int idx2 = vec.elementAt(i).intValue();
            result = result.children.elementAt(idx1).elementAt(idx2);
            i--;
        }
        return result;
    }

    /**
     * A NodeTextRep object contains only the nodeText, and mapping fields of a
     * NodeRepresentation object. I should probably refactor things so that
     * instead of having those two fields, a NodeRepresentation object contains
     * a NodeText field.
     * 
     * 2 Dec 2014: Added a renaming field.  See the field of the same
     * name of a Decomposition object.
     */
    static class NodeTextRep {
        // SemanticNode semanticNode = null ;
        String[] nodeText = null;
        Vector<MappingPair>[] mapping = null;
        Renaming renaming = new Renaming() ;

        public NodeTextRep(String[] text, Vector<MappingPair>[] map) {
            // semanticNode = node ;
            nodeText = text;
            mapping = map;
        }

        public NodeTextRep() {
            // TODO Auto-generated constructor stub
        }

        /**
         * Makes a deep copy of the NodeTextRep object.
         */
        public NodeTextRep clone() {
            NodeTextRep result = new NodeTextRep();
            result.nodeText = new String[this.nodeText.length];
            for (int i = 0; i < result.nodeText.length; i++) {
                result.nodeText[i] = this.nodeText[i];
            }
            result.mapping = null;
            if (this.mapping != null) {
                result.mapping = this.mapping.clone();
                for (int i = 0; i < result.mapping.length; i++) {
                    result.mapping[i] = new Vector<MappingPair>();
                    for (int j = 0; j < this.mapping[i].size(); j++) {
                        result.mapping[i].add(this.mapping[i].elementAt(j).clone());
                    }
                }
            }
            result.renaming = this.renaming.clone() ;
            return result;
        }

        public String toString() {
            String val = "";
            val = val + "nodeText: |=\n" + stringArrayToString(nodeText) + "=|";
            for (int i = 0; i < mapping.length; i++) {
                val = val + "\n" + i + ":";
                for (int j = 0; j < mapping[i].size(); j++) {
                    val = val + "  " + mapping[i].elementAt(j).toString();
                }
            }

            return val;
        }
    }
    
    /**
     * An InstanceSubstitution object provides the necessary data to handle an
     * expression obtained by expanding a definition imported into a module by 
     * instantiation.
     * 
     * In general, a definition in the current module comes from a usually empty
     * sequence of instantiations.  When expanding the definition, two kinds of
     * substitutions may have to be performed when that sequence is non-empty.
     * 
     * - The WITH clause of an instantiation specifies substitutions of expressions
     *   for module parameters.  
     *   
     * - Instantiation with renaming requires renaming of user-defined operators
     *   that appear in the body of the definition expansion.  For example,
     *   suppose an operator Op is defined in module M in terms of operator
     *   DOp.  If an occurrence of Foo(x+y,z)!Bar!Op(a) occurring in the current
     *   module is expanded, then each instance of DOp in the definition of Op
     *   must be replaced by Foo(x+y,z)!Bar!DOp.
     *   
     * The following issues arise in implementing these substitutions.
     * 
     * - When a definition is imported by a sequence of instantiations, these two
     *   kinds of substitutions may have to be made in the WITH expressions
     *   in all the INSTANCE statements in the sequence.  The substitution
     *   for module parameters in these WITH expressions is straightforward,
     *   indicated in the semantic tree by a sequence of SubstInNode objects. 
     *   (For example, it need not be done in the first WITH expressions
     *   in the first SubstInNode in the sequence.)  However, the substitution 
     *   for user-defined operators necessitated by renaming is not straightforward.  
     *   Consider the expression Foo(x+y,z)!Bar!Op(a).  We know that the sequence
     *   of INSTANCEs importing the definition of Foo!Bar!Op contains two instantiations
     *   with renaming.  It could contain any number of INSTANCEs with WITH
     *   clauses, which is the number of SubstInNode objects in the imported
     *   definition.  A user-defined operator POp appearing in one of those
     *   WITH clauses might have to be replaced by any one of these three possible
     *   names:
     *   
     *      POp    Foo(x+y,z)!POp   Foo(x+y,z)!Bar!POp
     *   
     *   The only way to determine which one it is is to look up all three of these
     *   names in the current module and choose the one whose semantic node
     *   leads to the same definition as does the semantic node of the occurrence
     *   of POp in the SubstInNode.  If its definition, or one of the INSTANCEs
     *   in the importing sequence is LOCAL, then no expansion of the expression
     *   Foo(x+y,z)!Bar!Op(a) in the current module is possible.  
     *   
     *   NOTE: TLAPS has this problem when expanding definitions.  If there is no 
     *   name for the importation of POp into the current module, TLAPS gives 
     *   it an untypable name--something like Foo!POp_$--that indicates what
     *   name the operator would have if its definition/importation were not LOCAL.
     *   When TLAPS is modified to use SANY's parse tree instead of its own parser,
     *   then it will not be able to provide this kind of name unless SANY is
     *   modified to add the necessary information.  It's probably not worth
     *   doing this, since a name like POp_$ is probably good enough.
     *   
     *   WARNING: This issue is an example of why a program should not be implemented
     *   incrementally, by handling the "important" cases first.  Probably about
     *   .01% of the definitions that TLAPS will have to expand come from instantiation.
     *   However, all definition expansion has to be able to handle that .01% 
     *   correctly, so the correct handling it has to be designed in from the beginning
     *   because it will be much harder to add it as an afterthought.
     *   
     * - 
     *  
     * @author lamport
     *
     */
    public class InstanceSubstitution {
        
        /**
         * Invariant: params.size() = substs.size()
         * 
         * params.elementAt(i) = opdecl, substs.elementAt(i) = expr
         * denotes the substitution of the string expr for the OpDeclNode opdecl,
         * where opdecl is a CONSTANT or VARIABLE declared in an instantiated model.
         */
        Vector<OpDeclNode> params = new Vector<OpDeclNode>();
        Vector<String> substs = new Vector<String>() ;
        
        /**
         * prefix is a string such as Foo!Bar! indicating that any use Op(...)
         * of an operator Op defined in the instantiated module is instantiated 
         * as the expression Foo!Bar!Op(...) in the instantiating module.
         */
        String prefix = "";
        
        /**
         * If this.prefix equals "Foo!Bar!", then this.defPrefixes() equals
         * the 3-element array {"", "Foo!", "Foo!Bar!"}, then an operator Op that
         * appears in an expression substituted for one of the parameters in params
         * could be imported into the instantiating module as Op, Foo!Op, or Foo!Bar!Op.
         */
        String[] defPrefixes() { 
            String[] split = prefix.split("!") ;
            String[] result = new String[split.length+1] ;
            for (int i=0 ; i < result.length; i++) {
                if (i == 0) {
                    result[i] = "" ;
                 }
                 else {
                     result[i] = result[i-1] + split[i-1] ;
                 }
                if (i != 0) {
                    result[i] = result[i] + "!" ;
                 }
            }
            return result ;
        }
                
      public InstanceSubstitution clone() {
          InstanceSubstitution result = new InstanceSubstitution() ;
          for (int i=0 ; i < this.params.size() ; i++) {
              result.params.add(this.params.elementAt(i)) ;
              result.substs.add(this.substs.elementAt(i)) ; 
          }
          result.prefix = this.prefix ;
          return result ;
      }
    }

    /**
     * Assumes that ntRep is a representation of the expression represented by
     * ntRepNode.  It assumes oaNode represents a subexpression of ntRepNode
     * whose principal operator is a user-defined operator.  It returns a clone
     * of ntRep modified by adding the String prefix immediately 
     * before that principal operator.  If it can't find the operator, 
     * the method returns null.  It will not find the operator if:
     * 
     *   - It was obtained by parametrized instantiation--for example if the
     *     operator's name is Foo!bar but the expression contains Foo(42)!bar.
     *     
     *   - The name is spread across multiple lines (which is possible if it
     *     contains "!").
     * 
     * @param ntRep
     * @param ntRepNode
     * @param oaNode
     * @param prefix
     * @return
     */
    static NodeTextRep prependToOpName(
              NodeTextRep ntRep, 
              SemanticNode ntRepNode, 
              OpApplNode oaNode, 
              String prefix) {
        
        NodeTextRep result = ntRep.clone() ;
        SymbolNode opSym = oaNode.getOperator();
        if (! (opSym instanceof OpDefNode))  {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "Something unexpected is going on at "
                            + "line 6617 of NDecomposeProofHandler.");
            return null ;
        }
        
        OpDefNode opDef = (OpDefNode) opSym ;
        if (opDef.getKind() != OpDefNode.UserDefinedOpKind) {
            MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                    "Decompose Proof Command",
                    "Something unexpected is going on at "
                            + "line 6626 of DecomposeProofHandler.");
            return null ;
        }
        
        // For an operator named Foo!Bar!Op, sets split to the
        // 3-element array {"Foo", "Bar", "Op"}.  Let's call "Op"
        // the PRINCIPAL PART of the operator name.
        String[] split = opDef.getName().toString().split("!") ;

        Location ntLoc = ntRepNode.getLocation() ;
        Location opApplLoc = oaNode.getLocation() ;
        
        // set isAlphaNum true iff the principal part of the operator
        // name is an ordinary identifier.
        boolean isAlphaNum = true ;
        String ppart = split[split.length - 1] ;
        int i = 0 ;
        while ((i < ppart.length()) && isAlphaNum) {
            Character ch = ppart.charAt(i) ;
            if(! (Character.isLetterOrDigit(ch) || (ch=='_'))) {
                isAlphaNum = false ;
            }
            i++ ;
        }
       
        // Set oaBeginLine, oaBeginCol, oaEndLine, oaEndCol to the (0-based)
        // positions of the beginning and end of oaNode's representation
        // in ntRep.
        int oaBeginLine = opApplLoc.beginLine() - ntLoc.beginLine() ;
        int bCol = opApplLoc.beginColumn() ;
        int oaBeginLoc = colToLoc(bCol,result.mapping[oaBeginLine]) ;
        int oaEndLine = opApplLoc.endLine() - ntLoc.beginLine() ;
        int oaEndLoc = colToLoc(opApplLoc.endColumn(), result.mapping[oaEndLine]) ;
        
        // Set bLine, bPos, ePos so that the operator name (which is assumed to
        // be on a single line) is between positions bPos to (excluding) ePos on
        // line bLine.
        int bLine = oaBeginLine ;
        int bPos  = oaBeginLoc  ;
        if (!isAlphaNum) {
            // In this case, set bLine, bPos to be right after the
            // first argument of the operator.
            SemanticNode[] oaArgs = oaNode.getArgs() ;
            if (oaArgs.length == 0) {
              MessageDialog.openError(UIHelper.getShellProvider() .getShell(), 
                      "Decompose Proof Command",
                       "Something unexpected is going on at "
                           + "line 6673 of DecomposeProofHandler.");
               return null ;  
            }
            Location firstArgLoc = oaArgs[0].getLocation() ;
            bLine = firstArgLoc.endLine() - ntLoc.beginLine();
            bCol = firstArgLoc.endColumn() + 1 ;
            bPos  = colToLoc(firstArgLoc.endColumn() + 1, result.mapping[bLine]);
        }
        
        // skip initial white space
        boolean notDone = true ;
        while (notDone) {
            while (notDone && bPos < result.nodeText[bLine].length()) {
               if (! Character.isWhitespace(result.nodeText[bLine].charAt(bPos))) {
                   notDone = false ;
               }
               else {
                   bCol ++ ;
                   bPos ++ ;
               }
            }
            if (notDone) {
                bLine ++ ;
                bPos = 0 ;
                if (bLine >= result.nodeText[bLine].length()) {
                    MessageDialog.openError(UIHelper.getShellProvider() .getShell(), 
                            "Decompose Proof Command",
                             "Something unexpected is going on at "
                                 + "line 6701 of DecomposeProofHandler.");
                     return null ; 
                }
            }
        }
        int ePos  = result.nodeText[bLine].length() ;
        if (oaEndLine == bLine) {
            ePos = oaEndLoc + 1 ;
        }
                
        // Check that bPos is at the beginning of the operator name.
        String[] aSplit = result.nodeText[bLine].substring(bPos, ePos).split("!") ;
        for (i = 0; i < aSplit.length; i++) {
            aSplit[i] = aSplit[i].trim() ;
        }
        boolean OK = aSplit.length >= split.length ;
        i = 0 ;
        while (OK && i < split.length) {
            OK = split[i].equals(aSplit[i]) 
                   || ((i == split.length - 1) 
                         && aSplit[i].startsWith(split[i])
                         && ! (isAlphaNum &&  (Character.isLetterOrDigit(aSplit[i].charAt(split[i].length()))
                                 || (aSplit[i].charAt(split[i].length())=='_') )));    
            i++ ;
        }        
        if (!OK) {
            MessageDialog.openError(UIHelper.getShellProvider()
                    .getShell(), "Decompose Proof Command",
                    "Cannot rename use of " + opDef.getName());
            return null ;
        }
        
        // Do the renaming.
        result.nodeText[bLine] =
         result.nodeText[bLine].substring(0,bPos) + prefix + 
           result.nodeText[bLine].substring(bPos) ;
        // First argument below changed from bCol to bCol+1 on 28 Nov 2014
        // because we have effectively replaced the name in bCol by a
        // longer name.
        adjustMappingPairVector(bCol + 1, prefix.length(), result.mapping[bLine]) ;  
        
        // correct the indentation
        Vector<Insertion>[] insVecArray = new Vector[result.nodeText.length] ;
        
        for (i=0; i < result.nodeText.length; i++) {
            insVecArray[i] = new Vector<Insertion>() ;
            if (i == bLine) {
                insVecArray[i].add(new Insertion(bPos, 0, prefix.length())) ;
            }
        }
        
        adjustIndentation(ntRep, result, insVecArray) ;
        return result ;
    }
    
    /**
     * Returns a brand new NodeTextRep that's equal to the nodeRep argument
     * except that the String str has been appended to the last line.
     */
    static NodeTextRep appendToNodeText(NodeTextRep nodeRep, String str) {
        NodeTextRep result = nodeRep.clone();
        result.nodeText[result.nodeText.length - 1] = result.nodeText[result.nodeText.length - 1]
                + str;
        return result;
    }

    /**
     * Returns a brand new NodeTextRep that's equal to the nodeRep argument
     * except that the String str has been prepended to the first line and
     * subsequent lines have been indented to preserve the alignment with the
     * original first line.
     */
    static NodeTextRep prependToNodeText(NodeTextRep nodeRep, String str) {
        NodeTextRep result = nodeRep.clone();
        for (int i = 0; i < nodeRep.nodeText.length; i++) {
            if (i == 0) {
                result.nodeText[0] = str + result.nodeText[0];
            } else {
                result.nodeText[i] = StringHelper.copyString(" ", str.length())
                        + result.nodeText[i];
            }
            adjustMappingPairVector(1, str.length(), result.mapping[i]);
        }
        return result;
    }

    /**
     * Returns a new string array that's the same as `array' except that the
     * String str has been appended to the last line.
     */
    static String[] appendToStringArray(String[] array, String str) {
        String[] result = new String[array.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = array[i];
        }
        result[result.length - 1] = array[result.length - 1] + str;
        return result;
    }

    /**
     * Returns a new string array that's the same as `array' except that the
     * String str has been prepended to the first line and subsequent lines have
     * added spaces to indent them to preserve the alignment with the original
     * first line.
     */
    static String[] prependToStringArray(String[] array, String str) {
        String[] result = new String[array.length];
        for (int i = 0; i < result.length; i++) {
            if (i == 0) {
                result[0] = str + array[0];
            } else {
                result[i] = StringHelper.copyString(" ", str.length())
                        + array[i];
            }
        }
        return result;
    }

    /**
     * Returns the concatenation of array1 and array2.
     */
    static String[] concatStringArrays(String[] array1, String[] array2) {
        String[] result = new String[array1.length + array2.length];
        for (int i = 0; i < array1.length; i++) {
            result[i] = array1[i];
        }
        for (int i = 0; i < array2.length; i++) {
            result[i + array1.length] = array2[i];
        }
        return result;
    }
    
    /**
     * returns the comma separated list obtained by concatening two
     * (possibly empty) comma separated lists.
     * 
     * @param str1
     * @param str2
     * @return
     */
    static String concatCommaSeparatedLists(String str1, String str2) {
        if (str1 == null || (str1.trim().equals(""))) {
            return str2 ;
        }
        String result = str1.trim();
        
        if (str2 == null || (str2.trim().equals(""))) {
            return result ;
        }
        
        return result + ", " + str2.trim();
    }

    /**
     * Returns a string containing a comma-separated list of the elements in the
     * set.
     */
    static String setOfStringsToList(Set<String> set) {
        String result = "";
        Iterator<String> iter = set.iterator();
        boolean first = true;
        while (iter.hasNext()) {
            if (first) {
                first = false;
            } else {
                result = result + ", ";
            }
            result = result + iter.next();
        }
        return result;
    }

    /**
     * A renaming object indicates that the name of each node
     * identifiers.elementAt(i) has been renamed to newNames.elementAt(i).
     * More generally, it indicates that instances of the node have
     * been replaced by the corresponding string, which may be an expression.
     * It is used both for recording the renaming of identifiers to 
     * avoid name clashes and the substitution of expressions for
     * module parameters in an instantiation.  (It does not seem to be
     * used to represent the substitution of arguments for operator-definition
     * expansion.)
     * 
     * @author lamport
     */
    private static class Renaming {
        Vector<FormalParamNode> identifiers = new Vector<FormalParamNode>();
        Vector<String> newNames = new Vector<String>();

        /**
         * Returns a new Renaming object that is the union of
         * the renamings of this object with the argument.
         * 
         * @param renaming
         * @return
         */
        public Renaming addAll(Renaming renaming) {
            Renaming result = this.clone() ;
            for (int i=0; i < renaming.identifiers.size(); i++) {
                int j = 0;
                boolean notFound = true ;
                while ((j < this.identifiers.size()) && notFound) {
                    if (renaming.identifiers.elementAt(i) == 
                            this.identifiers.elementAt(j)) {
                        notFound = false;
                    }
                    j++;
                }
                if (notFound) {
                    result.identifiers.add(renaming.identifiers.elementAt(i)) ;
                    result.newNames.add(renaming.newNames.elementAt(i)) ;
                }
            }
            return result ;
        }
        
        /**
         * Returns a new Renaming object whose fields are clones of this
         * object's fields (meaning that they are new Vector objects containing
         * the same elements).
         */
        public Renaming clone() {
            Renaming result = new Renaming();
            result.identifiers = (Vector<FormalParamNode>) this.identifiers
                    .clone();
            result.newNames = (Vector<String>) this.newNames.clone();
            return result;
        }
        
        public String toString() {
            String result = "[" ;
            for (int i=0; i < newNames.size(); i++) {
                if (i > 0) {
                    result = result + ", " ;
                } 
                result = result + identifiers.elementAt(i).getName() +
                           " <- " + "\"" + newNames.elementAt(i) + "\"" ;
            }
            return result + "]" ;
        }
    }

    /**
     * A Decomposition object describes the possible decomposition of an
     * assumption or goal.
     * 
     * @author lamport
     * 
     */
    class Decomposition {
        /**
         * The type of decomposition. Its value is any of the first six possible
         * nodeSubtype values of a NodeRepresentation object. This is redundant
         * information, since for any NodeRepresentation object nd,
         * nd.nodeSubtype should equal nd.decomposition.type if nd.decomposition
         * is non-null.
         */
        int type;

        /**
         * If non-null, then the decomposition is to be performed by expanding
         * the definition of this (user-defined) symbol.
         */
        String definedOp = null;

        /**
         * If definedOp != null, so this decomposition is expanding a
         * definition, then formalParms[i] is the FormalParamNode of the i-th
         * formal parameter of the definition, argNodes[i] is the semantic node
         * of the i-th argument, and arguments[i] is its string representation,
         * which must appear on a single line.
         */
        FormalParamNode[] formalParams = null;
        String[] arguments = null;
        SemanticNode[] argNodes = null;

        /**
         * If non-null, then this is the NodeTextRep representing the operator
         * use that is to be expanded. E.g., it could represent source text such
         * as Bar(a + b, c) . If this decomposition is effected by the user with
         * the appropriate button push, then
         */
        NodeTextRep definedOpRep = null;

        /**
         * If definedOp != null, then `renaming' indicates the renaming of bound
         * identifiers that have been performed in the definition of definedOp
         * to avoid name clashes.  For example, if \E decomposition is performed
         * on the assumption  \E x : A \/ B , which results in renaming x
         * to x_1, then the decomposition.renaming field for the  A \/ B
         * node will record the renaming of the bound symbol x to x_1.
         */
        Renaming renaming = new Renaming();

        /**
         * The instantiationSubstitutions field of the decomposition's
         * children's NodeRepresentation objects.  If definedOpRep = null
         * or definedOpRep is not an operator imported by instantiation, then
         * this will be the same as the instantiationSubstitutions field of
         * the NodeRepresentation whose decomposition field this Decomposition 
         * object is.  
         * 
         * A null value of this field indicates that it couldn't be computed
         * because the instantiated definition can't be decomposed because
         * the instantiation substitutes a multi-line formula for a parameter. 
         */
        InstanceSubstitution instantiationSubstitutions = new InstanceSubstitution() ;

        /**
         * If definedOp is not null, then this is the name of the module
         * containing the node's definition.
         */
        String moduleName = null;

        /**
         * The nodes into which the assumption or goal is to be decomposed.
         */
        Vector<SemanticNode> children = new Vector<SemanticNode>();

        /**
         * If definedOp is the string "foo", then children.elementAt(i) has the
         * name "foo" + namePath.elementAt(i).
         * 
         */
        Vector<String> namePath = new Vector<String>();

        /**
         * If this is a \A or \E decomposition, then this is the list of bound
         * identifiers.
         */
        Vector<FormalParamNode> quantIds = null;

        /**
         * If this is a \A or \E decomposition for a bounded quantifier (like \A
         * x \in S), then this is the list of bound identifiers.
         */
        Vector<ExprNode> quantBounds = null;

        /**
         * If this is a \A or \E decomposition for a bounded quantifier (like \A
         * x \in S), then this is the list of subexpression names for each of
         * the elements of quantBounds.
         */
        Vector<String> quantBoundsubexpNames = null;

        /**
         * True iff the Decomposition's children and quantBounds should be
         * primed.
         */
        boolean primed = false;

        /**
         * This is a deep clone only in that it clones the renaming and
         * definedOpRep fields. The other fields are strings, semantic nodes,
         * and values, which are (effectively) immutable as far as the command
         * is concerned.
         * 
         * @return
         */
        public Decomposition clone() {
            Decomposition result = new Decomposition();

            result.definedOpRep = null;
            if (this.definedOpRep != null) {
                result.definedOpRep = this.definedOpRep.clone();
            }

            result.renaming = null;
            if (this.renaming != null) {
                result.renaming = this.renaming.clone();
            }
            
//            result.instantiationSubstitutionsD =
//                        this.instantiationSubstitutionsD.clone() ;
//            result.instantiatedNamePrefixD = 
//                      this.instantiatedNamePrefixD ;            
            result.type = this.type;
            result.definedOp = this.definedOp;
            result.formalParams = this.formalParams;
            result.arguments = this.arguments;
            result.argNodes = this.argNodes;
            result.moduleName = this.moduleName;
            result.children = this.children;
            result.namePath = this.namePath;
            result.quantIds = this.quantIds;
            result.quantBounds = this.quantBounds;
            result.quantBoundsubexpNames = this.quantBoundsubexpNames;
            result.primed = this.primed;
            result.instantiationSubstitutions = 
                    this.instantiationSubstitutions.clone();
            return result;
        }

        public String toString() {
            String val = "type: " + nodeSubTypeToString(this.type);
            if (definedOp != null) {
                val = val + "\ndefinedOp: " + this.definedOp;
                val = val + "\ndefinedOpRep: " + definedOpRep.toString();
            }
            val = val + "\nmoduleName: " + this.moduleName;
            val = val + "\nchildren: ";
            for (int i = 0; i < this.children.size(); i++) {
                val = val + "\nchildren[" + i + "]:\n "
                        + children.elementAt(i).toString();
            }
            // val = val + "\nchildren: " + this.children.toString();
            val = val + "\nnamePath: " + this.namePath.toString();
            if (quantIds != null) {
                val = val + "\nquantIds: ";
                for (int i = 0; i < this.quantIds.size(); i++) {
                    if (i != 0) {
                        val = val + ", ";
                    }
                    val = val + quantIds.elementAt(i).getName().toString();
                }
            }
            if (quantBounds != null) {
                for (int i = 0; i < this.quantBounds.size(); i++) {
                    val = val + "\nquantBounds[" + i + "]:\n "
                            + quantBounds.elementAt(i).toString();
                }
                val = val + "quantBoundsubexpNames: ";
                for (int i = 0; i < this.quantBounds.size(); i++) {
                    val = val + ((i == 0) ? "" : ", ")
                            + quantBoundsubexpNames.elementAt(i);
                }

            }
            val = val + "\nprimed: " + primed;
            return val;
        }
    }

    /**
     * Adds to `result' all symbols in scope for NodeRepresentation `node' that
     * are defined or declared in the current step by NEW assumptions. It can be
     * called only when `node' is in this.state.assumeReps, is a descendant of a
     * node in this.state.assumeReps, or is the goal.
     * 
     * @param result
     * @param node
     */
    private void addDeclaredSymbols(StringSet result,
            NodeRepresentation node) {
        Vector<NodeRepresentation> parentVec = node.getParentVector();
        // node.parentVector = null iff node is the goal, the case we
        // handle by simply setting parentVec to state.assumeReps.
        if (parentVec == null) {
            parentVec = this.state.assumeReps;
        }

        int i = 0;
        while ((i < parentVec.size()) && (parentVec.elementAt(i) != node)) {
            NodeRepresentation parent = parentVec.elementAt(i);
            if (parent.nodeType == NodeRepresentation.NEW_NODE) {
                result.add(parent.newId);
            }
            i++;
        }

        // If this isn't a top-level assumption (or the goal), call the method
        // on
        // its parent.
        if (parentVec != this.state.assumeReps) {
            // If parentVec != null, then node.parentNode should be
            // non-null--but just in case
            if (node.parentNode != null) {
                addDeclaredSymbols(result, node.parentNode);
            } else {
                System.out
                        .println("Bug found in DecomposeProofHandler.addDeclaredSymbols.");
            }
        }
    }

    /**
     * Adds to `prevDeclared' all top-level NEW symbols that occur after the
     * position of NodeRepresentation `nodeRepArg' or its ancestor in
     * assumpReps. And, if includeGoal = true, to all bound symbols in the goal.
     * It can be called only when `nodeRepArg' is in this.state.assumeReps, is a
     * descendant of a node in this.state.assumeReps, or is the goal.
     * 
     * Change made 3 Dec 2014: when includeGoal = true, also add all bound
     * identifiers introduced in created assumptions that will follow the current
     * assumption in state.assumeReps.
     * 
     * @param prevDeclared
     * @param nodeRepArg
     * @param includeGoal
     */
    private void addSymbolsDeclaredLater(StringSet prevDeclared,
            NodeRepresentation nodeRepArg, boolean includeGoal) {
        // Set assumpRepNode to the NodeRepresentation and
        // set idx to the number such that assumpRepNode equals
        // assumpReps.elementAt(idx) and either equals or is an
        // ancestor of nodeRepArg.
        NodeRepresentation assumpRepNode = nodeRepArg;
        while (assumpRepNode.parentNode != null) {
            assumpRepNode = assumpRepNode.parentNode;
        }
        int idx = 0;
        while ((idx < this.state.assumeReps.size())
                && (this.state.assumeReps.elementAt(idx) != assumpRepNode)) {
            idx++;
        }
        if (idx == this.state.assumeReps.size()) {
            // This should be the goal, so there are no later declarations.
            return;
        }

        // Add to prevDeclared the set of all top-level NEW identifiers that
        // follow
        // assumpRepNode in state.assumeReps together with all the bound
        // identifiers
        // in the goal.
        for (int i = idx + 1; i < state.assumeReps.size(); i++) {
            NodeRepresentation anode = state.assumeReps.elementAt(i);
            if (anode.nodeType == NodeRepresentation.NEW_NODE) {
                prevDeclared.add(anode.newId);
            }
            // Following if added 3 Dec 2014            
            if (includeGoal && anode.isCreated) {
                ExprNode snode = null ;
                if ((anode.semanticNode != null) && (anode.semanticNode instanceof ExprNode)) {
                    snode = (ExprNode) anode.semanticNode; 
                }
                if (snode != null) {
                    FormalParamNode[] goalIdents = ResourceHelper
                            .getBoundIdentifiers(snode);
                    for (int j = 0; j < goalIdents.length; j++) {
                        // 4 Dec 2014: In following statement, changed
                        //    goalIdents[j].getName().toString()
                        // to
                        //   getCurrentName(goalIdents[j], this.state.renaming)
                        prevDeclared.add(getCurrentName(goalIdents[j], this.state.renaming));
                    }
                }
    
            }
        }

        if (includeGoal) {
            FormalParamNode[] goalIdents = ResourceHelper
                    .getBoundIdentifiers((ExprNode) this.state.goalRep.semanticNode);
            for (int i = 0; i < goalIdents.length; i++) {
                // 4 Dec 2014: In following statement, changed
                //    goalIdents[i].getName().toString()
                // to
                //   getCurrentName(goalIdents[i], this.state.renaming)
                prevDeclared.add(getCurrentName(goalIdents[i], this.state.renaming));
            }
        }
    }

    /**
     * Converts a NodeRepresentation subType to a string. Used for debugging.
     * 
     * @param subType
     * @return
     */
    public static String nodeSubTypeToString(int subType) {
        String val = "?";
        switch (subType) {
        case NodeRepresentation.AND_TYPE:
            val = "AND_TYPE";
            break;
        case NodeRepresentation.OR_TYPE:
            val = "OR_TYPE";
            break;
        case NodeRepresentation.IMPLIES_TYPE:
            val = "IMPLIES_TYPE";
            break;
        case NodeRepresentation.FORALL_TYPE:
            val = "FORALL_TYPE";
            break;
        case NodeRepresentation.EXISTS_TYPE:
            val = "EXISTS_TYPE";
            break;
        case NodeRepresentation.SQSUB_TYPE:
            val = "SQSUB_TYPE";
            break;
//        case NodeRepresentation.MULTI_TYPE:
//            val = "MULTI_TYPE";
//            break;
        case NodeRepresentation.OTHER_TYPE:
            val = "OTHER_TYPE";
            break;
        }
        return val;
    }

    /**
     * Returns the NodeRepresentation subtype for an OpApplNode whose operator
     * name is opId.
     * 
     * @param opId
     * @return
     */
    // private static int operatorNameToNodeSubtype(UniqueString opId) {
    // String opName = opId.toString();
    // if ((opId == ASTConstants.OP_cl) || opName.equals("\\land")) {
    // return NodeRepresentation.AND_TYPE;
    // } else if ((opId == ASTConstants.OP_dl) || opName.equals("\\lor")) {
    // return NodeRepresentation.OR_TYPE;
    // } else if (opName.equals("=>")) {
    // return NodeRepresentation.IMPLIES_TYPE;
    // } else if ((opId == ASTConstants.OP_bf) || (opId == ASTConstants.OP_uf))
    // {
    // return NodeRepresentation.FORALL_TYPE;
    // } else if ((opId == ASTConstants.OP_be) || (opId == ASTConstants.OP_ue))
    // {
    // return NodeRepresentation.EXISTS_TYPE;
    // } else if (opId == ASTConstants.OP_sa) {
    // return NodeRepresentation.SQSUB_TYPE;
    // } else {
    // return NodeRepresentation.OTHER_TYPE;
    // }
    // }

    /**
     * This computes the decompose field of a NodeRepresentation.
     * 
     * @param sn
     * @param decomp
     *            The Decomposition from which the initial identifier renamings
     *            of the result are obtained.
     * @return
     */
    private Decomposition decompose(NodeRepresentation nodeRep,
            Decomposition decomp, boolean isAssumption) {
        SemanticNode sn = nodeRep.semanticNode;
        if (!(sn instanceof OpApplNode)) {
            return null;
        }

        OpApplNode node = (OpApplNode) sn;
        OpApplNode unprimedNode = node;

        Decomposition result = new Decomposition();
        if (decomp != null) {
            result.renaming.identifiers = (Vector<FormalParamNode>) decomp.renaming.identifiers
                    .clone();
            result.renaming.newNames = (Vector<String>) decomp.renaming.newNames
                    .clone();
        }
        
        // LL-XXXXXXX  I'm not sure if the following is correct or necessary.
        // The field gets overwritten if the decomposition requires expanding
        // a definition.
        result.instantiationSubstitutions = nodeRep.instantiationSubstitutions ;

        // Check if primed expression.
        if (node.getOperator().getName() == ASTConstants.OP_prime) {
            if (!(node.getArgs()[0] instanceof OpApplNode)) {
                return null;
            }
            node = (OpApplNode) node.getArgs()[0];
            unprimedNode = node;
            result.primed = true;
        }

        // If nodeRep.isSubexpressionName is false (so it was not obtained by
        // decomposing a definition using subexpression names), then we
        // see if this is an operator definition we can handle.
        if ((!nodeRep.isSubexpressionName)
                && (node.getOperator().getKind() == ASTConstants.UserDefinedOpKind)) {
            // This is a user-defined operator
            OpDefNode definition = (OpDefNode) node.getOperator();
            String operatorName = definition.getName().toString();
            
            // Set opDef to the (OpArgNode) at the bottom of the SubstInNode chain
            // and instSubs to the new InstanceSubstitution for the decomposition
            // nodes.
            ExprNode opDef = definition.getBody();
            InstanceSubstitution instSubs = nodeRep.instantiationSubstitutions.clone(); 
            while (opDef instanceof SubstInNode) {
                instSubs = substInNodeToInstanceSub(
                        instSubs, operatorName, (SubstInNode) opDef) ;
               if (instSubs == null) {
                    MessageDialog.openError(UIHelper.getShellProvider().getShell(),
                            "Decompose Proof Command",
                            "Decomposing an instantiated definition whose\n"
                            + "instantiation cannot be handled.");
                    return null;
                }
                opDef = ((SubstInNode)opDef).getBody() ;                        
            }
            
            // Set instSubs.prefix to the concatenation of 
            // instantiationSubstitutions.prefix of nodeRepArg with the
            // prefix of the operator whose definition we're decomposing.
            // 
            String instNamePrefix = nodeRep.instantiationSubstitutions.prefix ;
            String restOfName = operatorName ;
            while (restOfName.indexOf("!") != -1) {
                instNamePrefix = instNamePrefix + 
                                    restOfName.substring(0, restOfName.indexOf("!")+1) ;
                restOfName = restOfName.substring(restOfName.indexOf("!")+1) ;
            }
            instSubs.prefix = instNamePrefix ;


            if (opDef instanceof OpApplNode) {
                // This is a user-defined operator. We can handle it iff
                // the arguments are all single-line expressions.
                ExprOrOpArgNode[] args = node.getArgs();
                for (int i = 0; i < args.length; i++) {
                    SyntaxTreeNode stn = (SyntaxTreeNode) args[i].stn;
                    Location stnLoc = stn.getLocation();
                    if (stnLoc.beginLine() != stnLoc.endLine()) {
                        return null;
                    }
                }
                node = (OpApplNode) opDef;

                // We now set the definedOp and definedOpRep fields
                // iff we want to use subexpression names.
                result.moduleName = ((SyntaxTreeNode) node.stn).getLocation()
                        .source();
                // The following test is to determine if the definition should
                // be expanded by subexpression naming or by actual expansion.
                // (Initially, we don't deal with expansion of names from
                // another module.)
                result.instantiationSubstitutions = instSubs ;
                result.definedOp = operatorName;
                result.definedOpRep = nodeRep.subNodeText(unprimedNode);
                result.formalParams = definition.getParams();
                result.arguments = new String[result.formalParams.length];
                result.argNodes = unprimedNode.getArgs();

                for (int i = 0; i < result.arguments.length; i++) {
                    result.arguments[i] = stringArrayToString(nodeRep
                            .subNodeText(((OpApplNode) unprimedNode).getArgs()[i]).nodeText);
                }
            } else {
                // This means that the definition is not an OpApplNode, which
                // I don't think is possible.
                return null;
            }
        }

        // Indicate exactly how it needs to be decomposed by setting
        // the type field and also:
        // - setting isAndOrOr true iff this is an infix /\ or \/
        // - setting isJunction true iff this is a bulleted disjunction
        // or conjunction.
        // - setting isQuantifier true iff this is a \A or \E.
        // - setting isBoundedQuantifier iff isQuantifier true and it's
        // a boundedquantifier.
        // Return null if it can't be decomposed.
        boolean isAndOrOr = false;
        boolean isJunction = false;
        boolean isQuantifier = false;
        boolean isBoundedQuantifier = false;

        // First check if the OpApplNode's operator is a defined or built-in
        // operator. If not, we can't decompose so we return null.
        if (!(node.getOperator() instanceof OpDefNode)) {
            return null;
        }
        UniqueString opId = ((OpDefNode) node.getOperator()).getName();
        String opName = opId.toString();
        // Note: experimentation reveals that /\ and \/ are parsed
        // with operator names "\\land" and "\\lor".
        if (((opId == ASTConstants.OP_cl) || opName.equals("\\land"))
                && ( (! isAssumption) || conjIsDecomposable(node))) {
            result.type = NodeRepresentation.AND_TYPE;
            if (opId == ASTConstants.OP_cl) {
                isJunction = true;
            } else {
                isAndOrOr = true;
            }
        } else if ((opId == ASTConstants.OP_dl) || opName.equals("\\lor")) {
            result.type = NodeRepresentation.OR_TYPE;
            if (opId == ASTConstants.OP_dl) {
                isJunction = true;
            } else {
                isAndOrOr = true;
            }
        } else if (opName.equals("=>")) {
            result.type = NodeRepresentation.IMPLIES_TYPE;
        } else if ((opId == ASTConstants.OP_bf) || (opId == ASTConstants.OP_uf)) {
            result.type = NodeRepresentation.FORALL_TYPE;
            isQuantifier = true;
            if (opId == ASTConstants.OP_bf) {
                isBoundedQuantifier = true;
            }
        } else if ((opId == ASTConstants.OP_be) || (opId == ASTConstants.OP_ue)) {
            result.type = NodeRepresentation.EXISTS_TYPE;
            isQuantifier = true;
            if (opId == ASTConstants.OP_be) {
                isBoundedQuantifier = true;
            }
        } else if (opId == ASTConstants.OP_sa) {
            result.type = NodeRepresentation.SQSUB_TYPE;
        } else {
            return null;
        }

        /**
         * Now set result.children and result.namePath.
         */
        if (isAndOrOr) {
            processAndOrOr(result, node, "", opName);
        } else if (isJunction) {
            SemanticNode[] juncts = node.getArgs();
            for (int i = 0; i < juncts.length; i++) {
                result.children.add(juncts[i]);
                result.namePath.add("!" + (i + 1));
            }
        } else if (isQuantifier) {
            // There is just a single child. Set it, and
            // set namePath to its namePath entry.
            result.children.add(node.getArgs()[0]);
            String namePath = "!(";
            result.quantIds = new Vector<FormalParamNode>();
            if (isBoundedQuantifier) {
                // Bounded Quantifier
                result.quantBounds = new Vector<ExprNode>();
                result.quantBoundsubexpNames = new Vector<String>();
                FormalParamNode[][] quantIdsArray = node
                        .getBdedQuantSymbolLists();
                ExprNode[] quantBounds = node.getBdedQuantBounds();
                for (int i = 0; i < quantIdsArray.length; i++) {
                    // We don't handle a quantifier bound of the form <<x, y>>
                    // \in S
                    if (node.isBdedQuantATuple()[i]) {
                        return null;
                    }
                    FormalParamNode[] quantIds = quantIdsArray[i];
                    for (int j = 0; j < quantIds.length; j++) {
                        result.quantIds.add(quantIds[j]);
                        // Note that we have to repeat the quantifier bound
                        // for x and y in \E x, y \in S : ...
                        result.quantBounds.add(quantBounds[i]);
                        result.quantBoundsubexpNames.add("!" + (i + 1));
                        if (!((i == 0) && (j == 0))) {
                            namePath = namePath + ",";
                        }
                        namePath = namePath + quantIds[j].getName().toString();
                    }
                }
            } else {
                // Unbounded Quantifier
                FormalParamNode[] quantIds = node.getUnbdedQuantSymbols();
                for (int i = 0; i < quantIds.length; i++) {
                    result.quantIds.add(quantIds[i]);
                    if (i != 0) {
                        namePath = namePath + ",";
                    }
                    namePath = namePath + quantIds[i].getName().toString();
                }

            }
            namePath = namePath + ")";
            result.namePath.add(namePath);

        } else if ((result.type == NodeRepresentation.IMPLIES_TYPE)
                || (result.type == NodeRepresentation.SQSUB_TYPE)) {
            result.children.add(node.getArgs()[0]);
            result.namePath.add("!1");
            result.children.add(node.getArgs()[1]);
            result.namePath.add("!2");
        }
        // System.out.println("Decomposition");
        // System.out.println(result.toString());
        return result;
    }

    /**
     * This method ssumes node represents a conjunction (either infix or bulleted list).
     * Returns true iff one of the conjuncts is either
     *   - a \E  or 
     *   - a disjunction and this.state.splitChosen() = false 
     * or a conjunction c for which conjIsDecomposable(c) is true.
     * 
     * It assumes that a conjunct that is a SubstInNode is not decomposable.
     * This should be valid because
     * This will have to be changed to allow decomposition of formulas imported
     * by instantiation.  LL-XXXXXX
     * 
     * @param node
     * @param allowOr
     * @return
     */
    private boolean conjIsDecomposable(OpApplNode node) {
        ExprOrOpArgNode[] conjuncts = node.getArgs();
        for (int i = 0; i < conjuncts.length; i++) {
            // To be decomposable, the conjunct must be an OpApplNode
            if (conjuncts[i] instanceof OpApplNode) {
                OpApplNode curNode = (OpApplNode) conjuncts[i];

                // if this is a user-defined operator application
                // must examine its definition.
                if ((curNode.getOperator().getKind() == ASTConstants.UserDefinedOpKind)
                        && ((OpDefNode) curNode.getOperator()).getBody() instanceof OpApplNode) {
                    curNode = (OpApplNode) ((OpDefNode) curNode.getOperator())
                            .getBody();
                }

                if (curNode.getOperator() instanceof OpDefNode) {
                    UniqueString opId = ((OpDefNode) curNode.getOperator())
                            .getName();
                    String opName = opId.toString();

                    if (   (   (! this.state.splitChosen())
                            && (   (opId == ASTConstants.OP_dl)
                                || opName.equals("\\lor")
                                || (opId == ASTConstants.OP_sa)))
                        || (opId == ASTConstants.OP_be)
                        || (opId == ASTConstants.OP_ue)
                        || (    (   (opId == ASTConstants.OP_cl) 
                                 || opName.equals("\\land")) 
                             && conjIsDecomposable(curNode))) {
                        return true;
                    }
                }
            } // end if instanceof OpApplNode
        }

        return false;
    }

    /**
     * Assumes node represents a conjunction (either infix or bulleted list).
     * Returns true iff one of the conjuncts is a a \E, or a
     * conjunction c for which conjContainsExists(c) is true.
     * 
     * It assumes that a conjunct that is a SubstInNode is not decomposable.
     * This will have to be changed to allow decomposition of formulas imported
     * by instantiation.
     * 
     * Note: This method obtained by cloning conjIsDecomposable.  A sensible 
     * implementation of the Decompose Proof command would combine them into
     * a single method that returns the type of decomposition possible.
     * 
     * @param node
     * @return
     */
    private boolean conjContainsExists(OpApplNode node) {
        ExprOrOpArgNode[] conjuncts = node.getArgs();
        for (int i = 0; i < conjuncts.length; i++) {
            // To be decomposable, the conjunct must be an OpApplNode
            if (conjuncts[i] instanceof OpApplNode) {
                OpApplNode curNode = (OpApplNode) conjuncts[i];

                // if this is a user-defined operator application
                // must examine its definition.
                if ((curNode.getOperator().getKind() == ASTConstants.UserDefinedOpKind)
                        && ((OpDefNode) curNode.getOperator()).getBody() instanceof OpApplNode) {
                    curNode = (OpApplNode) ((OpDefNode) curNode.getOperator())
                            .getBody();
                }

                if (curNode.getOperator() instanceof OpDefNode) {
                    UniqueString opId = ((OpDefNode) curNode.getOperator())
                            .getName();
                    String opName = opId.toString();

                    if (   (opId == ASTConstants.OP_be)
                        || (opId == ASTConstants.OP_ue)
                        || (   (   (opId == ASTConstants.OP_cl) 
                                || opName.equals("\\land")) 
                            && conjContainsExists(curNode))) {
                        return true;
                    }
                }
            } // end if instanceof OpApplNode
        }

        return false;
    }

    /**
     * Recursive procedure to set the children and namePath fields of a
     * Decomposition object for an infix /\ or \/ . It is based on the
     * observation that A /\ B /\ C is parsed as (A /\ B) /\ C (and similarly
     * for \/). It does the obvious depth-first dive into the left operand,
     * adding the entire node if it's not an op operation.
     * 
     * @param decomp
     *            The Decomposition object whose fields are being set.
     * @param node
     *            The node being decomposed.
     * @param namePathPrefix
     *            The prefix to be prepended to the constructed namePath entry.
     * @param op
     *            either "\\lor" or "\\land".
     */
    private static void processAndOrOr(Decomposition decomp, SemanticNode node,
            String namePathPrefix, String op) {
        if (!(node instanceof OpApplNode)) {
            decomp.children.add(node);
            decomp.namePath.add(namePathPrefix);
            return;
        }
        OpApplNode aonode = (OpApplNode) node;
        SymbolNode sym = aonode.getOperator();
        UniqueString opId = null;
        String opName = null;
        if (sym instanceof OpDefNode) {
            opId = ((OpDefNode) sym).getName();
            opName = opId.toString();
        }
        if ((opName == null) || (!opName.equals(op))) {
            decomp.children.add(node);
            decomp.namePath.add(namePathPrefix);
            return;
        }
        // This is an op infix operation, so recurse.
        processAndOrOr(decomp, aonode.getArgs()[0], namePathPrefix + "!1", op);
        decomp.children.add(aonode.getArgs()[1]);
        decomp.namePath.add(namePathPrefix + "!2");
        return;
    }

    /********************* MappingPairs and their methods *******************************/
    /**
     * Note: If the Decompose Proof command ever gets recoded, it would probably
     * be a good idea to do away with MappingPairs and replace them with
     * Insertions. See the comments for the Insertion class below.
     * 
     * A MappingPair contains two int-valued fields : `col' and `inc'.
     * 
     * A line-mapping is a mapping from column-numbers in a line of the
     * specification to positions in a string. It is represented by a vector V
     * of MappingPair objects such that V[0].col = 1 and i < j implies V[i].col
     * < V[j].col. Such an array represents the line-mapping M such that M(c)
     * equals c plus the sum of all V[i].inc such that V[i].col <= c.
     * 
     * Suppose NTR is a NodeTextRep that represents the text of a SemanticNode
     * SN after some substitutions for identifiers have been performed. Then
     * NTR.mapping[i] is the mapping M from character locations in the (i+1)st
     * line of the source text of SN (locations start at 1) to the corresponding
     * character position (starting from 0) in the string NTR.nodeText[i]. The
     * value of M(c) is the obvious position in the string if c is the location
     * of any character in the original source that does not lie within an
     * identifier that has been substituted for, or if c is the location of the
     * first character of an identifier that has been substituted for. Hence,
     * the restriction of M to all such character locations is monotone. If
     * character location c+i lies within an identifier starting at location c
     * that has been substituted for, then M(c+i) = M(c) + i. This implies that
     * M is not monotone on all character locations in the source if the string
     * substituted for an identifier has fewer characters than the identifier.
     * 
     * In order to preserve essential alignments after substitutions, it seems
     * to be necessary to understand how a vector V of MappingPair objects that
     * represents a line mapping is constructed. If V is a line mapping for a
     * line in a NodeTextRep for a source SemanticNode SN,
     * 
     * 
     * @author lamport
     * 
     */
    private static class MappingPair {
        int col;
        int inc;

        MappingPair(int c, int p) {
            col = c;
            inc = p;
        }

        public DecomposeProofHandler.MappingPair clone() {
            return new MappingPair(this.col, this.inc);

        }
        
        public String toString() {
            return "<" + col + ", " + inc + ">";
        }
    }

    /**
     * Returns the string position to which the line-mapping defined by
     * MappingPair vec maps the column col.
     * 
     * @param col
     * @param vec
     * @return
     */
    private static int colToLoc(int col, Vector<MappingPair> vec) {
        int loc = col;
        for (int i = 0; (i < vec.size()) && (vec.elementAt(i).col <= col); i++) {
            loc = loc + vec.elementAt(i).inc;
        }
        return loc;
    }

    /**
     * Modify vec so the line mapping nl it represents is related to the
     * original line mapping ol by nl[c] = IF c < col THEN ol[c] ELSE ol[c] +
     * incr.  In other words, if adding n characters (or removing -incr 
     * characters) before the character in column c, then call
     * adjustMappingPairVector(c, n, ...).  However, if replacing 
     * a token of length blen at column c by an expression of length nlen,
     * then call adjustMappingPairVector(c+1, nlen - olen, ...)
     * because: (a) the beginning position of the expression is the
     * same as that of the token, and (b) one should never be
     * looking at or modifying anything inside the expression,
     * so we can call adjustMappingPairVector with any first
     * argument between c+1 and c+(length of original token).
     * 
     * @param col
     * @param incr
     * @param vec
     * @return
     */
    private static void adjustMappingPairVector(int col, int incr,
            Vector<MappingPair> vec) {
        // set i to the smallest value such that vec[i].col >= col, or i =
        // vec.size() if
        // there is none.
        int i;
        for (i = 0; (i < vec.size()) && (vec.elementAt(i).col < col); i++) {
        }

        if (i == vec.size()) {
            vec.add(new MappingPair(col, incr));
        } else if (vec.elementAt(i).col == col) {
            vec.elementAt(i).inc = vec.elementAt(i).inc + incr;
        } else {
            vec.insertElementAt(new MappingPair(col, incr), i);
        }
    }

    /**
     * Returns a vector the same length as vec whose elements are clones of the
     * elements of vec.
     * 
     * @param vec
     * @return
     */
    private static Vector<MappingPair> cloneMappingPairVector(
            Vector<MappingPair> vec) {
        Vector<MappingPair> result = new Vector<DecomposeProofHandler.MappingPair>();
        for (int i = 0; i < vec.size(); i++) {
            result.add(vec.elementAt(i).clone());
        }
        return result;
    }

    /************************* Insertions and their methods ***************************/
    /**
     * An Insertion object o represents the modification of a string in which a
     * sequence of o.oldLen characters at string position o.pos (counting from
     * 0) is replaced by a sequence of o.newLen characters. The position
     * newInsertPos(p, o) in the modified string corresponding to position p in
     * the original string is defined by
     * 
     * newInsertPos(p, o) == CASE p =< o.pos -> p [] o.pos < p < o.pos +
     * o.oldLen -> IF o.newLen = 1 THEN o.pos ELSE some value in
     * (o.pos+1)..(o.pos + o.newLen - 1) [] o.pos + o.oldLen =
     * < p * ->
     * p + (o.newLen - o.oldLen)
     * 
     * A sequence s of Insertion objects represents a sequence of such
     * modifications. The position newVecInsertPos(p, s) in the modified string
     * corresponding to the position p in the original string is defined by
     * 
     * newVecInsertPos(p, s) == IF s = << >> THEN p ELSE
     * newVecInsertPos(newInsertPos(p, Head(p)), Tail(p))
     * 
     * Insertions and these operations are used to preserve significant
     * indentation in TLA+ formulas after substitution. More precisely, suppose
     * L1 is a line and L0 is the line above L1 and closest to it such that the
     * position of the first non-blank character of L0 is =< the position of the
     * first non-blank character of L1. Suppose L0' and L1' are obtained from L0
     * and L1 by insertions described by the vectors V0 and V1. If p is the
     * position of the first non-blank character in L1, then
     * 
     * newVecInsertPos(p, V0) - newVecInsertPos(p, V1)
     * 
     * space characters must be added to the beginning of L1 to preserve the
     * indentation. (Adding negative characters means deletion.)
     * 
     * In this application, modifications are represented by vectors of
     * non-overlapping insertions. Thus, the non-deterministic choice in the
     * evaluation of newInsertPos occurs at most once in the evaluation of
     * newVecInsertPos.
     * 
     * Line mappings can be defined in terms of Insertion vectors as well by
     * MappingPair vectors. Insertions contain more information than
     * MappingPairs, which is why I had to introduce them. It would probably
     * have been better to use Insertions instead of MappingPairs from the
     * beginning. However, I don't feel like rewriting the code that uses them.
     * 
     * @author lamport
     * 
     */
    private static class Insertion {
        int pos;
        int oldLen;
        int newLen;

        /**
         * The obvious constructor.
         */
        private Insertion(int pos, int oldLen, int newLen) {
            this.pos = pos;
            this.oldLen = oldLen;
            this.newLen = newLen;
        }

        public String toString() {
            return "[pos: " + pos + ", oldLen: " + oldLen + ", newLen: "
                    + newLen + "]";
        }
    }

    /**
     * The new position corresponding to old position oldPos after the insertion
     * ins. See comments for the Insertion class.
     * 
     * @param oldPos
     * @param ins
     * @return
     */
    static int newInsertPos(int oldPos, Insertion ins) {
        if (oldPos <= ins.pos) {
            return oldPos;
        }
        if (oldPos < ins.pos + ins.oldLen) {
            // oldPos lies inside the text that was replaced.
            if (oldPos < ins.pos + ins.newLen) {
                // if oldPos lies inside the replacing text, return its value.
                return oldPos;
            } else {
                // if oldPos isn't inside the replacing text, then we have to
                // move it left. We might as well minimize indentation by moving
                // it as far left as we can without making it align with ins.pos
                // (which it didn't do initially).
                return ins.pos + ins.newLen - ins.oldLen;
            }
        } else {
            // oldPos is to the right of the replacing text.
            return oldPos + ins.newLen - ins.oldLen;
        }

    }

    /**
     * The new position corresponding to old position oldPos after the sequence
     * vec of insertions. See comments for the Insertion class.
     * 
     * @param oldPos
     * @param ins
     * @return
     */
    static int newVecInsertPos(int oldPos, Vector<Insertion> vec) {
        return innerNewVecInsertPos(oldPos, 0, vec);
    }

    /**
     * The recursive procedure that evaluates newVecInsertPos(oldPos, v) where v
     * is the vector of elements vec[idx], vec[idx+1], ...
     * 
     * @param oldPos
     * @param idx
     * @param vec
     * @return
     */
    static int innerNewVecInsertPos(int oldPos, int idx, Vector<Insertion> vec) {
        if (vec.size() <= idx) {
            return oldPos;
        } else {
            return innerNewVecInsertPos(
                    newInsertPos(oldPos, vec.elementAt(idx)), idx + 1, vec);
        }
    }

    /**
     * This method assumes that newTextRep was obtained from oldTextRep by
     * substitutions as are described by insVecArray, where insVecArray[i]
     * describes the changes that produced newTextRep.nodeText[i] from
     * oldTextRep.nodeText[i]. (The arrays newTextRep.nodeText,
     * oldTextRep.nodeText, and insVecArray must have the same length.) It
     * modifies newTextRep.mapping by adding and/or removing leading blanks to
     * maintain any alignment necessary to preserve the meaning of the formula.
     * This requires modifying newTextRep.mapping as well as
     * newTextRep.nodeText. I think there are just two essential kinds of
     * alignment that must be preserved.
     * 
     * - If a /\ or \/ that begins a line L1 is part of a con/disjunction list
     * beginning on line L0, then the /\ or \/ beginning L1 must remain aligned
     * with the corresponding /\ or \/ on L0.
     * 
     * - If a token t that begins a line L1 is part of a con/disjunction-list
     * item started by a /\ or \/ on line L0, then t must remain to the right of
     * that /\ or \/.
     * 
     * Here is the what the method does.
     * 
     *    LET startingPos[i] == The position of the 1st non-blank character of oldTextRep.node[i],
     *                          or -1 if there is none.
     *        coveringLine[i] == LET S == {j \in 0..(i-1) : startingPos[j] \leq startingPos[i]}
     *                           IN  IF S = {} \/ startingPos[i] = -1
     *                                 THEN -1 ELSE Maximum S 
     *        newStartingPos[i] == IF coveringLine[i] = -1
     *                               THEN startingPos[i]
     *                               ELSE newVecInsertPos(startingPos[i], insVecArray[coveringLine[i]])
     *        addSpace[i] == newStartingPos[i] - startingPos[i] ;
     *    For each i, add addSpace[i] spaces to line i of newTextRep.
     *    (Adding a negative number of spaces means deletion.)
     *                                
     * 
     * @param oldTextRep
     * @param newTextRep
     * @param insVecArray
     */
    static void adjustIndentation(NodeTextRep oldTextRep,
            NodeTextRep newTextRep, Vector<Insertion>[] insVecArray) {
        int numOfLines = insVecArray.length;
        int[] startingPos = new int[numOfLines];

        for (int i = 0; i < numOfLines; i++) {
            // compute startingPos[i]
            String str = oldTextRep.nodeText[i];
            startingPos[i] = StringHelper.leadingSpaces(str);
            if (startingPos[i] == str.length()) {
                startingPos[i] = -1;
            }

            // compute coveringLine[i]
            int coveringLine;
            if (startingPos[i] == -1) {
                coveringLine = -1;
            } else {
                int j = i - 1;
                while ((j >= 0)
                        && ((startingPos[j] > startingPos[i]) || (startingPos[j] == -1))) {
                    j--;
                }
                coveringLine = j;
            }

            // Compute addSpace[i]
            int addSpace;
            if (coveringLine == -1) {
                addSpace = 0;
            } else {
                addSpace = newVecInsertPos(startingPos[i],
                        insVecArray[coveringLine]) - startingPos[i];
            }

            // Add or remove space
            str = newTextRep.nodeText[i];
            if (addSpace > 0) {
                newTextRep.nodeText[i] = StringHelper.copyString(" ", addSpace)
                        + str;
            } else if (addSpace < 0) {
                newTextRep.nodeText[i] = str.substring(-addSpace);
            }
            adjustMappingPairVector(1, addSpace, newTextRep.mapping[i]);
        }
    }

    /******************** Some Methods for String Arrays *****************************/
    /**
     * Returns the array of strings as a single string, with the obvious
     * line-breaks inserted.
     * 
     * @param A
     * @return
     */
    public static String stringArrayToString(String[] A) {
        if (A.length == 0) {
            return A[0];
        }
        String result = A[0];
        for (int i = 1; i < A.length; i++) {
            result = result + "\n" + A[i];
        }
        return result;
    }

    /**
     * Returns the array of strings as a single string, where the first line is
     * inserted at column indent (Java numbering, columns starting at 0).
     * 
     * @param A
     * @param indent
     * @return
     */
    public static String stringArrayToIndentedString(String[] A, int indent) {
        if (A.length == 0) {
            return A[0];
        }
        String result = A[0];
        for (int i = 1; i < A.length; i++) {
            result = result + "\n" + StringHelper.copyString(" ", indent)
                    + A[i];
        }
        return result;
    }

    /*
     * The following are the types of buttons in the window
     */
    public static final int MENU = 1;
    public static final int ACTION = 2;
    public static final int CHECK = 3;

    /*
     * The followingidentify the various menu buttons.
     */
    public static final int SHOW_CONTEXT_BUTTON = 3;
    public static final int PROVE_BUTTON = 2;
    public static final int BACK_BUTTON = 1;
    public static final int TEST_BUTTON = 99;

    /**
     * Used to set various parameters of a button
     * 
     * @param button
     * @param type
     *            The style type of the button.
     * @param text
     *            The button's text
     */
    private void setupMenuButton(Button button, int whichOne, String text) {
        button.addSelectionListener(new DecomposeProofButtonListener(this,
                new Integer(whichOne), MENU));
        // Image folderImg =
        // PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_LCL_LINKTO_HELP);
        // String foo = ISharedImages.IMG_LCL_LINKTO_HELP ;
        // button.setImage(folderImg);
        button.setText(text);
        // button.setSize(100, button.getSize().y);
        GridData gridData = new GridData();
        gridData.horizontalIndent = 5;
        button.setLayoutData(gridData);
    }

    private void setupCheckButton(Button button, String text) {
        // There doesn't seem to be a need to set a listener on a checkbutton;
        // It can be read when some action button is pushed.
        // button.addSelectionListener(new DecomposeProofButtonListener(this,
        // button, CHECK)) ;
        button.setText(text);
        // button.setSize(100, button.getSize().y);
        GridData gridData = new GridData();
        gridData.horizontalIndent = 10;
        button.setLayoutData(gridData);
    }

    private void setupActionButton(Button button, NodeRepresentation nodeRep,
            String text) {
        button.setText(text);
        // button.setSize(30, button.getSize().y + 100);
        GridData gridData = new GridData();
        gridData.horizontalIndent = 15;
        gridData.verticalAlignment = SWT.TOP;
        button.setLayoutData(gridData);
        // Change made by LL for NewDecomposeProofHandler on 21 Aug 2014:
        // nodeRep.nodeRepPath() instead of nodeRep is the object
        // that is attached to the button, and whose value is in
        // DecomposeProofButtonListener.object when
        // DecomposeProofButtonListener.widgetSelected is executed as the
        // result of clicking on the button.
        button.addSelectionListener(new DecomposeProofButtonListener(this,
                nodeRep.nodeRepPath(), ACTION));
        button.setFont(JFaceResources.getFontRegistry().get(
                JFaceResources.TEXT_FONT));
        if (text.equals("  ")) {
            button.setEnabled(false);
        }
    }

    /**
     * The listener for buttons on the DecomposeProof window. The button type
     * tells what to do when clicked. Data identifying the button or what it
     * should do is in the object fiel.
     * 
     * @author lamport
     * 
     */
    public class DecomposeProofButtonListener extends SelectionAdapter
            implements SelectionListener {

        public Object execute(ExecutionEvent event) throws ExecutionException {
            // TODO Auto-generated method stub
            return null;
        }

        DecomposeProofHandler decomposeHandler;
        int type;
        Object object;

        public DecomposeProofButtonListener(DecomposeProofHandler dHandler,
                Object but, int tp) {
            super();
            decomposeHandler = dHandler;
            type = tp;
            object = but;
        }

        /**
         * Sent when selection occurs in the control. The default behavior is to
         * do nothing.
         * 
         * @param e
         *            an event containing information about the selection
         */
        public void widgetSelected(SelectionEvent e) {
            readButtons();
            switch (type) {
            case MENU:
                // System.out.println("MENU Click");
                int buttonId = ((Integer) object).intValue();
                switch (buttonId) {
                case BACK_BUTTON:
                    state = state.previousState;
                    raiseWindow();
                    break;
                case PROVE_BUTTON:
                    makeProof(null, false, true);
                    break;
                case SHOW_CONTEXT_BUTTON:
                    System.out.println("button is " + showContextButton.getSelection()) ;
                    readButtons();
                    raiseWindow();
                    break;
                case TEST_BUTTON:
                    windowShell = decomposeHandler.windowShell;
                    decomposeHandler.location = windowShell.getLocation();
                    windowShell.close();
                    if (windowShell != null) {
                        if (windowShell.isDisposed()) {
                            System.out.println("closing disposes of window");
                        } else {
                            windowShell.dispose();
                        }
                        if (windowShell == null) {
                            System.out.println("Closing nullifies");
                        }
                    }
                    raiseWindow();
                    break;
                }
                break;
            case ACTION:
                // Clone the current state
                DecompositionState newState = state.clone();
                newState.previousState = state;
                state = newState;
                state.hasChanged = true;
                NodeRepresentation nodeObj = pathToNodeRep((Vector<Integer>) object);
                if (nodeObj.nodeType == NodeRepresentation.OR_DECOMP) {
                    decomposeHandler.caseAction(nodeObj);
                    // this is the action that produces an or-split proof.
                } else {
                    switch (nodeObj.nodeSubtype) {
                    case NodeRepresentation.AND_TYPE:
                        decomposeHandler.andAction(nodeObj);
                        break;
                    case NodeRepresentation.OR_TYPE:
                        decomposeHandler.orAction(nodeObj);
                        break;
                    case NodeRepresentation.IMPLIES_TYPE:
                        decomposeHandler.impliesAction(nodeObj);
                        break;
                    case NodeRepresentation.FORALL_TYPE:
                        decomposeHandler.forAllAction(nodeObj);
                        break;
                    case NodeRepresentation.EXISTS_TYPE:
                        decomposeHandler.existsAction(nodeObj);
                        break;
                    case NodeRepresentation.SQSUB_TYPE:
                        decomposeHandler.sqsubAction(nodeObj);
                        break;
                    case NodeRepresentation.OTHER_TYPE:
                        break;
                    }
                }

                break;
            }
            return; // Just a convenient place to put a breakpoint.
        }

        /**
         * Sent when default selection occurs in the control. The default
         * behavior is to do nothing.
         * 
         * @param e
         *            an event containing information about the default
         *            selection
         */
        public void widgetDefaultSelected(SelectionEvent e) {
            // System.out.println("widgetDefaultSelected called") ;
            widgetSelected(e);

        }

    }

    /**
     * This is a DisposeListener for the window that sets the editor to be
     * writable and sets the handler's `location' * field to the window's
     * current location, so it opens in the same place the next time the command
     * is issued.
     * 
     * @author lamport
     * 
     */
    class WindowDisposeListener implements DisposeListener {
        DecomposeProofHandler commandHandler;

        WindowDisposeListener(DecomposeProofHandler handler) {
            commandHandler = handler;

        }

        public void widgetDisposed(DisposeEvent e) {
            commandHandler.location = windowShell.getLocation();
            // The following method was deprecated because it was actually
            // possible to use it, so it had to be replaced by something
            // that requires a PhD in Eclipse to figure out how to use.
            commandHandler.editorIFile.setReadOnly(false);
        }
    }
    
// UP-DOWN ARROWS REMOVED
//    /**
//     * Listener for arrows to move /\ conjunctions up or down.
//     * 
//     * @author lamport
//     *
//     */
//    class ArrowSelectionListener implements SelectionListener {
//        int index;
//        int direction;
//        NewDecomposeProofHandler handler;
//
//        ArrowSelectionListener(int idx, int dir, NewDecomposeProofHandler han) {
//            index = idx;
//            direction = dir;
//            handler = han;
//        }
//
//        public void widgetSelected(SelectionEvent e) {
//
//            // Clone the current state, so can go back from an arrow operation.
//            DecompositionState newState = state.clone();
//            newState.previousState = state;
//            state = newState;
//
//            // SemanticNode node = handler.assumes.elementAt(index);
//            NodeRepresentation rep = handler.state.assumeReps.elementAt(index);
//            // handler.assumes.remove(index) ;
//            handler.state.assumeReps.remove(index);
//            int inc = (direction == SWT.DOWN) ? 1 : -1;
//            // handler.assumes.add(index + inc, node) ;
//            handler.state.assumeReps.add(index + inc, rep);
//            handler.raiseWindow();
//        }
//
//        public void widgetDefaultSelected(SelectionEvent e) {
//            widgetSelected(e);
//        }
//
//    }

    /**
     * A convenience method that returns the first line of a semantic node's
     * source in a module. I don't know what to do if the semantic node is
     * constructed and has no source.
     * 
     * @param nd
     * @return
     */
    static int getBeginLine(SemanticNode nd) {
        if (nd.stn == null) {
            System.out
                    .println("getBeginLine called on node with null stn field.");
            return -1;
        }
        return nd.stn.getLocation().beginLine();
    }

    /**
     * A convenience method that returns the first line of a semantic node's
     * source in a module. I don't know what to do if the semantic node is
     * constructed and has no source.
     * 
     * @param nd
     * @return
     */
    static int getEndLine(SemanticNode nd) {
        if (nd.stn == null) {
            System.out
                    .println("getEndLine called on node with null stn field.");
            return -1;
        }
        return nd.stn.getLocation().endLine();
    }

    /**
     * If nd is a step of a proof--that is, it is an element of the array
     * returned by NonLeafProofNode.getSteps()--then this returns the level
     * number of the proof, which is the i such that the step begins "<i>". A
     * little experimentation reveals that the parser turns "<+>" or "<*>" in
     * the source into "<i>" for the appropriate i.
     * 
     * This method must not be called if nd is a DefStepNode or InstanceNode,
     * since for an unnumbered step (which such a step is likely to be), there
     * is no way to find the level number. See the comments to the one place
     * where this method is called.
     * 
     * @param nd
     * @return
     */
    static int stepLevel(SemanticNode nd) {
        String stepStr = ((SyntaxTreeNode) nd.stn).getHeirs()[0].image
                .toString();
        String stepNum = stepStr.substring(stepStr.indexOf('<') + 1,
                stepStr.indexOf('>'));
        return Integer.valueOf(stepNum).intValue();
    }

    /**
     * Returns true if it may be necessary to put parentheses around the
     * expression represented by `node' in order to prime it. This is the case
     * if node is an OpApplNode whose operator is NOT a user-defined operator
     * with an identifier as its name (so it returns truen if the operator is
     * not in/prep/postfix) or if it's an OpApplNode with no arguments.
     * 
     * @param node
     * @return
     */
    static boolean primingNeedsParens(SemanticNode node) {
        if (!(node instanceof OpApplNode)) {
            return false;
        }
        if (((OpApplNode) node).getArgs().length == 0) {
            return false;
        }
        SymbolNode ops = ((OpApplNode) node).getOperator();
        if (ops instanceof OpDefNode) {
            OpDefNode odn = (OpDefNode) ops;
            return (odn.getKind() == ASTConstants.BuiltInKind)
                    || !StringHelper.isIdentifier(odn.getName().toString());
        } else {
            return false;
        }
    }

    /**
     * Returns true iff some module of the spec is unsaved. Code taken from
     * UIHelper.promptUserForDirtyModules. This is not optimal because it
     * returns true even if the dirty module is not a spec module, but that's
     * not worth worrying about.
     * 
     * @return
     */
    public boolean existDirtyModules() {
        final List<IEditorReference> dirtyEditors = new LinkedList<IEditorReference>();
        IEditorReference[] references = UIHelper.getActivePage()
                .getEditorReferences();
        if (references != null) {
            for (int i = 0; i < references.length; i++) {
                try {
                    if (references[i].isDirty()
                            && references[i].getEditorInput().getName()
                                    .endsWith(TLAConstants.Files.TLA_EXTENSION)) {
                        dirtyEditors.add(references[i]);
                    }
                } catch (PartInitException e) {
                    Activator.getDefault().logError(
                            "Error getting unsaved resources.", e);
                }
            }
        }

        return (dirtyEditors.size() > 0);

    }
    
    /*
     * Because Java's generics are so stupid, need to define a new method
     * to convert a Vector<T> to a T[] for every type T.
     */
    static OpDeclNode[] OpDeclNodeVectorToArray(Vector<OpDeclNode> vec) {
        OpDeclNode[] result = new OpDeclNode[vec.size()] ;
        for (int i = 0; i < vec.size(); i++) {
            result[i] = vec.elementAt(i) ;
        }
        return result ;
    }
    
    static String[] StringVectorToArray(Vector<String> vec) {
        String[] result = new String[vec.size()] ;
        for (int i = 0; i < vec.size(); i++) {
            result[i] = vec.elementAt(i) ;
        }
        return result ;
    }
    
}

/**
 * The following module provide a fairly good set of tests for the Decompose
 * Proof command.  It imports the two following modules
 * 
 * 
 --------- MODULE Test ----------
\* Everything in the file checked on 4 Dec 2014 

EXTENDS Integers, TLAPS


CONSTANTS Ax, Bx, Cx, Dx, Ex, Fx, Gx, Hx, Ix, Jx, Kx, Lx, Mx, Nx, Ox,
Px, Qx, Rx, Sx

A == Ax = "A"
B == Bx = "B"
C == Cx = "C"
D == Dx = "D"
E == Ex = "E"
F == Fx = "F"
G == Gx = "G"
H == Hx = "H"
I == Ix = "I"
J == Jx = "J"
K == Kx = "K"
L == Lx = "L"
M == Mx = "M"
N == Nx = "N"
O == Ox = "O"
P == Px = "P"
Q == Qx = "Q"
R == Rx = "R"
S == Sx = "S"

(***************************************************************************)
(* Tests of instantiated \A and \E decompositions.                         *)
(***************************************************************************)
I1 == INSTANCE Test1 WITH C1 <- "C1Inst"

THEOREM I1!T2I!T2Def("argument")

THEOREM I1!T12Def("argT12Def")

THEOREM I1!T2Def("argT2Def")  \* \A

THEOREM ASSUME \E x : I1!T123Def
        PROVE  FALSE

THEOREM FALSE
<1>1. ASSUME \E x : I1!T123Def
        PROVE  FALSE
  
<1> QED

THEOREM ASSUME I1!T1EA
        PROVE  FALSE

THEOREM FALSE
<1>1. ASSUME I1!T1EA
        PROVE  FALSE
<1> QED
        
THEOREM I1!T1AA

        
THEOREM  I1!T1EA =>  FALSE
        
THEOREM ASSUME I1!T1Or 
        PROVE  FALSE

THEOREM FALSE
<1>2. ASSUME I1!T1Or 
        PROVE  FALSE
<1> QED    

THEOREM ASSUME I1!T1OrA 
        PROVE  FALSE

THEOREM FALSE
<1>1. ASSUME I1!T1OrA 
        PROVE  FALSE
<1> QED

THEOREM ASSUME I1!T2I!T2Other(O) 
        PROVE  FALSE

THEOREM FALSE 
<1>1. ASSUME I1!T2I!T2Other(O) 
        PROVE  FALSE
  
<1> QED

-------------------------------------------
FF(a, b) == a \/ b

Apply(GG(_,_), a, b) == GG(a, b)

THEOREM Apply(FF, 42, 55)

THEOREM A /\ B => Ax \/ C


THEOREM ASSUME \E x : TRUE, \E x : FALSE \/ FALSE
        PROVE   Ax => ( Ax => \/ Ax
                              \/ B
                      )

THEOREM FALSE
<1>1. ASSUME \E x : TRUE, \E x : FALSE \/ FALSE
        PROVE   Ax => ( Ax => \/ Ax
                              \/ B
                      )
<1> QED
                     
THEOREM ASSUME \E x : x => /\ A
                           /\ B
        PROVE  \A x : FALSE

THEOREM FALSE
<1>1. ASSUME \E x : x => /\ A
                         /\ B
        PROVE  \A x : FALSE
<1> QED
      
MP2 == (\E x : A # "MP2")
MP1 == (\E mp1 : B # "MP1") /\ MP2 
MP3 == (C # "MP3") => (D # "MP3")
MP4 == (E # "MP4") \/ (F # "MP4") => (A # "MP4") 
MP5 == (G # "MP5") \/ (H # "MP5")
MP6a == (I # "MP6a") \/ (K # "MP6a")
MP6 == (J # "MP6") \/ MP6a
MP7 ==  MP6 => (K # "MP7")
MP10 == (O # "MP8") /\ (P # "MP8")
MP11 ==  (Q # "MP9") => MP10
MP12 == (R # MP11) /\ MP11
MP13 == MP4 /\ MP5


FooT == INSTANCE Test1 WITH C1 <- 42
THEOREM ASSUME A \/ B
        PROVE   FooT ! T2Def( "(") => /\ 43
                                      /\ 44
BY 1=1         

THEOREM ASSUME  (B \/ C)
        PROVE  A => (D => FALSE)
        

THEOREM FALSE
<1>1. ASSUME  (B \/ C)
        PROVE  A => (D => FALSE)
  BY 2=2 
  
<1> QED




Id(a) == a \/ a

(***************************************************************************)
(* The followings examples used to demonstrate a known bug, caused by not  *)
(* renaming bound identifiers in operator arguments.  Apparently that bug, *)
(* which still exists, isn't manifested because the order of assumptions   *)
(* in the decomposition has changed.                                       *)
(***************************************************************************)
THEOREM ASSUME \E x : MP5, Id(\E x: x # 1)
        PROVE  FALSE

THEOREM FALSE
<1>1. ASSUME \E x : MP5, Id(\E x: x # 1)
        PROVE  FALSE

<1> QED


THEOREM ASSUME MP6a
        PROVE  A => MP11

THEOREM FALSE
<1>1. ASSUME MP6a
        PROVE  A => MP11

<1> QED

THEOREM ASSUME \E i, j \in {14}, k \in {15} : TRUE
        PROVE  FALSE
BY 4=4

THEOREM FALSE
<1>0. MP7
<1>1. ASSUME MP2
      PROVE  MP12
     
<1>2. ASSUME \E xxxxxxxxxxxxxx1, xxxxxxxxxxxxxxxxx2, xxxxxxxxxxxxxxxxxxxxxxxxxxxxx3, xxxxxxxxxxxxxxxxxxxxxx4, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5 : TRUE
      PROVE TRUE  
      
<1>3. ASSUME \E x1 : TRUE, \E x2 : TRUE
      PROVE FALSE  
<1> QED


THEOREM MP7
<1>x. TRUE
<1>0. ASSUME MP2 
      PROVE  MP12
  
 
<1>a. MP6
<1>1. ASSUME MP2
      PROVE MP13  
       
<1>2. ASSUME \E x, y : MP2
      PROVE MP6 => MP4 /\ MP5  

  
<1> QED

THEOREM FALSE
<1>0. C # 3
<1>1. SUFFICES  ASSUME MP1
                PROVE  \A x : A # 3
<1>2. CASE MP2
  
  <2>1. MP3 \* CASE 1a

  <2>1_case2. MP12  

 <2>1x. MP3 \* CASE 1a -     

   
  <2>2. MP11  \* Case 1b

  <2> DEFINE DEFDEF == TRUE

  <2>3xx. A => B
     
     
  <2>_case1_with_obvious_suffices. ASSUME MP3
                                   PROVE  MP4 => MP5    
    
  
  \* Case 1b without SUFFICES  
  <2>2a. MP10 
    
   <2>2b. MP11 \* CASE 2     
 
   <2>3a. SUFFICES ASSUME MP5
                   PROVE  MP4 
                   
   <2>3b. MP3   \* Case 3, with case-split not from goal
    
   <2>3b2. MP3 \* Case 4, with case-split not from goal - 
       
    <2> DEFINE MP8 == (A # "MP8") \/ (B # "MP8")
              MP9 == (C # "MP9") /\ MP8
   <2> HIDE DEF MP8, MP9

   <2>3c. ASSUME MP9
          PROVE  D    \* Case 3, with case-split not from goal


   <2>3d. ASSUME MP9
          PROVE  FALSE    \* Case 4, with case-split not from goal

  
   <2>3. MP4 \* Case 3 from goal
 
  <2>3e. MP4 \* Case 4 from goal
             
  <2>4. MP7 \* Case 3 from goal
      
  <2>5. CASE MP6 \* Case 3, empty ASSUME for SUFFICES

 <2>6. TRUE  \* Not checking anything interesting.
   <2> QED
<1> QED


THEOREM ASSUME \E x : A, B \/ C
        PROVE  FALSE

THEOREM ASSUME A /\ [B]_C, D \/ E
        PROVE \A x \in {44} : F
<1>1. CASE \E x \in {} : H 

    
<1> QED
THEOREM ASSUME (A \/ B) /\ E PROVE \A x : C
<1>1. ASSUME C \/ D PROVE FALSE 
<1> QED


AQ1(a) == \E x \in {} : (x = a)
THEOREM ASSUME NEW x , \E x_1 : AQ1(x_1)
        PROVE FALSE

THEOREM ASSUME \E a : A, B \/ C
        PROVE FALSE
<1> ASSUME \E d : D, \E e : E, F \/ G , \E h : H
    PROVE  \A x : FALSE

<1> QED

THEOREM ASSUME \E x : TRUE, (A \/ B) /\ E, C\/ D
        PROVE \A x : FALSE
        
THEOREM ASSUME ((A \/ A) /\ B /\ (C \/ C)) 
        PROVE  \A x : \A y \in {x} : E \/ F => G

        
THEOREM \A x, y : \A z \in x : x /\ y => FALSE

foo == (\E x : A) \/ B

THEOREM ASSUME A \/ (\E x : B \/ (\E y : C \/ D))
        PROVE FALSE
  
THEOREM ASSUME E \* (A \/ B) 
        PROVE TRUE
<1>1. ASSUME (C /\ (D \/ E))
      PROVE  TRUE
 <1> QED

THEOREM A 
<1>1. CASE B \/ C
  <2>1. CASE D \/ E
   <2> QED

<1>2. QED
   

THEOREM ASSUME A, \E x : B
        PROVE  FALSE



\* ERROR: Decomposing the two \Es in either order fails to rename
\* the y in {x \in {y} : TRUE}  (This was a bug in the old version
\* of Decompose Proof as well.
\* FIXED 3 Dec 2014
THEOREM ASSUME \E y : y # {}, \E x \in {y \in {} : TRUE} : x # 0
        PROVE  FALSE

\* ERROR: Decomposing the two \Es in either order fails to rename
\* the x in {x \in {} : TRUE}  (This was a bug in the old version
\* of Decompose Proof as well.
\* FIXED 3 Dec 2014
\* 
THEOREM ASSUME \E x : x = <<x>>, \E y : ({x \in {y} : TRUE} = {} ) 
        PROVE  FALSE

THEOREM ASSUME \E x : x = {y \in {} : TRUE}, \E y : ({x \in {y} : TRUE} = {} ) 
        PROVE  FALSE
        
THEOREM (\E x : x = <<x>>) =>  \A y : ({x \in {y} : TRUE} = {} => FALSE )

THEOREM ASSUME \E x, y \in {32}, z \in {44} : TRUE
        PROVE   FALSE

THEOREM ASSUME \E x : "top-level"
        PROVE   FALSE
<1>1. ASSUME \E x : 1, \E x : 2, \E x : 3, \E x: 4
      PROVE FALSE

<1> QED

THEOREM ASSUME (A /\ (B \/ (\E x : D \/ E))) /\ (C /\ \E x : B), \E x: D , 
              NEW x33
        PROVE  \A x : E
 
  <1>a SUFFICES ASSUME NEW xxxxxx1, E \/ F,
                      ASSUME E    PROVE Dx = 4321
               PROVE  \A xxxxx : Cx  => Gx
    OBVIOUS
    
   \* Produced an empty BY for SUFFICES with \E  with Use Suffices chosen
   \* where the empty BY should have been OBVIOUS.  
   \* FIXED on 1 Dec 2014
  <1>xxx. ASSUME 3242 /\ 34255  PROVE FALSE
    
     <1>6. ASSUME \E x : FALSE
         PROVE  FALSE
  
  <1>b. \E x : x = <<x>>
  
  \* ERROR: Choosing the bottom \E on this produces a proof
  \* that failed.
  \* FIXED on 1 Dec 2014 
  <1>c. ~A
 
  \* bottom \E - mid \E - top /\ - mid /\ shows \E x_2_2
  \* FIXED 2 Dec 2014
  <1>d. ASSUME TRUE PROVE ~A
    
  
  <1>1. SUFFICES ASSUME NEW zzz, A \/ \A x : B, 44444
                 PROVE  C
  
  <1>2. PICK zzzzzz \in A : 333 \/ 444
  
  <1>3. ASSUME NEW x_2 PROVE \A x \in {} : FALSE
    <2>1. TAKE x \in {}
    <2>2 QED
  
  
  <1>4. HAVE 444 \/ 445

  \* Proof failed without SUFFICES, but I believe
  \* Obligation was true.  Unable to reproduce,
  \* But didn't try hard.
  <1>5. ASSUME NEW yyy, yyy = 13, 345
        PROVE  R \/ S

  <1> ASSUME F \/ G, 
             NEW newvar,
             ASSUME I PROVE J
      PROVE  H 
  
<1> QED
 \* FIXED BUG IN THIS EXAMPLE 2 Dec 2014
 THEOREM ASSUME ( (\E x : x \subseteq x) /\ ((\E x : x = {x}) /\ ((\E x : x \ {x} = {})) /\ (A \/ \A x : x = <<x>>))),
                NEW x
         PROVE  FALSE
   
  THEOREM (\E x : x \subseteq x) => ((\E x : x = {x}) => ((\E x : x \ {x} = {}) => (A \/ \A x : x = <<x>>)))  
         
 
 xzy3 == ((\E x : x \ {x} = {}) => (A \/ \A x : x = <<x>>))
 xzy2 == (\E x : x = {x})
 xzy1 ==  \E x : x \subseteq x    
 xzy == xzy1 => (xzy2 => xzy3)
  
THEOREM FALSE
\* ERROR: => \E => \E => \E failes to rename a previously renamed x_2 to avoid conflict.
\* FIXED 4 Dec 2014
<1>2 xzy
 
 <1> QED
THEOREM \* ASSUME  666 \/ 777, NEW newvar,
         \*    ASSUME 7651 PROVE 6543
        \* PROVE  
          A => 333 
  

THEOREM D
<1>1. ASSUME \E x : (A = 33 + 4) \/ ((\E y : B \/ C)) ,
             foo              
      PROVE  \A x \in F : G /\ C
<1> QED

THEOREM ASSUME A, B \/ C
        PROVE D

\* ERROR: Decomposing the two \Es in either order fails to rename
\* the x in {x \in {} : TRUE}
\* FIXED 3 Dec 2014
THEOREM ASSUME \E x : A, \E y : ({x \in {} : TRUE} = {} /\ FALSE)
        PROVE  FALSE


\*==============================
Q3(a, b) == \E x \in Int : (x = a) /\ (x = b)
Q2(a, b) == \E x \in Int : ((x = a) /\ (x = b)) \/ Q3(a, b+1)
Q1(a, b) == \E x \in Int: (* \E y \in {x} : *) ((x = a) /\ (x = b)) \/ Q2(a, b+1)

THEOREM  TT == \A y \in Int : Q1(y, 1) => (y = 1) \/ (y = 2) \/ (y = 3)
  <1> SUFFICES ASSUME NEW y \in Int,
                      NEW x \in Int,
                      NEW y_1 \in {x},
                      ((x = y) /\ (x = 1)) \/ Q2(y, 1+1)
               PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
    BY DEF Q1
  <1>1. ASSUME (x = y) /\ (x = 1)
        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
  <1>2. ASSUME NEW x_1 \in Int,
               (x_1 = y) /\ (x_1 = (1+1))
        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
  <1>3. ASSUME NEW x_1 \in Int,
               NEW x_2 \in Int,
               (x_2 = y) /\ (x_2 = ((1+1)+1))
        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
  <1>4. QED
    


THEOREM  ASSUME NEW y \in Int, Q1(y, 1) PROVE (y = 1) \/ (y = 2) \/ (y = 3)
  <1> SUFFICES ASSUME NEW x \in Int,
                      ((x = y) /\ (x = 1)) \/ Q2(y, 1+1)
               PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
    BY DEF Q1
  <1>1. CASE (x = y) /\ (x = 1)
  <1>2. ASSUME NEW x_1 \in Int,
               (x_1 = y) /\ (x_1 = (1+1))
        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
  <1>3. ASSUME NEW x_1 \in Int,
               NEW x_2 \in Int,
               (x_2 = y) /\ (x_2 = ((1+1)+1))
        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
  <1>4. QED
    
 

THEOREM ASSUME NEW a1(_), NEW a2(_, _), NEW b1(_), NEW b2(_), NEW Goal
        PROVE  FALSE
<1> DEFINE a(x) == \E y : a1(y) \/ \E z : a2(y, z) 
           b(x) == b1(x) \/ b2(x)
           Next ==  \E x : a(x) \/ b(x) 
           Thm == Next => Goal
<1>1.  ASSUME Next PROVE Goal
  <2> SUFFICES ASSUME NEW x,
                      a(x) \/ b(x)
               PROVE  Goal
    BY <1>1 DEF Next
  <2>1. ASSUME NEW y,
               a1(y)
        PROVE  Goal
  <2>2. ASSUME NEW y,
               NEW z,
               a2(y, z)
        PROVE  Goal
  <2>3. CASE b1(x)
  <2>4. CASE b2(x)
  <2>5. QED
    


 
<1> QED 

THEOREM  ASSUME NEW y \in Int, Q1(y, 1) PROVE (y = 1) \/ (y = 2) \/ (y = 3)

\* The following was produced by the old version.
\*  <1> SUFFICES ASSUME NEW x \in Int,
\*                      ((x = y) /\ (x = 1)) \/ Q2(y, 1+1)
\*               PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
\*    BY DEF Q1
\*  <1>1. CASE (x = y) /\ (x = 1)
\*  <1>2. ASSUME NEW x_1 \in Int,
\*               (x_1 = y) /\ (x_1 = (1+1))
\*        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
\*  <1>3. ASSUME NEW x_1 \in Int,
\*               NEW x_2 \in Int,
\*               (x_2 = y) /\ (x_2 = ((1+1)+1))
\*        PROVE  (y = 1) \/ (y = 2) \/ (y = 3)
\*  <1>4. QED
\*   BY <1>1, <1>2, <1>3 DEF Q2, Q3
\*

R3(b, a) == a = 3 \/ a = b
R2(b, a) == a = 2 \/ \E x \in {b, a} : R3(x, a+1)
R1(a) == a = 1 \/ \E x \in {a} : R2(x, a+1)
THEOREM TT2 == \A y \in {1, 2, 3} : R1(y) => (y = 1)



\*VARIABLES A, B, C, D, E, F

T3 == \E x : D \/ E
T2 == (C /\ A /\ T3)
T1 == B /\ T2
THEOREM T1 => A /\ B /\ H



S1 == A \/ (\E x \in {y_1 \in {44} : y_1 > 0} : x \in {44}) 
S1a == A \/ (\A x \in {y_1 \in {44} : y_1 > 0} : x \in {44}) 
S1b == A \/ ({y_1 \in {44} : y_1 > 0} = {x \in {44} : x > 0})
S1c == \E z : ({y_1 \in {44} : y_1 > 0} = {x \in {44} : x > 0})
\* Produces parse error on decomposition by \/ then \A then Prove,
\* with Suffices/Case options (and other options too)
\* Bug fixed by disallowing \/ then \A
THEOREM ASSUME NEW x , S1b  
        PROVE  \A x_1 : FALSE     

THEOREM ASSUME NEW x, [S1b]_x
        PROVE  \A x_1 : FALSE     
                               
\* If you do first \A then \E, an x is renamed to x_2
\* although x_1 would be an OK renaming.  This is 
\* acceptable.                                 
THEOREM ASSUME NEW x , NEW y_1, S1c  
        PROVE  \A x_1 : FALSE     


SS1 == (\E x \in {y_1 \in {41} : y_1 > 0} : x \in {411}) 
SS1a == (\A x \in {y_1 \in {42} : y_1 > 0} : x \in {421}) 
SS1b == ({y_1 \in {43} : y_1 > 0} = {x \in {431} : x > 0})
SS1c == \E z : ({y_1 \in {44} : y_1 > 0} = {x \in {441} : x > 0}) 
SS1d == B /\ \E q : A              
THEOREM ASSUME SS1c
        PROVE  FALSE


THEOREM ASSUME SS1d, \E x : E
        PROVE FALSE

THEOREM ASSUME \E x : A
        PROVE  C => A /\ B

P1 == \A x : A
P2 == \A x : P1
THEOREM P2


P3 == A \/ B
THEOREM FALSE
<1>0. TRUE

<1>1. SUFFICES ASSUME \E x \in A : A
               PROVE  F => \A x \in G : G

<1>a.  A => P1


\* \E decomposition (of step's \E formula) followed by \/ decomposition
\* with "Use SUFFICES" checked produces an invalid proof in both the old 
\* and new versions.
\* Bug fixed.
<1>1x. ASSUME \E a : D, P3
       PROVE  C


<1>2. CASE  A /\ \E x \in B : B
  <2>1. ASSUME \E x \in C : C
        PROVE  G => \A x \in H : H

    
  <2> QED
<1> QED

THEOREM ASSUME \E x \in {y \in {44} : y > 0} : x \in {41},
               \E x_1 \in {y \in {44} : y > 0} : \E x : x_1 \in {42},
               \E x \in {y \in {44} : y > 0} : x \in {43},
               NEW x
        PROVE  FALSE

S2 == \E x \in {y \in {44} : y > 0} : x \in {41}
S2a == \E x \in {y \in {44} : y > 0} : x \in {42}
S2b == \E x \in {y \in {44} : y > 0} : x \in {43}
THEOREM ASSUME NEW x, NEW y, S2, S2a, S2b, A \/ B
        PROVE FALSE 

THEOREM ASSUME S2, S2a, S2b, A \/ (\E x : B)
        PROVE FALSE 
\*<1>1. TRUE
\*<1> QED

THEOREM ASSUME (\E x : (TRUE \/ \E y : B)) \/ FALSE, NEW x, NEW y
        PROVE  TRUE

S22 == (\E x : TRUE) \/ FALSE
THEOREM ASSUME S22, NEW x
        PROVE  TRUE

        

S4 == \E x \in {y \in {44} : y > 0} : x \in {44}
S3 == (\E x \in {y \in {44} : y > 0} : x \in {44}) \/ S4 
\* Expanding all the way down with Use CASE checked produces cases with bogus variable x_1 
\* Fixed n now.
THEOREM ASSUME NEW x, NEW y, NEW y_1, S3
        PROVE  FALSE

U1 == \A x \in {y \in {44} : y > 0} : (x > 0) /\ A
THEOREM ASSUME NEW x , NEW y PROVE U1

U2 == \E x : A \/ \E x_1 : x = x_1

THEOREM ASSUME NEW x, U2 PROVE FALSE



THEOREM ASSUME \E x \in {1} : TRUE, A \/ \E x : FALSE
        PROVE  \A x : TRUE

W3(a, b) == \E x : <<a, b>> = A  \/ (x=1)
W2(a) == \E x : W3(a, x)
W1 == \E x : W2(x)
THEOREM W1 => \A x : FALSE
 

 
C3 == \E x : (x=2) \/ (x=3)
C2 == \E x : \E y : C3
THEOREM (\E x : C2) => FALSE

C5(y) == y /\ (B \/ C)
C4(x) == x /\ \E y : C5(y) /\ x 

\* QED proof used to fails with everything expanded and Use SUFFICE & with or without CASE
\* Seems to be fixed now
THEOREM ASSUME NEW y, (\E x : C4(x) /\ A) PROVE FALSE


THEOREM ASSUME NEW y, NEW x,  C4(x) /\ A PROVE FALSE
 


C7(u, v) == \E y : <<u, v, y>> \/ (y=v)
C6(a) == \E x : C7(a, x)
THEOREM C6(42) => FALSE

B2(a, b) == (a=1) \/ (b=1)
B1(a) == \E y : B2(a, y)
THEOREM (\E x : B1(x)) => FALSE
  
Bar(bb) == (bb \/ C)
Foo(aaaa, bbbb) ==  Bar(aaaa) => bbbb \/ /\ aaaa

                                         /\ bbbb => B
 
X(a, Op(_,_)) == \A x : Op(a, B) /\ a
W(a) == (a 
          \/ C)
Z(a) == \E z \in {E} : W(a) => \/ D
                               \/ D

ABar(bb) == \E y , yy : (Z(C) 

                           \/ D)
AFoo(aaaa) == \E x : ( ABar(<<x, aaaa>>) )
THEOREM AFoo(44) => FALSE

Y == A \/ (Z(B) \/ D)
AA == A
BB == (\E yB, yBB \in {}, yBBB \in {} : B \/ (\E yC, yCCC : \E yCC : (C \/ (\E yD : D))))
ZZ == AA /\ BB 
ZZZ == A /\ (\E yy : B)

THEOREM ZZ

THEOREM AA => ZZ

THEOREM XYZ == ASSUME NEW AAAA , ZZ, NEW BBBB PROVE FALSE

THEOREM Y => FALSE

THEOREM ASSUME NEW ZZ1, NEW ZZ123456 PROVE Foo(ZZ1, ZZ123456) 

CONSTANT Z77777
THEOREM Z(Z77777) => FALSE

THEOREM ASSUME A \/ B PROVE C

THEOREM ASSUME AFoo(F)
        PROVE FALSE

THEOREM ASSUME \E x : A \/ ABar(C)
        PROVE  FALSE 

 
THEOREM ASSUME Z(F)
        PROVE  Foo(A, B)

THEOREM \A x \in 23 +
                 24 : A
  
THEOREM \A x \in 23 +
                    24, y \in E : A => Bar(11)

THEOREM X(22+33, Foo)

\* Checking completed through here on 4 Dec 2014
===============================

------------ MODULE Test1 ----------
CONSTANT C1  

T2I == INSTANCE Test2 WITH C2 <- <<C1, "C2exp">>

T1D == TRUE
T1Oper == T2I!T2Other(T1D)
T1Or == C1 \/ T1Oper

T1OperA == C1 \/ ~C1
T1OrA == C1 \/ T1OperA

T1EA2(a) == \E x \in T1D : a = 0
T1EA == \E x \in C1 : T1EA2(x)

T1AA2(a) == \A x \in T1D : a = 0
T1AA == \A x \in C1 : T1AA2(x)

T2IDef(x) == x
T2Def(a) == \A y : (a = T2IDef(a))
T1Def(a) ==  \A y : <<C1, T2IDef(42), a>>
T12Def(a) == \A y \in <<C1, a>> : T2I!T2Def(<<C1, a>>)
T123Def == \E x \in C1 : T2I!T3Def(<<"somearg", x>>)
========================================

-------------- MODULE Test2 ---------------
CONSTANTS C2

T2Other3(a) == a
T2Other2(a) == C2 \/ T2Other3(C2)
T2Other(a) == T2Other2(a) \/ C2
T2Def(a) == \A x \in C2 : C2 = <<a, T2Other(a)>>

I3 == INSTANCE Test3 WITH C3 <- {C2, "C3"}
T3Def(a) == \E x \in C2 : I3!T3Def({C2, "T3DefArg1", x, a}, "T3DefArg2")
===========================================
 
------------------------------- MODULE Test3 -------------------------------
CONSTANT C3

T3Def(a, b) == \A x \in C3 : <<a, C3, b, x>>
=============================================================================
\* Modification History
\* Last modified Fri Nov 28 15:23:36 PST 2014 by lamport
\* Created Tue Jan 21 13:27:39 PST 2014 by lamport


 */



/*   The following module is a specification for code to enhance the 
     current module by allowing decomposition of operator applications
     whose arguments may span multiple lines.  It would replace the
     current method of performing substitions using MappingPair objects.


---------------------------- MODULE Substitution ----------------------------
(***************************************************************************)
(* This spec handles substitution under the assumption that when an        *)
(* expression e has been substituted for an identifier id, no later        *)
(* substitution will be performed within e.  However, one case arises in   *)
(* the Decompose Proof command in which this is not true: namely, when e   *)
(* itself is an identifier and a later substitution substitutes another    *)
(* identifier for it.  The NodeWithSubst object defined here is general    *)
(* enough to make that substitution easy to perform.  (Note that in this   *)
(* case, e lies on a single line.)                                         *)
(***************************************************************************)
(***************************************************************************)
(* A task that the DecomposeProof command must perform is to display to    *)
(* the user and insert into the spec formulas obtained from a formula F in *)
(* the spec by substituting expressions for identifiers.  One instance of  *)
(* this is replacing a formula Op(x+y+z) by the formula obtained from it   *)
(* by expanding the definition                                             *)
(*                                                                         *)
(*    Op(p) == expr                                                        *)
(*                                                                         *)
(* of Op.  This requires constructing a representation of the formula      *)
(* obtained from expr by substituting x+y+z for every instance of p in     *)
(* expr.  We write this substitution as p <- x+y+z.  However, note that p  *)
(* actually denotes a semantic node representing a declaration of the      *)
(* identifier "p", and the substitution is performed on an occurrence of   *)
(* that identifier that refers to that semantic node--not to any           *)
(* identifier "p" that that refers to a different semantic declaration     *)
(* node.                                                                   *)
(*                                                                         *)
(* Given the semantic node nd that represents expr, it's easy to construct *)
(* the semantic node produced by the substitution.  So, one way to perform *)
(* this task is to use a general procedure for "pretty-printing" a         *)
(* semantic node.  This is what TLAPS does.  However, our goal here is to  *)
(* maintain as much as possible the formatting of expr by the user.  So,   *)
(* this task will be performed by substituting the string "x+y+z" for all  *)
(* instances of the string "p" in the text of expr typed by the user.      *)
(* Those instances can be found using the semantic node nd for expr, from  *)
(* which all semantic nodes for instances of p can be found--since a       *)
(* semantic node points to the location of the user input corresponding to *)
(* that node.                                                              *)
(*                                                                         *)
(* This substitution task poses the following problems:                    *)
(*                                                                         *)
(* 1.  Suppose the definition of Op is                                     *)
(*                                                                         *)
(*     Op(p) == -p                                                         *)
(*                                                                         *)
(* Simply replacing "p" by "x+y+z" in the definition yields "-x+y+z"       *)
(* instead of the correct "-(x+y+z)".  We can solve this problem by always *)
(* putting parentheses around the expression being substituted, but it     *)
(* seems best to do this only when necessary.                              *)
(*                                                                         *)
(* 2.  Suppose now that expr is Op(x+y>z) and Op is defined by             *)
(*                                                                         *)
(*    Op(p) == p => /\ x=y                                                 *)
(*                  /\ y>4                                                 *)
(*                                                                         *)
(* Naive substitution would yield the expression                           *)
(*                                                                         *)
(*    x+y+z => /\ x=y                                                      *)
(*         /\ y>4                                                          *)
(*                                                                         *)
(* which is parsed as (x+y>z => /\ x=y) /\ (y>4), which is not equivalent  *)
(* to Op(x+y>z).                                                           *)
(*                                                                         *)
(* Another case in which substitution is needed is to avoid identifier     *)
(* conflict.  Suppose the expression `\A j : expr' is to be put into the   *)
(* spec in a location where the identifier j already has a meaning.  In    *)
(* that case j must be replaced as the quantifier variable and everywhere  *)
(* it occurs in expr by a new identifier.  (TLAPS uses a new identifier    *)
(* such as j_1, which seems like a good choice to use here.)               *)
(*                                                                         *)
(* Multiple substitutions may have to be done in an expression.  Clearly,  *)
(* if a operator has multiple arguments, or if both j and k have to be     *)
(* renamed in \A j, k : expr, then there will be substitutions for all the *)
(* arguments or all the renamed variables.  Such a multiple substitution   *)
(* poses no problem because in no matter what order the substitutions are  *)
(* done, the following is true:                                            *)
(*                                                                         *)
(*    Single-Substitution Property:  A substitution is never performed on  *)
(*    text that was inserted by a substitution.                            *)
(*                                                                         *)
(* However, this property is not true for all multiple substitutions--for  *)
(* example if we first perform the substitution p <- x+y+z and then the    *)
(* substitution y <- a-b in expr.  However, observe that the sequence of   *)
(* substitutions                                                           *)
(*                                                                         *)
(*    Substitute y <- a-b in Substitute p <- x+y>z in expr                 *)
(*                                                                         *)
(* is equivalent to the                                                    *)
(*                                                                         *)
(*    Substitute p <- x+(a-b)>z in Substitute y <- a-b in expr             *)
(*                                                                         *)
(* Those two substitutions satisfy the single-substitution property, no    *)
(* matter in which order they are performed because neither of the         *)
(* expressions being inserted by the substitutions contain either of the   *)
(* identifiers being substituted for.                                      *)
(*                                                                         *)
(* To maintain the single-substitution property, a sequences of            *)
(* substitutions                                                           *)
(*                                                                         *)
(*    Substitute p_1 <- exp_1 in Substitute p_2 <- exp_2 in                *)
(*        ...  p_n <- exp_n  Substitute expr                               *)
(*                                                                         *)
(* must satisfy the                                                        *)
(*                                                                         *)
(*    Hierarchical Substitution Property: The  p_i are all different, and  *)
(*    each p_j cannot occur in any expression exp_k with k < j.            *)
(*                                                                         *)
(* In that case, let                                                       *)
(*                                                                         *)
(*      xexp_1 == exp_1                                                    *)
(*      xexp_2 == Substitute p_1 <- xexp_1 in exp2                         *)
(*      xexp_3 == Substitute p_2 <- xexp_2                                 *)
(*                   in Substitute p_1 <- xexp_1 in exp_3                  *)
(*      ...                                                                *)
(*      xexp_n == Substitute p_(n-1) <- xexp_(n-1) in ... in exp_n         *)
(*                                                                         *)
(* and the result of the original sequence of substitutions is             *)
(*                                                                         *)
(*    Substitute p_1 <- xexp_1 in Substitute p_2 <- xexp_2 in              *)
(*        ...  p_n <- xexp_n  Substitute expr                              *)
(*                                                                         *)
(* The hierarchical substitution property implies that the substitutions   *)
(* in this sequence and all the substitutions in constructing the xexp_i   *)
(* satisfy the single-substitution property.                               *)
(*                                                                         *)
(* The hierarchical substitution property is maintained in the             *)
(* substitutions done by the DecomposeProof command for the following      *)
(* reason.  There are two types of substitutions performed:                *)
(*                                                                         *)
(* 1.  Replacing an operator use Op(e), where Op is defined by             *)
(*                                                                         *)
(*    Op(p) == expr                                                        *)
(*                                                                         *)
(* with the expression                                                     *)
(*                                                                         *)
(*    Substitute [p <- e] in expr                                          *)
(*                                                                         *)
(* This replacement is done only when Op(p) is the entire expression.      *)
(* Hence the expression cannot contain any identifiers declared in the     *)
(* resulting expression--or the parameters in the definitions of any any   *)
(* operator used in that expression.                                       *)
(*                                                                         *)
(* 2.  Replacing a declaration of an identifier in an expression by a      *)
(* brand new identifier.  This brand new identifier must be different from *)
(* (have a different semantic declaration node) than that of any           *)
(* identifier appearing in an expression that has already been substituted *)
(* for some identifier.                                                    *)
(***************************************************************************)

EXTENDS Integers, Sequences, FiniteSets, TLC

(***************************************************************************)
(* LOCATIONS.                                                              *)
(*                                                                         *)
(* A Location describes the line & column coordinates of the first and     *)
(* last characters of some semantic unit.  These coordinates are 1-based,  *)
(* the first line of a module being line 1 and the first column of a line  *)
(* being column 1.                                                         *)
(*                                                                         *)
(* A POSITION is a pair of positive integers representing line and column  *)
(* coordinates of a character.                                             *)
(***************************************************************************)
PosNat == Nat \ {0}

PairPrecedes(pair1, pair2) ==
  (*************************************************************************)
  (* True iff pair1 represents a position that precedes the position       *)
  (* represented by pair2.                                                 *)
  (*************************************************************************)
  \/ pair1[1] < pair2[1]
  \/ (pair1[1] = pair2[1]) /\ (pair1[1] < pair2[2])

PairPrecedesOrEq(pair1, pair2) == PairPrecedes(pair1, pair2) \/ (pair1 = pair2)

(***************************************************************************)
(* A Location is a record with fields:                                     *)
(*    bLine, bColumn : The position of the first character.                *)
(*    eLine, eColumn : The position of the last character.                 *)
(***************************************************************************)
Location == { loc \in [bLine : PosNat, bColumn : PosNat, 
                       eLine : PosNat, eColumn : PosNat] :
                PairPrecedesOrEq(<<loc.bLine, loc.bColumn>>, 
                                 <<loc.eLine, loc.eColumn>>) }

(***************************************************************************)
(* For some reason that I have forgotten, location loc1 is defined to      *)
(* precede location loc2 iff the end position of loc1 precedes OR EQUALS   *)
(* the beginning position of loc2.  In particular, a 1-character location  *)
(* precedes itself.                                                        *)
(***************************************************************************)
LocationPrecedes(loc1, loc2) == 
   PairPrecedesOrEq(<<loc1.eLine, loc1.eColumn>>, 
                    <<loc2.bLine, loc2.bColumn>>)

(***************************************************************************)
(* Note LocationContainedIn is defined so a location is contained in       *)
(* itself.                                                                 *)
(***************************************************************************)
LocationContainedIn(loc1, loc2) == 
  /\ PairPrecedesOrEq(<<loc2.bLine, loc2.bColumn>>, 
                      <<loc1.bLine, loc1.bColumn>>)
  /\ PairPrecedesOrEq(<<loc1.eLine, loc1.eColumn>>, 
                      <<loc2.bLine, loc2.bColumn>>)  

(***************************************************************************)
(* ++ is coordinate-wise addition of two positions.                        *)
(***************************************************************************)
pair1 ++ pair2 == <<pair1[1] + pair2[1], pair1[2] + pair2[2]>>

(***************************************************************************)
(* PosSum(f, i) == f[0] ++ f[1] ++ ...  ++ f[i] where                      *)
(* PosSum(f, -1) = <<0, 0>> .                                              *)
(***************************************************************************)
RECURSIVE PosSum(_, _)
PosSum(f, i) == IF i = -1 THEN <<0, 0>>
                          ELSE f[i] ++ PosSum(f, i-1)

(***************************************************************************)
(* We define the Max and Min of a set S of array indices, which will be    *)
(* non-negative integers.  Max of the empty set is defined to be -1; Min   *)
(* of the empty set is undefined.                                          *)
(***************************************************************************)
IndexMax(S) == IF S = {} THEN -1
                         ELSE CHOOSE x \in S : \A y \in S : x >= y
IndexMin(S) == CHOOSE x \in S : \A y \in S : x =< y

(***************************************************************************)
(* (Semantic) Nodes                                                        *)
(***************************************************************************)
IsSeq(s) == /\ Len(s) \in Nat
            /\ s = [i \in 1..Len(s) |-> s[i]]
  (*************************************************************************)
  (* True iff s is a sequence.                                             *)
  (*************************************************************************)

IsSeqOf(seq, IsElem(_)) ==
  (*************************************************************************)
  (* True iff seq is a sequence of elements e_i, with IsElem(e_i) true for *)
  (* all i.                                                                *)
  (*************************************************************************)
  /\ IsSeq(seq)
  /\ \A i \in 1..Len(seq) : IsElem(seq[i])

(***************************************************************************)
(* We define a JArray to be a function with domain 0..n for some integer   *)
(* n, which is the mathematical representation of a Java array.  We define *)
(* some operators on JArrays corresponding to operators on sequences.      *)
(* Note that an array of length 0 is the function whose domain is the      *)
(* empty set--the function that can be written << >>.                      *)
(***************************************************************************)
JArray(S) == {<< >>} \cup UNION {[0..n -> S] : n \in Nat}
JLen(A) == 1 + IndexMax(DOMAIN A)
JConcat(s, t) == [i \in 0 .. (JLen(s) + JLen(t)-1) |-> 
                    IF i < JLen(s) THEN s[i] ELSE t[i-JLen(s)]] 
JSubArray(A, m, n) ==
  (*************************************************************************)
  (* The JArray A[m], A[m+1], ...  , A[n].                                 *)
  (*************************************************************************)
  [i \in 0 .. n-m |-> A[i+m]]

IsJArray(A) == DOMAIN A = 0 .. IndexMax(DOMAIN A)

IsJArrayOf(A, S) == /\ IsJArray(A)
                    /\ \A x \in DOMAIN A : A[x] \in S

(***************************************************************************)
(* The operator StoJ maps from sequences to JArrays, and JtoS maps from    *)
(* JArrays to sequences.                                                   *)
(***************************************************************************)
StoJ(seq) == [i \in 0..(Len(seq)-1) |-> seq[i+1]]
JtoS(A) == [i \in 1..JLen(A) |-> A[i-1]]


(***************************************************************************)
(* Assume some set S of records, each element of which has a `children'    *)
(* field that is a sequence of elements of S called the node's children.   *)
(* The descendants of a node nd consists of it and its children and its    *)
(* children's children, and its children's children's children, etc.  The  *)
(* following defines Descendants(nd) to be the set of all descendants of   *)
(* nd.  Note that its possible for this set to be infinite if there is an  *)
(* infinite sequence seq of elements of S each of which is a child of the  *)
(* preceding one.  It's also possible for this set to be finite if there   *)
(* is such an infinite sequence seq--for example, if all the elements of   *)
(* the infinite sequence are the same.  To understand how this is          *)
(* possible, observe that if z is an infinite sequence of zeroes, then the *)
(* tail of z (obtained by removing the first zero in the sequence) equals  *)
(* z.                                                                      *)
(***************************************************************************)
Descendants(nd) ==
  LET RangeOfFcn(f) == {f[i] : i \in DOMAIN f}
      RECURSIVE D(_)
      D(n) == IF n.children = << >>
                   THEN {n}
                   ELSE {n} \cup
                          UNION {D(n.children[i]) 
                                   : i \in DOMAIN n.children}
  IN  D(nd)

(***************************************************************************)
(* Because TLC doesn't treat Strings as first-class sequences, we          *)
(* represent a String as an array of Chars, where a Char is a string of    *)
(* length 1.  Also, to simplify translation to Java, we use 0-based        *)
(* addressing of Chars in a String, and for vectors of Strings.  Note that *)
(* the empty string "" is the function whose domain is the empty set,      *)
(* which can be written as << >>.                                          *)
(***************************************************************************)
Char == {s \in STRING : Len(s) = 1}
String == UNION {[0..n -> Char] : n \in Nat \cup {-1}}
StringVector == UNION {[0..n -> String] : n \in Nat \cup {-1}}
IsString(s) == IsJArrayOf(s, Char)
IsStringVector(v) == /\ IsJArray(v)
                     /\ \A x \in DOMAIN v : IsString(v[x])

SpaceChar == " "
NSpaces(n) == [i \in 0..(n-1) |-> SpaceChar]

(***************************************************************************)
(* A node has nd has the following fields                                  *)
(*   uid : A unique number                                                 *)
(*   loc : A Location                                                      *)
(*   image : Like a StringVector, except its 0th line is numbered          *)
(*           nd.loc.bLine and its contents are the portion of the module   *)
(*           occupied by the text that produced the node.  (Enclosing      *)
(*           parentheses are not included in the image.                    *)
(*   children : The sequence of subnodes, ordered by their loc fields.     *)
(***************************************************************************)
RECURSIVE IsNode(_)
IsNode(nd) ==
   /\ nd = [uid |-> nd.uid, loc |-> nd.loc, image |-> nd.image, 
            children |-> nd.children]
   /\ /\ nd.uid \in Int
      /\ \A d1, d2 \in Descendants(nd) : (d1 # d2) => (d1.uid # d2.uid)
           \* uid's are unique.
   /\ nd.loc \in Location
   /\ /\ /\ DOMAIN nd.image = nd.loc.bLine .. nd.loc.eLine 
         /\ \A i \in DOMAIN nd.image : IsString(nd.image[i])
      /\ IF nd.loc.bLine = nd.loc.eLine 
           THEN JLen(nd.image[nd.loc.bLine]) = nd.loc.eColumn - nd.loc.bColumn + 1
           ELSE JLen(nd.image[nd.loc.eLine]) = nd.loc.eColumn
      /\ nd.image[nd.loc.bLine][1] # SpaceChar
      /\ nd.image[nd.loc.eLine][JLen(nd.image[nd.loc.eLine])-1] # SpaceChar
   /\ /\ IsSeqOf(nd.children, IsNode)
      /\ \A i \in DOMAIN nd.children :
            /\ LocationContainedIn(nd.children[i].loc, nd.loc)
            /\ (i = 1) => /\ nd.children[i].loc.bLine = nd.loc.bLine
                          /\ nd.children[i].loc.bColumn = nd.loc.bColumn
            /\ (i = Len(nd.children)) => /\ nd.children[i].loc.eLine = nd.loc.eLine
                                         /\ nd.children[i].loc.eColumn = nd.loc.eColumn
            /\ (i > 1) => LocationPrecedes(nd.children[i-1].loc, nd.children[i].loc)

IsIdentifier(nd) == /\ IsNode(nd)
                    /\ nd.children = << >>
                    /\ nd.loc.bLine = nd.loc.eLine           

(***************************************************************************)
(* A TLA+ semantic unit (such as an expression) will be represented (for   *)
(* display on the screen or insertion into a specification) by an array of *)
(* STRINGs, where the array is indexed by 0..i for some i in Nat.          *)
(***************************************************************************)

(***************************************************************************)
(* An insertion ins describes the replacement of a token node t, that is a *)
(* descendant of a semantic node nd, in the StringVector representing nd   *)
(* by a StringVector rep, where                                            *)
(*                                                                         *)
(*    ins.col = t.loc.bColumn                                              *)
(*    ins.oldLen = t.loc.eColumn - t.loc.bColumn + 1                       *)
(*    DOMAIN rep = 0..ins.linesAdded                                       *)
(*    newLen = JLen(rep[ins.linesAdded])                                   *)
(***************************************************************************)
Insertion == [col : Nat, oldLen : Nat, newLen : Nat, linesAdded : Nat]

(***************************************************************************)
(* A NodeWithSubst nws consists of the following fields                    *)
(*                                                                         *)
(*     node : Node -- The original node that was substituted into.         *)
(*                                                                         *)
(*     repr : StringVector -- The representation of the node after         *)
(*                            substitutions.                               *)
(*                                                                         *)
(*     startInc : Int \X Int --                                            *)
(*                  equals the pair <<ln, col>> such that                  *)
(*                    -- ln = -nws.node.loc.bLine                          *)
(*                    -- the position <<nws.node.loc.beginLine,            *)
(*                                      nws.node.loc.beginColumn>>         *)
(*                       in nws.node corresponds to nws.repr character     *)
(*                       nws.repr[0][nd.loc.beginColumn + col]             *)
(*                                                                         *)
(*     lineInc : JArray(Int \X Int) --                                     *)
(*                 -- JLen(nws.lineInc) equals                             *)
(*                       nws.node.loc.eLine - nws.loc.bLine + 1 and        *)
(*                 -- nws.lineInc[i] equals the pair <<ln, col>> such      *)
(*                    that the first descendant d of nws.node with         *)
(*                      d.loc.bLine + nws.startInc[1] = i                  *)
(*                   (or the expression substituted for d) begins in repr  *)
(*                   at character                                          *)
(*                     repr[i + lineInc[i][1]]                             *)
(*                            [d.loc.bColumn + lineInc[i][2]]              *)
(*                 Note that for each i \in DOMAIN lineInc,                *)
(*                   lines in                                              *)
(*                      (nws.lineInc[i] + 1)                               *)
(*                        .. (IF i+1 = JLen(lineInc)                       *)
(*                              THEN JLen(nws.repr) - 1                    *)
(*                              ELSE nws.lineInc[i+1] - 1)                 *)
(*                   consist of lines added to nws.node.image, where the   *)
(*                   last of those lines ends with tokens that were        *)
(*                   originally to the right of a replaced token that      *)
(*                   would have been on line nws.lineInc[i] had it not     *)
(*                   been replaced.                                        *)
(*                                                                         *)
(*     inserts : JArray(JArray(Insertion)) --                              *)
(*                  inserts[i] equals the Insertions that represent        *)
(*                  substitutions made to tokens t in                      *)
(*                  Descendants(nws.node) with                             *)
(*                     t.loc.bLine + startInc[1] = i                       *)
(*                  The elements ins of inserts[i] are ordered by ins.col. *)
(***************************************************************************)
IsNodeWithSubst(nws) ==
  /\ DOMAIN nws = {"node", "repr", "startInc", "lineInc", "inserts"}
  /\ IsNode(nws.node)
  /\ IsStringVector(nws.repr)
  /\ nws.startInc \in Int \X Int
  /\ IsJArrayOf(nws.lineInc, Int \X Int)
  /\ /\ IsJArray(nws.inserts)
     /\ \A x \in DOMAIN nws.inserts : IsJArrayOf(nws.inserts[x], Insertion)


LeadingSpaces(str) == 
  (*************************************************************************)
  (* The number of space characters at the beginning of String str.        *)
  (*************************************************************************)
  1 + IndexMax({i \in DOMAIN str : \A j \in 0..i : str[j] = SpaceChar})

AddSpaces(n, sv) ==
  (*************************************************************************)
  (* The String obtained by adding n SpaceChars to the beginning of String *)
  (* sv.  If n < 0, adding n Space characters means deleting -n            *)
  (* characters.                                                           *)
  (*************************************************************************) 
  [i \in 0..(JLen(sv)+n-1) |-> 
     IF n >= 0 THEN IF i < n THEN " " ELSE sv[i-n]
                             ELSE sv[i-n] ]
      
(***************************************************************************)
(* NodeToNodeWithSubst(nd) is the NodeWithSubst representing node nd after *)
(* no substitutions have been performed.                                   *)
(***************************************************************************)
NodeToNodeWithSubst(nd) == 
  LET Lines == 0..(nd.loc.eLine - nd.loc.bLine)
      image == [i \in Lines 
                       |-> IF i = 0 THEN AddSpaces(nd.loc.bColumn - 1, 
                                                   nd.image[nd.loc.bLine])
                                    ELSE nd.image[i + nd.loc.bLine]]
      BlankLines == {i \in Lines : \A j \in DOMAIN image[i] : image[i][j] = SpaceChar}
      trim == IndexMin({LeadingSpaces(image[i]) : i \in Lines \ BlankLines}) 
      trimVec(strVec) == [i \in 0..(JLen(strVec)-1-trim) |-> strVec[i+trim]]
      repr == [i \in Lines |-> IF i \in BlankLines THEN ""
                                                   ELSE trimVec(image[i])]
      
  IN  [node     |-> nd,
       repr     |-> repr,
       startInc |-> <<-nd.loc.bLine, -trim - 1>>,
       lineInc  |-> [j \in Lines |-> <<0, 0>>],
       inserts  |-> [j \in Lines |-> << >>] ]
  
(***************************************************************************)
(* ReprPos(pos, nws) is defined to be the pair <<i, j>> so that if nws is  *)
(* a NodeWithSubstitution and pos is a <<line number, column number>> pair *)
(* that represents a position in nws.node that does not lie within a token *)
(* that has been substituted for, then the character at position pos       *)
(* appears is at nws.repr[i][j].                                           *)
(***************************************************************************)
ReprPos(pos, nws) == 
   pos ++ nws.startInc
       ++ nws.lineInc[pos[1] + nws.startInc[1]]
       ++ LET inserts == nws.inserts[pos[1] + nws.startInc[1]]
              ipos == [i \in DOMAIN inserts |->
                        <<inserts[i].linesAdded,
                          inserts[i].newLen - inserts[i].oldLen>>]
          IN  PosSum(ipos,
                     IndexMax({i \in DOMAIN inserts :
                                inserts[i].col < pos[2]}))

(***************************************************************************)
(* The NodeWithSubstitution produced by replacing the token with Location  *)
(* tokLoc by the StringVector sVec in NodeWithSubstitution nws.  The       *)
(* expression in sVec is parenthesized iff parens = TRUE.                  *)
(***************************************************************************)
SubstForToken(tokLoc, sVec, nws, parens) == 
  LET (*********************************************************************)
      (* sV is sVec with parentheses added iff parens = TRUE               *)
      (*********************************************************************)
      sV == 
        (*******************************************************************)
        (* sVec with parentheses added iff parens = TRUE                   *)
        (*******************************************************************)
        IF parens
          THEN [[i \in DOMAIN sVec |->
                  [j \in 0..JLen(sVec[i]) |-> 
                     IF j = 0 THEN IF i = 0 THEN "(" ELSE " "
                              ELSE  sVec[i][j-1]]]
                  EXCEPT ![JLen(sVec)-1] = 
                             [j \in 0..JLen(@) |-> 
                                IF j = JLen(@) THEN ")" ELSE @[j]]]
          ELSE sVec
      insert == 
        (*******************************************************************)
        (* The Insertion describing the parameters of the substitution.    *)
        (*******************************************************************)
        [col        |-> tokLoc.bColumn, 
         oldLen     |-> tokLoc.eColumn - tokLoc.bColumn + 1,
         linesAdded |-> JLen(sV) - 1,
         newLen     |-> JLen(sV[JLen(sV) - 1])]

      beginPos == ReprPos(<<tokLoc.bLine, tokLoc.bColumn>>, nws)

      repr1 ==
        (*******************************************************************)
        (* nws.repr with the substitution of the first line of sV for the  *)
        (* token                                                           *)
        (*******************************************************************)
        [nws.repr EXCEPT 
           ![beginPos[1]] = 
              [i \in 0..(JLen(@)-1 + JLen(sV[0]) - insert.oldLen) |->
                 IF i < beginPos[2] THEN @[i]
                                    ELSE IF i < beginPos[2] + JLen(sV[0])
                                           THEN sV[0][i-beginPos[2]]
                                           ELSE @[i-JLen(sV[0])+insert.oldLen] ] ]                      

      repr2 ==
       (********************************************************************)
       (* repr2 with the substitutions made for the rest of the lines of   *)
       (* sV.                                                              *)
       (********************************************************************)
     IF JLen(sV) = 1 
       THEN repr1
       ELSE [i \in 0..(JLen(repr1) + JLen(sV) -2) |->
              CASE i < beginPos[1] -> repr1[i] 
                [] i = beginPos[1] -> 
                     JSubArray(repr1[i], 0, beginPos[2] + JLen(sV[0])-1)
                [] i \in (beginPos[1]+1) .. (beginPos[1] + JLen(sV)-2) ->
                     AddSpaces(beginPos[2], sV[i - beginPos[1]])   
                [] i = beginPos[1] + insert.linesAdded -> 
                        AddSpaces(beginPos[2], 
                                  JConcat(sV[JLen(sV)-1],
                                          JSubArray(repr1[beginPos[1]],
                                                    beginPos[2]+JLen(sV[0]),
                                                    JLen(repr1[beginPos[1]])-1)))
                [] OTHER ->  repr1[i-insert.linesAdded] ]
 
      affectedRepLines ==
        (*******************************************************************)
        (* The numbers of the contiguous set of lines in repr2 following   *)
        (* tokLoc's line that begin (have first non-space character) in    *)
        (* the same column or to the right of the first character in the   *)
        (* replaced token's representation in repr2.  These lines must be  *)
        (* shifted left or right to maintain the alignment if its tokens   *)
        (* with tokens that originally appeared to the right of the        *)
        (* replaced token.                                                 *)
        (*******************************************************************)
        {i \in (beginPos[1] + insert.linesAdded + 1) .. (JLen(repr2)-1) :
           \A j \in (beginPos[1] + insert.linesAdded + 1) .. i :
              LeadingSpaces(repr2[i]) >= beginPos[2]}

      repr ==
        (*******************************************************************)
        (* The repr component of the result, obtained by adding or         *)
        (* removing spaces to the lines of affectedRepLines.               *)
        (*******************************************************************)
        [i \in DOMAIN repr2 |->
           IF i \in affectedRepLines 
             THEN AddSpaces(insert.newLen - insert.oldLen, repr2[i])    
             ELSE repr2[i]]  
      
      insertIndex == tokLoc.bLine + nws.startInc[1]
        (*******************************************************************)
        (* The index in repr and lineInc at which the insertion is being   *)
        (* made.                                                           *)
        (*******************************************************************)
                 
      lineInc1 ==
        (*******************************************************************)
        (* nws.lineInc with line increments (first components) adjusted.   *)
        (*******************************************************************)
        [i \in DOMAIN nws.lineInc |->
           IF i =< insertIndex
             THEN nws.lineInc[i]
             ELSE [nws.lineInc[i] EXCEPT ![1] = @ + insert.linesAdded]]   

      affectedNodeLines ==
        (*******************************************************************)
        (* These are the numbers of lines in the domains of startInc and   *)
        (* lineInc that correspond to line numbers of repr that are in     *)
        (* affectedRepLines.                                               *)
        (*******************************************************************)
        {i \in DOMAIN lineInc1 :
          i + lineInc1[i][1] \in affectedRepLines}   
          
     lineInc ==
        (*******************************************************************)
        (* The lineInc component of the result, which equals lineInc1 with *)
        (* column increments (second components) adjusted to reflect the   *)
        (* spaces added or removed from lines in affectedNodeLines.        *)
        (*******************************************************************)
        [i \in DOMAIN lineInc1 |->
           IF i \in affectedNodeLines
             THEN [lineInc1[i] EXCEPT ![2] = @ + insert.newLen - insert.oldLen]
             ELSE lineInc1[i] ] 
     inserts ==
       (********************************************************************)
       (* The inserts component of the result, obtained by adding `insert' *)
       (* to nws.inserts[insertIndex].                                     *)
       (********************************************************************)
       LET ins == nws.inserts[insertIndex] \* nws.inserts[beginPos[1]]
           insertPos == IndexMax({i \in DOMAIN ins : ins[i].col < insert.col})
       IN  [i \in DOMAIN nws.inserts |->
             IF i = insertIndex 
               THEN [j \in 0 .. JLen(ins) |->
                      CASE j =< insertPos -> ins[j]
                        [] j = insertPos+1 -> insert     
                        [] OTHER -> ins[j-1] ] 
               ELSE nws.inserts[i]  ]
      
  IN [node     |-> nws.node,
      repr     |-> repr,
      startInc |-> nws.startInc,
      lineInc  |-> lineInc,
      inserts  |-> inserts]
----------------------------------------------------------------------------
(***************************************************************************)
(* Operators for writing test cases.                                       *)
(***************************************************************************)
(***************************************************************************)
(* S("abcd") is the String corresponding to "abcd".  SV(<<"abc", "def ",   *)
(* "g">>) is the StringVector corresponding to                             *)
(*     "abc\nde f\ng"                                                      *)
(***************************************************************************)
S(str) == 
  LET RECURSIVE seq(_)
      seq(s) == IF Len(s) = 0 THEN << >> ELSE <<SubSeq(s,1,1)>> \o seq(Tail(s))
  IN StoJ(seq(str))
SV(strSeq) == StoJ([i \in 1..Len(strSeq) |-> S(strSeq[i])])

JJtoSS(jaOfJa) == JtoS([i \in DOMAIN jaOfJa |-> JtoS(jaOfJa[i])])

(****************************************************************************
The expression bcd + ...  - hh in this "module"

   q == uu 
   foo == a + (bcdd + ef
                       g - hq) + ijk
   12345678901234567890123456789012345
****************************************************************************)
Module1 == SV(
<<
"q  == uu",
"foo == a + (bcdd + ef",
"                    g - hh) + ijk" >>)

node1 == 
 [uid |-> 1,
  loc |-> [bLine |-> 2, bColumn |-> 13, eLine |-> 3, eColumn |-> 25],
  image |-> 
  (2 :> S("bcdd + ef") @@ 3 :> 
        S("                    g - hh") ),
  children |-> << >>]

nws1 == NodeToNodeWithSubst(node1)
tokLoc1 == [bLine |-> 2, bColumn |-> 15, eLine |-> 2, eColumn |-> 16]
tokLoc1a == [bLine |-> 2, bColumn |-> 20, eLine |-> 2, eColumn |-> 20]
tokLoc1b == [bLine |-> 3, bColumn |-> 21, eLine |-> 3, eColumn |-> 21]
sub1 == SV(<<"xxx", "yyyy", "ZZZZZZ">>) \* for dd
sub1a == SV(<<"[222", "22]">>)   \* for e
sub1b == SV(<<"GGG", "GG">>)            \* for g

Subst1 == SubstForToken(tokLoc1, sub1, nws1, FALSE)
\*Subst1a == SubstForToken(tokLoc1a, sub1a, Subst1, FALSE)
\*Subst1b == SubstForToken(tokLoc1b, sub1b, Subst1a, FALSE)
Subst1b == SubstForToken(tokLoc1b, sub1b, Subst1, FALSE)
Subst1a == SubstForToken(tokLoc1a, sub1a, Subst1b, FALSE)
Result1x == JJtoSS(nws1.repr)
Result1 ==  JJtoSS(Subst1.repr)
Result1a ==  JJtoSS(Subst1a.repr)
Result1b ==  JJtoSS(Subst1b.repr)
(***************************************************************************)
(* The expression bcd + ...  - hh in this "module"                         *)
(*                                                                         *)
(*    q == uu                                                              *)
(*    foo == a + (bcd + ef - EF                                            *)
(*             g - hq) + ijk                                               *)
(*    123456789012345678901234567890                                       *)
(***************************************************************************)
Module2 == SV(
<<
"q  == uu",
"foo == a + (bcd + ef - EF",
"         g - hq) + ijk" >>)


node2 == 
 [uid |-> 1,
  loc |-> [bLine |-> 2, bColumn |-> 13, eLine |-> 3, eColumn |-> 15],
  image |-> 
  (2 :> S("bcd + ef - EF") @@ 3 :> S("         g - hq")),
  children |-> << >>]

nws2 == NodeToNodeWithSubst(node2)
tokLoc2 ==  [bLine |-> 2, bColumn |-> 19, eLine |-> 2, eColumn |-> 20] \* ef
tokLoc2b ==  [bLine |-> 2, bColumn |-> 13, eLine |-> 2, eColumn |-> 15] \*bcd

sub2a == SV(<<"x", "xxxx">>)
sub2b == SV(<<"Y","YYYY">>)
Subst2a == SubstForToken(tokLoc2, sub2a, nws2, FALSE)
Subst2b == SubstForToken(tokLoc2b, sub2b, Subst2a, FALSE)
Result2x == JJtoSS(nws2.repr)
Result2a == JJtoSS(Subst2a.repr)
Result2b == JJtoSS(Subst2b.repr)
(****************************************************************************
The expression b12345 + ...  - hh in this "module"

   q == uu 
   foo == a + (b12345 + ef
                    g - hq) + ijk
   12345678901234567890123456789012345
****************************************************************************)
Module3 == SV(
<<
"q  == uu",
"foo == a + (b12345 + ef",
"                 g - hh) + ijk" >>)

node3 == 
 [uid |-> 1,
  loc |-> [bLine |-> 2, bColumn |-> 13, eLine |-> 3, eColumn |-> 23],
  image |-> 
  (2 :> S("b12345 + ef") @@ 3 :> S("                 g - hq") ),
  children |-> << >>]

nws3 == NodeToNodeWithSubst(node3)
tokLoc3a == [bLine |-> 2, bColumn |-> 14, eLine |-> 2, eColumn |-> 18] \* 12345
tokLoc3b == [bLine |-> 2, bColumn |-> 22, eLine |-> 2, eColumn |-> 22] \* e
sub3a == SV(<<"XX", "XXXXX", "XXXXXXXXXXXX">>)
sub3b == SV(<<"YYYYY",  "YY">>)
\*Subst3a == SubstForToken(tokLoc3a, sub3a, nws3, TRUE)
\*Subst3b == SubstForToken(tokLoc3b, sub3b, Subst3a, TRUE)

Subst3b == SubstForToken(tokLoc3b, sub3b, nws3, FALSE)
Subst3a == SubstForToken(tokLoc3a, sub3a, Subst3b, FALSE)


Result3x == JJtoSS(nws3.repr)
Result3a == JJtoSS(Subst3a.repr)
Result3b == JJtoSS(Subst3b.repr)
=====

(***************************************************************************
NEED TO RECORD The mapping from coordinates in Node to 
coordinates in StringVector.
 ***************************************************************************)
RECURSIVE NTail(_, _)
NTail(n, seq) == IF n = 0 THEN seq ELSE NTail(n-1, Tail(seq))

StringVectorOfNode(nd) ==
  IF nd.loc.bLine = nd.loc.eLine
    THEN [i \in {0} |-> nd.image[nd.loc.bLine]]
    ELSE LET Lines == 0..(nd.loc.eLine - nd.loc.bLine)
             SVN == [i \in Lines 
                       |-> IF i = 0 THEN NSpaces(nd.loc.bColumn - 1) 
                                           \o nd.image[nd.loc.bLine]
                                    ELSE nd.image[i + nd.loc.bLine]]
             BlankLines == {i \in Lines : \A j \in 1..Len(SVN[i]) :
                                             SVN[i][j] = SpaceChar}
             LeadingSpaces(str) == SetMax({i \in DOMAIN str :
                                            \A j \in 1..i : str[j] = SpaceChar})
             trim == IndexMin({LeadingSpaces(SVN[i]) : i \in Lines \ BlankLines})   
         IN [i \in Lines |-> IF i \in BlankLines THEN ""
                                                 ELSE NTail(trim, SVN[i])]
        
=============================================================================
\* Modification History
\* Last modified Thu Aug 21 18:41:11 PDT 2014 by lamport
\* Created Fri Jul 04 17:30:53 PDT 2014 by lamport

*/

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/ValueOutputStream.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

package tlc2.value;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.zip.GZIPOutputStream;

import tlc2.TLCGlobals;
import util.BufferedDataOutputStream;

public final class ValueOutputStream implements IValueOutputStream {

  private final BufferedDataOutputStream dos;
  private final HandleTable handles;

  public ValueOutputStream(File file) throws IOException {
	  this(file, TLCGlobals.useGZIP);
  }

  public ValueOutputStream(File file, final boolean compress) throws IOException {
	  this(new FileOutputStream(file), compress);
  }
  
  public ValueOutputStream(final OutputStream out, final boolean compress) throws IOException {
    if (compress) {
      OutputStream os = new GZIPOutputStream(out);
      this.dos = new BufferedDataOutputStream(os);
    }
    else {
      this.dos = new BufferedDataOutputStream(out);
    }
    this.handles = new HandleTable();
  }

  public ValueOutputStream(String fname) throws IOException {
	  this(fname, TLCGlobals.useGZIP);
  }
  
  public ValueOutputStream(String fname, boolean zip) throws IOException {
	    if (zip) {
	      OutputStream os = new GZIPOutputStream(new FileOutputStream(fname));
	      this.dos = new BufferedDataOutputStream(os);
	    }
	    else {
	      this.dos = new BufferedDataOutputStream(fname);
	    }
	    this.handles = new HandleTable();
	  }

  @Override
  public final void writeShort(short x) throws IOException {
	  this.dos.writeShort(x);
  }
  
  @Override
  public final void writeInt(int x) throws IOException {
    this.dos.writeInt(x);
  }

  @Override
  public final void writeLong(long x) throws IOException {
    this.dos.writeLong(x);
  }
  
  @Override
  public final void close() throws IOException {
    this.dos.close();
  }
  
  /* Precondition: x is a non-negative short. */
  @Override
  public final void writeShortNat(short x) throws IOException {
    if (x > 0x7f) {
      this.dos.writeShort((short) -x);
    }
    else {
      this.dos.writeByte((byte)x);
    }
  }

  /* Precondition: x is a non-negative int. */
  @Override
  public final void writeNat(int x) throws IOException {
    if (x > 0x7fff) {
      this.dos.writeInt(-x);
    }
    else {
      this.dos.writeShort((short)x);
    }
  }

  /* Precondition: x is a non-negative long. */
  @Override
  public final void writeLongNat(long x) throws IOException {
    if (x <= 0x7fffffff) {
      this.dos.writeInt((int)x);
    }
    else {
      this.dos.writeLong(-x);
    }
  }
	
	@Override
	public final void writeByte(final byte b) throws IOException {
		this.dos.writeByte(b);
	}

	@Override
	public final void writeBoolean(final boolean b) throws IOException {
		this.dos.writeBoolean(b);
	}

	@Override
	public final BufferedDataOutputStream getOutputStream() {
		return dos;
	}

	/**
	 * Check if another TLCState - which is currently also being serialized to the
	 * same storage (i.e. disk file) - has/contains an identical Value. If yes, do
	 * not serialize the Value instance again but make this TLCState point to the
	 * Value instance previously serialized for the other TLCState. In other words,
	 * this is a custom-tailored compression/de-duplication mechanism for Value
	 * instances.
	 * <p>
	 * This approach only works because both TLCStates are serialized to the same
	 * storage and thus de-serialized as part of the same operation (same
	 * Value*Stream instance).
	 * <p>
	 * The purpose of this approach appears to be:
	 * <ul>
	 * <li>Reduce serialization efforts and storage size</li>
	 * <li>Reduce the number of Value instances created during de-serialization</li>
	 * <li>Allow identity comparison on Value instances (AFAICT not used by Value
	 * explicitly, just UniqueString) to speed up check. Value#equals internally
	 * likely uses identity comparison as first check.</li>
	 * </ul>
	 * <p>
	 * A disadvantage is the cost of maintaining the internal HandleTable which can
	 * grow to thousands of elements during serialization/de-serialization (in
	 * ValueInputStream). Since serialization suspends the DiskStateQueue and thus
	 * blocks tlc2.tool.Workers from exploring the state space, this might has
	 * adverse effects.
	 */
	@Override
	public final int put(final Object obj) {
		return this.handles.put(obj);
	}
  
  private static class HandleTable {
    private int[] spine;
    private int[] next;
    private Object[] values;
    private int size;
    private int threshold;
    
    HandleTable() {
      this.spine = new int[17];
      Arrays.fill(spine, -1);
      this.next = new int[16];
      this.values = new Object[16];
      this.size = 0;
      this.threshold = (int)(this.spine.length * 0.75);
    }

// SZ Jul 13, 2009: not used
//    final int size() { return this.size; }
    
    final int put(Object val) {
      int index = (System.identityHashCode(val) & 0x7FFFFFFF) % this.spine.length;
      // lookup:
      for (int i = spine[index]; i >= 0; i = next[i]) {
	if (values[i] == val) { return i; }
      }
      // grow if needed:
      if (this.size >= this.next.length) {
	this.growEntries();
      }
      if (this.size >= this.threshold) {
	this.growSpine();
	index = (System.identityHashCode(val) & 0x7FFFFFFF) % this.spine.length;
      }
      // add val to the table:
      this.values[this.size] = val;
      this.next[this.size] = this.spine[index];
      this.spine[index] = this.size;
      this.size++;
      return -1;
    }

    private final void growEntries() {
      int newLength = this.next.length * 2;
      int[] newNext = new int[newLength];
      System.arraycopy(this.next, 0, newNext, 0, this.size);
      this.next = newNext;

      Object[] newValues = new Object[newLength];
      System.arraycopy(this.values, 0, newValues, 0, this.size);
      this.values = newValues;
    }

    private final void growSpine() {
      int len = (this.spine.length * 2) + 1;
      this.spine = new int[len];
      this.threshold = (int)(len * 0.75);
      Arrays.fill(this.spine, -1);
      for (int i = 0; i < this.size; i++) {
	int index = (System.identityHashCode(this.values[i]) & 0x7FFFFFFF) % len;
	this.next[i] = this.spine[index];
	this.spine[index] = i;
      }
    }
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/other/FileClassLoader.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:27:29 PST by lamport
//      modified on Wed Jan 10 00:11:43 PST 2001 by yuanyu

package tlc2.tool.other;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * This class is not used from anywhere from the project
 * it seems to be a helper utility used during the development 
 * @deprecated according to the paths it is not used (SZ February 19, 2009) 
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class FileClassLoader extends ClassLoader {
  /* Load a class from a file. */
  private String dir;

  public FileClassLoader(String dir) {
    this.dir = dir;
    if (dir.length() != 0 &&
	!dir.endsWith(File.separator)) {
      this.dir += File.separator;
    }
  }
    
  private byte[] loadClassData(String name) {
    byte[] bytes = null;
    String fileName = name + ".class";
    try {
      FileInputStream fis = new FileInputStream(this.dir + fileName);
      int size = fis.available();
      bytes = new byte[size];
      fis.read(bytes);
      fis.close();
    }
    catch (IOException e) { bytes = null; }
    return bytes;
  }

  public synchronized Class loadClass(String name, boolean resolve) {
    Class c = null;
    byte[] data = loadClassData(name);
    if (data != null) {
      c = defineClass(name, data, 0, data.length);
      if (resolve) resolveClass(c);
    }
    return c;
  }

  public static void main(String argv[]) {
    FileClassLoader fcl = new FileClassLoader("/udir/yuanyu/proj/tlc/module");
    try {
      Class c = fcl.loadClass("Strings", true);  // must set CLASSPATH correctly
      System.err.println(c);
    }
    catch (Exception e) {
      // Assert.printStack();
      System.err.println("Error: " + e.getMessage());
    }
  }

}




<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/PropertiesHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.jface.action.IAction;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Opens the properties dialog; the underlying object is fetched by the passed
 * ISelectionProvider. It only returns selected Specs.
 * 
 * @author <NAME>
 */
public class PropertiesHandler extends AbstractHandler {
	private boolean m_enabled = false;
	
    /**
     * {@inheritDoc}
     */
	@Override
	public void setEnabled(final Object evaluationContext) {
		final IEvaluationContext context = (IEvaluationContext)evaluationContext;
		final Object defaultVariable = context.getDefaultVariable();
		Spec spec = null;
		
		if (defaultVariable instanceof List) {
			final List<?> list = (List<?>)defaultVariable;
			
			if (list.size() == 1) {
				final Object o = list.get(0);
				
				if (o instanceof Spec) {
					spec = (Spec)o;
				}
			}
		}
		
		m_enabled = (spec != null);
	}
	
    /**
     * {@inheritDoc}
     */
	@Override
	public boolean isEnabled() {
		return m_enabled;
	}
	
    /**
     * {@inheritDoc}
     */
	public Object execute(ExecutionEvent event) throws ExecutionException {
		final IAction action = new PropertyDialogAction(UIHelper.getShellProvider(), Activator.getSpecManager());

		action.run();

		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/CachingTLCOutputSource.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.ITypedRegion;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.ITLCOutputListener;

/**
 * TLC output source, caching the output for listeners registered after the source 
 * has received the output 
 *  
 * @author <NAME>
 */
public class CachingTLCOutputSource implements ITLCOutputSource
{
    private Vector<ListenerProgressHolder> listenerHolders = new Vector<ListenerProgressHolder>();
    private boolean done = false;
    /**
     * List of {@link TypedRegionAndText}s.
     */
    private final Vector<TypedRegionAndText> detectedRegions = new Vector<TypedRegionAndText>();
    private final Model model;
    private final int priority;

    /**
     * Constructor of the source for a given name and prio
     * @param model
     * @param priority
     */
    public CachingTLCOutputSource(Model model, int priority)
    {
    	Assert.isNotNull(model);
        this.model = model;
        this.priority = priority;
    }

    /**
     * Inform the listeners about the change. The change comes in the form
     * of an {@link ITypedRegion} and the text represented by the region. The
     * text represented by the region is the text that could be obtained from this
     * source's document using the region's offset and length when the region was created.
     * However, the document may have changed since the region was created, so its
     * offset and length may not correspond to anything useful. However, its type
     * is useful, and if it is a {@link TLCRegion}, then it could contain other
     * useful information.
     * 
     * @param regionText TODO
     */
    public synchronized void onOutput(ITypedRegion region, String regionText)
    {
        Assert.isTrue(!done, "Output source is not accepting new output after it reported the finalization");

        this.detectedRegions.add(new TypedRegionAndText(region, regionText));
        for (int i = 0; i < this.listenerHolders.size(); i++)
        {
            onOutput((this.listenerHolders.get(i)), region, regionText);
        }
    }

    /**
     * Inform the listeners about completion
     */
    public synchronized void onDone()
    {
        this.done = true;
        for (int i = 0; i < this.listenerHolders.size(); i++)
        {
            (this.listenerHolders.get(i)).listener.onDone();
        }
    }

    /**
     * Inform the listener about the change. The change comes in the form
     * of an {@link ITypedRegion} and the text represented by the region. The
     * text represented by the region is the text that could be obtained from this
     * source's document using the region's offset and length when the region was created.
     * However, the document may have changed since the region was created, so its
     * offset and length may not correspond to anything useful. However, its type
     * is useful, and if it is a {@link TLCRegion}, then it could contain other
     * useful information.
     * 
     * @param holder
     * @param region
     * @param regionText
     */
    private synchronized void onOutput(ListenerProgressHolder holder, ITypedRegion region, String regionText)
    {
        holder.listener.onOutput(region, regionText);
    }

    public void addTLCOutputListener(ITLCOutputListener listener)
    {
        ListenerProgressHolder holder = new ListenerProgressHolder(listener);
        // remove the existing
        if (this.listenerHolders.contains(holder))
        {
            removeTLCOutputListener(listener);
        }
        // add the new one
        this.listenerHolders.add(holder);
        for (int i = 0; i < this.detectedRegions.size(); i++)
        {
            /* inform the listener about missed changes */
            onOutput(holder, (this.detectedRegions.get(i)).getRegion(),
                    (this.detectedRegions.get(i)).getText());
        }
        if (done)
        {
            holder.listener.onDone();
        }

    }

    public void removeTLCOutputListener(ITLCOutputListener listener)
    {
        this.listenerHolders.remove(new ListenerProgressHolder(listener));
    }

    /**
     * @see org.lamport.tla.toolbox.tool.tlc.output.source.ITLCOutputSource#getModel()
     */
    public Model getModel()
    {
        return model;
    }

    /**
     * @see org.lamport.tla.toolbox.tool.tlc.output.source.ITLCOutputSource#getListeners()
     */
    public ITLCOutputListener[] getListeners()
    {
        ITLCOutputListener[] listeners = new ITLCOutputListener[listenerHolders.size()];
        for (int i = 0; i < listeners.length; i++)
        {
            listeners[i] = (listenerHolders.get(i)).listener;
        }
        return listeners;
    }

    /**
     * @see org.lamport.tla.toolbox.tool.tlc.output.source.ITLCOutputSource#getSourcePrio()
     */
    public int getSourcePrio()
    {
        return priority;
    }

    /**
     * Holder for the listener and the number of message reported
     */
    class ListenerProgressHolder
    {
        ITLCOutputListener listener;

        /**
         * Constructor
         * @param listener
         * @param reported
         */
        public ListenerProgressHolder(ITLCOutputListener listener)
        {
            this.listener = listener;
        }

        public boolean equals(Object obj)
        {
            if (obj instanceof ListenerProgressHolder)
                return listener.equals(((ListenerProgressHolder) obj).listener);
            else if (obj instanceof ITLCOutputListener)
                return listener.equals(obj);
            else
                return false;
        }

        public int hashCode()
        {
            return listener.hashCode();
        }

        public String toString()
        {
            return listener.toString();
        }

    }

    /**
     * Wrapper class for a region and the text that it
     * represents in the document when it was created.
     * 
     * @author <NAME>
     *
     */
    private class TypedRegionAndText
    {
        private ITypedRegion region;
        private String text;

        private TypedRegionAndText(ITypedRegion region, String text)
        {
            this.region = region;
            this.text = text;
        }

        /**
         * @return the region
         */
        public ITypedRegion getRegion()
        {
            return region;
        }

        /**
         * @return the text
         */
        public String getText()
        {
            return text;
        }

    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/contribution/ParseStatusContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.ui.contribution;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A widget placed to the status line that shows the parse status of the root
 * module <br>
 * For additional help look at org.eclipse.ui.examples.contributions plugin
 * 
 * @author <NAME>
 * @version $Id: ParseStatusContributionItem.java 13736 2009-08-28 23:51:29Z
 *          lamport $
 */
public class ParseStatusContributionItem extends WorkbenchWindowControlContribution
{
    // the element
    private Composite composite;
    // label to display status
    private Label statusLabel;

    public ParseStatusContributionItem()
    {
        super("specParseStatusState");
        
        // Updates the Parse status widget on any spec operations
        Activator.getSpecManager().addSpecLifecycleParticipant(new SpecLifecycleParticipant() {
			
			/* (non-Javadoc)
			 * @see org.lamport.tla.toolbox.tool.SpecLifecycleParticipant#eventOccured(org.lamport.tla.toolbox.tool.SpecEvent)
			 */
			public boolean eventOccured(SpecEvent event) {
				ParseStatusContributionItem.this.updateStatus();
				return true;
			}
		});
    }

    protected Control createControl(Composite parent)
    {
        // If the composite is good just return it.
        if (composite != null && !composite.isDisposed())
        {
            return composite;
        }

        // Create a composite to place the label in
        composite = new Composite(parent, SWT.NONE);
        // composite.setData(this);

        // Give some room around the control
        FillLayout layout = new FillLayout();
        layout.marginHeight = 2;
        layout.marginWidth = 2;
        composite.setLayout(layout);

        // label informing the user that this reflects the parse status of the spec
        Label description = new Label(composite, SWT.NONE);
        description.setText("Spec Status : ");
        description.setSize(70, 20);

        // Create label inside composite.
        statusLabel = new Label(composite, SWT.BORDER | SWT.CENTER);
        statusLabel.setToolTipText("Specification Parse Status");
        statusLabel.setSize(100, 20);

        // update status
        updateStatus();
        return composite;
    }

    // Updates status from the specification currently loaded in the SpecManager
	public void updateStatus() {
		if (statusLabel == null || statusLabel.isDisposed()) {
			return;
		}

		final Job j = new ToolboxJob("Calculating specification size...") {
			/* (non-Javadoc)
			 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
			 */
			protected IStatus run(IProgressMonitor monitor) {
				final Spec spec = Activator.getSpecManager().getSpecLoaded();

				UIHelper.runUIAsync(new Runnable() {
					/* (non-Javadoc)
					 * @see java.lang.Runnable#run()
					 */
					public void run() {
						if (spec == null && !composite.isDisposed()) {
							composite.setVisible(false);
						} else if(!statusLabel.isDisposed() && !composite.isDisposed()) {
							statusLabel.setText(AdapterFactory.getStatusAsString(spec));
							statusLabel.setBackground(statusLabel.getDisplay().getSystemColor(AdapterFactory.getStatusAsSWTBGColor(spec)));
							statusLabel.setForeground(statusLabel.getDisplay().getSystemColor(AdapterFactory.getStatusAsSWTFGColor(spec)));
							statusLabel.redraw();
							composite.setVisible(true);
						}
					}
				});
				return Status.OK_STATUS;
			}
		};
		j.schedule();
	}
	
    public void update()
    {
        updateStatus();
    }

    protected int computeWidth(Control control)
    {
        return 170;
    }

}



<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/PDFBrowserEditor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.view;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

public class PDFBrowserEditor extends EditorPart {

	public static final String ID = "org.lamport.tla.toolbox.PDFBrowserEditor";
	
	private Browser browser;

	@Override
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
		setSite(site);
		setInput(input);
		this.setPartName(input.getName());
		if (browser != null && input instanceof IFileEditorInput) {
			setFileInput((IFileEditorInput) input);
		}
	}

	@Override
	public void createPartControl(Composite parent) {
		final Composite body = new Composite(parent, SWT.NONE);
        body.setLayout(new FillLayout());
        this.browser = new Browser(body, SWT.NONE);
        if (getEditorInput() instanceof IFileEditorInput) {
        	setFileInput((IFileEditorInput) getEditorInput());
        } else {
        	this.browser.setText("<html><body></body></html>");
        }
	}

	private void setFileInput(IFileEditorInput input) {
		this.browser.setUrl(input.getFile().getLocationURI().toASCIIString());
	}

	@Override
	public void setFocus() {
		this.browser.getParent().setFocus();
	}
	
	//** Methods below not relevant because PDF editor is read-only. **//
	
	@Override
	public boolean isDirty() {
		return false;
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		// unsupported
	}

	@Override
	public void doSaveAs() {
		// unsupported
	}

	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/suite/Test215.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.suite;

import static org.junit.Assert.assertFalse;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;

public class Test215 extends SuiteETestCase {

	public Test215() {
		super(ExitStatus.ERROR_SPEC_PARSE);
	}
	
	@Test
	public void testSpec() {
		assertFalse(recorder.recorded(EC.GENERAL));
		assertSubstring("Semantic errors:\n" + 
				"\n" + 
				"*** Errors: 8\n" + 
				"\n" + 
				"line 8, col 6 to line 8, col 14 of module test215\n" + 
				"\n" + 
				"Action used where only temporal formula or state predicate allowed.\n" + 
				"\n" + 
				"\n" + 
				"line 9, col 6 to line 9, col 14 of module test215\n" + 
				"\n" + 
				"Action used where only temporal formula or state predicate allowed.\n" + 
				"\n" + 
				"\n" + 
				"line 12, col 6 to line 12, col 16 of module test215\n" + 
				"\n" + 
				"Action used where only temporal formula or state predicate allowed.\n" + 
				"\n" + 
				"\n" + 
				"line 13, col 6 to line 13, col 16 of module test215\n" + 
				"\n" + 
				"Action used where only temporal formula or state predicate allowed.\n" + 
				"\n" + 
				"\n" + 
				"line 16, col 6 to line 16, col 11 of module test215\n" + 
				"\n" + 
				"<> followed by action not of form <<A>>_v.\n" + 
				"\n" + 
				"\n" + 
				"line 20, col 8 to line 20, col 13 of module test215\n" + 
				"\n" + 
				"[] followed by action not of form [A]_v.\n" + 
				"\n" + 
				"\n" + 
				"line 23, col 25 to line 23, col 26 of module test215\n" + 
				"\n" + 
				"Action-level bound of quantified temporal formula.\n" + 
				"\n" + 
				"\n" + 
				"line 26, col 26 to line 26, col 27 of module test215\n" + 
				"\n" + 
				"Action-level bound of quantified temporal formula.\n" + 
				"\n" + 
				"\n");
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/navigator/ToolboxExplorerResourceListener.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.navigator;

import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.ui.navigator.CommonViewer;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.UIHelper;

public class ToolboxExplorerResourceListener extends ToolboxLifecycleParticipant implements IResourceChangeListener {

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.lifecycle.ToolboxLifecycleParticipant#postWorkbenchWindowOpen()
	 */
	public void postWorkbenchWindowOpen() {
		// We might have missed events during Toolbox startup when there was
		// a workspace but no UI yet.
		resourceChanged(null);
		
		// update CNF viewers
		final IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspace.addResourceChangeListener(this);
	}
	
	public void resourceChanged(final IResourceChangeEvent event) {
		UIHelper.runUIAsync(new Runnable() {
			public void run() {
				ToolboxExplorer.refresh();
				// Expand the current spec and all its children
				final CommonViewer viewer = ToolboxExplorer.getViewer();
				// Event is only null when this Ctor calls us causing the
				// initial expanded state of a spec to be fully expanded.
				// Afterwards, the users expanded states is preserved.
				if (event == null && viewer != null) { // viewer might already be disposed which happens when the Toolbox shuts down.
					final Spec specLoaded = Activator.getSpecManager().getSpecLoaded();
					viewer.expandToLevel(specLoaded, ToolboxExplorer.DEFAULT_EXPAND_LEVEL);
				}
			}
		});
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ExprNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import tla2sany.st.TreeNode;

/**
 * An ExprNode is a node that represents some kind of expression
 * (i.e., not an operator argument).
 *
 * Exception as of 18 May 2008 modification made by LL. LabelNode
 * extends ExprNode, but it can represent a labeled ASSUME/PROVE as
 * well as a labeled expression.
 *
 * It is extended by AtNode, DecimalNode, LetInNode, NumeralNode,
 *                   OpApplNode, StringNode, SubstInNode
 *
 * It extends the ExprOrOpArgNode class.
 *
 * It contains the methods getLevel and getLevelParams that specify the
 * expression's level, where the level indicates the TLA level of the
 * expression as follows.
 *
 *   0 : Constant Level
 *   1 : State Level
 *   2 : Action Level
 *   3 : Temporal Level
 *
 * In general, the expression will be in the scope of some formal
 * parameters, so its level will depend on the level of the expressions
 * substituted for some of those parameters.  For example, if p and q
 * are formal parameters, and x is a declared variable, then the level
 * of the expression
 *
 *    ENABLED(p' = x) /\ q
 *
 * is the maximum of 1 (the level of the ENABLED expression) and the
 * level of q.  For the ExprNode n that represents this expression,
 * n.getLevel() equals 1 and n.getLevelParams() is the array of length 1
 * whose single element is (a ref to) the FormalParamNode for q.
 *
 * Now suppose that an expression e in a constant module contains a
 * declared constant c.  If the module is instantiated, then the level
 * of the instantiated version of e will depend on the level of the
 * expression substituted for c.  In that case, the array
 * getLevelParams() for the node representing e will contain a ref to
 * the OpDeclNode for the declaration of c.  Note that an instantiation
 * of a nonconstant module must substitute a constant expression for a
 * constant parameter, so in this case there's no need to put any refs
 * to constant declarations in the array getLevelParams().
 *
 * Implementation Note.  A module is a constant module iff the following
 * conditions are satisfied:
 *
 *   1. It contains no VARIABLE declarations (or other nonCONSTANT
 *      declarations in an ASSUME).
 *   2. It contains no nonconstant operators such as prime ('), ENABLED,
 *      or [].
 *   3. It extends and instantiates only constant modules.
 *
 * The Front End can thus easily determine during the parsing phase
 * whether or not a module is a constant module.  Thus, it can have that
 * information available when building the semantic tree.
 */
public abstract class ExprNode extends ExprOrOpArgNode {

    // This class is empty. It inherits all the methods it requires
    // from the ExprOrOpArgNode class.

    public SymbolNode subExpressionOf = null ;
      /*********************************************************************
      * For an expression that is constructed as a subexpression of a      *
      * UserDefinedOpNode or ThmOrAssumpDefNode, this field equals that    *
      * node.                                                              *
      *********************************************************************/

    ExprNode(int kind, TreeNode stn) { super(kind, stn); }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Misc.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Misc                                                               *
*                                                                          *
* Miscellaneous static methods (aka procedures).                           *
*                                                                          *
*                                                                          *
* stringToFloat : Converts a String to a float.                            *
*                                                                          *
* BreakStringOut                                                           *
*    Writes a string to an OutputFileWriter, splitting long lines          *
*    at spaces.                                                            *
*                                                                          *
* WriteIfNonNull                                                           *
*    Calls BreakStringOut to write a string, if it's not null.             *
*                                                                          *
* EliminateLeadingBlanks                                                   *
*    Removes leading spaces from a string.                                 *
*                                                                          *
* TeXify                                                                   *
*    Replace LaTeX's special characters in the string with LaTex           *
*    commands to produce them.                                             *
*                                                                          *
* TeXifyIdent                                                              *
*    Replaces each "_"  by a "\_" command in a string.                     *
*                                                                          *
* BreakLine                                                                *
*    Replaces each tab in the string by a space or a "\n", to break the    *
*    string into short lines for printing.  Useful for printing messages   *
*    or debugging output.                                                  *
*                                                                          *
* IsLetter                                                                 *
*    Tests if a char is a letter or "_".                                   *
*                                                                          *
* IsDigit                                                                  *
*    Tests if a char is a digit.                                           *
*                                                                          *
* IsLowerCase                                                              *
*    Tests if a string consists entirely of lower-case letters.            *
*                                                                          *
* IsUpperCase                                                              *
*    Tests if a string consists entirely of upper-case letters.            *
*                                                                          *
* IsCapitalized                                                            *
*    Tests if a string consists of an upper-case letter followed           *
*    by a string of lower-case letters.                                    *
***************************************************************************/
package tla2tex;

public final class Misc
{  public static float stringToFloat(String str)
     /**********************************************************************
     * Converts a string such as "123.456", ".123", "123.", or "123" to a  *
     * float.  (Lord knows why the standard Java libraries don't provide   *
     * such a method.)                                                     *
     **********************************************************************/
     { int pointPos = str.indexOf(".");
       if (pointPos == -1)
         { Debug.Assert(str.length() > 0, 
                  "stringToFloat called with empty string");
           if (str.length() > 18)
              { String substr = str.substring(0,18) ;
                float multiplier = 1;
                float exponent = str.length() - 18;
                while (exponent > 0)
                 { multiplier = multiplier * 10 ;
                   exponent = exponent - 1;
                 } ;
                return ((float) Long.parseLong(substr)) * multiplier ;
              } ;
            return (float) Long.parseLong(str); 
         } ;
       String strMinusPoint 
         = str.substring(0,pointPos) + str.substring(pointPos + 1) ;
       Debug.Assert(strMinusPoint.length() > 0, 
                  "stringToFloat called with the string \".\"");
       if (strMinusPoint.length() > 18)
         { strMinusPoint = strMinusPoint.substring(0,18);};
       long divisor = 1;
       long exponent = strMinusPoint.length() - pointPos;
       while (exponent > 0)
        { divisor = divisor * 10 ;
          exponent = exponent - 1;
        } ;
      return ((float) Long.parseLong(strMinusPoint)) / divisor ;
     } ;

  public static String floatToString(float f, int d)
    /***********************************************************************
    * Converts the float f to a string of the form "xxx.yyyyy", where the  *
    * number of digits in yyyyy is at most d.                              *
    ***********************************************************************/
    { String fStr = "" + f;
      int ePos = fStr.indexOf("E");
      int shiftRight = 0 ;
      int ptPos;
      float tenToTheMinusD = 1;
      int i = d ;
      while (i > 0)
       { tenToTheMinusD = tenToTheMinusD / 10 ;
         i = i-1 ;
       } ;
      if (f <= tenToTheMinusD) {return "0";} ;
      if (ePos != -1)
        { shiftRight = Integer.parseInt(fStr.substring(ePos + 1));
          fStr = fStr.substring(0, ePos);
          ptPos = fStr.indexOf(".") ;
          fStr = fStr.substring(0, ptPos) + fStr.substring(ptPos + 1);
          ptPos = ptPos + shiftRight ;
          while (ptPos < 0)
           { fStr = "0" + fStr;
             ptPos = ptPos + 1;
           } ;
          while (ptPos > fStr.length())
           { fStr = fStr + "0" ;
           } ;
          if (ptPos != fStr.length())
           { fStr = fStr.substring(0, ptPos) + "." + fStr.substring(ptPos);
           }
        } ; // END if (ePos != -1)
      ptPos = fStr.indexOf(".") ;
      if (ptPos == -1) {return fStr;}
      while (fStr.length() - ptPos > d+1)
       { fStr = fStr.substring(0, fStr.length()-1); }
      return fStr ;      
    }

  public static void WriteIfNonNull(OutputFileWriter writer, String str)
    /***********************************************************************
    * If str is non-empty, write it to writer, breaking long lines.        *
    ***********************************************************************/
    { if (! str.equals(""))
        { BreakStringOut(writer, str); }
    }



  public static void BreakStringOut(OutputFileWriter output, String str)
  /*************************************************************************
  * Writes str to output, trying to limit the length of output lines by    *
  * breaking the string at spaces into separate lines.                     *
  *************************************************************************/
  { String restOfString = str ;
    String nextLine = "" ;
    boolean done = false ;
    boolean cut = false ;
    while (   (!done) 
           && (restOfString.length() > Parameters.MaxOutputLineLength))
     { /********************************************************************
       * If there is a space char in the line, set lastSpace to the index  *
       * of the char at which to break the line: either the last space     *
       * char before index MaxOutputLineLength, or the first one after     *
       * it.  If there is no space char in the line, set lastSpace to -1.  *
       ********************************************************************/
       int lastSpace = restOfString.lastIndexOf(' ', 
                          Parameters.MaxOutputLineLength - 1);

       if (lastSpace == -1)
        { lastSpace = restOfString.indexOf(' ');
        };

       if (lastSpace <= Parameters.MaxOutputLineLength / 4)
        { done = true ; 
        }
       else
        { /*****************************************************************
          * There is a line break possible.  Set outputLine to the line    *
          * to be output and restOfString to the rest.                     *
          *****************************************************************/
          cut = true ;
          String outputLine = 
              EliminateLeadingBlanks(restOfString.substring(0, lastSpace)) ;
          restOfString = restOfString.substring(lastSpace);
          if (! outputLine.equals(""))
            { output.putLine(" " + outputLine);
            } ;
        } ;
     };
    if (cut)
      { restOfString = EliminateLeadingBlanks(restOfString) ;
        if (! restOfString.equals(""))
         { output.putLine(" " + restOfString); };
      } 
    else
     { output.putLine(restOfString); 
     };
  }  

  public static String EliminateLeadingBlanks(String str)
    /***********************************************************************
    * Equals str with leading blanks removed.                              *
    ***********************************************************************/
    { int firstNonBlank = 0 ;
      while (   (firstNonBlank < str.length())
             && (str.charAt(firstNonBlank) == ' '))
        { firstNonBlank = firstNonBlank + 1; } ;
      return str.substring(firstNonBlank) ;
    }
    
  public static String TeXify(String str)
    /***********************************************************************
    * Result is str with each of TeX's special characters replaced by the  *
    * command to produce it.                                               *
    ***********************************************************************/
    { String result = "" ;
      int pos = 0 ;
      while (pos < str.length())
       { switch (str.charAt(pos))
           { case '_' :
               result = result + "\\_" ;
               break ;
             case '{' :
               result = result + "\\{" ;
               break ;
             case '}' :
               result = result + "\\}" ;
               break ;
             case '\\' :          
               result = result + "\\ensuremath{\\backslash}" ;
               break ;
             case '&' :
               result = result + "\\&" ;
               break ;
             case '%' :
               result = result + "\\%" ;
               break ;
             case '$' :
               result = result + "\\$" ;
               break ;
             case '#' :
               result = result + "\\#" ;
               break ;
             case '~' : 
               result = result + "\\ensuremath{\\sim}" ;
               break ;
             case '^' :
               result = result + "\\ensuremath{\\ct}" ;
               break ;
             case '<' :
               result = result + "\\ensuremath{<}" ;
               break ;
             case '>' :
               result = result + "\\ensuremath{>}" ;
               break ;
             case '|' :          
               result = result + "\\ensuremath{|}" ;
               break ;
             default :
               result = result + str.charAt(pos) ;
            } ;
        pos = pos + 1 ;
       } ;
      return result ;
    }    

  public static String TeXifyIdent(String str)
    /***********************************************************************
    * Result is str with each occurrence of "_" replaced by a \\_ command. *
    ***********************************************************************/
    { String out = str ;
      int nextUS = str.indexOf("_");
      while (nextUS != -1)
       { 
         if (nextUS == 0)
          { out = "\\" + out;
          }
         else
          { out = out.substring(0, nextUS) + "\\_" + out.substring(nextUS+1);
          } ;
         nextUS = out.indexOf("_", nextUS + 2) ;
       };
      return out ;
    }

  /**
   * The LaTeX output for producing a label.  As a first attempt, here is
   * the algorithm:
   * 
   *    - typeset the Ident part of the label as in TeXifyIdent.
   *    - add \@s{.5} or \@s{2.5} depending on whether or not there
   *      is one or more spaces before the ":"
   *    - put the ":", ":+", or ":-" in a \textrm command, eliminating
   *      any spaces.
   *    - add \@s{3} or @s{4} depending on whether there are spaces before
   *      the ":"
   * @param str
   * @return
   */
  public static String TeXifyPcalLabel(String str) {
      String out = "";
      int next = 0 ;
      while (    (next < str.length())
              && (   IsLetter(str.charAt(next))) 
                  || IsDigit(str.charAt(next))) {
          char nextChar = str.charAt(next) ;
          next++ ;
          if (nextChar == '_') {
              out = out + "\\" ;
          } 
          out = out + nextChar ;
      }
      int numberOfSpaces = 0 ;
      while (next < str.length() && IsSpace(str.charAt(next))) {
          numberOfSpaces++ ;
          next++ ;
      }
      if (numberOfSpaces == 0) {
          out = out + "\\@s{.5}" ;
      }
      else {
          out = out + "\\@s{2.5}" ;
      }
      out = out + "\\textrm{" ;
      while (next < str.length()) {
          char nextChar = str.charAt(next) ;
          next++ ;
          if (! IsSpace(nextChar)) {
              out = out + nextChar ;
          }
      }
      out = out + ((numberOfSpaces == 0) ? "}\\@s{3}" : "}\\@s{4}") ;
      return out;
  }

  private static final int MAXLEN = 48;
    /***********************************************************************
    * The maximum output line length for the BreakLine method.             *
    ***********************************************************************/
    
  public static String BreakLine(String str)
  /*************************************************************************
  * Used for printing output with reasonable line breaks.  The argument    *
  * str is a string with '\t' characters.  The method returns str with     *
  * each '\t' character either removed or replaced by a '\n' if the        *
  * current line of the result string has more than MAXLEN characters.     *
  **************************************************************************/
  { int lineLen = 0 ; 
    int nextChar = 0 ;
    String newStr = "" ;
    char ch = '0' ;
    while (nextChar < str.length())
      { ch = str.charAt(nextChar) ;
        if (ch == '\t')
          { if (lineLen > MAXLEN)
              { newStr = newStr + "\n       " ;
                lineLen = 7;
              }
          }
        else
          { newStr = newStr + ch;
            lineLen = lineLen + 1;
          } ;
        nextChar = nextChar + 1 ;
      };
    return newStr ;
   } ;

    public static boolean IsLetter(char c) 
      /*********************************************************************
      * True iff c is a letter or '_'.                                     *
      *********************************************************************/
      { return      ( ('a' <= c ) && (c <= 'z') )
                 || ( ('A' <= c ) && (c <= 'Z') )
                 || ( c == '_' ) ;} ;

                 
    public static boolean hasLetter(String str) {
       boolean notFound = true ;
       int i = 0 ;
       while (notFound && (i < str.length())) {
          if (IsLetter(str.charAt(i))) {
              notFound = false ;
          }
          i++ ;
       }
       return ! notFound ;
    }
    
    public static boolean IsDigit(char c) 
      /*********************************************************************
      * True iff c is a digit.                                             *
      *********************************************************************/
      { return ('0' <= c ) && (c <= '9'); } ;

    public static boolean IsSpace(char c) 
      /*********************************************************************
      * True iff c is a space character--that is, one of the following:    *
      * \f, \r, or ' '.  A \n is not considered a space character.         *
      *********************************************************************/
      { return  (c == ' ')  | (c == '\f') | (c == '\r') ; } ;


  public static boolean isBlank(String str) 
    /***********************************************************************
    * True iff str has nothing but space characters.                       *
    ***********************************************************************/
   { return str.trim().equals("") ;
   }

  public static boolean IsLowerCase(String str)
    /***********************************************************************
    * True iff str consists entirely of lower-case letters.                *
    ***********************************************************************/
    { int i = 0 ;
      boolean result = true ;
      while (   (i < str.length())
             && result)
       { char c = str.charAt(i);
         if (('a' >  c ) || ( c > 'z'))
           { result = false ; };
         i = i+1;
       }
      return result;
    }

  public static boolean IsUpperCase(String str)
    /***********************************************************************
    * True iff str consists entirely of upper-case letters.                *
    ***********************************************************************/
    { int i = 0 ;
      boolean result = true ;
      while (   (i < str.length())
             && result)
       { char c = str.charAt(i);
         if (('A' >  c ) || ( c > 'Z'))
           { result = false ; };
         i = i+1;
       }
      return result;
    }

  public static boolean IsCapitalized(String str)
    /***********************************************************************
    * True iff str consists of an upper-case letter followed by a          *
    * possibly null string of lower-case letters.                          *
    ***********************************************************************/
    { if (str.length() > 0)
       { char c = str.charAt(0);
         return  ('A' <= c ) && (c <= 'Z') && IsLowerCase(str.substring(1));
       } ;
      return false;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/GrowingLongVecTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.junit.Test;

public class GrowingLongVecTest extends LongVecTest {

	// A capacity that means the LongVec has to grow
	protected LongVec getLongVec() {
		return new LongVec(0);
	}
	
	@Test
	public void testGrowAndShrink() {
		// Zero capacity, LongVec has to grow
		final LongVec vec = new LongVec(0);
		vec.addElement(1L);
		vec.addElement(2L);

		assertEquals(2, vec.size());

		// Remove in reverse order
		vec.removeElement(1);
		vec.removeElement(0);
		
		assertEquals(0, vec.size());
		
		try {
			vec.removeElement(0);
		} catch (Exception e) {
			return;
		}
		fail("Removed non-existing element");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/AbsoluteSpecPathTest.java<|end_filename|>
package tlc2.tool;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;

import org.junit.Test;

import tlc2.TLC;
import tlc2.TestMPRecorder;
import tlc2.output.EC;
import tlc2.output.MP;

public class AbsoluteSpecPathTest extends CommonTestCase {

	public AbsoluteSpecPathTest() {
		super(new TestMPRecorder());
	}

	@Test
	public void test() throws Exception {
		// Check that BASE_DIR is actually set to make sure we have an absolute path to
		// work with. If this test gets executed from within the Eclipse IDE, manually
		// set -Dbasedir=/path/to/tlatools/
		assumeFalse(BASE_DIR.equals(""));
		
		MP.setRecorder(recorder);
		
		// Do not call TLC#main because we won't get control back (system.exit) to check
		// assertions below.
		final TLC tlc = new TLC();
		tlc.handleParameters(new String[] {BASE_PATH + "Test2"});
		tlc.process();
		
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "5"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "6", "5", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/AdapterFactory.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.util.List;
import java.util.Vector;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.swt.SWT;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.model.WorkbenchAdapter;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;

import pcal.TLAtoPCalMapping;
import tla2sany.st.Location;

/**
 * A toolkit with adapter methods
 * @author <NAME>
 */
public class AdapterFactory implements IAdapterFactory
{
    // list of supported targets
    private static final Class<?>[] CLASSES = new Class[] { IWorkbenchAdapter.class, IResource.class };

    /*
     * (non-Javadoc)
     * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
     */
    public Class<?>[] getAdapterList()
    {
        return CLASSES;
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
     */
    @SuppressWarnings("unchecked")
	public <T> T getAdapter(Object adaptableObject, Class<T> adapterType)
    {
        if (adapterType == IWorkbenchAdapter.class)
        {
            if (adaptableObject instanceof Spec)
            {
                return (T) new SpecWorkbenchAdapter();
            }
        }
		if (IResource.class.equals(adapterType) && adaptableObject instanceof Module) {
			return (T) ((Module) adaptableObject).getResource();
		}
		if (IResource.class.equals(adapterType) && adaptableObject instanceof Spec) {
			return (T) ((Spec) adaptableObject).getRootFile();
		}
        return null;
    }

    /**
     * Retrieves formated problem location
     * @param moduleName
     * @param coordinates
     * @return
     */
    public static String getFormattedLocation(int[] coordinates, String moduleName)
    {
        return "from line " + coordinates[0] + ", column " + coordinates[1] + " to line " + coordinates[2]
                + ", column " + coordinates[3] + " of module " + moduleName;
    }

    /**
     * Converts four-int {@link Location} that is 1-based to a two int {@link IRegion} that is
     * 0-based.
     * 
     * TODO: unit test!
     * @param document
     * @param location
     * @return
     * @throws BadLocationException 
     */
    public static IRegion locationToRegion(IDocument document, Location location) throws BadLocationException
    {
        /* 
         * The coordinates returned by location are 1-based and the coordinates
         * for a region in a document should be 0-based to be consistent with Positions
         * in documents. Therefore, we subtract 1 from each location coordinate.
         */
        int offset = document.getLineOffset(location.beginLine() - 1) + location.beginColumn() - 1;
        /*
         * If location describes a two-character sequence beginning at column x, then it would
         * have location.endColumn() = x+1. This means that when computing the length, we add 1 to
         * the offset of the second point described by location. In other words, the offset of the
         * second point described by location is:
         * 
         * document.getLineOffset(location.endLine() - 1) + location.endColumn()-1
         * 
         * So the length is:
         * 
         * (document.getLineOffset(location.endLine() - 1) + location.endColumn()-1)+1 - offset
         * 
         * which equals:
         * 
         * document.getLineOffset(location.endLine() - 1) + location.endColumn() - offset
         */
        int length = document.getLineOffset(location.endLine() - 1) + location.endColumn() - offset;
        return new Region(offset, length);
    }

    /**
     * Converts four-int {@link Location} that is 1-based to a two int {@link IRegion} that is
     * 0-based. Different than {@link #locationToRegion(IDocument, Location)} because
     * it does not need a document as an argument but instead creates one.
     * 
     * Returns null if the location cannot be converted to a region for any reason.
     * Possible reasons are that the location points to a non-existent module or a
     * location in a module that does not exist.
     * 
     * WARNING: A module named "foo" is considered not to exist if the file containing
     * it is named "Foo.tla"--that is, if the file name and the module name don't
     * agree exactly.  This is because org.eclipse.core.internal.resources.File.exists()
     * returns false if the names disagree in the case of some letter(s).  Working
     * around this bug/feature is not trivial because it requires getting hold of
     * those two names, and this doesn't seem to be easy to do here.
     * (Added by LL on 16 Jan 2014).
     * 
     * @param location
     * @return
     */
    public static IRegion locationToRegion(Location location)
    {

        IFile module = (IFile) ResourceHelper.getResourceByModuleName(location.source());

        if (module != null && module instanceof IFile && module.exists())
        {
            try
            {
                return locationToRegion(ResourceHelper.getDocFromFile(module), location);
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error converting location to region for location " + location, e);
            }
        }

        return null;

    }

    /**
     * Adapts the spec object to the workbench<br>
     * Using this adapter the spec can be represented in workbench containers
     * 
     * @author zambrovski
     */
    class SpecWorkbenchAdapter extends WorkbenchAdapter
    {

        /*
         * (non-Javadoc)
         * @see org.eclipse.ui.model.WorkbenchAdapter#getLabel(java.lang.Object)
         */
        public String getLabel(Object object)
        {
            Spec spec = (Spec) object;
            return (spec == null) ? "" : spec.getName();
        }

    }

    /**
     * Converts a parse status to a human-readable string
     * @param status the integer representing the parse status
     * @return human readable string
     */
    public static String getStatusAsString(int status)
    {
        switch (status) {
        case IParseConstants.COULD_NOT_FIND_MODULE:
            return " module not found ";
        case IParseConstants.PARSED:
            return " parsed ";
        case IParseConstants.SEMANTIC_WARNING:
            return " error ";
        case IParseConstants.SEMANTIC_ERROR:
        case IParseConstants.SYNTAX_ERROR:
        case IParseConstants.UNKNOWN_ERROR:
            return " error ";
        case IParseConstants.UNPARSED:
            return " unparsed ";
        default:
            return " unknown " + status;
        }
    }

    /**
     * Converts a parse status of the spec to a human-readable string
     * @param spec specification holding the parse status
     * @return human readable string
     */
    public static String getStatusAsString(Spec spec)
    {
        if (spec != null)
        {
            return getStatusAsString(spec.getStatus());
        } else
        {
            return " no spec ";
        }
    }

    /**
     * Converts parse status to a background color for display in the status contribution item
     * @param spec specification holding the parse status
     * @return SWT color constant
     */
    public static int getStatusAsSWTBGColor(Spec spec)
    {
        if (spec != null)
        {
            switch (spec.getStatus()) {
            case IParseConstants.PARSED:
                return SWT.COLOR_GREEN;
            case IParseConstants.COULD_NOT_FIND_MODULE:
            case IParseConstants.SEMANTIC_WARNING:
            case IParseConstants.SEMANTIC_ERROR:
            case IParseConstants.SYNTAX_ERROR:
            case IParseConstants.UNKNOWN_ERROR:
                return SWT.COLOR_DARK_RED;
            case IParseConstants.UNPARSED:
                return SWT.COLOR_YELLOW;
            case IParseConstants.UNKNOWN:
            default:
                return SWT.COLOR_GRAY;
            }
        } else
        {
            return SWT.COLOR_GRAY;
        }
    }

    /**
     * Converts parse status to a foreground color for display in the status contribution item
     * @param spec specification holding the parse status
     * @return SWT color constant
     */
    public static int getStatusAsSWTFGColor(Spec spec)
    {
        if (spec != null)
        {
            switch (spec.getStatus()) {
            case IParseConstants.PARSED:
                return SWT.COLOR_BLACK;
            case IParseConstants.COULD_NOT_FIND_MODULE:
            case IParseConstants.SEMANTIC_WARNING:
            case IParseConstants.SEMANTIC_ERROR:
            case IParseConstants.SYNTAX_ERROR:
            case IParseConstants.UNKNOWN_ERROR:
                return SWT.COLOR_WHITE;
            case IParseConstants.UNPARSED:
                return SWT.COLOR_BLACK;
            case IParseConstants.UNKNOWN:
            default:
                return SWT.COLOR_BLACK;
            }
        } else
        {
            return SWT.COLOR_BLACK;
        }
    }

    /**
     * Decides, if a parse status is a problem
     * @param status status to decide on
     * @return true if status if one of the {@link IParseConstants#COULD_NOT_FIND_MODULE}
     * {@link IParseConstants#SEMANTIC_ERROR}, {@link IParseConstants#SYNTAX_ERROR} or {@link IParseConstants#UNKNOWN_ERROR}
     */
    public static boolean isProblemStatus(int parseStatus)
    {
        switch (parseStatus) {
        // error cases
        case IParseConstants.COULD_NOT_FIND_MODULE:
        case IParseConstants.SEMANTIC_WARNING:
        case IParseConstants.SEMANTIC_ERROR:
        case IParseConstants.SYNTAX_ERROR:
        case IParseConstants.UNKNOWN_ERROR:
            return true;
            // non-error cases
        case IParseConstants.UNPARSED:
        case IParseConstants.PARSED:
        case IParseConstants.UNKNOWN:
            return false;
        default:
            return false;
        }

    }

    /**
     * Checks if the spec holding the parse status has problems
     * @param spec specification holding the parse status
     * @return if spec is not null delegates on {@link AdapterFactory#isProblemStatus(int)} otherwise false
     */
    public static boolean hasProblemStatus(Spec spec)
    {
        if (spec != null)
        {
            return isProblemStatus(spec.getStatus());
        } else
        {
            return false;
        }
    }

    /**
     * Retrieves the text representation of the TLA+ parse problem
     * @param problem
     * @return
     */
    public static String getSeverityAsText(int severity)
    {
        switch (severity) {
        case IMarker.SEVERITY_ERROR:
            return "Error";
        case IMarker.SEVERITY_WARNING:
            return "Warning";
        case IMarker.SEVERITY_INFO:
        default:
            return "Info";
        }
    }

    /**
     * Resolves the origin of the marker 
     * @param markerType
     * @return
     */
    public static String getMarkerTypeAsText(String markerType)
    {
        if (markerType == null || "".equals(markerType))
        {
            return "";
        }
        if (TLAMarkerHelper.TOOLBOX_MARKERS_ALL_MARKER_ID.equals(markerType))
        {
            return "TLA+ Toolbox";
        } else if (TLAMarkerHelper.TOOLBOX_MARKERS_TRANSLATOR_MARKER_ID.equals(markerType))
        {
            return "PCal Translator";
        } else if (TLAMarkerHelper.TOOLBOX_MARKERS_TLAPARSER_MARKER_ID.equals(markerType))
        {
            return "TLA+ Parser";
        } else
        {
            return "";
        }
    }

    /**
     * Adapts a list of modules including all dependent modules and the
     * module itself to the form, accepted by the dependency storage.<br>
     *  
     * As of the current implementation, this means that its arguments
     * are a module name and a list of modules; it returns the list of
     * names of those modules, minus the first argument if it is the
     * name of one of those modules.<br>
     * 
     * TODO improve the storage
     *  
     * @param name A name of the module that has been parsed
     * @param userModules a list of {@link Module} objects representing the depending modules, which eventually include
     *                    one module representing the parsed module itself
     * @return a list of module names (Strings) containing all modules from the <code>userModule</code> argument, 
     *         excluding the module specified by the <code>name</code> argument    
     */
    public static List<String> adaptModules(String name, List<Module> userModules)
    {
        Vector<String> dependents = new Vector<String>(userModules.size());
        // iterate over all modules
        for (int i = 0; i < userModules.size(); i++)
        {
            Module module = userModules.get(i);
            if (!module.getFile().getName().equals(name))
            {
                // add the module name iff the name is not matching the one provided in the name argument
                dependents.add(module.getFile().getName());
            }
        }
        return dependents;
    }
    
    public static pcal.Region jumptToPCal(TLAtoPCalMapping mapping, Location location, IDocument document) throws BadLocationException {
        /*
         * Get the best guess of the line number in the
         * current contents of the editor that corresponds to what was line
         * mapping.tlaStartLine when the algorithm was translated. 
         * It is computed by assuming that neither the algorithm nor the translation
         * have changed, but they both may have been moved down by the same 
         * number delta of lines (possibly negative).  A more sophisticated approach 
         * using fingerprints of lines could be used, requiring that the necessary 
         * fingerprint information be put in TLAtoPCalMapping.
         */
        int beginAlgorithmLine = AdapterFactory.GetLineOfPCalAlgorithm(document);
        if (beginAlgorithmLine == -1) {
        	throw new BadLocationException("The algorithm is no longer in the module.");
        }

		// Translate editor location to pcal.Region
        final pcal.Region tlaRegion = location.toRegion();
		
        // Do actual mapping
        return mapping.mapTLAtoPCalRegion(tlaRegion,
				beginAlgorithmLine);
    }
    
    /**
     * Returns the line number (in Java coordinates/zero based) of the line containing the first
     * "--algorithm" or "--fair algorithm" token(s) that begin(s) a PlusCal algorithm. 
     * Returns -1 if there is none.
     * 
     * @param document
     * @return
     */
    public static int GetLineOfPCalAlgorithm(IDocument document) {
		try {
			final String moduleAsString = document.get();
			return LocationToLine(document,
					TLAtoPCalMapping.GetLineOfPCalAlgorithm(moduleAsString));
		} catch (BadLocationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
    }
    
    public static int GetLineOfPCalAlgorithm(final IFile module) {
		return GetLineOfPCalAlgorithm(ResourceHelper.getDocFromFile(module));
    }

    /** 
     * If location = -1, then it returns -1.  Else it returns the number of the line with
     * this location.
     * @param document
     * @param location
     * @return
     * @throws BadLocationException
     */
    private static int LocationToLine(IDocument document, int location) throws BadLocationException {
        if (location == -1) {
            return -1;
        } else {
            return document.getLineOfOffset(location);
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/impl/IntervalValueTest.java<|end_filename|>
package tlc2.value.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.junit.Test;

import util.Assert.TLCRuntimeException;

public class IntervalValueTest {

	@Test
	public void testElementAt() {
		final IntervalValue iv = new IntervalValue(3, 11);
		for (int i = 0; i < iv.size(); i++) {
			assertEquals(IntValue.gen(i + 3), iv.elementAt(i));
		}
	}

	@Test
	public void testElementAtOutOfBoundsNegative() {
		final IntervalValue iv = new IntervalValue(3, 11);
		try {
			iv.elementAt(-1);
		} catch (TLCRuntimeException e) {
			return;
		}
		fail();
	}

	@Test
	public void testElementAtOutOfBoundsSize() {
		final IntervalValue iv = new IntervalValue(3, 11);
		try {
			iv.elementAt(iv.size());
		} catch (TLCRuntimeException e) {
			return;
		}
		fail();
	}
	
	@Test
	public void sizeOverflow() {
		assertEquals(Integer.MAX_VALUE, new IntervalValue(1, Integer.MAX_VALUE).size());
		assertEquals(Integer.MAX_VALUE, new IntervalValue(Integer.MIN_VALUE, -2).size());
		
		try {
			assertEquals(0, new IntervalValue(-989_822_976, 1_157_660_672).size());
		} catch (TLCRuntimeException e) {
			assertTrue(e.getMessage().contains("Size of interval value exceeds the maximum representable size (32bits)"));
			return;
		}
		fail();
	}
	
	@Test
	public void compareToOverflow1() {
		final IntervalValue iv = new IntervalValue(Integer.MAX_VALUE - 1, Integer.MAX_VALUE);
		assertEquals(2, iv.size());
		
		final IntervalValue iv2 = new IntervalValue(Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 2);
		assertEquals(2, iv2.size());
		
		assertEquals(1, iv.compareTo(iv2));
	}

	@Test
	public void testCompareExtremeIntervals() {
		final IntervalValue x = new IntervalValue(Integer.MIN_VALUE, -2);
		final IntervalValue y = new IntervalValue(1, Integer.MAX_VALUE);
		assertEquals(x.size(), y.size());
		assertTrue(x.compareTo(y) < 0);
		assertTrue(y.compareTo(x) > 0);
	}

	@Test
	public void testEmptyIntervalEquality() {
		IntervalValue i1 = new IntervalValue(10, 1);
		IntervalValue i2 = new IntervalValue(20, 15);
		assertEquals(i1, i2);
	}

	@Test
	public void testCompareEmptyIntervals() {
		int cmp = new IntervalValue(10, 1).compareTo(new IntervalValue(20, 15));
		assertEquals(0, cmp);
	}

	@Test
	public void testSizeOfMaximumRepresentableInterval() {
		final IntervalValue iv = new IntervalValue(Integer.MIN_VALUE, Integer.MAX_VALUE);
		try {
			iv.size();
		} catch (TLCRuntimeException e) {
			assertTrue(e.getMessage().contains("Size of interval value exceeds the maximum representable size (32bits)"));
			return;
		}
		fail();
	}

	@Test
	public void testExtremeIntervalSize() {
		final IntervalValue iv1 = new IntervalValue(Integer.MAX_VALUE, Integer.MAX_VALUE);
		assertEquals(1, iv1.size());
		final IntervalValue iv2 = new IntervalValue(Integer.MIN_VALUE, Integer.MIN_VALUE);
		assertEquals(1, iv2.size());
		final IntervalValue iv3 = new IntervalValue(Integer.MAX_VALUE-10, Integer.MAX_VALUE);
		assertEquals(11, iv3.size());
		final IntervalValue iv4 = new IntervalValue(Integer.MIN_VALUE, Integer.MIN_VALUE+10);
		assertEquals(11, iv4.size());
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/tlc-options-page.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/tlc-options-page.html  -->


<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>TLC Options Page</title>
</head>
<!-- a comment here -->

<body>
<h1>TLC Options Page</h1>


<pre>
Contents
  <a href="#config">Configuration</a>
  <a href="#checking">Checking Mode</a>
  <a href="#features">Features</a>
  <a href="#parameters">Parameters</a>
</pre>

<P>
This model editor page allows you to add less-often
used parts of a model.&nbsp;  It's a good idea to browse
this page just to see what options it provides, since
some of the features are not ones you would expect.
 </P>
<h2><a name="config">Configuration</a>

<h3>Number of worker threads</h3>

TLC's algorithm for computing the set (actually the graph) of reachable states
is highly parallelizable, and it can make good use of arbitrarily many processors.&nbsp;
This parameter specifies the number of separate threads that TLC will spawn to
perform that computation.&nbsp;  You should not set it to be greater than the number of
separate processors (cores) on your computer; the Toolbox will warn you if you do.

<h3>Fraction of physical memory allocated to TLC</h3>

This determines how large a heap TLC will use.&nbsp;  If you make it too small, TLC
could run out of heap space and crash.&nbsp;  If you make it too large, your machine will not have
enough memory and everything will run slowly.&nbsp;  The slider's color warns you if
you are giving TLC too little or too much memory.&nbsp;
TLC can keep the set of reachable states it has found
on disk, so having too many reachable states can't run it out of memory.&nbsp;
However, it runs much faster when it can keep those states in memory.&nbsp;
TLC can run out of heap space if it takes too much memory to represent the
set of initial states or the set of successor states of a single state.&nbsp;
If TLC does run out of memory in the middle of a long run,
you can give it more and restart it from a checkpoint.

<p>

Setting the this parameter too large may produce a
<em>Could not create the Java virtual machine</em> error.


<h3>Log base 2 of number of disk storage files</h3>

If your computer has multiple disk drives, setting this parameter to a value greater
than 0 might make it possible to reduce the time
TLC spends writing to disk on a model with a very large number of reachable states.&nbsp;

Contact us for more information.

<h3>Saving defaults</h3>

Clicking on the "Save as default" button in this section will save this configuration and use
it as the configuration in new models.

<h2><a name="checking">Checking Mode</a></h2>

You can choose between two basic ways of running TLC:

<h3><a  name="model-mode">Model-checking mode</a></h3>
<p>
This is the normal method of running TLC, in which it
essentially tries to check all possible behaviors allowed
by the behavior spec.&nbsp;  Its default method of doing this
is to find the graph of all reachable states using
breadth-first search.&nbsp;  This has the advantage that if
TLC finds a violation of a safety property, then it will
produce a shortest possible behavior that exhibits the
error.&nbsp;  You can direct TLC to use a depth-first search
by choosing the <em>Depth-first</em> option and specifying
the depth of its search.&nbsp;  (Limiting the depth ensures
that only a finite set of states is explored, even if
the complete set of reachable states is infinite.)&nbsp;
With depth-first search, TLC will usually not produce
a shortest-length error trace.&nbsp;  When running in depth-first
mode, TLC does not compute the entire state graph and does not use a state
queue, so it does not produce any
 <i>Diameter</i> or <i>Queue size</i>
 statistics.
</p>
<p>
<b>Warning:</b> Depth-first search is an experimental TLC
option that has not been used much. We don't know
if it offers any advantages.
If you do try it and find it useful, please tell us what you did.
</p>

<p>
You can also specify a <em>View</em> to be used in model-checking
mode.&nbsp;  If you're curious about what that is and how it is used,
see Section 14.3.3 (page 243) of
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em>.
</p>
<h3>Simulation Mode</h3>

<p>
In simulation mode, TLC does not try to examine all reachable states.&nbsp;
Instead, it checks an unending series of behaviors, each of which it constructs by
starting from a randomly choosen initial state and repeatedly making a random
choice of a possible next state.&nbsp;  (In this mode, you  stop TLC by clicking the&nbsp;
<samp>Cancel</samp>&nbsp; button on the dialog that the Toolbox pops up when it
runs TLC.)&nbsp; You specify the maximum length of each behavior that it generates.&nbsp;
If you want to know what specifying the <em>Seed</em> and <em>Aril</em> does,
look them up in
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em>.&nbsp;  When run in simulation mode, the only
statistics TLC reports are for <i>States Found</i>.
</p>

<h2><a name="features">Features</a></h2>


<A name="checkpoint"></A><h3>Checkpoint Recovery</h3></A>

 <p>
TLC takes regular checkpoints, from which it can be restarted if it is
stopped for any reason--for example, if your computer crashes.&nbsp;

The <em>Recover from checkpoint</em> option tells TLC to start from where it
was when the last checkpoint was taken.&nbsp;

This option is enabled if the last time you ran TLC, it ran long enough to
produce a checkpoint.&nbsp; The Toolbox will fill in the <em>Checkpoint
id</em> for you.
 </p>
 <p>
Warning: If you exit the Toolbox, it will stop any executions of TLC that are
in process.&nbsp;

However, it is possible to stop the Toolbox in some drastic fashion that
leaves TLC running as a background process.&nbsp;

Restarting from a checkpoint while the TLC process that created it is still
running can cause the checkpoint to be destroyed, making recovery
impossible.&nbsp;

If you have reason to believe TLC was not stopped, check to see if it is
still running before trying to recover from a checkpoint.
 </p>
 <p>
The checkpoint TLC produces after a short run does not take up
much space.&nbsp;

However, if TLC finds an error after running for a long time, the
checkpoint files could take up a lot of space--sometimes on the order
of a gigabyte for a model that has run for several days.&nbsp;

These files are deleted if the model is re-run and a new checkpoint is
produced, or if the model is validated when the
<em>Recover from checkpoint</em> option is not selected.&nbsp;

When TLC has created a checkpoint, the <em>Features</em> section
of the TLC Options page displays how much storage the checkpoint
occupies.&nbsp;

It also provides a button that you can click to delete the checkpoint.&nbsp;
 </p>

<p>
Checkpointing does not yet work when TLC is run in distributed mode.
</p>

<A name="profiling"></A><h3>Profiling</h3>
<p>TLC supports detailed profiling at the action as well as the expression level.  Profiling helps to identify specification errors such as permanently disabled actions
(compare <i>Enabled</i> predicate in <a href="https://lamport.azurewebsites.net/pubs/lamport-actions.pdf">The Temporal Logic of Actions</a> section 2.7, page 6).
Similarly it helps pinpoint the source of state space explosion by reporting the states found and distinct states on a per action level.
</p>

<p>
In addition to action profiling, invocation and cost profiling allows to diagnose expensive expressions.  Please refer to the
<a href="profiling.html">dedicated profiler documentation</a> for more information.
</p>
<p>
<b>Warning</b>: Profiling negatively impacts model checking performance and should thus be off when checking large models.
</p>

<h3>Visualize state graph after completion</h3>
<p>
Visualize the generated state graph graphically after completion of model checking. The
visualization helps to better understand the system being specified. Initial states are represented by gray vertices.
<p><b>Warning: </b>Can reasonably display only  state graphs with at most around a hundred states.</b></p>
<p>
In order to visualize a state graph, the path to the <em>dot</em> executable of the
<a href="http://www.graphviz.org/">GraphViz</a> project has to be set under <em>Specify dot command</em> on the <em>PDF viewer</em> preference
page on the File/Preferences menu. On macOS dot is most easily installed with the ports system. Homebrew has a Graphviz port too.
On Windows, GraphViz can be obtained through Cygwin or installed standalone. On most Linux derivatives, GraphViz can be installed with the package manager.
After installation, the dot binary can usually be found at:
</p>

<p>
<table>
 <tr>
  <td>OS</td>
  <td>Default path</td>
 </tr>
 <tr>
  <td>Windows (Cygwin)</td>
  <td>C:\cygwin\bin\dot.exe</td>
 <tr>
  <td>Windows (standalone)</td>
  <td>C:\Program Files (x86)\Graphviz2.38\bin\dot.exe</td>
 </tr>
 <tr>
  <td>macOS (ports)</td>
  <td>/opt/local/bin/dot</td>
 </tr>
 <tr>
  <td>Linux</td>
  <td>/usr/bin/dot</td>
 </tr>
<table>
</p>
<p>
On Windows and Linux the state graph will be visualized with either the built-in or standalone PDF viewer
depending on which is selected on the PDF viewer preference page
(selecting a standalone viewer is advised for best results).
</p>



<h2><a name="parameters">Parameters</a></h2>
<h3>Verify temporal properties upon termination only</h3>
<p>
Defer the verification of temporal properties (liveness) to the end of model checking.
<b>This reduces the overall model checking time</b> with the additional side effect that invariant (safety)
violations will always be found first. In other words, check liveness only after the <em>complete</em>
state space has been checked for safety violations.
If unchecked, temporal properties are checked periodically on the <em>incomplete</em>
state graph. Deferring verification of temporal properties is especially useful if it is highly
likely that the model does not violate its temporal properties (e.g. a smaller instance
of the model has successfully been verified for liveness violations).

<h3>Fingerprint seed index</h3>
<p>
TLC saves only 64-bit fingerprints (hashes) of the reachable states that it finds, not the
complete states.&nbsp;  If two different reachable states have the same fingerprint, a situation
called a  <em>collision</em>, TLC may not find all reachable states.&nbsp;
At the
end of a run, TLC prints estimates of how likely it was that a collision occurred.&nbsp;
If you're worried that a collision might have occurred, you can re-run the model with a
different fingerprint function.&nbsp;  The fingerprint seed index specifies which of 64 fingerprint
functions TLC should use.&nbsp; If the two runs produce different numbers of reachable
states, then there was a collision in at least one of the runs.&nbsp;  If not, the probability
that there was a collision in both is the square of the probability that either one had
a collision--a probability that is probably very, very small.&nbsp;  By default, which fingerprint
function to use is chosen randomly.


<h3> Cardinality of largest enumerable set</h3>

If TLC tries to enumerate the elements of a set, it will report an error if the set
contains more than this number of elements.&nbsp;

<h3><A name="jvmargs">JVM arguments</A></h3>

These are the arguments given to the Java Virtual Machine when TLC is run on the model.&nbsp;
Certain parameters for running TLC in
<a href="distributed-mode.html">distributed mode</a> are specified this way.&nbsp;
Only sophisticated users who know what they are doing should specify other JVM arguments.

<h3>TLC command line parameters</h3>

These are options given to TLC when it is run on the model.&nbsp;
A complete list of TLC options can be found in the
 <code>tlatools > src > tlc2 > TLC.java</code>
file in the
  <a href="https://github.com/tlaplus/tlaplus">GitHub repository on
  the web</a>.&nbsp;
An option specified here can override an option otherwise specified by the rest of the model,
which can cause strange things to happen.&nbsp; You should therefore use this
feature with care.


</p>

<!--  I don't know what I'm saving the following for
<h2><a name="how">How to run?</a></h2>
<hr>
<!-- delete rest of line to comment out
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 -->
<!-- delete rest of line to comment out -->
<a href = "creating-model.html">&uarr; Creating a Model</a>
<!-- -->
</hr>

</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/TreeNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// jcg wrote this.
// last revised February 3rd 2000

// Interface to the syntax tree node data structure.

package tla2sany.st;

public interface TreeNode {
  public TreeNode[]             heirs();           // always returns an array, never null
  public String                 getFilename();
  public Location               getLocation();
  public String                 getImage();
  public int                    getKind();
  public boolean                isKind( int k );
  public TreeNode[]             zero();
  public TreeNode[]             one();
  public util.UniqueString      getUS();
  public String[]               getPreComments();  // always returns an array, never null
//  public String[]               getPostComments(); // always returns an array, never null
  public boolean                local();
  public void                   printST(int indentation);
  public String					getHumanReadableImage();
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/ParseErrors.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// jcg wrote this.
// last revised February 1st 2000

package tla2sany.st;

public interface ParseErrors {
  public  ParseError[] errors();
}


<|start_filename|>tlatools/org.lamport.tlatools/src-aj/tlc2/tool/distributed/TLCStatistics.java<|end_filename|>
package tlc2.tool.distributed;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class TLCStatistics {
	
	/**
	 * writes stats to .csv
	 */
	public static void writeStats(TLCServer server, Date processStart,
			Date computationStart, Date computationEnd, Date processEnd) {
		File sFile;
		File wFile;

		// has the user given an output path?
		final String path = System.getProperty(TLCStatistics.class.getName()
				+ ".path");
		if (path != null) {
			sFile = new File(path + File.separator + "server.csv");
			wFile = new File(path + File.separator + "worker.csv");
		} else {
			sFile = new File("server.csv");
			wFile = new File("worker.csv");
		}

		try {
			sFile.createNewFile();
			wFile.createNewFile();

			serverStats(server, sFile, processStart, computationStart, computationEnd, processEnd);
			workerStats(server, wFile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// create server stats .csv file
	private static void workerStats(TLCServer server, File file)
			throws IOException {
		final FileWriter writer = new FileWriter(file);

		// headlines
		writer.write("WorkerName");
		writer.write(",");
		writer.write("StatesReceived");
		writer.write(",");
		writer.write("StatesComputed");
		writer.write("\n");

		// values
		final TLCServerThread[] threads = server.getThreads();
		for (int i = 0; i < threads.length && threads[i] != null; i++) {
			// print worker stats
			int sentStates = threads[i].getSentStates();
			int receivedStates = threads[i].getReceivedStates();
			URI name = threads[i].getUri();

			writer.write(name.toString());
			writer.write(",");
			writer.write(Integer.toString(sentStates));
			writer.write(",");
			writer.write(Integer.toString(receivedStates));
			writer.write("\n");
		}

		writer.close();
	}

	// create server stats .csv file
	private static void serverStats(TLCServer server, File file,
			Date processStartTime, Date computationStart,
			Date computationEnd, Date processEndTime) throws IOException {
		final FileWriter writer = new FileWriter(file);

		// headlines
		writer.write("SpecName");
		writer.write(",");
		writer.write("ConfigName");
		writer.write(",");
		writer.write("NumberFingerprintServer");
		writer.write(",");
		writer.write("NumberWorkers");
		writer.write(",");
		writer.write("NumberCores");
		writer.write(",");
		writer.write("ProcessStartupTime");
		writer.write(",");
		writer.write("ComputationStartupTime");
		writer.write(",");
		writer.write("ComputationEndTime");
		writer.write(",");
		writer.write("ProcessEndTime");
		writer.write(",");
		writer.write("TimePassedDuringComputationInSeconds");
		writer.write(",");
		writer.write("NumberDistinctStates");
		writer.write(",");
		
		// get all rmi method invocations from monitor if any
		final Map<String, Integer> invocations = RMIMethodMonitor.getInvocations();
		for (Iterator<String> iterator = invocations.keySet().iterator(); iterator.hasNext();) {
			final String methodName = (String) iterator.next();
			writer.write(methodName);
			writer.write(",");
		}
		
		// write "end tag"
		writer.write("\n");

		// values
		writer.write(server.getSpecFileName());
		writer.write(",");
		writer.write(server.getConfigFileName());
		writer.write(",");
		writer.write(server.getFPSetManager().numOfServers());
		writer.write(",");
		writer.write(Integer.toString(server.getWorkerCount()));
		writer.write(",");
		
		// print core count by checking how many threads ran on the same node
		Set<String> hosts = new HashSet<String>();
		final TLCServerThread[] threads = server.getThreads();
		for (int i = 0; i < threads.length && threads[i] != null; i++) {
			String host = threads[i].getUri().getHost();
			hosts.add(host);
		}
		int size = hosts.size();
		int workerCount = server.getWorkerCount();
		if (workerCount == 0 || size == 0) {
			writer.write(0);
		} else {
			writer.write(Integer.toString(workerCount / size));
		}
		writer.write(",");
		
		writer.write(processStartTime.toString());
		writer.write(",");
		writer.write(computationStart.toString());
		writer.write(",");
		writer.write(computationEnd.toString());
		writer.write(",");
		writer.write(processEndTime.toString());
		writer.write(",");
		long elapsed = (computationEnd.getTime()
				- computationStart.getTime()) / 1000;
		writer.write(Long.toString(elapsed));
		writer.write(",");
		// NumberDistinctStates
		writer.write(Long.toString(TLCServer.finalNumberOfDistinctStates));
		writer.write(",");

		// write number of invocations
		for (Iterator<Integer> iterator = invocations.values().iterator(); iterator.hasNext();) {
			final Integer amountOfInvocations = (Integer) iterator.next();
			writer.write(Integer.toString(amountOfInvocations));
			writer.write(",");
		}
		
		// write "end tag"
		writer.write("\n");

		// close file
		writer.close();
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/SingleThreadedReadersWriterLock.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.util;


/**
 * A no-op implementation of {@link ReadersWriterLock}, that does not waste time
 * on locking in a single threaded context.
 */
public class SingleThreadedReadersWriterLock extends ReadersWriterLock {

	/* (non-Javadoc)
	 * @see tlc2.util.ReadersWriterLock#BeginRead()
	 */
	@Override
	public void BeginRead() {
	}

	/* (non-Javadoc)
	 * @see tlc2.util.ReadersWriterLock#EndRead()
	 */
	@Override
	public void EndRead() {
	}

	/* (non-Javadoc)
	 * @see tlc2.util.ReadersWriterLock#BeginWrite()
	 */
	@Override
	public void BeginWrite() {
	}

	/* (non-Javadoc)
	 * @see tlc2.util.ReadersWriterLock#EndWrite()
	 */
	@Override
	public void EndWrite() {
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/Defns.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 15:29:55 PST by lamport
//      modified on Sat Jun 30 10:05:29 PDT 2001 by yuanyu

package tlc2.tool;

import java.io.Serializable;

import util.UniqueString;

/**
 * The purpose of this class is to hold definitions.
 * The index of a definition in the array is stored in
 * the UniqueString, that holds the name of the operation.    
 * 
 * 
 * There are two kinds of definitions stored in the table:
 * an OpDefNode or a TLC value. A java override method is
 * stored as a MethodValue.
 * 
 * @author <NAME>, <NAME>
 * @version $Id$
 * 
 */
// SZ 10.04.2009: This class is used only once in {@link Spec}
// class. There exist exactly one instance of it in runtime.
// there is no reason to have any static fields in it. 
public class Defns implements ToolGlobals, Serializable
{
    private int defnIdx;
    private Object[] table;

    /**
     * Constructs the storage of initial size + 32
     */
    // SZ 10.04.2009: changed constructor to accept the initial 
    // value explicit during the object creation
    public Defns(int initialSize)
    {
        this.defnIdx = initialSize;
        this.table = new Object[defnIdx + 32];
    }

    public Defns()
    {
        this.table = new Object[defnIdx + 32];
    }

    Defns(Defns other) {
    	this.defnIdx = other.defnIdx;
    	this.table = new Object[other.table.length];
        System.arraycopy(other.table, 0, this.table, 0, other.table.length);
    }
    
    /**
     * Returns the definition of key if its definition exists.
     * Otherwise, returns null.
     */
    public Object get(UniqueString key)
    {
        int loc = key.getDefnLoc();
        if (loc < 0 || loc >= this.table.length)
        {
            return null;
        }
        return this.table[loc];
    }

    /**
     * Convenience method for {@link Defns#get(UniqueString)} 
     * @param key
     * @return
     */
    public Object get(String key)
    {
        UniqueString var = UniqueString.uniqueStringOf(key);
        return this.get(var);
    }

    /**
     * Store a new definition for key.  If there was an entry in the
     * table for the key, overwrite it.
     */
    public void put(UniqueString key, Object val)
    {
        int loc = key.getDefnLoc();
        if (loc == -1)
        {
            loc = defnIdx++;
            key.setLoc(loc);
        }
        if (loc >= this.table.length)
        {
            int oldSize = this.table.length;
            int newSize = Math.max(2 * oldSize, loc + 1);
            Object[] old = this.table;
            this.table = new Object[newSize];
            // SZ 10.04.2009: changed a for loop of array copy to the 
            // native system copy call
            System.arraycopy(old, 0, this.table, 0, old.length);
        }
        this.table[loc] = val;
    }

    /**
     * Puts an object to the definitions
     * @param key a string representation of the key
     * @param val the object to be stored
     */
    public void put(String key, Object val)
    {
        this.put(UniqueString.uniqueStringOf(key), val);
    }

    public void setDefnCount(int index)
    {
        this.defnIdx = index;
    }
    
    public Defns snapshot() {
    	return new Defns(this);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/WriteTLAFile.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS WriteTLAFile                                                       *
*                                                                          *
* Contains the method Write for writing out a tokenized spec as a TLA      *
* file, deleting the "`^ ... ^'" parts of comments, and replacing "`~",    *
* "~'", "`.", and ".'" by spaces.                                          *
***************************************************************************/
package tla2tex ;

public class WriteTLAFile
 { public static void Write(Token[][] spec , String fileName)
    { OutputFileWriter writer = new OutputFileWriter(fileName) ;
      int line = 0 ;

      boolean deleting = false ;
        /*******************************************************************
        * true if we have processed a line from a multi-line comment with  *
        * a "`^", but have not yet encountered the matching "^'".          *
        *******************************************************************/

      int multiBelow = 0 ;
        /*******************************************************************
        * When, after deleting characters inside a "`^" in a multi-line    *
        * comment, we wind up with nothing but space characters on the     *
        * line, we don't print out that line.  Instead, we print in its    *
        * place the next line of the comment that has something that's     *
        * not deleted.  The value of multiBelow is the number of lines     *
        * below that we have to look for the current line of the comment.  *
        * In other words, when we get to a line of a multi-line comment    *
        * on line ln, we process the comment-line at line ln +             *
        * multiBelow.                                                      *
        *******************************************************************/
        
      while (line < spec.length)
       {String outLine = "" ;
        int item = 0 ;
        boolean nullComment = false ;
          /*****************************************************************
          * True iff produced no output for a multi-line comment line      *
          * because of deletions.                                          *
          *****************************************************************/
        while (item < spec[line].length)
         {Token tok = spec[line][item] ;
          if (item > 0)
           { outLine = 
                outLine + SpacesString(tok.column 
                                        - spec[line][item-1].column 
                                        - spec[line][item-1].getWidth()) ;
           } 
          else
           { outLine = outLine + SpacesString(tok.column);
           } ;
          switch (tok.type)
           {case Token.BUILTIN    : 
            case Token.NUMBER     : 
            case Token.IDENT      : 
            case Token.PCAL_LABEL :
            case Token.DASHES     : 
            case Token.END_MODULE : 
            case Token.PROLOG     : 
            case Token.EPILOG     : 
            case Token.PF_STEP    :
              outLine = outLine + tok.string ;
              break ;
            case Token.STRING : 
              outLine = outLine + "\"" + tok.string + "\"" ;
              break ;

            case Token.COMMENT : 
              /*************************************************************
              * Set ctok to the current comment token we are processing.   *
              *************************************************************/
              CommentToken ctok = (CommentToken) tok ;
              if (ctok.subtype == CommentToken.BEGIN_MULTI)
                /***********************************************************
                * Reset deleting and multiBelow when beginning a           *
                * mult-line comment.                                       *
                ***********************************************************/
                { deleting = false ;
                  multiBelow = 0 ;
                } ;

              String commentString = "" ;
                /***********************************************************
                * Will set commentString to the current comment line       *
                * minus the deleted characters.                            *
                ***********************************************************/
              if (   (ctok.subtype == CommentToken.MULTI)
                  || (ctok.subtype == CommentToken.NULL))
                /***********************************************************
                * Set ctok to the token multiBelow lines below this one,   *
                * following the belowAlign pointers, or null if this       *
                * takes us past the end of the comment--which means we've  *
                * output the entire comment already.                       *
                ***********************************************************/
                { int i = 0 ;
                  while (   (ctok != null)
                         && (i < multiBelow))
                   { Position bpos = ctok.belowAlign;
                     ctok = null ;
                     if (bpos.line != -1)
                      { Token btok = bpos.toToken(spec) ;
                        if (btok.type == Token.COMMENT)
                          { CommentToken bctok = (CommentToken) btok ;
                            if (   (bctok.subtype == CommentToken.MULTI)
                                || (bctok.subtype == CommentToken.NULL))
                              { ctok = bctok ;
                              } ;
                          }
                      } ;
                     i = i+1;
                   }

                  if (ctok != null)
                   { commentString = ctok.string ;
                     if (deleting)
                       { commentString = "`^" + commentString ;}
                     deleting = UnmatchedDelete(commentString) ;
                     commentString = RemoveDeletions(commentString) ;
                     while (    deleting
                            &&  (ctok != null)
                            &&  Misc.isBlank(commentString))
                     { Position bpos = ctok.belowAlign;
                       ctok = null ;
                       if (bpos.line != -1)
                        { Token btok = bpos.toToken(spec) ;
                          if (btok.type == Token.COMMENT)
                          { CommentToken bctok = (CommentToken) btok ;
                              if (   (bctok.subtype == CommentToken.MULTI)
                                  || (bctok.subtype == CommentToken.NULL))
                                { ctok = bctok ;
                                  multiBelow = multiBelow + 1;
                                  commentString = ctok.string ;
                                  deleting = 
                                     UnmatchedDelete("`^" + commentString) ;
                                  commentString = 
                                    RemoveDeletions("`^" + commentString) ;
                                } ;
                          }
                        } ;
                     } // END while ( deleting ... )
                   }  
                 if (   (ctok != null)
                     && Misc.isBlank(commentString))
                   { commentString = SpacesString(ctok.string.length()) ;
                   } ;
                }
              else
                { /*********************************************************
                  * This is not a MULTI or NULL comment token.             *
                  *********************************************************/
                  commentString = RemoveDeletions(ctok.string);
                  commentString = commentString + 
                                   SpacesString(ctok.string.length() - 
                                                commentString.length()) ;
                }

              if (ctok != null)
               {
                commentString = ReplaceQuoteTildes(commentString);
                switch (ctok.rsubtype)
                 {case CommentToken.NORMAL :
                    outLine = outLine + "(*" + commentString + "*)" ;
                    break ;
                  case CommentToken.LINE : 
                    outLine = outLine + "\\*" + commentString ;
                    break ;
                  case CommentToken.BEGIN_OVERRUN : 
                    outLine = outLine + "(*" + commentString ;
                    break ;
                  case CommentToken.END_OVERRUN : 
                    outLine = outLine + commentString + "*)" ;
                    break ;
                  case CommentToken.OVERRUN : 
                    outLine = outLine + commentString ;
                    break ;
                  default :
                    Debug.ReportBug("Bad CommentToken subtype found.");
                 }
               }
              else
               { nullComment = true ;
               } ;
              break ;

            default :
              Debug.ReportBug("Bad token type found.");
            break ;
           }
          item = item + 1;
         };        
        if ( ! (   nullComment
                && (spec[line].length == 1)))
          { writer.putLine(outLine) ; } ;
        line = line + 1;
       }
      writer.close() ;
    }

   private static String SpacesString(int n)
    /***********************************************************************
    * A string of n spaces.                                                *
    ***********************************************************************/
    { int i = 0 ;
      String result = "" ;
      while (i < n)
       { result = result + " ";
         i = i + 1;
       }
      return result;
    }

  private static boolean UnmatchedDelete(String str)
    /***********************************************************************
    * True iff the last "`^" string comes after the last "^'" string.      *
    ***********************************************************************/
    { return (str.lastIndexOf("^'") < str.lastIndexOf("`^")) ;
    }

  private static String RemoveDeletions(String str)
    /***********************************************************************
    * The string obtained by removing everything from each "`^" through    *
    * the next "^'" (if there is one).                                     *
    ***********************************************************************/
    { String rest  = str ;
      String start = "" ;
      int nextDel = rest.indexOf("`^") ;
      while ( nextDel != -1 )
       { start = start + rest.substring(0, nextDel) ;
         rest = rest.substring(nextDel) ;
         int nextEnd = rest.indexOf("^'") ;
         if (nextEnd == -1)
           { nextDel = -1 ;
             rest = "" ; }
         else 
           { rest = rest.substring(nextEnd + 2) ; 
             nextDel = rest.indexOf("`^") ;
           }
       } ;
      return start + rest ;
    }
  private static String ReplaceQuoteTildes(String str)
    /***********************************************************************
    * The string obtained by replacing each "`~", "~'", "`.", and ".'" by  *
    * spaces.                                                              *
    ***********************************************************************/
    { String result = str ;
      int nextRepl = result.indexOf("`~") ;
      while ( nextRepl != -1 )
       { result = result.substring(0, nextRepl) 
                  + "  " + result.substring(nextRepl+2);
         nextRepl = result.indexOf("`~") ;
       } ;
     nextRepl = result.indexOf("~'") ;
      while ( nextRepl != -1 )
       { result = result.substring(0, nextRepl) 
                  + "  " + result.substring(nextRepl+2);
         nextRepl = result.indexOf("~'") ;
       } ;
      nextRepl = result.indexOf("`.") ;
      while ( nextRepl != -1 )
       { result = result.substring(0, nextRepl) 
                  + "  " + result.substring(nextRepl+2);
         nextRepl = result.indexOf("`.") ;
       } ;
     nextRepl = result.indexOf(".'") ;
      while ( nextRepl != -1 )
       { result = result.substring(0, nextRepl) 
                  + "  " + result.substring(nextRepl+2);
         nextRepl = result.indexOf(".'") ;
       } ;
     return result ;
    }
 }  

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/SyntaxTreeNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// jcg wrote this.
// Last modified on Wed  1 July 2009 at 16:30:00 PST by lamport
// last revised February 1st 2000

/***************************************************************************
* I think that the following comment is obsolete because the offending     *
* variable (lastSN) was eliminated when post-comments were eliminated.     *
***************************************************************************/
// XXX Watch out !!!
// This code uses a static variable to hold the last SyntaxTreeNode 
// previously generated from a Token. This is necessary to properly attach 
// the comments, but unfortunately makes the code non-reentrant.
//
// Removing this variable would require modifying the signature of 
// constructors which are extensively used, or possibly use a trick to 
// memorize these pointers for each thread.
 
package tla2sany.parser;

import tla2sany.semantic.ASTConstants;
import tla2sany.st.Location;
import tla2sany.st.SyntaxTreeConstants;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import util.UniqueString;

// The SyntaxTreeNode is the node of the syntax tree. It holds key 
// information from the tokens (string, position). Heirs are held in two 
// arrays. This is a trick to facilitate construction, and also to test 
// for the presence of the LOCAL token more easily.

// all strings are resolved internally to UniqueString.

/* methods
 * various constructors
 * kind manipulation : getKind, setKind, isKind
 * heirs()
 * getLocation()
 * getFileName, and US version.
 * possibly other methods to facilitate the semantic analysis.
 */

public class SyntaxTreeNode implements TreeNode, SyntaxTreeConstants, 
             ASTConstants {

  private static SyntaxTreeNode[] nullArray   = new SyntaxTreeNode[0];
  protected SyntaxTreeNode[]      zero, one;
    /***********************************************************************
    * The arrays `zero' and `one' describe the sequence of heirs, which    *
    * equals                                                               *
    *                                                                      *
    *   [i \in 1..zero.length |-> zero[i]]                                 *
    *        \o [i \in 1..one.length |-> one[i]]                           *
    *                                                                      *
    * Why there are two different arrays and how they are used is, of      *
    * course, completely undocumented.  The use I've found so far is:      *
    *                                                                      *
    *    For an N_OperatorDefinition, N_FunctionDefinition,                *
    *    N_ModuleDefinition, or N_Instance node, the optional "LOCAL"      *
    *    token is placed in the zero field (which is thus null if          *
    *    there is no "LOCAL" token, and the rest of the heirs are in       *
    *    the one field.                                                    *
    ***********************************************************************/
  int                             kind        = 0;
    /***********************************************************************
    * The type/kind of node.  The list of all kinds of non-terminal nodes  *
    * is in st/SyntaxTreeConstants.java.  If this is a terminal/token      *
    * node, formed from a token t, then `kind' seems to equal t.kind.      *
    * The list of all token kinds is in                                    *
    * parser/TLAplusParserConstants.java.  (That list begins with          *
    * "int EOF = 0" and ends with "int ProofStepLexeme = 222".)  Another   *
    * (currently incomplete) list is in documentation/token-kinds.txt.     *
    ***********************************************************************/
  public UniqueString             image       = null;
    /***********************************************************************
    * For a token node formed from a Token t, this equals t.image.  For a  *
    * non-terminal node, it is the name of the node type.                  *
    ***********************************************************************/

  public UniqueString             originalImage  = null;
    /***********************************************************************
    * This is a hack for dealing with step numbers of the form <*>...      *
    * and <+>...  .  For those step numbers, originalImage is the actual   *
    * image, while image is the UniqueString of the string obtained by     *
    * substituting the correct level number for the "*" or "+".            *
    *                                                                      *
    * This may result in strange error messages if the modified image is   *
    * printed instead of the originalImage.  If that turns out to be a     *
    * problem, Perhaps the error message generator can be changed to print *
    * originalImage if it's not null.                                      *
    *                                                                      *
    * (Added by LL 13 Oct 2007.)                                           *
    ***********************************************************************/

  int []                          location    = new int[4];
    /***********************************************************************
    *    location[0] = beginning line number                               *
    *    location[1] = beginning column number                             *
    *    location[2] = beginning line number                               *
    *    location[3] = beginning column number                             *
    *                                                                      *
    * If the node contains a single token t, then these are the four       *
    * values t.beginLine, t.beginColumn, t.endLine, and t.endColumn.  The  *
    * comments in parser/Token.java say that these "describe" the          *
    * positions of the first and last characters of the token, but they    *
    * don't say how they describe those positions.  (Since they're of      *
    * type int, we can at least assume that the descriptions are not in    *
    * English prose.)                                                      *
    *                                                                      *
    * For a node containing multiple tokens, it appears that under the     *
    * usual lexicographical ordering of pairs, <<location[0],              *
    * location[1]>> is the min of the values <<beginLine, beginColumn>>    *
    * of its tokens and that <<location[2], location[3]>> is the max of    *
    * the values <<endLine, endColumn>> of its tokens.                     *
    ***********************************************************************/
    
  private UniqueString            fileName    = null;
    /***********************************************************************
    * fileName seems to be the name of the module containing this node.    *
    ***********************************************************************/
  private static final String []  ns          = new String[0];
    /***********************************************************************
    * This just seemed to be a constant, so it was changed to a static     *
    * final field by LL on 21 Aug 2007.                                    *
    ***********************************************************************/
  private String []               preComment  = ns;
    /***********************************************************************
    * This is an array of length 0 unless this is a token node, in which   *
    * case it is the sequence of comments that immediately precede the     *
    * token in the input stream.                                           *
    ***********************************************************************/

//  private static SyntaxTreeNode   lastSN      = null;
    /***********************************************************************
    * In the original TLA+1 syntax, there were two kinds of comments:      *
    * pre-comments began "(*." or "\*." and post-comments didn't.          *
    * Pre-comments were attached to the following token node and           *
    * post-comments were attached to the previous token node.  This        *
    * distinction was eliminated in TLA+2, in which all comments are       *
    * pre-comments.                                                        *
    *                                                                      *
    * The field lastSN seems to be the static variable warned about in     *
    * the comments near the beginning of the file.  It was apparently set  *
    * equal to the last "token" node (node consisting of a single token)   *
    * that was created.  When a post-comment was discovered (attached by   *
    * javacc to the next token), lastSN.postComment was set to that        *
    * post-comment.                                                        *
    ***********************************************************************/

  public static SyntaxTreeNode nullSTN =
    new SyntaxTreeNode( UniqueString.uniqueStringOf("***I do not exist***") );

  public SyntaxTreeNode() {
    zero = nullArray; one = nullArray;
  }

  public SyntaxTreeNode( UniqueString fn ) {
    kind = 0; 
    image = fn;
    zero = nullArray;
    one = nullArray;
    location[0] = 0; location[1] = 0; location[2] = 0; location[3] = 0;
    fileName = UniqueString.uniqueStringOf("--TLA+ BUILTINS--");
  }


  public SyntaxTreeNode(UniqueString fn, Token t) {
    this.kind = t.kind; 
    this.image = UniqueString.uniqueStringOf( t.image );
    zero = nullArray; 
    one = nullArray;
    location[0] = t.beginLine;
    location[1] = t.beginColumn;
    location[2] = t.endLine;
    location[3] = t.endColumn;
    fileName = fn;
    preComment = comments( t );
  }


  public SyntaxTreeNode(UniqueString fn, int kind, Token t) {
    this.kind = kind;
//  this.image = SyntaxNodeImage[ kind ];
    /***********************************************************************
    * I have no idea why this was commented out, or by whom.               *
    ***********************************************************************/
    this.image = UniqueString.uniqueStringOf( t.image );
    zero = nullArray;
    one = nullArray;
    location[0] = t.beginLine;
    location[1] = t.beginColumn;
    location[2] = t.endLine;
    location[3] = t.endColumn;
    fileName = fn;
    preComment = comments( t );
  }


  public SyntaxTreeNode(UniqueString fn, int kind, SyntaxTreeNode a[]) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    zero = a;
    fileName = fn;
    updateLocation();
  }


  public SyntaxTreeNode( int kind, SyntaxTreeNode a[]) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    zero = a;
    fileName = a[0].fileName;
    updateLocation();
  }

  // This constructor used only in Generator class for handling @  in 
  // EXCEPT construct
  public SyntaxTreeNode( int kind, SyntaxTreeNode a[], boolean ignored) {
    this.kind = kind;
    zero = a;
  }


  public SyntaxTreeNode(UniqueString fn, int kind, SyntaxTreeNode a, 
                        SyntaxTreeNode b[]) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    if (a != null) {
      zero = new SyntaxTreeNode[1]; 
      zero[0] = a;
    }
    one = b;
    fileName = fn;
    updateLocation();
  }


  public SyntaxTreeNode(UniqueString fn, int kind, SyntaxTreeNode a[], 
                        SyntaxTreeNode b[]) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    zero = a;
    one = b;
    fileName = fn;
    updateLocation();
  }


  public SyntaxTreeNode(int kind, SyntaxTreeNode a, SyntaxTreeNode b) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    fileName = a.fileName;
    zero = new SyntaxTreeNode[2];
    zero[0] = a;
    zero[1] = b;
    updateLocation();
  }


  public SyntaxTreeNode(int kind, SyntaxTreeNode a, SyntaxTreeNode b, 
                        SyntaxTreeNode c) {
    this.kind = kind;
    image = SyntaxNodeImage[ kind ];
    fileName = a.fileName;
    zero = new SyntaxTreeNode[3];
    zero[0] = a; 
    zero[1] = b;
    zero[2] = c;
    updateLocation();
  }


  public final int       getKind()         { return kind; }


         final void      setKind( int k )  { kind = k ; }


  public final boolean   isKind( int k )   { return kind == k; }


  public final String [] getPreComments()  { return preComment; }

   /***********************************************************************
   * For a token node, returns its pre-comments.  Otherwise, it returns   *
   * the pre-comments attached to the first token-node descendant of      *
   * this node.                                                           *
   ***********************************************************************/
  public final String [] getAttachedComments() {
    if (this.kind < SyntaxTreeConstants.NULL_ID) { return preComment; } ;
    if (this.heirs().length == 0) {
        String[] res = new String[0] ;
     /** 
      * On 3 Jul 2009 LL replaced the following code with this.  It
      * appears that this method was never used until printing of 
      * comments in debug mode was added in Jul 2009.
      */
//      String[] res = new String[1] ;
//      res[0] = "No left-most token node???" ;
      return res ; } ;
    return ((SyntaxTreeNode) this.heirs()[0]).getAttachedComments() ;
   }

  public boolean isGenOp() {
    if ( kind == N_GenPrefixOp || kind == N_GenNonExpPrefixOp || 
         kind == N_GenInfixOp || kind == N_GenPostfixOp )
       return true;
    else
      return false;
  }


  private static Token nullToken = new Token();


  private final String[] comments( Token t ) {
     Token nextPre  = nullToken;
     int cPre = 0;

     if (t.specialToken == null) {
       return ns; } ;

     Token tmp_t = t.specialToken;
     while (tmp_t != null) {
         cPre++;
         tmp_t.next = nextPre;
         nextPre = tmp_t;
         tmp_t = tmp_t.specialToken; } ;

     String []aPre = new String[ cPre ];
     tmp_t = nextPre; 
     cPre = 0;
     while (tmp_t != nullToken) { 
       aPre[ cPre ] = tmp_t.image; 
       cPre++; 
       tmp_t = tmp_t.next; } ; 
     return aPre;
  }

  /**
   * Through some piece of stupidity whose origin is lost to history,
   * the heirs() method declares its return value type to be
   * TreeNode[].  This results in a lot of needless type casting, 
   * since the only class that implements the TreeNode interface
   * seems to be SyntaxTreeNode.  Eclipse doesn't seem to be able
   * to find the errors that are caused by simply changing the
   * return type of heirs() to SyntaxTreeNode[]; it just finds errors
   * when it runs ant.  So, LL added this method, which is line-for-line
   * identical to heirs() except for the declaration of the return type.
   */
  public final SyntaxTreeNode[] getHeirs() {
    if ( zero == null && one == null ) {
      return nullArray;
    } else {
      SyntaxTreeNode result[];
      if ( zero != null ) {
        if ( one != null ) {
          result = new SyntaxTreeNode[ zero.length + one.length ];
          System.arraycopy(zero, 0, result, 0, zero.length);
          System.arraycopy(one, 0, result, zero.length, one.length);
        } else {
          result = new SyntaxTreeNode[ zero.length ];
          System.arraycopy(zero, 0, result, 0, zero.length);
        }
      } else {
        result = new SyntaxTreeNode[ one.length ];
        System.arraycopy(one, 0, result, 0, one.length);
      }
      return result;
    }
  }
  
  public final TreeNode[] heirs() {
    if ( zero == null && one == null ) {
      return nullArray;
    } else {
      SyntaxTreeNode result[];
      if ( zero != null ) {
        if ( one != null ) {
          result = new SyntaxTreeNode[ zero.length + one.length ];
          System.arraycopy(zero, 0, result, 0, zero.length);
          System.arraycopy(one, 0, result, zero.length, one.length);
        } else {
          result = new SyntaxTreeNode[ zero.length ];
          System.arraycopy(zero, 0, result, 0, zero.length);
        }
      } else {
        result = new SyntaxTreeNode[ one.length ];
        System.arraycopy(one, 0, result, 0, one.length);
      }
      return result;
    }
  }
  

  public final String         getFilename() {return fileName.toString(); }

  public final UniqueString   getFN() { return fileName; }

  public final Location       getLocation( ) {
    return new Location( fileName, location[0], location[1], location[2], 
                         location[3] );
   }

  public final String         getImage() { return image.toString(); }

  public final UniqueString   getUS() { return image; }

  public final SyntaxTreeNode first() {
    //System.out.println( image);
    if (zero != null) return zero[0]; else return one[0]; 
  }
  
	public String getHumanReadableImage() {
		if (zero != null && zero.length > 0) {
			final StringBuffer buf = new StringBuffer(zero.length);
			for (SyntaxTreeNode z : zero) {
				buf.append(z.getHumanReadableImage());
			}
			if (one != null && one.length > 0) {
				for (SyntaxTreeNode o : one) {
					buf.append(o.getHumanReadableImage());
				}
			}
			return buf.toString();
		} else {
			final String string = image.toString();
			// See SyntaxTreeNodeConstants. The strings below are the ones with
			// which non-human-readable images start.
			if (string.startsWith("N_")) {
				return "";
			}
			if (string.startsWith("Not a node")) {
				return "";
			}
			if (string.startsWith("Token")) {
				return "";
			}
			return string;
		}
	}
  
  /******************
 * Bogus old version
 */
//  private void updateLocation() {
//    int lvi = 0;
//    location[0] = java.lang.Integer.MAX_VALUE;
//    location[1] = java.lang.Integer.MAX_VALUE;
//    location[2] = java.lang.Integer.MIN_VALUE;
//    location[3] = java.lang.Integer.MIN_VALUE;
//
//    if ( zero != null) {
//      for ( lvi = 0; lvi < zero.length; lvi++ ) {
//        if ( zero[lvi].location[0] != java.lang.Integer.MAX_VALUE ) {
//          location[0] = Math.min ( location[0], zero[lvi].location[0] );
//          if ( location[0] == zero[lvi].location[0] )
//            location[1] = Math.min ( location[1], zero[lvi].location[1]) ;
//          location[2] = Math.max ( location[2], zero[lvi].location[2]);
//          if ( location[2] == zero[lvi].location[2] )
//            location[3] = Math.max ( location[3], zero[lvi].location[3]);
//        }
//      }
//    }
//
//    if ( one != null) {
//      for ( lvi=0; lvi < one.length; lvi++ ) {
//        if ( one[lvi].location[0] != java.lang.Integer.MAX_VALUE ) {
//          location[0] = Math.min ( location[0], one[lvi].location[0] );
//          if ( location[0] == one[lvi].location[0] )
//            location[1] = Math.min ( location[1], one[lvi].location[1]) ;
//          location[2] = Math.max ( location[2], one[lvi].location[2]);
//          if ( location[2] == one[lvi].location[2] )
//            location[3] = Math.max ( location[3], one[lvi].location[3]);
//        }
//      }
//    }
//  }

  /**
   * updateLocation() computes the location field from the location fields
   * of the heirs (descendants).  This would seem to be a matter of just
   * copying the location fields of the first and last heirs, in the 
   * obvious way.  However, there seem to be some nodes with no heirs
   * that have their locations set to
   *  
   *   (java.lang.Integer.MAX_VALUE, ...MAX_VALUE, ...MIN_VALUE, ...MIN_VALUE)
   * 
   * The only ones I've found are N_IdPrefix nodes, which don't have any
   * corresponding tokens in the module.  Instead of being efficient and
   * looking for the first and last heirs that have a real location, we
   * write a simple loop that works regardless of how the heirs are
   * ordered.   LL 26 Nov 2009
   */
  private void updateLocation() {
      int lvi = 0;
      location[0] = java.lang.Integer.MAX_VALUE;
      location[1] = java.lang.Integer.MAX_VALUE;
      location[2] = java.lang.Integer.MIN_VALUE;
      location[3] = java.lang.Integer.MIN_VALUE;
      
      if ( zero != null) {
        for ( lvi = 0; lvi < zero.length; lvi++ ) {

            if ( (zero[lvi].location[0] < location[0] )
                  || (zero[lvi].location[0] == location[0] && zero[lvi].location[1] < location[1])) {
            location[0] = zero[lvi].location[0] ;
            location[1] = zero[lvi].location[1] ;
           }
          if ( (zero[lvi].location[2] > location[2] )
                  || (zero[lvi].location[2] == location[2] && zero[lvi].location[3] > location[3])) {
            location[2] = zero[lvi].location[2] ;
            location[3] = zero[lvi].location[3] ;
           }
        }
      }

      if ( one != null) {
          for ( lvi = 0; lvi < one.length; lvi++ ) {
              if ( (one[lvi].location[0] < location[0] )
                      || (one[lvi].location[0] == location[0] && one[lvi].location[1] < location[1])) {
                location[0] = one[lvi].location[0] ;
                location[1] = one[lvi].location[1] ;
               }
              if ( (one[lvi].location[2] > location[2] )
                      || (one[lvi].location[2] == location[2] && one[lvi].location[3] > location[3])) {
                location[2] = one[lvi].location[2] ;
                location[3] = one[lvi].location[3] ;
               }
            }
      }
    }


  public final tla2sany.st.TreeNode[] one() { return one; }

  public final tla2sany.st.TreeNode[] zero() { return zero; }

  /*************************************************************************
  * Aha! This seems to prove that whenever a node may start with "LOCAL",  *
  * the "LOCAL" token is put in the array zero and the rest of the tokens  *
  * are put in the array one.                                              *
  *************************************************************************/
  public final boolean local() { return zero!= null; }

  public void printST(int indentLevel) {

    String      operator = "";
    TreeNode [] heirs    = this.heirs();

    if (image != null && image.toString().equals("N_OperatorDefinition")) {
       if (((SyntaxTreeNode)(heirs()[0])).image.toString().equals(
                                              "N_IdentLHS")) {
          operator = "*" + ((SyntaxTreeNode)(((SyntaxTreeNode)(
                              heirs()[0])).heirs()[0])).image.toString();
       }
       if (((SyntaxTreeNode)(heirs()[1])).image.toString().equals(
                                                    "N_IdentLHS")) {
          operator = ((SyntaxTreeNode)(((SyntaxTreeNode)(
                              heirs()[1])).heirs()[0])).image.toString();
       }
       if (((SyntaxTreeNode)(heirs()[0])).image.toString().equals(
                                                    "N_InfixLHS")) {
          operator = ((SyntaxTreeNode)(((SyntaxTreeNode)(
                            heirs()[0])).heirs()[1])).image.toString();
       }
    }

    for (int i = 0; i < indentLevel; i++) System.out.print(Strings.blanks[2]);
    
    System.out.print((image == null ? "(" + SyntaxNodeImage[kind].toString() 
         + ")" : image.toString()) 
         + "\t" + (!operator.equals("") ? operator + "\t" : "")
         + "  #heirs: " + heirs.length + "\t"
         + "  kind:   " + kind + PreCommentToString(preComment) + "\n"      
                  // Printing of preComment added by LL on 2 Jul 2009
    );

    for (int i=0; i<heirs.length; i++) {
      if (heirs[i] != null)
        ((SyntaxTreeNode)heirs[i]).printST(indentLevel+1);  
                // Indent 1 more level
      else {
        for (int j = 0; j <= indentLevel; j++) {
            System.out.print(Strings.blanks[2]);} ;
        System.out.println("<null>");
      } // end else
    } // end for
    
  } // end method
 
  public static String PreCommentToString(String[] pcarray) {
    if (pcarray == null || pcarray.length == 0) {return "";};
    String res = "\n preComment: ";
    for (int i = 0; i < pcarray.length; i++) {
      res = res +  ((i==0)?"":"\n             ") + i + " " + pcarray[i];
    };
    return res ;
  }
  }


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/DummyBucketStatistics.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util.statistics;

import java.util.NavigableMap;
import java.util.TreeMap;

/**
 * Doesn't really do a thing. Can be instantiated multiple times contrary to
 * BucketStatistics which registers itself via JMX.
 */
public class DummyBucketStatistics implements IBucketStatistics {

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#addSample(int)
	 */
	public void addSample(int amount) {
		// ignore
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getObservations()
	 */
	public long getObservations() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getMedian()
	 */
	public int getMedian() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getMean()
	 */
	public double getMean() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getMin()
	 */
	public int getMin() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getMax()
	 */
	public int getMax() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getStdDev()
	 */
	public double getStdDev() {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getPercentile(double)
	 */
	public double getPercentile(double quantile) {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getSamples()
	 */
	public NavigableMap<Integer, Long> getSamples() {
		return new TreeMap<Integer, Long>();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#addSamples(tlc2.util.statistics.IBucketStatistics)
	 */
	public void addSamples(IBucketStatistics stat) {
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/util/ProverHelper.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.prover.job.ITLAPMOptions;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob.ProverJobMatcher;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.tool.prover.ui.dialog.TLAPMErrorDialog;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ColorPredicate;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ErrorMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ObligationStatus;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ObligationStatusMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.StepStatusMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.StepTuple;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.WarningMessage;
import org.lamport.tla.toolbox.tool.prover.ui.preference.MainProverPreferencePage;
import org.lamport.tla.toolbox.tool.prover.ui.view.ObligationsView;
import org.lamport.tla.toolbox.ui.dialog.InformationDialog;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.LegacyFileDocumentProvider;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2sany.semantic.LeafProofNode;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.NonLeafProofNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.ProofNode;
import tla2sany.semantic.TheoremNode;
import tla2sany.semantic.UseOrHideNode;
import tla2sany.st.Location;
import util.UniqueString;

/**
 * Helper methods for the launching of the prover.
 * 
 * @author <NAME>
 *
 */
public class ProverHelper
{

    /*********************************************************************
     * Obligation marker and marker attribute constants.                 *
     *********************************************************************/
    /**
     * Type of a marker that contains information about an obligation. 
     */
    public static final String OBLIGATION_MARKER = "org.lamport.tla.toolbox.tool.prover.obligation";
    /**
     * Attribute on an obligation marker giving the integer id of the obligation.
     */
    public static final String OBLIGATION_ID = "org.lamport.tla.toolbox.tool.prover.obId";
    // /**
    // * Attribute on an obligation marker giving the formatted String of the obligation.
    // */
    // public static final String OBLIGATION_STRING = "org.lamport.tla.toolbox.tool.prover.obString";
    // /**
    // * Attribute on an obligation marker giving the current state of the obligation. This is
    // * an int corresponding to a state. Obligation states are explained in {@link ColorPredicate}.
    // */
    // public static final String OBLIGATION_STATE = "org.lamport.tla.toolbox.tool.prover.obState";
    // /**
    // * String attribute on an obligation marker giving the location of the obligation as reported by
    // * tlapm. Note that this location is not necessarily the same as the markers current location
    // * in the editor, nor is it necessarily the same location as reported by the markers
    // * {@link IMarker#CHAR_END} and {@link IMarker#CHAR_START} attributes. These attributes are
    // * somewhat "sticky". They can change with some user editing.
    // *
    // * The string value should be set from a {@link Location}
    // * using {@link #locToString(Location)}. The {@link Location} object
    // * can be retreived using {@link #stringToLoc(String)}.
    // */
    // public static final String OBLIGATION_LOCATION = "org.lamport.tla.toolbox.tool.prover.obLoc";

    /******************************************************************************
     * SANY marker and marker attribute constants.                                *
     ******************************************************************************/
    /**
     * Type of marker that contains SANY information about a proof step.
     * In particular, it contains the location of the proof step as reported
     * by SANY when the prover was last launched for a step status update.
     * This location may not be the same as the marker's location
     * because the marker is sticky and the module may have been edited since
     * the prover was last launch for a status check.
     */
    public static final String SANY_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.sanyMarker";
    /**
     * String attribute on a SANY marker giving the location of the proof
     * step the last time the prover was launched for a proof step
     * status check. The string value should be set from a {@link Location}
     * using {@link #locToString(Location)}. This location
     * is the beginning of the step to the end of the statement
     * of the step.
     */
    public static final String SANY_LOC_ATR = "org.lamport.tla.toolbox.tool.prover.ui.sanyLoc";
    /**
     * Boolean attribute on a SANY marker that should be true iff the step is
     * a step with no children or with only a leaf proof.
     */
    public static final String SANY_IS_LEAF_ATR = "org.lamport.tla.toolbox.tool.prover.ui.isLeafStep";

    /**
     * Delimiter used for representing
     * locations as strings.
     */
    public static final String LOC_DELIM = ":";

    /******************************************************************************
     * Obligation string status constants as returned by the TLAPM                *
     ******************************************************************************/
    /**
     * Obligation status that occurs when
     * zenon or isabelle "takes time" to prove an obligation.
     */
    public static final String BEING_PROVED = "being proved";
    /**
     * Obligation status indicating that the obligation
     * has been proved by the value of the "prover" field.
     */
    public static final String PROVED = "proved";
    /**
     * Obligation status indicating that proving the obligation
     * has failed.
     */
    public static final String FAILED = "failed";
    /**
     * Obligation status indicating that the obligation
     * is considered trivial.
     */
    public static final String TRIVIAL = "trivial";
    // /**
    // * Obligation status indicating that the obligation
    // * has been skipped by the value of the "meth" field.
    // */
    // public static final String SKIPPED = "skipped";
    // /**
    // * Obligation status indicating that the obligation
    // * has been checked.
    // */
    // public static final String CHECKED = "checked";
    // /**
    // * Obligation status indicating that the checking
    // * has failed on the obligation.
    // */
    // public static final String CHECKING_FAILED = "checking failed";
    // /**
    // * Obligation status indicating that checking an obligation
    // * was interrupted.
    // */
    // public static final String CHECKING_INTERUPTED = "checking interrupted";
    /**
     * Obligation status indicating that proving the obligation
     * was interrupted.
     */
    public static final String INTERUPTED = "interrupted";
    // /**
    // * Obligation status indicating that the obligation
    // * has been proved in a prior run of the prover.
    // */
    // public static final String PROVED_ALREADY = "proved (already processed)";
    // /**
    // * Obligation status indicating that the obligation
    // * was determined to be trivial in a prior run of the prover.
    // */
    // public static final String TRIVIAL_ALREADY = "trivial (already processed)";
    // /**
    // * Obligation status indicating that proving the obligation
    // * failed in a prior run of the prover.
    // */
    // public static final String FAILED_ALREADY = "failed (already processed)";
    // /**
    // * Obligation status indicating that the obligation
    // * has been checked in a prior run of the prover.
    // */
    // public static final String CHECKED_ALREADY = "checked (already processed)";
    /**
     * Obligation status indicating that the obligation
     * has not yet been sent anywhere to be proved.
     */
    public static final String TO_BE_PROVED = "to be proved";

    /***********************************************************************************
     * Step status marker types.                                                       *
     ***********************************************************************************/
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#PROVING_FAILED} for non-leaf
     * steps (steps with children).
     */
    public static final String STEP_PROVING_FAILED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepProvingFailed";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#CHECKING_FAILED}
     */
    public static final String STEP_CHECKING_FAILED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepCheckingFailed";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#MISSING_PROOFS}
     */
    public static final String STEP_MISSING_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepMissing";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#OMITTED}
     */
    public static final String STEP_OMITTED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepOmitted";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#CHECKED}
     */
    public static final String STEP_CHECKED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepChecked";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#PROVED}
     */
    public static final String STEP_PROVED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepProved";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#BEING_PROVED}.
     */
    public static final String STEP_BEING_PROVED_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.stepBeingProved";
    /**
     * Marker type corresponding to the status {@link StepStatusMessage#PROVING_FAILED} for leaf
     * steps (steps with a leaf proof or with no children.
     */
    public static final String STEP_LEAF_FAILED = "org.lamport.tla.toolbox.tool.prover.ui.leafFailed";
    /**
     * Super type for the following four marker types for step status.
     */
    public static final String STEP_STATUS_MARKER = "org.lamport.tla.toolbox.tool.prover.ui.proofStepStatus";

    /**************************************************************************************
     * Step status integers. Used for easy computation of max status.                     *
     **************************************************************************************/
    public static final int STEP_CHECKED_INT = 0;
    public static final int STEP_PROVED_INT = 1;
    public static final int STEP_TO_BE_PROVED_INT = 2;
    public static final int STEP_BEING_PROVED_INT = 3;
    public static final int STEP_PROOF_OMITTED_INT = 4;
    public static final int STEP_PROOF_MISSING_INT = 5;
    public static final int STEP_PROVING_FAILED_INT = 6;
    public static final int STEP_CHECKING_FAILED_INT = 100;
    public static final int STEP_UNKNOWN_INT = -1;

    /**
     * Removes all markers indicating obligation information on  a resource. Does
     * nothing if the resource does not exist. It deletes these markers only at one level
     * under the resource. That is, if the resource is a directory, it deletes markers
     * on its children.
     * 
     * @param resource
     * @throws CoreException 
     */
    public static void clearObligationMarkers(IResource resource) throws CoreException
    {
        if (resource.exists())
        {
            /*
             * Obligation markers should only be on files directly in the project folder, so we
             * only need to delete markers to depth one. Depth infinite would search any
             * checkpoint folders, which can be slow if there are many files.
             */
            resource.deleteMarkers(OBLIGATION_MARKER, false, IResource.DEPTH_ONE);
        }
    }

    /**
     * Returns true iff the status represents
     * an obligation that is in an "interesting" state.
     * 
     * An obligation is interesting if
     * 
     * \/ At least one backend is trying to prove it.
     * \/ /\ No backends have succeeded.
     *    /\ \/ At least one backend has failed.
     *       \/ At least one backend has been stopped.
     * 
     * @param marker
     * @return
     * @throws CoreException 
     */
    public static boolean isInterestingObligation(ObligationStatus status)
    {
        int obState = status.getObligationState();
        String[] proverStatuses = ColorPredicate.proverStatuses(obState);

        // will be set to true if at least one backend has succeeded
        boolean oneSucceeded = false;
        // will be set to true if at least one backend has failed
        boolean oneFailed = false;
        // will be set to true if at least one backend has been stopped
        boolean oneStopped = false;

        for (int i = 0; i < proverStatuses.length; i++)
        {
            if (proverStatuses[i].equals(ColorPredicate.PROVING_STATUS))
            {
                // At least one backend is trying to prove it.
                return true;
            } else if (proverStatuses[i].equals(ColorPredicate.FAILED_STATUS))
            {
                oneFailed = true;
            } else if (proverStatuses[i].equals(ColorPredicate.STOPPED_STATUS))
            {
                oneStopped = true;
            } else if (proverStatuses[i].equals(ColorPredicate.PROVED_STATUS))
            {
                oneSucceeded = true;
            }
        }

        /*
         * The condition "At least one backend is trying to prove it." is false.
         * Return the value of
         * 
         * /\ No backends have succeeded.
         * /\ \/ At least one backend has failed.
         *    \/ At least one backend has been stopped.
         */
        return !oneSucceeded && (oneFailed || oneStopped);

    }

    /**
     * Returns true iff the status represents
     * an obligation that is currently being proved.
     * 
     * @param status the current obligation status
     * @return
     * @throws CoreException 
     */
    public static boolean isBeingProvedObligation(ObligationStatus status)
    {
        int obState = status.getObligationState();
        String[] proverStatuses = ColorPredicate.proverStatuses(obState);
        for (int i = 0; i < proverStatuses.length; i++)
        {
            if (proverStatuses[i].equals(ColorPredicate.PROVING_STATUS))
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns true iff the marker represents an obligation that is
     * finished being processed in any way (proving or checking).
     * 
     * The proverJob gives information about the parameters used to launch
     * the prover.
     * 
     * @param message
     * @param proverJob
     * @return
     * @throws CoreException 
     */
    public static boolean isObligationFinished(ObligationStatusMessage message, ProverJob proverJob)
    {

        String status = message.getStatus();

        boolean isTrivial = status.equals(TRIVIAL);

        return isTrivial || status.equals(PROVED);

    }

    /**
     * Returns all {@link IMarker} of type {@link ProverHelper#OBLIGATION_MARKER}
     * for the currently opened spec. These markers contain information about obligations.
     * 
     * If there is no spec currently open in the toolbox, this returns null.
     * 
     * @return
     * @throws CoreException 
     */
    public static IMarker[] getObMarkersCurSpec() throws CoreException
    {

        if (ToolboxHandle.getCurrentSpec() != null)
        {
            return ToolboxHandle.getCurrentSpec().getProject().findMarkers(OBLIGATION_MARKER, false,
                    IResource.DEPTH_ONE);
        }

        return null;

    }

    /**
     * Returns the {@link Collection} of {@link ObligationStatus}s
     * from the most recent run of the prover if the most recent run
     * of the prover is on the current spec. Returns null if the
     * prover has not yet been launched during this instance of the
     * toolbox or if the most recent run of the prover is not
     * on the current spec.
     * 
     * @return
     */
    public static ObligationStatus[] getObligationStatuses()
    {
        if (ProverJob.getLastJob() == null)
        {
            return null;
        }
        ProverJob lastJob = ProverJob.getLastJob();
        if (ToolboxHandle.getCurrentSpec() == null
                || !lastJob.getModule().getProject().equals(ToolboxHandle.getCurrentSpec().getProject()))
        {
            // most recent prover job not from the current spec
            return null;
        }
        Collection<ObligationStatus> statuses = lastJob.getObsMap().values();
        return (ObligationStatus[]) statuses.toArray(new ObligationStatus[statuses.size()]);
    }

    /**
     * Removes all SANY step markers on the module.
     * See {@link ProverHelper#SANY_MARKER} for a description of
     * these markers.
     * 
     * @param module
     * @throws CoreException 
     */
    public static void removeSANYStepMarkers(IResource module) throws CoreException
    {
        module.deleteMarkers(SANY_MARKER, false, IResource.DEPTH_ZERO);
    }

    /**
     * This method prepares the module for the launch of the prover.
     * In the following, levelNode is the levelNode in proverJob.
     * If levelNode or module, it prints debugging info and returns.
     * If not, it takes the following steps:
     * 
     * 1.) Call {@link #removeSANYStepMarkers(IResource)} on the module.
     * 2.) If level node is not an instance of {@link ModuleNode},
     *     call {@link #removeStatusFromTree(IFile, LevelNode)}. Else
     *     call {@link #removeStatusFromModule(IResource)}.
     * 3.) If levelNode is an instance of {@link ModuleNode}, then the following
     *     is done for the entire module. If it is not an instance, the following is
     *     only done for the tree rooted at levelNode:
     * 
     * Create SANY markers on all nodes for which there can be
     * a prover status. A SANY marker stores the location of the node as returned
     * by SANY when the marker is created. Since markers are "sticky", SANY markers
     * can be used to map from locations returned by the prover to the current
     * location of a node. A location returned by the prover should equal
     * the SANY location of a SANY marker.
     * 
     * This currently puts SANY markers on all step or top level
     * USE nodes. If levelNode is null and there is no valid parse result for the module,
     * this method does nothing.
     * 
     * See {@link ProverHelper#SANY_MARKER} for a description of
     * these markers.
     * 
     * This method also creates the tree of {@link StepTuple}s for
     * this module or LevelNode.
     * 
     * The proverJob is the instance of {@link ProverJob} used to launch the prover
     * and passed to listeners of TLAPM output for that launch. It provides access
     * to information about launch parameters and other useful data structures.
     * 
     * @param module
     * @throws CoreException 
     */
    public static void prepareModuleForProverLaunch(final IFile module, final ProverJob proverJob) throws CoreException
    {
        /*
         * This does a lot of stuff creating, deleting, and modifying
         * markers. Each of these operations results in a separate resource change
         * notification sent to all listeners unless the operations are wrapped
         * in an IWorkspaceRunnable(). If they are wrapped in an IWorkspaceRunnable
         * and the flag IWorkspace.AVOID_UPDATE is specified when running the runnable,
         * the resource change notifications will be delayed until after the runnables run method
         * has completed. The notification will then be batched as a single notification. This
         * seems to be more efficient.
         */
        IWorkspaceRunnable runnable = new IWorkspaceRunnable() {

            public void run(IProgressMonitor monitor) throws CoreException
            {
                if (module == null)
                {
                    ProverUIActivator.getDefault().logDebug("Module is null in method prepareModuleForProverLaunch. This is a bug.");
                    return;
                }

                if (proverJob.getLevelNode() == null)
                {
                    ProverUIActivator.getDefault().logDebug("Module is null in method prepareModuleForProverLaunch. This is a bug.");
                    return;
                }

                /*
                 * Remove existing sany markers and step status markers.
                 */
                removeSANYStepMarkers(module);
                if (proverJob.getLevelNode() instanceof ModuleNode)
                {
                    removeStatusFromModule(module);
                } else
                {
                    removeStatusFromTree(module, proverJob.getLevelNode());
                }
                /*
                 * Clear the maps that hold information about obligations
                 * and steps.
                 */
                proverJob.getObsMap().clear();
                proverJob.getLeafStepMap().clear();
                proverJob.getStepMessageMap().clear();

                /*
                 * Create new SANY markers and prepare the data structures for computing step statuses.
                 */
                if (proverJob.getLevelNode() instanceof ModuleNode)
                {
                    ParseResult parseResult = ResourceHelper.getValidParseResult(module);
                    if (parseResult == null)
                    {
                        return;
                    }

                    String moduleName = ResourceHelper.getModuleName(module);

                    ModuleNode moduleNode = parseResult.getSpecObj().getExternalModuleTable().getModuleNode(
                            UniqueString.uniqueStringOf(moduleName));
                    LevelNode[] topLevelNodes = moduleNode.getTopLevel();

                    for (int i = 0; i < topLevelNodes.length; i++)
                    {

                        if (topLevelNodes[i].getLocation().source().equals(moduleName))
                        {
                            // found a theorem in the module
                            prepareTreeForProverLaunch(topLevelNodes[i], module, proverJob);
                        }
                    }
                } else
                {
                    prepareTreeForProverLaunch(proverJob.getLevelNode(), module, proverJob);
                    return;
                }
            }
        };

        module.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
    }

    /**
     * Creates a SANY marker for levelNode if it is a {@link TheoremNode} or a {@link UseOrHideNode}.
     * If it has a proof, this method recursively calls it self on all children. The SANY location
     * attribute for these markers is a string representation of the location of the node
     * if it is a {@link UseOrHideNode} and the string representation of the location of the node
     * {@link TheoremNode#getTheorem()} if it is a {@link TheoremNode}.
     * 
     * The methods {@link #locToString(Location)} and {@link #stringToLoc(String)} convert from
     * {@link Location} to Strings and back.
     * 
     * See {@link ProverHelper#SANY_MARKER} for a description of
     * these markers.
     * 
     * Creates and returns the {@link StepTuple} for levelNode if levelNode is an instance of
     * {@link UseOrHideNode} or {@link TheoremNode}. Sets the marker for this tuple.
     * Returns null otherwise. If levelNode is a {@link TheoremNode} then it sets levelNode
     * as the parent of all non-null {@link StepTuple}s returned by calling this method on its children.
     * 
     * The proverJob is the instance of {@link ProverJob} used to launch the prover
     * and passed to listeners of TLAPM output for that launch. It provides access
     * to information about launch parameters and other useful data structures.
     * 
     * @param theoremNode
     * @throws CoreException 
     */
    public static StepTuple prepareTreeForProverLaunch(LevelNode levelNode, IResource module, ProverJob proverJob)
            throws CoreException
    {
        if (levelNode == null)
        {
            return null;
        }

        if (levelNode instanceof UseOrHideNode || levelNode instanceof TheoremNode)
        {
            IMarker marker = module.createMarker(SANY_MARKER);
            // the location to be used for setting the sany location attribute on the marker
            Location locForAttr;
            if (levelNode instanceof UseOrHideNode)
            {
                locForAttr = levelNode.getLocation();
            } else
            {
                TheoremNode theoremNode = (TheoremNode) levelNode;
                /*
                 * The location of a theorem node is the location beginning at the
                 * step number or keyword THEOREM and ending at the end of the statement
                 * of the step or theorem.
                 */
                Location beginLoc = theoremNode.getLocation();
                Location statementLoc = theoremNode.getTheorem().getLocation();
                locForAttr = new Location(UniqueString.uniqueStringOf(statementLoc.source()), beginLoc.beginLine(),
                        beginLoc.beginColumn(), statementLoc.endLine(), statementLoc.endColumn());
            }
            marker.setAttribute(SANY_LOC_ATR, locToString(locForAttr));
            IRegion locRegion = AdapterFactory.locationToRegion(locForAttr);
            marker.setAttribute(IMarker.CHAR_START, locRegion.getOffset());
            /*
             * For marking a region that starts at offset o and has length l, the
             * start character is o and the end character is o+l.
             */
            marker.setAttribute(IMarker.CHAR_END, locRegion.getOffset() + locRegion.getLength());

            /*
             * Create the tuple. Eventually return this tuple.
             * 
             * For step tuples with PROOF OMITTED, we add a dummy child obligation
             * indicating that the proof is explicitly omitted. For all other
             * steps that have something to prove, the tlapm will send either
             * a "to be proved" message for each obligation that it will try to
             * prove for that step.  If the step can take a user-provide proof, but
             * the user does not provide it, then tlapm will send a "missing" message
             * and will not try to prove any obligations for that step.
             * 
             * See the method processObligationMessage() for information
             * on how information about the status of obligations
             * is used to update the status of steps.
             */
            StepTuple stepTuple = new StepTuple(proverJob);
            stepTuple.setSanyMarker(marker);

            if (levelNode instanceof TheoremNode)
            {

                TheoremNode theoremNode = (TheoremNode) levelNode;
                ProofNode proof = theoremNode.getProof();
                if (proof != null)
                {
                    if (proof instanceof NonLeafProofNode)
                    {
                        NonLeafProofNode nonLeafProof = (NonLeafProofNode) proof;
                        LevelNode[] steps = nonLeafProof.getSteps();
                        // the step is not a leaf iff it has at least 1 step
                        marker.setAttribute(SANY_IS_LEAF_ATR, steps.length == 0);

                        /*
                         * Recursively put markers on each child node.
                         */
                        for (int i = 0; i < steps.length; i++)
                        {
                            StepTuple childTuple = prepareTreeForProverLaunch(steps[i], module, proverJob);
                            // child tuple will be null if the step
                            // is not a TheoremNode or UseOrHideNode
                            if (childTuple != null)
                            {
                                childTuple.setParent(stepTuple);
                                stepTuple.addChild(childTuple);
                            }
                        }
                    } else
                    {
                        marker.setAttribute(SANY_IS_LEAF_ATR, true);

                        // leaf proof
                        LeafProofNode leafProof = (LeafProofNode) proof;
                        if (leafProof.getOmitted())
                        {
                            // We create a dummy marker for this dummy obligation
                            // because ObligationStatus stores information
                            // about the obligation in a marker.
                            // The marker can have id -1 because the id
                            // is meaningless for a dummy marker. The location
                            // simply must be in the correct module so that the marker
                            // is put on the correct resource. The exact start
                            // and end positions don't matter.
                            stepTuple.addChild(new ObligationStatus(stepTuple, createObligationMarker(-1, theoremNode
                                    .getLocation()), ColorPredicate.NUMBER_OF_OMITTED_STATE, theoremNode.getLocation(),
                                    -1));
                        }

                    }
                } else
                {
                    marker.setAttribute(SANY_IS_LEAF_ATR, true);

                    // Add a missing dummy obligation unless this is a Have, Take, or Witness step
                    LevelNode assertion = theoremNode.getTheorem();
                    boolean shouldHaveProof = true;
                    if (assertion instanceof OpApplNode)
                    {
                        OpApplNode opApplAss = (OpApplNode) assertion;
                        String name = opApplAss.getOperator().getName().toString();
                        if (name.equals("$Have") || name.equals("$Take") || name.equals("$Witness"))
                            shouldHaveProof = false;
                    }

                    if (shouldHaveProof)
                    {
                        // We create a dummy marker for this dummy obligation
                        // because ObligationStatus stores information
                        // about the obligation in a marker.
                        // The marker can have id -1 because the id
                        // is meaningless for a dummy marker. The location
                        // simply must be in the correct module so that the marker
                        // is put on the correct resource. The exact start
                        // and end positions don't matter.
                        stepTuple
                                .addChild(new ObligationStatus(stepTuple, createObligationMarker(-1, theoremNode
                                        .getLocation()), ColorPredicate.NUMBER_OF_MISSING_STATE, theoremNode
                                        .getLocation(), -1));
                    }

                }

            } else
            {
                marker.setAttribute(SANY_IS_LEAF_ATR, true);
            }

            if (marker.getAttribute(SANY_IS_LEAF_ATR, false)) {
                if (proverJob.getLeafStepMap().put(
                		Integer.valueOf(locForAttr.beginLine()), stepTuple) != null) {
                    // If there are two proof steps that begin at the same line,
                    // then raise a warning. Added by LL on 14 Feb 2013. 
                    System.out.println("Two steps start on line " + locForAttr.beginLine());
                    UIHelper.runUIAsync(
                            new ResourceHelper.ErrorMessageRunnable(
                               "Error in Proof",
                               "Two different proof steps begin on line" 
                                 + locForAttr.beginLine() +
                               ".\nThis may cause an error in reporting the proof status of some steps." +
                               "\n\nAlways start a new proof step on a separate line."
                               )
                            );
                }
            }

            return stepTuple;
        }

        return null;

    }

    /**
     * Turns a {@link Location} into a String that can
     * be parsed back to a location using {@link ProverHelper#stringToLoc(String)}.
     * @param location
     * @return
     */
    public static String locToString(Location location)
    {
        /*
         * moduleName:bl:bc:el:ec
         */
        StringBuilder sb = new StringBuilder();
        sb.append(location.source()).append(LOC_DELIM).append(location.beginLine()).append(LOC_DELIM).append(
                location.beginColumn()).append(LOC_DELIM).append(location.endLine()).append(LOC_DELIM).append(
                location.endColumn());
        return sb.toString();
    }

    /**
     * Takes a string produced by {@link #locToString(Location)}
     * and produces a {@link Location}. Will throw a number format exception if
     * the string was not produced by {@link #locToString(Location)}.
     * 
     * @param locString
     * @return
     */
    public static Location stringToLoc(String locString)
    {
        /*
         * moduleName:bl:bc:el:ec
         */
        String[] segments = locString.split(LOC_DELIM);
        return new Location(UniqueString.uniqueStringOf(segments[0]), Integer.parseInt(segments[1]), Integer
                .parseInt(segments[2]), Integer.parseInt(segments[3]), Integer.parseInt(segments[4]));
    }

    /**
     * Returns the SANY step marker on the module whose SANY location
     * has the same begin and end line as the location passed to this method.
     * Returns null if such a marker is not found.
     * 
     * See {@link ProverHelper#SANY_MARKER} for a description of
     * these markers.
     * 
     * @param location
     * @param module
     * @return
     */
    public static IMarker findSANYMarker(IResource module, Location location)
    {
        try
        {
            IMarker[] sanyMarkers = module.findMarkers(SANY_MARKER, false, IResource.DEPTH_ZERO);
            /*
             * Iterate through all markers. For each marker, retrieve
             * the SANY location. Return the marker if its SANY location
             * equals location.
             */
            for (int i = 0; i < sanyMarkers.length; i++)
            {
                String sanyLocString = sanyMarkers[i].getAttribute(SANY_LOC_ATR, "");
                if (!(sanyLocString.length() == 0))
                {
                    Location sanyLoc = stringToLoc(sanyLocString);
                    if (sanyLoc.beginLine() == location.beginLine()/* && sanyLoc.endLine() == location.endLine()*/)
                    {
                        return sanyMarkers[i];
                    }
                }
            }
        } catch (CoreException e)
        {
            ProverUIActivator.getDefault().logError("Error finding existing SANY marker for location " + location, e);
        }
        return null;
    }

    /**
     * Converts the status string to the correct marker type.
     * The status string should be one of : 
     * 
     * {@link StepStatusMessage#CHECKED}
     * {@link StepStatusMessage#CHECKING_FAILED}
     * {@link StepStatusMessage.MISSING_PROOFS}
     * {@link StepStatusMessage.OMITTED}
     * {@link StepStatusMessage.PROVED}
     * {@link StepStatusMessage.PROVING_FAILED}
     * {@link StepStatusMessage.BEING_PROVED}
     * 
     * If status is not one of these, this
     * method will return null.
     * 
     * If status is null, this method returns null.
     * 
     * The marker type for proving failed steps is different depending
     * on whether it is a leaf step or not.
     * 
     * @param status
     * @param isLeafStep true iff the status is for a leaf step (a step with no
     * children or with a leaf proof).
     * @return
     */
    public static String statusStringToMarkerType(String status, boolean isLeafStep)
    {
        if (status == null)
        {
            return null;
        }

        if (status.equals(StepStatusMessage.CHECKED))
        {
            return STEP_CHECKED_MARKER;
        } else if (status.equals(StepStatusMessage.CHECKING_FAILED))
        {
            return STEP_CHECKING_FAILED_MARKER;
        } else if (status.equals(StepStatusMessage.MISSING_PROOFS))
        {
            return STEP_MISSING_MARKER;
        } else if (status.equals(StepStatusMessage.OMITTED))
        {
            return STEP_OMITTED_MARKER;
        } else if (status.equals(StepStatusMessage.PROVED))
        {
            return STEP_PROVED_MARKER;
        } else if (status.equals(StepStatusMessage.PROVING_FAILED))
        {
            if (isLeafStep)
            {
                return STEP_LEAF_FAILED;
            } else
            {
                return STEP_PROVING_FAILED_MARKER;
            }
        } else if (status.equals(StepStatusMessage.BEING_PROVED))
        {
            return STEP_BEING_PROVED_MARKER;
        }
        return null;
    }

    /**
     * Returns the marker type corresponding to the predicate given
     * by predNum. The marker type depends on whether the marker
     * is for a leaf step or not.
     * 
     * Color predicate numbers begin at 1 and end at
     * {@link ProverPreferencePage#NUM_STATUS_COLORS}.
     * 
     * @param predNum
     * @return
     */
    public static String colorPredNumToMarkerType(int predNum, boolean isLeaf)
    {
        return "org.lamport.tla.toolbox.tool.prover.ui.stepColor" + predNum + (isLeaf ? "B" : "A");
    }

    /**
     * Converts from an integer status of a step to
     * the marker type. The int should be one of
     * 
     * {@link #STEP_CHECKED_INT}
     * {@link #STEP_CHECKING_FAILED_INT}
     * {@link #STEP_PROOF_MISSING_INT}
     * {@link #STEP_PROOF_OMITTED_INT}
     * {@link #STEP_PROVED_INT}
     * {@link #STEP_PROVING_FAILED_INT}
     * {@link #STEP_BEING_PROVED_INT}
     * 
     * Else, this method returns null.
     * 
     * @param status
     * @return
     */
    public static String statusIntToStatusString(int status)
    {
        switch (status) {
        case STEP_CHECKED_INT:
            return StepStatusMessage.CHECKED;
        case STEP_CHECKING_FAILED_INT:
            return StepStatusMessage.CHECKING_FAILED;
        case STEP_PROOF_MISSING_INT:
            return StepStatusMessage.MISSING_PROOFS;
        case STEP_PROOF_OMITTED_INT:
            return StepStatusMessage.OMITTED;
        case STEP_PROVED_INT:
            return StepStatusMessage.PROVED;
        case STEP_PROVING_FAILED_INT:
            return StepStatusMessage.PROVING_FAILED;
        case STEP_BEING_PROVED_INT:
            return StepStatusMessage.BEING_PROVED;
        case STEP_TO_BE_PROVED_INT:
            return StepStatusMessage.TO_BE_PROVED;
        default:
            return null;
        }
    }

    /**
     * Process the obligation message. If the status of the message is not
     * {@link #TO_BE_PROVED} then it creates a marker for that obligation
     * by calling {@link #createObligationMarker(ObligationStatusMessage)}. Else, it prepares
     * the necessary data structure for computing proof step statuses.
     * 
     * The proverJob is the instance of {@link ProverJob} used to launch the prover
     * and passed to listeners of TLAPM output for that launch. It provides access
     * to information about launch parameters and other useful data structures.
     * 
     * @param message
     * @param nodeToProve the step or module on which the prover was launched
     */
    public static void processObligationMessage(ObligationStatusMessage message, final ProverJob proverJob)
    {
        if (message.getStatus().equals(TO_BE_PROVED))
        {
            if (proverJob.getNoToBeProved())
            {
                ProverUIActivator.getDefault().logDebug("First to be proved " + proverJob.getCurRelTime());
                proverJob.setNoToBeProved(false);
            }

            /*
             * Simply add all to be proved messages to a list.
             * They will be processed later. This is done once
             * the first non "to be proved" message is sent. See below.
             */
            proverJob.addObMessageList(message);

            /*
             * Create a new ObligationStatus with null as the initial status and
             * to be proved as the initial state.
             * 
             * The parent is initially null because we set it later. We set the parent
             * of all non-dummy obligations when the first obligation message arrives that
             * does not have status "to be proved". This condition is captured below in the
             * if block with condition obStatus.getParent() == null. This condition should
             * only be true once, because the code in that if block sets the parent
             * for every obligation.
             */
            // IMarker obMarker = createObligationMarker(message.getID(), ColorPredicate.TO_BE_PROVED_STATE, message
            // .getLocation());
            // ObligationStatus obStatus = new ObligationStatus(null, obMarker);
            // proverJob.getObsMap().put(new Integer(message.getID()), obStatus);
        } else
        {
            /*
             * When the first message arrives that is not "to be proved"
             * we create all obligation markers at once. Batching marker creation
             * and wrapping the creation in an IWorkspaceRunnable sends one batch
             * resource change notification instead of one notification for each
             * marker modification. This is significantly faster than not wrapping the
             * creation in an IWorkspaceRunnable.
             */
            if (proverJob.isToBeProvedOnly())
            {
            	ProverUIActivator.getDefault().logDebug("Before obligation marker creation " + proverJob.getCurRelTime());
                IWorkspaceRunnable runnable = new IWorkspaceRunnable() {

                    public void run(IProgressMonitor monitor) throws CoreException
                    {
                        for (Iterator<ObligationStatusMessage> it = proverJob.getObMessageList().iterator(); it.hasNext();)
                        {
                            ObligationStatusMessage message = it.next();
                            IMarker obMarker = createObligationMarker(message.getID(), message.getLocation());
                            ObligationStatus obStatus = new ObligationStatus(null, obMarker,
                                    ColorPredicate.TO_BE_PROVED_STATE, message.getLocation(), message.getID());
                            proverJob.getObsMap().put(Integer.valueOf(message.getID()), obStatus);
                        }
                    }
                };

                try
                {
                    proverJob.getModule().getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
                } catch (CoreException e)
                {
                    ProverUIActivator.getDefault().logError("Error creating marker obligations", e);
                }
                proverJob.setToBeProvedOnly(false);
                ProverUIActivator.getDefault().logDebug("After obligation marker creation " + proverJob.getCurRelTime());
            }
            /*
             * Update the state of the obligation. The obligation will
             * inform its parents step that its status should be updated.
             */
            final ObligationStatus obStatus = (ObligationStatus) proverJob.getObsMap().get(Integer.valueOf(message.getID()));

            /*
             * If the obligation does not yet have a parent, then
             * set parents for all obligations. This should only occur
             * once.
             */
            if (obStatus.getParent() == null)
            {
            	ProverUIActivator.getDefault().logDebug("Before ob parenting creation " + proverJob.getCurRelTime());
                /*
                 * The following iterates through all non-dummy
                 * obligations. For each obligation, we search through
                 * the map of leaf steps until we find a parent. We search
                 * by line numbers (because that is the key of the leaf step
                 * map). We search upward in the file (decreasing the line number)
                 * until we find a step that begins on that line number. This
                 * assumes only one step per line. This is hopefully efficient
                 * because obligations should be only a few lines below their parent
                 * step.
                 */
                for (Iterator<ObligationStatus> it = proverJob.getObs().iterator(); it.hasNext();)
                {
                    ObligationStatus obligation = it.next();
                    int searchLine = obligation.getTLAPMLocation().beginLine();
                    // The following loop was changed from a while (true) loop by
                    // LL on 10 Jan 2013.  Apparently because of a bad message being
                    // sent by tlapm, the non-null value of stepTuple was never
                    // being found and the program kept looping until searchLine 
                    // got to be too large a negative number and some exception was
                    // thrown.  Tlapm has been fixed not to send the bad message.
                    // However, it seems like a good idea to keep the sanity check
                    // and to raise an error if insanity is found.
                    while (searchLine >= 0)
                    {
                        StepTuple stepTuple = proverJob.getLeafStepMap().get(Integer.valueOf(searchLine));
                        if (stepTuple != null)
                        {
                            obligation.setParent(stepTuple);
                            stepTuple.addChild(obligation);
                            break;
                        }
                        searchLine--;
                    }
                    if (searchLine < 0) {
                        // If this sanity check fails, then raise a warning. The 
                         // following code added  by LL on 14 Feb 2013.
                        UIHelper.runUIAsync(
                            new ResourceHelper.ErrorMessageRunnable(
                                "Error", 
                                "There is an error in the information sent by"+
                                "\nTLAPS to the Toolbox.  This may cause incorrect"+
                                "\nreporting of a step's proof status." +
                                "\n\nPlease report this problem to the developers.")
                            );
                    }
                }
                
                ProverUIActivator.getDefault().logDebug(
                        "After ob parenting creation " + proverJob.getCurRelTime());
            }

            // The following try/catch added by LL on 10 Jan 2012.  The exception seems to
            // be thrown when the while loop above exists because searchLine goes negative.
            try {
              obStatus.updateObligation(message);
            } catch (NullPointerException e) {
                System.out.println("NullPointerException caused by message with id " + 
                  message.getID() + " and location " + message.getLocation().toString());
            }

            // update the obligations view with the new information
            UIHelper.runUIAsync(new Runnable() {

                public void run()
                {
                    ObligationsView.updateObligationView(obStatus);
                }
            });
        }
    }

    /**
     * Installs a new marker for the obligation with the given input information.
     * 
     * The message location should be for a module in the currently opened spec. If no
     * such module exists, this method returns null.
     * 
     * The initialState is the state of the obligation at the time of creation
     * of this marker. Obligation states are explained in {@link ColorPredicate}.
     * 
     * Returns the marker created.
     */
    public static IMarker createObligationMarker(int id, Location location)
    {
        IResource module = ResourceHelper.getResourceByModuleName(location.source());
        if (module != null && module instanceof IFile && module.exists())
        {
            /*
             * We may need to convert the 4-int location of the message
             * to a 2-int region if an existing marker is not found. We use a FileDocumentProvider.
             * We create it now so that if it is used, it can be disconnected in
             * the finally block of the following try block to avoid a memory leak.
             */
            FileEditorInput fileEditorInput = new FileEditorInput((IFile) module);
			// Fix deadlock introduced with upgrade to Eclipse Oxygen framework/platform.
			// FileDocumentProvider has changed an no longer checks if the IFile module is
			// synced. This results in a refresh Job with a lock on the file which deadlocks
			// because the ProverJob locked the entire workspace (including the file). At
			// the same time, the ProverJob waits for
			// org.lamport.tla.toolbox.tool.prover.ui.output.TagBasedTLAPMOutputIncrementalParser.appendText(String)
			// to finish. Its implementation calls this method. In other words, the
			// ProverJob locks the workspace and triggers a (workspace) Job to refresh the
			// module. The refresh Job and the ProverJob deadlock.
			// Alternatively, it's possible to acquire/create the IDocument in the ProverJob
			// and pass it to the TagBasedTLAPMOutputIncrementalParser. However, I'm not
			// sure if this causes problems if a proof spans across multiple files.
            final FileDocumentProvider fileDocumentProvider = new LegacyFileDocumentProvider();

            try
            {

                // the marker created
                Map<String, Integer> markerAttributes = new HashMap<String, Integer>();
                markerAttributes.put(OBLIGATION_ID, Integer.valueOf(id));
                // markerAttributes.put(OBLIGATION_STATE, new Integer(initialState));
                // markerAttributes.put(OBLIGATION_LOCATION, locToString(location));

                fileDocumentProvider.connect(fileEditorInput);
                IDocument document = fileDocumentProvider.getDocument(fileEditorInput);
                IRegion obRegion = AdapterFactory.locationToRegion(document, location);
                /*
                 * For marking a region that starts at offset o and has length l, the
                 * start character is o and the end character is o+l.
                 */
                markerAttributes.put(IMarker.CHAR_START, Integer.valueOf(obRegion.getOffset()));
                markerAttributes.put(IMarker.CHAR_END, Integer.valueOf(obRegion.getOffset() + obRegion.getLength()));

                IMarker marker = module.createMarker(OBLIGATION_MARKER);
                marker.setAttributes(markerAttributes);

                // DEBUG
                // ProverUIActivator.getDefault().logDebug("Marker created for obligation from message \n" + message);
                return marker;
            } catch (CoreException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (BadLocationException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally
            {
                fileDocumentProvider.disconnect(fileEditorInput);
            }
        }
        return null;

    }

    /**
     * Should be called to update the status of a proof
     * step using a message from the tlapm. This method always
     * stores the message in a map for later use comparing messages
     * from the tlapm to step status computed by the toolbox.
     * 
     * If addMarker is true, this searches for an existing SANY marker
     * with the same location as the status. If found, replaces
     * this marker with the appropriate step status marker. If
     * a SANY marker is not found, this is a bug and will be
     * printed out on the console.
     * 
     * The proverJob is the instance of {@link ProverJob} used to launch the prover
     * and passed to listeners of TLAPM output for that launch. It provides access
     * to information about launch parameters and other useful data structures.
     * 
     * @param status
     * @param proverJob the description of the launch of the prover
     * indicating its status
     */
    public static void newStepStatusMessage(StepStatusMessage status, ProverJob proverJob)
    {
        proverJob.getStepMessageMap().put(Integer.valueOf(status.getLocation().beginLine()), status);

        /*
         * The following was commented out because the proof step status markers are now always
         * put on by the toolbox.
         */
        // if (proverJob.isStatusCheck())
        // {
        //
        // if (status == null)
        // {
        // return;
        // }
        // /*
        // * Create a marker located at the proof step. The current location
        // * of the proof step is determined by finding an existing SANY marker
        // * whose attribute matches the location according to the method
        // * findSANYMarker().
        // */
        // Location location = status.getLocation();
        // IResource module = ResourceHelper.getResourceByModuleName(location.source());
        // if (module != null && module instanceof IFile && module.exists())
        // {
        // /*
        // * Try to find an existing SANY marker.
        // *
        // * If a sany marker is found, put a marker at the current location
        // * of the sany marker (not at the SANY location attribute of the sany marker).
        // */
        // IMarker sanyMarker = findSANYMarker(module, location);
        //
        // if (sanyMarker == null)
        // {
        // ProverUIActivator.getDefault().logDebug("Existing SANY marker not found for location " + location
        // + ". This is a bug.");
        // }
        //
        // newStepStatusMarker(sanyMarker, status.getStatus());
        //
        // // the following code was commented out because it is basically
        // // done in newStepStatusMarker().
        // // try
        // // {
        // // /*
        // // * If the status string does not correspond
        // // * to a marker type, then do not create a marker.
        // // */
        // // String markerType = statusStringToMarkerType(status.getStatus());
        // //
        // // if (markerType == null)
        // // {
        // // ProverUIActivator
        // // .logDebug("Status of proof step does not correspond to an existing marker type. The status is "
        // // + status.getStatus());
        // // return;
        // // }
        // //
        // // IMarker newMarker = module.createMarker(markerType);
        // // Map markerAttributes = new HashMap(2);
        // // // value based on whether a sany marker is found or not
        // // int newCharStart;
        // // int newCharEnd;
        // // if (sanyMarker != null)
        // // {
        // // newCharStart = sanyMarker.getAttribute(IMarker.CHAR_START, 0);
        // // newCharEnd = sanyMarker.getAttribute(IMarker.CHAR_END, 0);
        // // } else
        // // {
        // // ProverUIActivator.getDefault().logDebug("Existing SANY marker not found for location " + location
        // // + ". This is a bug.");
        // // // the region from the tlapm message
        // // IRegion messageRegion = AdapterFactory.locationToRegion(location);
        // // /*
        // // * For marking a region that starts at offset o and has length l, the
        // // * start character is o and the end character is o+l.
        // // */
        // // newCharStart = messageRegion.getOffset();
        // // newCharEnd = messageRegion.getOffset() + messageRegion.getLength();
        // // return;
        // // }
        // //
        // // /*
        // // * Remove any existing step status markers that overlap
        // // * with the new step status marker.
        // // */
        // // IMarker[] existingMarkers = module.findMarkers(ProverHelper.STEP_STATUS_MARKER, true,
        // // IResource.DEPTH_ZERO);
        // // for (int i = 0; i < existingMarkers.length; i++)
        // // {
        // // IMarker existingMarker = existingMarkers[i];
        // // int existingCharStart = existingMarker.getAttribute(IMarker.CHAR_START, -1);
        // // int existingCharEnd = existingMarker.getAttribute(IMarker.CHAR_END, -1);
        // //
        // // // conditions for overlapping
        // // if (existingCharStart < newCharEnd && existingCharEnd > newCharStart)
        // // {
        // // existingMarker.delete();
        // // }
        // // }
        // //
        // // markerAttributes.put(IMarker.CHAR_START, new Integer(newCharStart));
        // // markerAttributes.put(IMarker.CHAR_END, new Integer(newCharEnd));
        // // newMarker.setAttributes(markerAttributes);
        // //
        // // } catch (CoreException e)
        // // {
        // // ProverUIActivator.getDefault().logError("Error creating new status marker.", e);
        // // }
        // } else
        // {
        // ProverUIActivator.getDefault().logDebug("A module could not be located for a step status.\n" + "Status : "
        // + status.getStatus() + "\nLocation : " + location);
        // }
        // }
    }

    /**
     * Compares the step status computations of the TLAPM and the toolbox.
     * Any discrepancies are reported. Currently the reporting is to the
     * console.
     * 
     * This method does the comparison for the step statuses computed
     * for the launch of the prover described by proverJob.
     * This is the instance of {@link ProverJob} used to launch the prover
     * and passed to listeners of TLAPM output for that launch.
     */
    public static void compareStepStatusComputations(ProverJob proverJob)
    {
        // ProverUIActivator.getDefault().logDebug("------------------Comparing TLAPM and Toolbox Step Status------------");
        // Collection stepTuples = proverJob.getStepMap().values();
        // for (Iterator it = stepTuples.iterator(); it.hasNext();)
        // {
        // StepTuple stepTuple = (StepTuple) it.next();
        // Location stepLoc = stringToLoc(stepTuple.getSanyMarker().getAttribute(SANY_LOC_ATR, ""));
        // StepStatusMessage stepMessage = (StepStatusMessage) proverJob.getStepMessageMap().remove(
        // new Integer(stepLoc.beginLine()));
        // if (stepMessage == null)
        // {
        // ProverUIActivator.getDefault().logDebug("NO STATUS BUG :\n No TLAPM step status message found for the step at " + stepLoc
        // + " . The Toolbox thinks the status is "
        // + statusIntToStatusString(stepTuple.getColorPredicateValues()));
        // } else if (!stepMessage.getStatus().equals(statusIntToStatusString(stepTuple.getColorPredicateValues())))
        // {
        // ProverUIActivator.getDefault().logDebug("DIFFERENT STATUS BUG : \n Loc : " + stepLoc + "\n TLAPM : "
        // + stepMessage.getStatus() + "\n Toolbox : "
        // + statusIntToStatusString(stepTuple.getColorPredicateValues()));
        // }
        // }
        //
        // Collection remainingMessages = proverJob.getStepMessageMap().values();
        // for (Iterator it = remainingMessages.iterator(); it.hasNext();)
        // {
        // StepStatusMessage message = (StepStatusMessage) it.next();
        // ProverUIActivator.getDefault().logDebug("NO STATUS BUG :\n No Toolbox step status message found for the step at "
        // + message.getLocation() + " . The TLAPM reports the status " + message.getStatus());
        // }
        //
        // ProverUIActivator.getDefault().logDebug("------------------Done Comparing TLAPM and Toolbox Step Status------------");
    }

    /**
     * Creates a new marker at the current location of sanyMarker indicating the
     * status given by status. If status is not a known type (the method
     * {@link #colorPredNumToMarkerType(int, boolean) returns null) then this deletes
     * any markers overlapping with sanyMarker but does not create a new marker. If sanyMarker is null, this also
     * prints some debugging message and returns. This method removes any step status markers
     * overlapping with the new marker that is created.
     * 
     * Color predicate numbers begin at 1 and end at {@link ProverPreferencePage#NUM_STATUS_COLORS}.
     * 
     * @param sanyMarker
     * @param predNum
     */
    public static void newStepStatusMarker(final IMarker sanyMarker, int predNum)
    {
        if (sanyMarker == null)
        {
            ProverUIActivator.getDefault().logDebug("Null sanyMarker passed to newStepStatusMarker. This is a bug.");
            return;
        }

        try
        {
            final IResource module = sanyMarker.getResource();
            /*
             * If the status string does not correspond
             * to a marker type, then do not create a marker.
             */
            final String markerType = colorPredNumToMarkerType(predNum, sanyMarker
                    .getAttribute(SANY_IS_LEAF_ATR, false));

            // This is commented out because we now will not create a marker if
            // marker type is null. A null marker type indicates that all overlapping markers
            // should be deleted and a new one not created.
            // if (markerType == null)
            // {
            // ProverUIActivator
            // .logDebug("Status of proof step does not correspond to an existing marker type. The status is "
            // + status);
            // return;
            // }

            /*
             * We wrap the marker creation and deletion operation
             * in a runnable that tells the workspace to avoid
             * sending resource change notifications while
             * the run method is executing.
             */
            IWorkspaceRunnable runnable = new IWorkspaceRunnable() {

                public void run(IProgressMonitor monitor) throws CoreException
                {
                    /*
                     * Its important to note that the location of the marker
                     * obtained by sanyMarker.getAttribute(IMarker.CHAR_START, 0)
                     * and sanyMarker.getAttribute(IMarker.CHAR_END, 0) can be different
                     * than the location of the marker in the editor if the editor is
                     * currently dirty. It seems that the eclipse text editors update
                     * the CHAR_START and CHAR_END attributes of markers only on save.
                     * The current position of the marker in the editor can be obtained
                     * through the editor's annotation model. The code for doing this
                     * is in the method EditorUtil.getMarkerPosition(sanyMarker).
                     */

                    // The current position of the sany marker in the editor
                    // if there is at least one editor open on the module.
                    Position curPosition = EditorUtil.getMarkerPosition(sanyMarker);
                    // char start and end of the marker to be created
                    int newCharStart;
                    int newCharEnd;

                    if (curPosition != null)
                    {
                        newCharStart = curPosition.getOffset();
                        newCharEnd = curPosition.getOffset() + curPosition.getLength();
                    } else
                    {
                        /*
                         * We cannot get the position, which means there may not be
                         * an editor open on the module, so we just use the marker's location
                         * attributes.
                         */
                        newCharStart = sanyMarker.getAttribute(IMarker.CHAR_START, 0);
                        newCharEnd = sanyMarker.getAttribute(IMarker.CHAR_END, 0);
                    }

                    /*
                     * Remove any existing step status markers that overlap
                     * with the new step status marker.
                     */
                    IMarker[] existingMarkers = module.findMarkers(ProverHelper.STEP_STATUS_MARKER, true,
                            IResource.DEPTH_ZERO);
                    for (int i = 0; i < existingMarkers.length; i++)
                    {
                        IMarker existingMarker = existingMarkers[i];
                        int existingCharStart = existingMarker.getAttribute(IMarker.CHAR_START, -1);
                        int existingCharEnd = existingMarker.getAttribute(IMarker.CHAR_END, -1);

                        // conditions for overlapping
                        if (existingCharStart < newCharEnd && existingCharEnd > newCharStart)
                        {
                            existingMarker.delete();
                        }
                    }

                    if (markerType != null)
                    {
                        // the attributes for the new marker to be created
                        Map<String, Integer> markerAttributes = new HashMap<String, Integer>(2);
                        markerAttributes.put(IMarker.CHAR_START, Integer.valueOf(newCharStart));
                        markerAttributes.put(IMarker.CHAR_END, Integer.valueOf(newCharEnd));
                        markerAttributes.put(IMarker.LINE_NUMBER, Integer.valueOf(stringToLoc(
                                sanyMarker.getAttribute(SANY_LOC_ATR, "")).beginLine()));

                        // create the new marker and set its attributes
                        IMarker newMarker = module.createMarker(markerType);
                        newMarker.setAttributes(markerAttributes);
                    }
                }
            };

            module.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);

        } catch (CoreException e)
        {
            ProverUIActivator.getDefault().logError("Error creating new status marker.", e);
        }
    }

    /**
     * Removes all status markers from the module.
     */
    public static void removeStatusFromModule(IResource module)
    {
        try
        {
            module.deleteMarkers(STEP_STATUS_MARKER, true, IResource.DEPTH_ZERO);
        } catch (CoreException e)
        {
            ProverUIActivator.getDefault().logError("Error removing status markers from module " + module, e);
        }
    }

    /**
     * Removes or modifies status markers so that no markers appear on any
     * of the lines from the begin line to the end line of the root.
     * Any markers that are only on those lines are deleted. Any markers that overlap
     * with those lines are shortened so that they do not overlap.
     * 
     * If root is a TheoremNode with a proof, then the begin line is
     * root.getLocation().beginLine() and the end line is
     * root.getProof().getLocation().endLine().
     * 
     * For all other cases, the begin line is root.getLocation().beginLine()
     * and the end line is root.getLocation().endLine().
     *  
     * @param module
     * @param root
     */
    public static void removeStatusFromTree(IFile module, LevelNode root)
    {
        try
        {
            /*
             * We need a  document to convert
             * from the 4-int location provided by SANY
             * to the 2-int location of markers.
             */
            IDocument document = ResourceHelper.getDocFromFile(module);
            /*
             * SANY lines are 1-based and document lines
             * are 0-based. We use document lines from now
             * on.
             */
            int beginLine = root.getLocation().beginLine() - 1;
            int endLine = root.getLocation().endLine() - 1;

            if (root instanceof TheoremNode && ((TheoremNode) root).getProof() != null)
            {
                endLine = ((TheoremNode) root).getProof().getLocation().endLine() - 1;
            }
            // get the start and end characters of the tree
            int treeBeginChar = document.getLineOffset(beginLine);
            /*
             * In the following, we subtract 1 to get the end char.
             * 
             * For a marker representing a region that starts at offset o and has length l, the
             * start character is o and the end character is o+l.
             */
            int treeEndChar = document.getLineOffset(endLine) + document.getLineLength(endLine);

            // get all existing step status markers on the module
            IMarker[] markers = module.findMarkers(STEP_STATUS_MARKER, true, IResource.DEPTH_ZERO);
            for (int i = 0; i < markers.length; i++)
            {
                IMarker oldMarker = markers[i];
                // get the start and end characters of the marker
                int markerStartChar = oldMarker.getAttribute(IMarker.CHAR_START, -1);
                int markerEndChar = oldMarker.getAttribute(IMarker.CHAR_END, -1);

                /*
                 * It appears that simply altering the char start and char end
                 * attributes of a marker will not cause that change to be reflected in the
                 * open editor. To solve this, markers that should be altered will instead
                 * be deleted and one or two markers will be created at the correct locations.
                 * 
                 * If the marker is completely contained by the tree, delete it.
                 * 
                 * If the marker starts before the tree and ends inside the tree, delete
                 * the marker and create one new marker that begins at the same point
                 * as the deleted marker but ends one character before the start of the tree.
                 * 
                 * If the marker completely contains the tree, delete that marker. Create two
                 * new markers. One marker will start at the old marker's start point and end
                 * one character before the tree. The second marker will begin one character after
                 * the end of the tree and end at the old marker's end point.
                 * 
                 * If the marker starts inside the tree and ends after the tree, delete that marker.
                 * Create a new marker that begins one character after the end of the tree and
                 * ends at the old marker's end point.
                 */
                if (markerStartChar >= treeBeginChar && markerEndChar <= treeEndChar)
                {
                    oldMarker.delete();
                } else if (markerStartChar < treeBeginChar && markerEndChar >= treeBeginChar
                        && markerEndChar <= treeEndChar)
                {
                    IMarker newMarker = module.createMarker(oldMarker.getType());
                    newMarker.setAttribute(IMarker.CHAR_START, markerStartChar);
                    newMarker.setAttribute(IMarker.CHAR_END, treeBeginChar - 1);
                    oldMarker.delete();
                } else if (markerStartChar < treeBeginChar && markerEndChar > treeEndChar)
                {
                    // marker before the tree
                    IMarker beforeMarker = module.createMarker(oldMarker.getType());
                    beforeMarker.setAttribute(IMarker.CHAR_START, markerStartChar);
                    beforeMarker.setAttribute(IMarker.CHAR_END, treeBeginChar - 1);

                    // marker after the tree
                    IMarker afterMarker = module.createMarker(oldMarker.getType());
                    afterMarker.setAttribute(IMarker.CHAR_START, treeEndChar + 1);
                    afterMarker.setAttribute(IMarker.CHAR_END, markerEndChar);

                    oldMarker.delete();
                } else if (markerStartChar >= treeBeginChar && markerStartChar <= treeEndChar
                        && markerEndChar > treeEndChar)
                {
                    IMarker newMarker = module.createMarker(oldMarker.getType());
                    newMarker.setAttribute(IMarker.CHAR_START, treeEndChar + 1);
                    newMarker.setAttribute(IMarker.CHAR_END, markerEndChar);
                    oldMarker.delete();
                }
            }
        } catch (CoreException e)
        {
            ProverUIActivator.getDefault().logError("Error removing status markers from tree rooted at " + root, e);
        } catch (BadLocationException e)
        {
            ProverUIActivator.getDefault().logError("Error removing status markers from tree rooted at " + root, e);
        }
    }

    /**
     * Requests cancellation of all running prover jobs. If wait
     * is true, sleeps the current thread until all prover jobs are done
     * that they are done.
     */
    public static void cancelProverJobs(boolean wait)
    {

        ProverJobMatcher jobMatcher = new ProverJob.ProverJobMatcher();
        Job.getJobManager().cancel(jobMatcher);
        if (wait)
        {
            while (Job.getJobManager().find(jobMatcher).length > 0)
            {
                try
                {
                    Thread.sleep(1000);
                } catch (InterruptedException e)
                {
                    ProverUIActivator.getDefault().logError("Error sleeping thread.", e);
                }
            }
        }

    }

    /**
     * Runs the prover on the active selection in the {@link TLAEditor} with
     * focus. The active selection is the position of the caret. This method
     * runs the prover on the step at the caret, where step is either a proof
     * step or a top level USE node. A step is at the caret if the method
     * {@link ResourceHelper#getPfStepOrUseHideFromMod(ParseResult, String, ITextSelection, IDocument)}
     * returns that node for the text selection representing the caret position.
     * 
     * If there is not a step at the caret, this method will launch the prover
     * on the entire module.
     * 
     * If there are dirty editors open, this method will prompt the user
     * to save them before continuing. If there is not a valid parse result
     * available, this method will parse the module in the editor with focus.
     * If there are parse errors, the prover will not be launched, but the parse
     * error window will show the errors.
     * 
     * If statusCheck is true, this tells prover job to launch the prover
     * for status checking, not proving. If isaprove is true, the PM will
     * be launched with the --isaprove option.
     * 
     * @param checkStatus true iff the prover should only be run for status checking
     * @param isaprove true iff the PM should be called with the isaprove option
     * 
     * @return
     */
    public static void runProverForActiveSelection(boolean checkStatus, boolean isaprove)
    {
        boolean proceed = UIHelper.promptUserForDirtyModules();
        if (!proceed)
        {
            // the user cancelled
            return;
        }

        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();
        Assert.isNotNull(editor, "User attempted to run prover without a tla editor in focus. This is a bug.");

        String[] options = null;
        if (isaprove)
        {
            options = new String[] { ITLAPMOptions.ISAPROVE };
        }

        ProverJob proverJob = new ProverJob(((FileEditorInput) editor.getEditorInput()).getFile(),
                ((ITextSelection) editor.getSelectionProvider().getSelection()).getOffset(), checkStatus, options, true);

        proverJob.setUser(true);
        proverJob.schedule();

    }

    /**
     * Runs the prover on the entire module in the active editor. If checkStatus is true,
     * the prover is launched only for status checking. If it is false,
     * the prover is launched for proving. If isaprove is true, the PM will
     * be launched with the --isaprove option.
     * 
     * If there are dirty editors, this method first prompts the user to save them.
     * 
     * @param checkStatus true iff the prover should only be run for status checking
     * @param isaprove true iff the PM should be called with the isaprove option
     */
    public static void runProverForEntireModule(boolean checkStatus, boolean isaprove)
    {
        boolean proceed = UIHelper.promptUserForDirtyModules();
        if (!proceed)
        {
            // the user cancelled
            return;
        }

        String[] options = null;
        if (isaprove)
        {
            options = new String[] { ITLAPMOptions.ISAPROVE };
        }

        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();
        Assert.isNotNull(editor, "User attempted to run prover without a tla editor in focus. This is a bug.");

        ProverJob proverJob = new ProverJob(((FileEditorInput) editor.getEditorInput()).getFile(), -1, checkStatus,
                options, true);
        proverJob.setUser(true);
        proverJob.schedule();
    }

    /**
     * Takes the String representation of the status of a step
     * or obligation and translates to the integer representation
     * of the status of a proof step.
     * 
     * This can be used to map from the current state of an obligation
     * and the new status of the obligation for a prover into the new state
     * of the obligation. See {@link ColorPredicate} for explanation of
     * obligation states.
     * 
     * Returns currentStatus if status is not a known status. Also throws
     * an {@link AssertionFailedException} in that case.
     * 
     * @param status the new status string from tlapm
     * @param currentState the current state of the obligation
     * @param backEndName the name of the backend, e.g. isabelle, tlapm, zenon
     * @return
     */
    public static int getIntFromStringStatus(String status, int currentState, String backEndName)
    {
        int backendNum = getNumOfBackend(backEndName);

        if (status.equals(PROVED) || status.equals(TRIVIAL))
        {
            return ColorPredicate.newStateNumber(currentState, backendNum, ColorPredicate.numberOfProverStatus(
                    backendNum, ColorPredicate.PROVED_STATUS));
        } else if (status.equals(BEING_PROVED))
        {
            return ColorPredicate.newStateNumber(currentState, backendNum, ColorPredicate.numberOfProverStatus(
                    backendNum, ColorPredicate.PROVING_STATUS));
        } else if (status.equals(FAILED))
        {
            return ColorPredicate.newStateNumber(currentState, backendNum, ColorPredicate.numberOfProverStatus(
                    backendNum, ColorPredicate.FAILED_STATUS));
        } else if (status.equals(INTERUPTED))
        {
            return ColorPredicate.newStateNumber(currentState, backendNum, ColorPredicate.numberOfProverStatus(
                    backendNum, ColorPredicate.STOPPED_STATUS));
        }

        Assert.isTrue(false, "Unknown status : " + status);
        return currentState;

    }

    /**
     * Returns the number in {@link ColorPredicate} corresponding
     * to the backend reported by tlapm.
     * 
     * @param backend
     * @return
     */
    public static int getNumOfBackend(String backend)
    {
        if (backend.equals("isabelle"))
        {
            return ColorPredicate.ISABELLE_NUM;
        } else if (backend.equals("tlapm"))
        {
            return ColorPredicate.TLAPM_NUM;
        } else
        {
            return ColorPredicate.OTHER_BACKEND_NUM;
        }
    }

    /**
     * Processes a warning message from the tlapm. This simply displays
     * a warning to the user.
     * 
     * @param warningMessage
     */
    public static void processWarningMessage(final WarningMessage warningMessage)
    {
        UIHelper.runUIAsync(new Runnable() {

            public void run()
            {
                InformationDialog.openWarning(warningMessage.getMessage(), "TLAPM Warning");
            }
        });

    }

    /**
     * Processes an error message from the tlapm.
     * 
     * @param message
     */
    public static void processErrorMessage(final ErrorMessage message)
    {

        UIHelper.runUIAsync(new Runnable() {

            public void run()
            {
                TLAPMErrorDialog.open(message.getMessage(), "TLAPM Error", message.getURL());
            }
        });

    }

    /**
     * Sends a signal to the prover indicating that the obligation,
     * whose status is represented by marker, should be stopped.
     * 
     * The marker should by of the type {@link #OBLIGATION_MARKER}.
     * 
     * This method assumes that there is at most one prover job currently
     * running and that this marker is for an obligation from that prover
     * job.
     * 
     * @param marker
     */
    public static void stopObligation(IMarker marker)
    {

    	ProverUIActivator.getDefault().logDebug("Stop obligation " + marker.getAttribute(OBLIGATION_ID, -1));

        // a count of running prover jobs for debugging
        // check to see that there is at most 1
        int numProverJobs = 0;
        Job[] jobs = Job.getJobManager().find(new ProverJob.ProverJobMatcher());
        for (int i = 0; i < jobs.length; i++)
        {
            if (jobs[i] instanceof ProverJob && jobs[i].getState() == Job.RUNNING)
            {
                numProverJobs++;
                ProverJob proverJob = (ProverJob) jobs[i];
                proverJob.stopObligation(marker.getAttribute(OBLIGATION_ID, -1));
            }
        }

        if (numProverJobs > 1)
        {
            ProverUIActivator.getDefault().logDebug("We found " + numProverJobs + " running when obligation "
                    + marker.getAttribute(OBLIGATION_ID, -1) + " was stopped. This is a bug.");
        }

    }

    /**
     * If the user has specified a number of threads preference of i,
     * then adds the appropriate entries to the list command of arguments.
     * @return
     */
    public static void setThreadsOption(List<String> command)
    {
        String numThreadsText = ProverUIActivator.getDefault().getPreferenceStore().getString(
        		MainProverPreferencePage.NUM_THREADS_KEY);
        if (numThreadsText.trim().length() == 0)
        {
            return;
        }
        command.add(ITLAPMOptions.THREADS);
        command.add(numThreadsText);
    }

    /**
     * If the user has specified a solver preference pref,
     * then adds the appropriate entries to the list command of arguments.
     * @return
     */
    public static void setSolverOption(List<String> command)
    {
        String solverText = ProverUIActivator.getDefault().getPreferenceStore().getString(
        		MainProverPreferencePage.SOLVER_KEY);
        if (solverText.trim().length() == 0)
        {
            return;
        }
        command.add(ITLAPMOptions.SOLVER);
        command.add(solverText);  /* Changed by DD: do not add quotes. */
    }

    /**
     * If the user has specified a solver preference pref,
     * then adds the appropriate entries to the list command of arguments.
     * @return
     */
    public static void setSafeFPOption(List<String> command)
    {
        boolean safefp = ProverUIActivator.getDefault().getPreferenceStore().getBoolean(
        		MainProverPreferencePage.SAFEFP_KEY);
        if (safefp)
        {
            command.add(ITLAPMOptions.SAFEFP);
        }
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/ResultPresenter.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui;

import org.lamport.tla.toolbox.tool.tlc.launch.TraceExplorerDelegate;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.result.IResultPresenter;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.tool.tlc.ui.view.TLCErrorView;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Responsible for presenting the TLC launch results
 * 
 * @author <NAME>
 */
public class ResultPresenter implements IResultPresenter {
	public void showResults(Model model) {
        /*
         * For trace exploration, just update the error view with the data
         * from the run of TLC for trace exploration. For model checking, open
         * the editor for that model, show the result page, and update the
         * data on the result page.
         */
		if (model.getLastLaunch().getLaunchMode().equals(TraceExplorerDelegate.MODE_TRACE_EXPLORE)) {
            final ModelEditor modelEditor = model.getAdapter(ModelEditor.class);
			if ((modelEditor != null) && (modelEditor.getActivePage() != -1)) {
                // If an editor is open and active on the model, update the error view.
                // Although the trace explorer only takes a few seconds to run,
                // the user could still switch to another model.
                // If so, this code should not be run.
                TLCErrorView.updateErrorView(modelEditor);
            }
		} else {
			final ModelEditor editor = (ModelEditor) UIHelper.openEditor(ModelEditor.ID, model.getFile());
			if (editor != null) {
                editor.addOrShowResultsPage();
            }
        }
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCError.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;

import tlc2.model.Formula;
import tlc2.model.TraceExpressionInformationHolder;
import util.TLAConstants;

/**
 * Representation of the TLC error
 * @author <NAME>
 */
public class TLCError
{
	public enum Length {
		ALL, RESTRICTED;
	}
	
	public enum Order {
		OneToN, NToOne;
		
		public static Order valueOf(final boolean b) {
			if (b) {
				return NToOne;
			}
			return OneToN;
		}
	}
	
    private String message = "";
    private LinkedList<TLCState> states = new LinkedList<TLCState>();
    private TLCError cause;
    private int errorCode;
	private int numberOfStatesToShow = Integer.MAX_VALUE; // no restriction by default
    /**
     * Sort order in which states are sorted in the variable viewer
     */
	private Order stateSortDirection;

	public TLCError() {
		this(Order.OneToN);
	}
	
	public TLCError(final Order order) {
		this.stateSortDirection = order;
	}
	
    /**
     * Add a state to a trace
     * @param state state to add
     */
    public void addState(TLCState state)
    {
        if (stateSortDirection == Order.NToOne) {
        	states.addFirst(state);
        } else {
        	states.add(state);
        }
    }

    /**
     * Retrieves a cause of this error (or null if not a chained error)
     * @return the causing error
     */
    public final TLCError getCause()
    {
        return cause;
    }

    public final void setCause(TLCError cause)
    {
        this.cause = cause;
    }

    public final String getMessage()
    {
        return message;
    }

	public void restrictTraceTo(int numberOfStatesToShow) {
		this.numberOfStatesToShow = numberOfStatesToShow;
	}
	
	public boolean isTraceRestricted() {
		return this.states.size() > this.numberOfStatesToShow;
	}
	
	/**
	 * @return The amount of trace states currently hidden because of the
	 *         restriction.
	 */
	public int getNumberOfRestrictedTraceStates() {
		if (isTraceRestricted()) {
			return this.states.size() - this.numberOfStatesToShow;
		} else {
			return 0;
		}
	}

	public int getTraceRestriction() {
		return this.numberOfStatesToShow;
	}
	
	public void reduceTraceRestrictionBy(int numberOfStatesToShow) {
		this.numberOfStatesToShow += numberOfStatesToShow;
	}

	public int getTraceSize(final int level) {
		if (states.isEmpty()) {
			return 0;
		}
		
		TLCState representative = this.states.getFirst();
		if (representative.isInitialState()) {
			representative = states.getLast();
		}
		final int varCnt = representative.getVariableCount(level);
		
		if (numberOfStatesToShow < states.size()) {
			return numberOfStatesToShow * (varCnt + 1);
		}
		return states.size() * (varCnt + 1);
	}
	
	public int getTraceSize() {
		return getTraceSize(0);
	}
	
	public final List<TLCState> getStates() {
		return getStates(Length.RESTRICTED);
	}

	/**
	 * Returns the {@link TLCState}s that represent the trace of this
	 * {@link TLCError}. If {@link Length#ALL} is given, all {@link TLCState}s
	 * are returned regardless of any restriction imposed. Length.RESTRICTED
	 * returns the subList of states according to the restriction set.
	 * 
	 * @param l
	 * @return
	 */
	public final List<TLCState> getStates(Length l) {
		if (l == Length.ALL) {
			return states;
		}
		if (states.size() > numberOfStatesToShow) {
			// If only a sublist is requested, the current order of the list has
			// to be taken into account. Otherwise, reversing the tree's sort
			// order with a subList input will alternate between the states' 
			// head and tail.
			// I.e. the tree starts with the state's tail. The user then changes
			// the sort order which triggers a call to getStates again. However,
			// because the underlying states list had been reversed in the
			// meantime, it now returns the head.
			if (states.getFirst().isInitialState()) {
				// If the first state is the initial state, the list is sorted in
				// ascending order. Thus, return the states' tail. Otherwise, head.
				return states.subList(states.size() - numberOfStatesToShow, states.size());
			}
			return states.subList(0, numberOfStatesToShow);
		}
		return states;
	}
	
	public void removeStates(final List<TLCState> statesToRemove) {
		states.removeAll(statesToRemove);
	}

	public boolean isTraceEmpty() {
		return numberOfStatesToShow == 0 || states.isEmpty();
	}

    public final int getErrorCode()
    {
        return errorCode;
    }

    public final void setErrorCode(int errorCode)
    {
        this.errorCode = errorCode;
    }

    public void setMessage(String message)
    {
        this.message = message;
    }

    public boolean hasTrace()
    {
        return this.states != null && !this.states.isEmpty();
    }
    
	public void reverseTrace() {
		stateSortDirection = stateSortDirection == Order.OneToN ? Order.NToOne : Order.OneToN;
		Collections.reverse(states);
	}
	
	public Order getOrder() {
		return stateSortDirection;
	}

	public boolean isOrder(Order o) {
		return stateSortDirection == o;
	}

	private void orderTrace(Order order) {
		if (stateSortDirection != order) {
			Collections.reverse(states);
			stateSortDirection = order;
		}
	}

	public String toSequenceOfRecords(final boolean includeHeaders) {
		final StringBuffer buf = new StringBuffer();
		buf.append(TLAConstants.BEGIN_TUPLE);
		buf.append(TLAConstants.CR);
		
		for (int i = 0; i < states.size(); i++) {
			final TLCState tlcState = states.get(i);
			if (tlcState.isBackToState() || tlcState.isStuttering()) {
				//TODO How to represent these two types of states?
				continue;
			}
			if (tlcState.getVariablesAsList().isEmpty() && includeHeaders == false) {
				// When an user has used filtering to hide all variables, the error trace here
				// has no variables. In this case just return empty sequence <<>> by breaking
				// from the loop.
				break;
			}
			
			if (i > 0) {
				// Append a comma if a record is going to be added below.
				buf.append(TLAConstants.COMMA).append(TLAConstants.CR);
			}
			buf.append(tlcState.asRecord(includeHeaders));
		}
			
		buf.append(TLAConstants.CR);
		buf.append(TLAConstants.END_TUPLE);
		return buf.toString();
	}

	public void applyFrom(final TLCError originalErrorWithTrace, final Map<String, Formula> traceExplorerExpressions,
			final Hashtable<String, TraceExpressionInformationHolder> traceExpressionDataTable,
			final String modelName) {

		// retrieve the original trace
		// this is necessary for items (3) and (5) from the list in the
		// documentation for this method
		List<TLCState> originalTrace = originalErrorWithTrace.getStates(Length.ALL);
		Assert.isNotNull(originalTrace, "Could not get original trace after running trace explorer. This is a bug.");

		// a comparator used for sorting the variables within each
		// state so that the variables representing the trace explorer
		// expressions appear first in each state
		final Comparator<TLCVariable> varComparator = new Comparator<TLCVariable>() {

			public int compare(TLCVariable var0, TLCVariable var1) {
				if ((var0.isTraceExplorerVar() && var1.isTraceExplorerVar())
						|| (!var0.isTraceExplorerVar() && !var1.isTraceExplorerVar())) {
					// both represent TE expressions or neither does
					// use string comparison to make sure
					// that the variables appear in the same order
					// in every state
					return var0.getName().compareTo(var1.getName());
				} else if (var0.isTraceExplorerVar()) {
					// var0 should appear before
					return -1;
				} else {
					// var1 represents TE expression, so it should appear before
					return 1;
				}
			}
		};

		final Order requestedOrder = originalErrorWithTrace.stateSortDirection;
		
		// Aligning both traces to the canonical order (OneToN) as precondition to the
		// code below which hasn't been written to support the NToOne order. The requested
		// order is applied at the end.
		this.orderTrace(Order.OneToN);
		originalErrorWithTrace.orderTrace(Order.OneToN);

		// found an error with a trace
		// this is the trace produced by the run
		// of TLC for the trace explorer
		List<TLCState> newTrace = this.getStates();

		Iterator<TLCState> newTraceIt = newTrace.iterator();
		Iterator<TLCState> originalTraceIt = originalTrace.iterator();

		TLCState currentStateNewTrace = newTraceIt.next();
		TLCState nextStateNewTrace = null;

		TLCState currentStateOriginalTrace = originalTraceIt.next();

		/*
		 * The following while loop performs items 1-4 for some of the states. In
		 * particular, if the original trace has n states and the trace produced by the
		 * trace explorer has m states, this loop performs items 1-4 for states 1
		 * through min(n-1, m-1). The trace produced by the trace explorer can be
		 * shorter than the original trace if there is a TLC error during evaluation of
		 * one of the states. The trace produced by the trace explorer can be longer
		 * than the original trace as in the example of item 5.
		 * 
		 * The final state of the trace produced by the trace explorer is processed
		 * after this loop. Item 5 is also accomplished after this loop.
		 */
		while (newTraceIt.hasNext() && originalTraceIt.hasNext()) {

			// change the label of the state of newTrace to the label of the state
			// of the original trace
			currentStateNewTrace.setLabel(currentStateOriginalTrace.getLabel());

			// set the location of the current state of the new trace
			currentStateNewTrace.setLocation(currentStateOriginalTrace.getModuleLocation());

			// need to get the next state in order to perform any
			// shifting of expression values (item 2 in the documentation)
			nextStateNewTrace = (TLCState) newTraceIt.next();

			TLCVariable[] currentStateNewTraceVariables = currentStateNewTrace.getVariables();
			TLCVariable[] nextStateNewTraceVariables = nextStateNewTrace.getVariables();

			applyFrom(traceExplorerExpressions, traceExpressionDataTable, nextStateNewTrace,
					currentStateNewTraceVariables, nextStateNewTraceVariables);

			// sort the variables so that the variables representing trace explorer
			// expressions appear first
			Arrays.sort(currentStateNewTraceVariables, varComparator);

			currentStateNewTrace = nextStateNewTrace;

			currentStateOriginalTrace = originalTraceIt.next();
		}

		/*
		 * Remove any extra states (item 5).
		 * 
		 * This is only necessary for looping or stuttering traces (n elements in
		 * original trace, m elements in new trace)- if (m >= n) remove states n..m else
		 * do nothing
		 * 
		 * if (m >= n), the new trace will be left with n-1 elements. Later code adds
		 * the final stuttering or "back to state" state to these traces.
		 * 
		 * There should never be extra states for non-looping, non-stuttering traces.
		 */
		if ((currentStateOriginalTrace.isBackToState() || currentStateOriginalTrace.isStuttering())
				&& newTrace.size() >= originalTrace.size()) {
			newTrace.subList(originalTrace.size() - 1, newTrace.size()).clear();
		}

		this.restrictTraceTo(originalErrorWithTrace.getTraceRestriction());

		// new trace should now be no longer than the original trace
		Assert.isTrue(newTrace.size() <= originalTrace.size(),
				"States from trace explorer trace not removed properly.");

		// fix the final state
		final TLCState finalStateOriginalTrace = (TLCState) originalTrace.get(originalTrace.size() - 1);

		if (newTrace.size() < originalTrace.size() - 1
				|| (!finalStateOriginalTrace.isStuttering() && !finalStateOriginalTrace.isBackToState())) {
			/*
			 * For a non-looping and non-stuttering state, just set the expressions with
			 * primed variables equal to "--" for the last state.
			 * 
			 * Do the same thing if the new trace is less than the original trace size minus
			 * 1. This means there was a TLC error before evaluating all of the states, so
			 * even if the original trace finished with a looping state or a stuttering
			 * state, the trace that is displayed to the user should not. It should
			 * terminate before the TLC error occurred.
			 */

			TLCState finalStateNewTrace = (TLCState) newTrace.get(newTrace.size() - 1);

			// state in the original trace at the same position as finalStateNewTrace
			TLCState samePositionOriginalTrace = (TLCState) originalTrace.get(newTrace.size() - 1);

			// set the label of the final state of the new trace
			finalStateNewTrace.setLabel(samePositionOriginalTrace.getLabel());

			// set the location of the final state of the new trace
			finalStateNewTrace.setLocation(samePositionOriginalTrace.getModuleLocation());

			TLCVariable[] finalStateNewTraceVariables = finalStateNewTrace.getVariables();

			// iterate through the variables
			for (int i = 0; i < finalStateNewTraceVariables.length; i++) {

				TraceExpressionInformationHolder traceExpressionData = traceExpressionDataTable
						.get(finalStateNewTraceVariables[i].getName().trim());

				if (traceExpressionData != null) {
					// we have located a trace expression variable

					if (traceExpressionData.getLevel() == 2) {
						// expression with primed variables
						// shift the value from the next state to the current state
						finalStateNewTraceVariables[i].setValue(TLCVariableValue.parseValue("\"--\""));
					}

					// set the name to be the expression the variable represents
					finalStateNewTraceVariables[i].setName(traceExpressionData.getExpression());
					// flag this as a variable representing a trace explorer expression
					finalStateNewTraceVariables[i].setTraceExplorerVar(true);
				}
			}

			// sort the variables of the final state
			Arrays.sort(finalStateNewTraceVariables, varComparator);
		} else if (finalStateOriginalTrace.isBackToState()) {
			this.addState(TLCState.BACK_TO_STATE(finalStateOriginalTrace.getStateNumber(), modelName));
		} else {
			// stuttering trace
			this.addState(TLCState.STUTTERING_STATE(finalStateOriginalTrace.getStateNumber(), modelName));
		}
		
		this.orderTrace(requestedOrder);
	}

	private void applyFrom(final Map<String, Formula> traceExplorerExpressions,
			final Hashtable<String, TraceExpressionInformationHolder> traceExpressionDataTable,
			TLCState nextStateNewTrace, TLCVariable[] currentStateNewTraceVariables,
			TLCVariable[] nextStateNewTraceVariables) {
		// iterate through the variables
		for (int i = 0; i < currentStateNewTraceVariables.length; i++) {
			// This code assumes that the variables are in the same order in each state
			String variableName = currentStateNewTraceVariables[i].getName();
			// if next state is back to state or stuttering, it has no variables, so the
			// code
			// contained within the if block would cause an NPE
			if (!nextStateNewTrace.isBackToState() && !nextStateNewTrace.isStuttering()) {
				Assert.isTrue(variableName.equals(nextStateNewTraceVariables[i].getName()),
						"Variables are not in the same order in each state. This is unexpected.");
			}

			// retrieve the object containing the data corresponding to the variable.
			// this object will be null if the variable currently being looked at does
			// not represent a trace explorer expression
			// If the variable does represent a trace explorer expression, then the
			// following
			// object will contain the variable name, the expression, and the level of the
			// expression
			TraceExpressionInformationHolder traceExpressionData = traceExpressionDataTable.get(variableName.trim());

			if (traceExpressionData != null) {
				// we have located a trace expression variable

				// If next state is back to state or stuttering, it has no variables, so the
				// code contained within this if block would not apply. It should be unnecessary
				// to check for this because the while loop should terminate before this
				// happens.
				if (!nextStateNewTrace.isBackToState() && !nextStateNewTrace.isStuttering()
						&& traceExpressionData.getLevel() == 2) {
					// found expression with primed variables
					// shift the value from the next state to the current state
					currentStateNewTraceVariables[i].setValue(nextStateNewTraceVariables[i].getValue());

				}

				// set the name to be the expression the variable represents
				currentStateNewTraceVariables[i].setName(traceExpressionData.getExpression());

				// flag this as a variable representing a trace explorer expression
				currentStateNewTraceVariables[i].setTraceExplorerVar(true);

				continue;
			}

			if (traceExplorerExpressions.containsKey(variableName.trim())) {
				currentStateNewTraceVariables[i].setTraceExplorerVar(true);
			}
		}
	}
	
	/**
	 * This clone includes clones of each TLCState held.
	 */
	@Override
	public TLCError clone() {
		final TLCError clone = new TLCError(stateSortDirection);
		
		clone.message = message;
		clone.cause = cause;
		clone.errorCode = errorCode;
		clone.numberOfStatesToShow =  numberOfStatesToShow;
		states.stream().forEach((state) -> clone.states.add(state.clone()));
		
		return clone;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/UnrecoverableException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class UnrecoverableException extends Throwable
{
    public UnrecoverableException(String message)
    {
        super(message);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/RMIFilenameToStreamResolver.java<|end_filename|>
package tlc2.tool.distributed;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;

import util.FilenameToStream;

/**
 * This class extends the SimpleFilenameToStream class in the way that it first
 * tries to resolve file with the local {@link FilenameToStream} resolver, but
 * falls back to RMI if the local resolver fails.
 *
 * This is used for distributed TLC where a worker does not necessarily have
 * access to the specification and/or configuration files.
 *
 * Care must be taken with transferring big files. This implementation is
 * inefficient in the way that it requires the server to read the full file into
 * memory before it gets transferred to the client. The client too, will buffer
 * the full file in memory. This constraint is acceptable for TLA specifications
 * and configurations as they are usually small enough to fit into memory "easily".
 */
public class RMIFilenameToStreamResolver implements FilenameToStream {

	private static final String javaTempDir = System.getProperty("java.io.tmpdir") + File.separator;

	private TLCServerRMI server;

	private final Map<String, File> fileCache = new HashMap<String, File>();
	private final String rndPrefix;

	public RMIFilenameToStreamResolver() {
		rndPrefix = getRandomStoragePrefix();
	}

	public RMIFilenameToStreamResolver(final String[] libraryPaths) {
		rndPrefix = getRandomStoragePrefix();
	}

	public void setTLCServer(final TLCServerRMI aServer) {
		this.server = aServer;
	}

	/* (non-Javadoc)
	 * @see util.FilenameToStream#resolve(java.lang.String, boolean)
	 */
	public File resolve(final String filename, final boolean isModule) {

		// read the file from the server
		// strip off path
		final String name = new TLAFile(filename, this).getName();

		File file = fileCache.get(name);
		// not in cache
		if (file == null ||  !file.exists()) {

			// read bytes from server
			byte[] bs = new byte[0];
			try {
				bs = server.getFile(name);
			} catch (RemoteException e) {
				e.printStackTrace();
			}

			// write into temp file
			file  = writeToNewTempFile(name, bs);

			// add to local file cache
			fileCache.put(name, file);
		}

		return file;
	}

	/**
	 * I am hoping that a resolver of this class is never used to parse
	 * the spec.  If it is, then a module's isStandard field will always
	 * be false in a run of distributed TLC.  This isn't a problem, since
	 * that field was added for use by a version of SANY called by TLAPS.
	 *
	 * Added by LL on 24 July 2013.
	 */
	public boolean isStandardModule(String moduleName) {
		// The following error message code should be uncommented
		// if the parser should not be called with an object of
		// this class.
//		 String[] foo = new String[] {
//	       "Parsing called with unexpected FileNameToString implementation."} ;
//		 MP.printTLCBug(42, foo) ;
		 return false ;
	}

	private String getRandomStoragePrefix() {
		final File file = new File(javaTempDir + System.currentTimeMillis());
		file.deleteOnExit();
		file.mkdir();
		return file.getAbsolutePath();
	}

	private File writeToNewTempFile(String name, byte[] bs) {
		final File f = new TLAFile(rndPrefix + File.separator + name, this);
		f.deleteOnExit();

		FileOutputStream outputStream = null;
		try {
			outputStream = new FileOutputStream(f);
			outputStream.write(bs);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return f;
	}

	public String getFullPath() {
		StringBuffer buf = new StringBuffer();

		String[] strings = fileCache.keySet().toArray(new String[fileCache.size()]);
		for (int i = 0; i < strings.length; i++) {
			String string = strings[i];
			buf.append(string);
			if (i < string.length() - 1) {
				buf.append(", ");
			}
		}
		return buf.toString();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAEditorAndPDFViewer.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import java.io.File;
import java.io.IOException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.INavigationLocationProvider;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * This is a multi page editor with two tabs.
 * The first tab is a module text editor.
 * The second tab is a browser that displays a pdf file
 * generated using tla2tex on the given module. This tab will only appear
 * after a pdf file has first been generated.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLAEditorAndPDFViewer extends FormEditor implements INavigationLocationProvider, ITextEditor
{

    /**
     * Editor ID
     */
    public static final String ID = "org.lamport.tla.toolbox.editor.basic.TLAEditorAndPDFViewer";
    public static final String PDFPage_ID = "pdfPage";
    // index at which the tla module editor tab appears
    private static final int tlaEditorIndex = 0;

    private Image rootImage = TLAEditorActivator.imageDescriptorFromPlugin(TLAEditorActivator.PLUGIN_ID,
            "/icons/root_file.gif").createImage();

    PDFViewingPage pdfViewingPage;
    IEditorInput tlaEditorInput;
    TLAEditor tlaEditor;

    /* (non-Javadoc)
     * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
     */
    @Override
    protected void addPages()
    {
        try
        {

            // This code moves the tabs to the top of the page.
            // This makes them more obvious to the user.
            if (getContainer() instanceof CTabFolder)
            {
                final CTabFolder cTabFolder = (CTabFolder) getContainer();
				cTabFolder.setTabPosition(SWT.TOP);
				
				// If there is only the editor but no PDF shown next to it, the tab bar of the
				// ctabfolder just wastes screen estate.
				if (cTabFolder.getItemCount() <= 1) {
					cTabFolder.setTabHeight(0);
				} else {
					cTabFolder.setTabHeight(-1);
				}
            }

            tlaEditor = new TLAEditor();

            addPage(tlaEditorIndex, tlaEditor, tlaEditorInput);
            setPageText(tlaEditorIndex, "TLA Module");

        } catch (PartInitException e)
        {
        	// I hope you don't choke swallowing all those exceptions...
            e.printStackTrace();
        }
    }
    
	
	@Override
	public int addPage(IFormPage page) throws PartInitException {
		final int idx = super.addPage(page);
		
		if (getContainer() instanceof CTabFolder) {
			final CTabFolder cTabFolder = (CTabFolder) getContainer();
			// If there is only the editor but no PDF shown next to it, the tab bar of the
			// ctabfolder just wastes screen estate.
			if (cTabFolder.getItemCount() <= 1) {
				cTabFolder.setTabHeight(0);
			} else {
				cTabFolder.setTabHeight(-1);
			}
		}
		return idx;
	}

	@Override
	public void removePage(int pageIndex) {
		super.removePage(pageIndex);
		if (getContainer() instanceof CTabFolder) {
			final CTabFolder cTabFolder = (CTabFolder) getContainer();
			// If there is only the editor but no PDF shown next to it, the tab bar of the
			// ctabfolder just wastes screen estate.
			if (cTabFolder.getItemCount() <= 1) {
				cTabFolder.setTabHeight(0);
			} else {
				cTabFolder.setTabHeight(-1);
			}
		}
	}

    /* (non-Javadoc)
     * @see org.eclipse.ui.forms.editor.FormEditor#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
     */
    public void init(IEditorSite site, IEditorInput input) throws PartInitException
    {

        tlaEditorInput = input;
        if (input instanceof FileEditorInput)
        {
            FileEditorInput finput = (FileEditorInput) input;
            if (finput != null)
            {
                final IFile file = finput.getFile();
				if (ResourceHelper.isModule(file))
                {
					// MAK 04/2019: Strip off filename extension to align with Toolbox's Spec
					// Explorer which doesn't show the extension either.  The Toolbox only has
					// two editors (TLA+ specs and TLC models).  Showing the extension thus
					// provides little value to users.  Also, the editor description shows the
					// full path to the actual file on disk right below where the part name
					// is shown.
                    this.setPartName(file.getName().replaceFirst(".tla$", ""));
                }

                if (ResourceHelper.isRoot(file))
                {
                    setTitleImage(rootImage);
                }
            }
        }
        super.init(site, input);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
     */
    public void doSave(IProgressMonitor monitor)
    {
        tlaEditor.doSave(monitor);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.EditorPart#doSaveAs()
     */
    public void doSaveAs()
    {

        IFile file = ((FileEditorInput) getEditorInput()).getFile();
        Shell shell = UIHelper.getShellProvider().getShell();

        // TODO fix this?
        IPath specRootPrefix = new Path(ResourceHelper.getParentDirName(ToolboxHandle.getRootModule()));

        FileDialog saveAsDialog = null;
        while (true)
        {
            // construct the dialog
            // should this be replaced by a dialog showing the logical view of the FS?
            saveAsDialog = new FileDialog(shell, SWT.SAVE);
            saveAsDialog.setOverwrite(true);
            saveAsDialog.setText("Select the new filename...");
            saveAsDialog.setFilterExtensions(new String[] { "*.tla" });
            saveAsDialog.setFilterNames(new String[] { "TLA+ Files" });
            saveAsDialog.setFilterPath(ResourceHelper.getParentDirName(file));
            String result = saveAsDialog.open();
            saveAsDialog = null;
            // no cancellation
            if (result != null)
            {
                IPath newPath = new Path(result);
                // check whether the file is in the same directory as the root module
                if (!specRootPrefix.isPrefixOf(newPath))
                {
                    MessageDialog.openError(shell, "Wrong location selected",
                            "The provided filename must point to the same directory as the specification root file");
                    continue;
                }

                // fix the extension
                if (!"tla".equals(newPath.getFileExtension()))
                {
                    newPath = newPath.addFileExtension("tla");
                }

                File newFile = newPath.toFile();
                if (newFile.exists())
                {
                    boolean confirmOverwrite = MessageDialog.openQuestion(shell, "Overwrite file?",
                            "The provided filename already exists. The existing file will be overwritten.\nDo you want to overwrite the file "
                                    + newPath.toOSString() + "?");
                    if (!confirmOverwrite)
                    {
                        continue;
                    }

                    // overwriting existing file file exists
                } else
                {
                    // file does not exist
                    // create the empty file
                    boolean newFileCreated = false;
                    try
                    {
                        newFileCreated = newFile.createNewFile();
                    } catch (IOException e)
                    {
                        // do nothing, since we react on the newFileCreated being false
                    }
                    if (!newFileCreated)
                    {
                        MessageDialog.openError(shell, "Error saving a file", "File could not be created");
                        break;
                    }
                }

                // create a link to a file
                IFile newResource = ResourceHelper.getLinkedFile(file.getProject(), newPath.toOSString());

                // new editor input
                IEditorInput newInput = new FileEditorInput(newResource);

                //TLAEditorActivator.getDefault().logDebug("TODO: Save " + file.getLocation().toOSString() + " as " + newPath);

                // get the document provider
                IDocumentProvider provider = tlaEditor.getDocumentProvider();
                boolean saveAsSuccess = false;
                try
                {
                    // notify
                    provider.aboutToChange(newInput);
                    // perform the save
                    provider.saveDocument(new NullProgressMonitor(), newInput, provider.getDocument(getEditorInput()),
                            true);
                    saveAsSuccess = true;
                } catch (CoreException x)
                {
                    MessageDialog.openError(shell, "Error saving a file", "File could not be created");
                } finally
                {
                    // notify
                    provider.changed(newInput);
                    if (saveAsSuccess)
                    {
                        // change the input
                        // alternatively, open another editor with the new resource?
                        setInput(newInput);
                        tlaEditor.setInput(newInput);
                        if (newInput instanceof FileEditorInput)
                        {
                            FileEditorInput fin = (FileEditorInput) newInput;
                            setPartName(fin.getFile().getName());
                        }
                    }
                }
                // break out on save
                break;
            } else
            {
                // break out on cancel of the dialog
                break;
            }
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
     */
    public boolean isSaveAsAllowed()
    {
        return tlaEditor.isSaveAsAllowed();
    }


    
	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocationProvider#createEmptyNavigationLocation()
	 */
	public INavigationLocation createEmptyNavigationLocation() {
		return tlaEditor.createEmptyNavigationLocation();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation()
	 */
	public INavigationLocation createNavigationLocation() {
		return tlaEditor.createNavigationLocation();
	}

	/**
     * Creates the pdfViewinPage and adds it to the editor if it does not exist.
     * Returns the pdfViewing page whether it previously existed or not.
     * @return
     */
    public PDFViewingPage getPDFViewingPage()
    {
        if (pdfViewingPage == null)
        {
            pdfViewingPage = new PDFViewingPage(this, PDFPage_ID, "PDF Viewer");
            try
            {
                addPage(pdfViewingPage);
            } catch (PartInitException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        // setActivePage(PDFPage_ID);
        return pdfViewingPage;
    }

    public TLAEditor getTLAEditor()
    {
        return tlaEditor;
    }
    
	@Override
	public void setFocus() {
		super.setFocus();

		// Show the OS's location of this spec in the Toolbox's status line (bottom
		// left). Before, this was shown in this editor's content description but this
		// wastes too much space.
		final IEditorInput input = getEditorInput();
		if (input != null) {
			if (input instanceof FileEditorInput) {
				FileEditorInput fin = (FileEditorInput) input;
				tlaEditor.setStatusMessage(String.format("%s [ %s ]", getPartName(), fin.getPath().toOSString()));
			} else {
				tlaEditor.setStatusMessage(input.getName());
			}
		}
	}
    
    /**
     * Sets the TLA module editor as the active
     * tab for this editor. Does not necessarily make
     * this multi-page editor the active editor.
     */
    public void setTLAEditorActive()
    {
        setActivePage(tlaEditorIndex);
    }


    /* (non-Javadoc)
     * @see org.eclipse.ui.texteditor.ITextEditor#getDocumentProvider()
     */
    public IDocumentProvider getDocumentProvider() {
		return tlaEditor.getDocumentProvider();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#isEditable()
	 */
	public boolean isEditable() {
		return tlaEditor.isEditable();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#doRevertToSaved()
	 */
	public void doRevertToSaved() {
		tlaEditor.doRevertToSaved();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#setAction(java.lang.String, org.eclipse.jface.action.IAction)
	 */
	public void setAction(String actionID, IAction action) {
		tlaEditor.setAction(actionID, action);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#getAction(java.lang.String)
	 */
	public IAction getAction(String actionId) {
		return tlaEditor.getAction(actionId);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#setActionActivationCode(java.lang.String, char, int, int)
	 */
	public void setActionActivationCode(String actionId,
			char activationCharacter, int activationKeyCode,
			int activationStateMask) {
		tlaEditor.setActionActivationCode(actionId, activationCharacter, activationKeyCode, activationStateMask);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#removeActionActivationCode(java.lang.String)
	 */
	public void removeActionActivationCode(String actionId) {
		tlaEditor.removeActionActivationCode(actionId);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#showsHighlightRangeOnly()
	 */
	public boolean showsHighlightRangeOnly() {
		return tlaEditor.showsHighlightRangeOnly();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#showHighlightRangeOnly(boolean)
	 */
	public void showHighlightRangeOnly(boolean showHighlightRangeOnly) {
		tlaEditor.showHighlightRangeOnly(showHighlightRangeOnly);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#setHighlightRange(int, int, boolean)
	 */
	public void setHighlightRange(int offset, int length, boolean moveCursor) {
		tlaEditor.setHighlightRange(offset, length, moveCursor);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#getHighlightRange()
	 */
	public IRegion getHighlightRange() {
		return tlaEditor.getHighlightRange();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#resetHighlightRange()
	 */
	public void resetHighlightRange() {
		tlaEditor.resetHighlightRange();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#getSelectionProvider()
	 */
	public ISelectionProvider getSelectionProvider() {
		return tlaEditor.getSelectionProvider();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.texteditor.ITextEditor#selectAndReveal(int, int)
	 */
	public void selectAndReveal(int offset, int length) {
		tlaEditor.selectAndReveal(offset, length);
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/source/Bug267Test.java<|end_filename|>
// Copyright (c) Feb 6, 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox.tool.tlc.output.source;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;

import org.easymock.EasyMock;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITypedRegion;
import org.junit.Assert;
import org.junit.Test;
import org.lamport.tla.toolbox.tool.tlc.model.Model;

public class Bug267Test {

	public String getInput(String name) throws Exception {
		URL url = this.getClass().getClassLoader().getResource(name);
        InputStream inputStream = url.openConnection().getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		
		// Read the input fully here
		StringBuffer buf = new StringBuffer();
		String line;
		while((line = reader.readLine()) != null) {
			buf.append(line);
			buf.append("\n");
		}
		
		reader.close();

		return buf.toString();
	}
	
	@Test
	public void testSuccess() throws Exception {
		final TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		
		final Bug267Listener listener = new Bug267Listener();

		final ITLCOutputSource source = parser.getSource();
		source.addTLCOutputListener(listener);
		
		// read in test input and feed it to the parser
		try {
			parser.addIncrement(getInput("files/Bug267success.out"));
		} catch (BadLocationException e) {
			fail();
		}
		
		source.removeTLCOutputListener(listener);
		
		assertTrue(listener.getErrors().size() == 2);
	}
	
	@Test
	public void testAdd2154And2132Nested() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		final String startTag = "@!@!@STARTMSG 2154:0 @!@!@\n";
		final String text = "Attempted to apply the operator overridden by the Java method\n"
				+ "public static tlc2.value.Value tlc2.module.TLC.Assert(tlc2.value.Value,tlc2.value.Value),\n"
				+ "but it produced the following error:\n";
		final String endTag = "@!@!@ENDMSG 2154 @!@!@\n";
		
		final String nestedStartTag = "@!@!@STARTMSG 2132:0 @!@!@\n";
		final String nestedText = "The first argument of Assert evaluated to FALSE; the second argument was:\n\"Failure of assertion.\"\n";
		final String nestedEndTag = "@!@!@ENDMSG 2132 @!@!@\n";

		final String fullText = startTag + text + nestedStartTag + nestedText + nestedEndTag + endTag;
		
		// read in test input and feed it to the parser
		try {

			parser.addIncrement(startTag);
			
				parser.addIncrement(text);
				
				parser.addIncrement(nestedStartTag);
	
					parser.addIncrement(nestedText);
				
				parser.addIncrement(nestedEndTag);
			
			parser.addIncrement(endTag);
			
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}

		parser.done();

		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all or too many regions detected", 1, regions.size());

		// assert that the input text can be found with the given region
		final TLCRegionContainer region = (TLCRegionContainer) regions.get(0); // safe due to previous assert
		final ITypedRegion[] subRegions = region.getSubRegions();
		
		// outter text
		final ITypedRegion subRegionsOutter = subRegions[1];
		final String regionText = fullText.substring(
				subRegionsOutter.getOffset(), subRegionsOutter.getOffset()
						+ subRegionsOutter.getLength());
		Assert.assertEquals(text, regionText);
		
		// nested/inner text
		final ITypedRegion subRegionsNested = subRegions[0];
		final String nestedRegionText = fullText.substring(
				subRegionsNested.getOffset(), subRegionsNested.getOffset()
						+ subRegionsNested.getLength() + 1);
		Assert.assertEquals(nestedText, nestedRegionText);
	}

	@Test
	public void testAdd2132Region() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		final String startTag = "@!@!@STARTMSG 2132:0 @!@!@\n";
		final String text = "The first argument of Assert evaluated to FALSE; the second argument was:\n\"Failure of assertion.\"\n";
		final String endTag = "@!@!@ENDMSG 2132 @!@!@\n";
		
		// read in test input and feed it to the parser
		try {

			parser.addIncrement(startTag);
			parser.addIncrement(text);
			parser.addIncrement(endTag);
			
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}
		
		parser.done();
		
		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());
		
		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all or too many regions detected", 1, regions.size());
		
		// assert that the input text can be found with the given region
		final ITypedRegion region = regions.get(0); // safe due to previous assert
		final String regionText = (startTag + text + endTag).substring(
				region.getOffset(), region.getOffset() + region.getLength()
				+ 1);
		Assert.assertEquals(text, regionText);
	}

	@Test
	public void testAdd2154Region() throws IOException {
		TagBasedTLCOutputIncrementalParser parser = new TagBasedTLCOutputIncrementalParser(new DummyModel(), 0, false);
		// Register test listener with parser output

		ITLCOutputSource source = parser.getSource();
		DummyListener testListener = new DummyListener();
		source.addTLCOutputListener(testListener);

		final String startTag = "@!@!@STARTMSG 2154:0 @!@!@\n";
		final String text = "Attempted to apply the operator overridden by the Java method\n"
				+ "public static tlc2.value.Value tlc2.module.TLC.Assert(tlc2.value.Value,tlc2.value.Value),\n"
				+ "but it produced the following error:\n";
		final String endTag = "@!@!@ENDMSG 2154 @!@!@\n";

		// read in test input and feed it to the parser
		try {

			parser.addIncrement(startTag);
			parser.addIncrement(text);
			parser.addIncrement(endTag);
			
		} catch (BadLocationException e) {
			Assert.fail(e.getMessage());
		}

		parser.done();
		// expected, since tests call done()
		Assert.assertTrue(testListener.isDone());

		// all regions detected?
		final List<ITypedRegion> regions = testListener.getRegions();
		Assert.assertNotNull(regions);
		Assert.assertEquals("Not all or too many regions detected", 1, regions.size());

		// assert that the input text can be found with the given region
		final ITypedRegion region = regions.get(0); // safe due to previous assert
		final String regionText = (startTag + text + endTag).substring(
				region.getOffset(), region.getOffset() + region.getLength()
				+ 1);
		Assert.assertEquals(text, regionText);
	}
	
	private class DummyModel extends Model {

		DummyModel() {
			super(EasyMock.createNiceMock(ILaunchConfiguration.class));
		}
		
		public String getName() {
			// Stop super from delegating to ILC
			return "Bug267Test";
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/OneBitMutexTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.junit.Ignore;
import org.junit.Test;

import tlc2.output.EC;

public class OneBitMutexTest extends ModelCheckerTestCase {

	public OneBitMutexTest() {
		super("OneBitMutexMC", "symmetry" + File.separator + "OneBitMutex");
	}
	
	@Test
	@Ignore("Ignored for as long as symmetry is incorrectly handled by TLC with liveness checking.")
	public void testSpec() {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "133", "68", "0"));
		assertFalse(recorder.recorded(EC.GENERAL));

		// Assert it has found the temporal violation and also a counter example
		assertTrue(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
		assertTrue(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));
		
		assertNodeAndPtrSizes(7380L, 2368L);

		// Assert the error trace
		assertTrue(recorder.recorded(EC.TLC_STATE_PRINT2));
		final List<String> expectedTrace = new ArrayList<String>(17);
		//1
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"ncs\" @@ B :> \"ncs\")");
		//2
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n"
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> FALSE)\n"
						+ "/\\ pc = (A :> \"e1\" @@ B :> \"ncs\")");
		//3
		expectedTrace.add("/\\ unchecked = (A :> {B} @@ B :> {})\n"
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> FALSE)\n"
						+ "/\\ pc = (A :> \"e2\" @@ B :> \"ncs\")");
		//4
		expectedTrace.add("/\\ unchecked = (A :> {B} @@ B :> {})\n"
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"e2\" @@ B :> \"e1\")");
		//5
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"e3\" @@ B :> \"e1\")");
		//6
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {A})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> TRUE)\n" 
						+ "/\\ pc = (A :> \"e3\" @@ B :> \"e2\")");
		//7
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> TRUE)\n" 
						+ "/\\ pc = (A :> \"e3\" @@ B :> \"e3\")");
		//8 (Loops back to)
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> TRUE)\n" 
						+ "/\\ pc = (A :> \"e4\" @@ B :> \"e3\")");
		//9
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> TRUE @@ B :> TRUE)\n" 
						+ "/\\ pc = (A :> \"e4\" @@ B :> \"e4\")");
		//10
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> TRUE)\n" 
						+ "/\\ pc = (A :> \"e5\" @@ B :> \"e4\")");
		//11
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"e5\" @@ B :> \"e5\")");
		//12
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"e1\" @@ B :> \"e5\")");
		//13
		expectedTrace.add("/\\ unchecked = (A :> {} @@ B :> {})\n" 
						+ "/\\ other = (A :> B @@ B :> A)\n"
						+ "/\\ x = (A :> FALSE @@ B :> FALSE)\n" 
						+ "/\\ pc = (A :> \"e1\" @@ B :> \"e1\")");
		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);

		assertBackToState(4, "<Action line 60, col 13 to line 64, col 29 of module OneBitMutex>");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/MonolithSpecTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.regex.Pattern;

import org.junit.Before;
import org.junit.Test;

import tlc2.output.EC;
import tlc2.tool.liveness.ModelCheckerTestCase;
import util.TestPrintStream;
import util.ToolIO;

public class MonolithSpecTest extends ModelCheckerTestCase {
        final TestPrintStream testPrintStreamErr = new TestPrintStream();
		final TestPrintStream testPrintStreamOut = new TestPrintStream();

	public MonolithSpecTest() {
		super("MonolithSpec", new String[] { "-config", "MonolithSpec.tla" /* note the extension */ });
	}

        @Before
        public void beforeSetUp() {
            ToolIO.err = testPrintStreamErr;
			ToolIO.out = testPrintStreamOut;
            ToolIO.reset();
        }

	@Test
	public void testSpec() {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "214", "54", "0"));

        // Check that the warning or inexistent file does not occur.
        testPrintStreamErr.assertNoSubstring("File does not exist");

		// Test that the library path appears between `( )` after parsing the file.		
		final String sep = Pattern.quote(File.separator);
		testPrintStreamOut.assertRegex("Parsing file .*" + sep + "EWD840.tla \\(.*" + sep + "test-model" + sep + "MonolithSpec.tla\\)");
		testPrintStreamOut.assertRegex("Parsing file .*" + sep + "Mod4711.tla \\(.*" + sep + "test-model" + sep + "MonolithSpec.tla\\)");
		testPrintStreamOut.assertRegex("Parsing file .*" + sep + "Mod4712.tla \\(.*" + sep + "test-model" + sep + "MonolithSpec.tla\\)");

		assertZeroUncovered();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/coverage/ActionWrapper.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import tla2sany.semantic.LetInNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SubstInNode;
import tla2sany.st.Location;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.Action;

public final class ActionWrapper extends CostModelNode {

	public enum Relation {
		INIT, NEXT, PROP, CONSTRAINT;
	}
	
	private final Action action;
	private final Relation relation;
	
	public ActionWrapper(final Action action, Relation rel) {
		this.action = action;
		this.relation = rel;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.coverage.CostModelNode#getLocation()
	 */
	@Override
	protected Location getLocation() {
		if (this.action.isDeclared()) {
			return this.action.getDeclaration();
		}
		return this.action.pred.getLocation();
	}

	private String printLocation() {
		if (!this.action.isDeclared()) {
			// Safeguard for legacy cases if any.
			return this.action.toString();
		}
		// Determine if the mapping from the action's name/identifier/declaration to the
		// action's definition is 1:1 or 1:N.
		//
		// Act == /\ x  = 23
		//        /\ x' = 42
		// vs
		// Act == \/ /\ x  = 23
		//           /\ x' = 42
		//        \/ /\ x  = 123
		//           /\ x' = 4711
		// or
		// Act == (x  = 23 /\ x' = 42) \/ (x  = 123 /\ x' = 4711)
		//
		// For a 1:1 mapping this prints just the location of Act. For a 1:N mapping it
		// prints the location of Act _and_ the location (in shortened form) of the actual
		// disjunct.
		final Location declaration = this.action.getDeclaration();
		final Location definition = this.action.getOpDef().getBody().getLocation();
		final Location actual = this.action.pred.getLocation();
		if (definition.equals(actual)) {
			// 1:1
			return String.format("<%s %s>", this.action.getName(), declaration);
		} else {
			// 1:N
			return String.format("<%s %s (%s %s %s %s)>", this.action.getName(), declaration, actual.beginLine(),
					actual.beginColumn(), actual.endLine(), actual.endColumn());
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.coverage.CostModelNode#getRoot()
	 */
	@Override
	public CostModelNode getRoot() {
		return this;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.CostModel#get(tla2sany.semantic.SemanticNode)
	 */
	@Override
	public final CostModel get(final SemanticNode eon) {
		// returns this instance in case no match is found in children. As a result, the
		// CostModel will be incorrect which is not as severe as running into an NPE.
		if (eon instanceof SubstInNode) {
			final SubstInNode sin = (SubstInNode) eon;
			return this.children.getOrDefault(sin.getBody(), this);
		} else if (eon instanceof LetInNode) {
			final LetInNode lin = (LetInNode) eon;
			return this.children.getOrDefault(lin.getBody(), this);
		}
		return this.children.getOrDefault(eon, this);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.coverage.CostModelNode#getNode()
	 */
	@Override
	SemanticNode getNode() {
		return action.pred;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.coverage.CostModelNode#isRoot()
	 */
	@Override
	boolean isRoot() {
		return true;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.coverage.CostModel#report()
	 */
	public CostModel report() {
		// Report count for action itself.
		if (relation == Relation.PROP) {
			assert getEvalCount() == 0L && this.secondary.getCount() == 0L;
			MP.printMessage(EC.TLC_COVERAGE_PROPERTY, new String[] { printLocation() });
		} else if (relation == Relation.INIT) {
			// TODO Eventually coverage for init and next should consistently report states
			// found and distinct states into the same counters.
			MP.printMessage(EC.TLC_COVERAGE_INIT, new String[] { printLocation(), String.valueOf(getEvalCount()),
					String.valueOf(getEvalCount() + this.secondary.getCount()) });
		} else if (relation == Relation.CONSTRAINT) {
			MP.printMessage(EC.TLC_COVERAGE_CONSTRAINT,
					new String[] { printLocation(), String.valueOf(this.secondary.getCount()),
							String.valueOf(getEvalCount() + this.secondary.getCount()) });
		} else {
			MP.printMessage(EC.TLC_COVERAGE_NEXT, new String[] { printLocation(),
					String.valueOf(this.secondary.getCount()), String.valueOf(getEvalCount()) });
		}

		// An action has single child which is the OpApplNodeWrapper with the OpApplNode
		// for this OpDefNode unless the action's pred is a substitution or a let/in expr.
		assert !(this.action.pred instanceof SubstInNode || this.action.pred instanceof LetInNode)
				? this.children.size() == 1
				: !this.children.isEmpty();
		// Let children report.
		// Could disable here if decided to implement action-only coverage at the TLC
		// level (see org.lamport.tla.toolbox.tool.tlc.model.Model.Coverage).
		this.children.values().forEach(c -> c.report());
		return this;
	}

	public boolean is(Relation r) {
		return r == this.relation;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/Sx.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:42 PST by lamport
//      modified on Fri Jun 11 16:16:03 PDT 1999 by yuanyu

package tlc2.util;

import java.io.PrintWriter;
import java.util.Hashtable;

import util.WrongInvocationException;

public abstract class Sx {

  public static SxNil nil = new SxNil();

  private static Hashtable atomTbl = new Hashtable();
  private static int symCount = 0;  // Number of symbols returned by genSym().
  
  public static Sx cons(Sx a, Sx b) {
    return new SxPair(a, b);
  }

  public static Sx car(Sx a) {
    if (!(a instanceof SxPair)) {
        throw new WrongInvocationException("Car must be applied to cons.");
    }
    return ((SxPair)a).car;
  }

  public static Sx cdr(Sx a) {
    if (!(a instanceof SxPair)) {
        throw new WrongInvocationException("Cdr must be applied to cons.");
    }
    return ((SxPair)a).cdr;
  }
    
  public static Sx List(Sx a) { return cons(a, nil); }

  public static Sx List(Sx a, Sx b) {
    return cons(a, cons(b, nil));
  }

  public static Sx List(Sx a, Sx b, Sx c) {
    return cons(a, cons(b, cons(c, nil)));
  }

  public static Sx List(Sx a, Sx b, Sx c, Sx d) {
    return cons(a, cons(b, cons(c, cons(d, nil))));
  }

  public static Sx Append(Sx a, Sx b) {
    if (a == nil) return b;
    return cons(car(a), Append(cdr(a), b));
  }

  // Successive calls to genSym return distinct atoms.
  public static SxAtom genSym() {
    return Atom("F__" + (symCount++));
  }
  
  /* Returns true iff a is eq to an element of list p. */
  public static boolean memq(SxAtom a, Sx p) {
    while (p != nil) {
      if (a == car(p)) {
	return true;
      }
      else {
	p = cdr(p);
      }
    }
    return false;
  }
  
  public static SxAtom Atom(String st) {
    SxAtom res = (SxAtom)atomTbl.get(st);
    if (res == null) {
      res = new SxAtom(st);
      atomTbl.put(st, res);
    }
    return res;
  }

  public static Sx FromInt(int k) { return new SxInt(k); }
  
  public abstract void print(PrintWriter pw);
  
  public static class SxAtom extends Sx {
    public String st;
  
    private SxAtom(String st) { this.st = st; }

    public void print(PrintWriter pw) { pw.print(this.st); }
  }

  public static class SxInt extends Sx {
    public int val;
  
    public SxInt(int k) { this.val = k; }

    public void print(PrintWriter pw) { pw.print(this.val); }
  }

  public static class SxNil extends Sx {
    private SxNil() { /*SKIP*/ }

    public void print(PrintWriter pw) { pw.print("nil"); }
  }
  
  public static class SxPair extends Sx {
    public Sx car, cdr;
  
    public SxPair(Sx a, Sx b) {
      this.car = a;
      this.cdr = b;
    }

    public void print(PrintWriter pw) {
      pw.print("(");
      this.car.print(pw);
      Sx next = this.cdr;
      while (next instanceof SxPair) {
	pw.print(" ");
	((SxPair)next).car.print(pw);
	next = ((SxPair)next).cdr;
      }
      if (next != nil) { pw.print(" . "); next.print(pw); }
      pw.print(")");
    }
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.uitest/src/org/lamport/tla/toolbox/tool/tlc/ui/test/ModelCheckerTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.test;

import java.io.File;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.matchers.WithText;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.waits.Conditions;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.ui.IEditorPart;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

@RunWith(SWTBotJunit4ClassRunner.class)
public class ModelCheckerTest extends AbstractTest {

	@BeforeClass
	public static void beforeClass() {
		// mimic super
		AbstractTest.beforeClass();
	}

	@Test
	public void testNewModel() {
		// Open specA
		SWTBotMenu fileMenu = bot.menu("File");
		SWTBotMenu openSpecMenu = fileMenu.menu("Open Spec");
		SWTBotMenu addNewSpecMenu = openSpecMenu.menu("Add New Spec...");
		addNewSpecMenu.click();

		bot.textWithLabel("Root-module file:").setText(specA);
		bot.button("Finish").click();

		final String specName = getSpecName(new File(specA));

		// specs are created in non-UI thread asynchronously which causes a
		// delay before the menu entry becomes available
		bot.waitUntil(Conditions.waitForMenu(bot.activeShell(), WithText.<MenuItem> withText(specName)));
		
		// create a new model
		final SWTBotMenu modelMenu = bot.menu("TLC Model Checker");
		final SWTBotMenu newModelMenu = modelMenu.menu("New Model...");
		newModelMenu.click();
		bot.button("OK").click();

		// wait for model editor to show up and parse
		bot.waitUntil(new ModelEditorOpenCondition("Model_"));
		
		// register job listener who listens for the model checker job
		final String modelName = UIHelper.getActiveEditor().getTitle();
		final Model model = ToolboxHandle.getCurrentSpec().getAdapter(TLCSpec.class).getModel(modelName);
		final IJobChangeListener listener = new DummyJobChangeListener(model);
		Job.getJobManager().addJobChangeListener(listener);
		
		// start model checking by clicking the menu. This is more robust
		// compared to the f11 keystroke which can get lost when fired during
		// initialization of the model editor.
		bot.menu("TLC Model Checker").menu("Run model").click();

		// make unit test wait for model checker job to finish
		bot.waitUntil((ICondition) listener, SWTBotPreferences.TIMEOUT * 3);

		// Do some unregistration prior to model deletion:
		Job.getJobManager().removeJobChangeListener(listener);
		
		// close corresponding editor if open
		final IEditorPart editorWithModelOpened = model.getAdapter(ModelEditor.class);
		if (editorWithModelOpened != null) {
			UIHelper.runUISync(new Runnable() {
				public void run() {
					UIHelper.getActivePage().closeEditor(editorWithModelOpened,
							false);
				}
			});
		}

		// Delete the newly created model again. It does not use the UI because
		// SWTBot cannot handle the modal confirmation dialog do delete the
		// model.
		// Deleting the model is necessary because repeated test execution would
		// leave huge numbers of model leftovers contributing to slowed down test
		// execution (see SizeControlContribution for reason why).
		try {
			model.delete(new NullProgressMonitor());
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/TLCWorkerSmartProxy.java<|end_filename|>
package tlc2.tool.distributed;

import java.net.URI;
import java.rmi.RemoteException;

import tlc2.tool.TLCState;
import tlc2.tool.WorkerException;

/**
 * Poor mans RMI smart proxy which is used to measure network overhead
 */
public class TLCWorkerSmartProxy implements TLCWorkerRMI {

	/**
	 * The remote reference
	 */
	private final TLCWorkerRMI worker;
	/**
	 * Network overhead for a getNextStates method invocation
	 */
	private double networkOverhead = Double.MAX_VALUE;

	public TLCWorkerSmartProxy(final TLCWorkerRMI aWorker) {
		worker = aWorker;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerRMI#getNextStates(tlc2.tool.TLCState[])
	 */
	public NextStateResult getNextStates(final TLCState[] states) throws RemoteException, WorkerException {
		// Prefer currentTimeMillis over nanoTime as it uses less CPU cycles to read
		final long start = System.currentTimeMillis();
		
		// do actual remote call
		final NextStateResult nextStates = worker.getNextStates(states);

		final long roundTripTime = (System.currentTimeMillis() - start) + 1; // at least one millisecond if get next below resolution
		final long computationTime = sanitizeComputationTime(nextStates.getComputationTime());

		// RTT has to be bigger than computation alone
		double networkTime = Math.max(roundTripTime - computationTime, 0.00001d);

		double percentageNetworkOverhead = networkTime / roundTripTime;
		
		// network overhead per state
		networkOverhead = percentageNetworkOverhead / states.length;
		
		return nextStates;
	}
	
	// handle illegal values from worker
	private long sanitizeComputationTime(Long computationTime) {
		return Math.max(Math.abs(computationTime), 1);
	}

	/**
	 * @return The network overhead for a remote call in %
	 */
	public double getNetworkOverhead() {
		return networkOverhead;
	}
	
	/* All other methods just delegate */

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerRMI#exit()
	 */
	public void exit() throws RemoteException {
		worker.exit();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerRMI#getURI()
	 */
	public URI getURI() throws RemoteException {
		return worker.getURI();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerRMI#isAlive()
	 */
	public boolean isAlive() throws RemoteException {
		return worker.isAlive();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.TLCWorkerRMI#getCacheRateRatio()
	 */
	public double getCacheRateRatio() throws RemoteException {
		return worker.getCacheRateRatio();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/expression/ModelErrorsTester.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.expression;

import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.ui.IEditorPart;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCOutputSourceRegistry;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

public class ModelErrorsTester extends PropertyTester
{

    /**
     * 
     */
    public boolean test(Object receiver, String property, Object[] args, Object expectedValue)
    {
        if (UIHelper.getActivePage() != null)
        {
            IEditorPart activeEditor = UIHelper.getActiveEditor();
            if (activeEditor != null)
            {
                if (activeEditor instanceof ModelEditor)
                {
                    ModelEditor activeModelEditor = (ModelEditor) activeEditor;
                    Model model = activeModelEditor.getModel();
                    if (model != null)
                    {
                        return TLCOutputSourceRegistry.getModelCheckSourceRegistry().getProvider(model).getErrors().size() > 0;
                    }
                }
            }
        }
        return false;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/BTGraphNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:36 PST by lamport
//      modified on Sun Sep  3 10:33:35 PDT 2000 by yuanyu

package tlc2.tool.liveness;

public class BTGraphNode extends BEGraphNode {
	/**
	 * BTGraphNode is a node in the behaviour graph. We're going to only store
	 * fingerprints of states, rather than actual states. So, as we encounter
	 * each state, we will calculate all the <>[] and []<>s listed in our order
	 * of solution. For each arrow we must record the target node and the
	 * checkActions along it.
	 */

	/**
	 * The unique index for the tableau graph node. Bit 31 is used as the "done"
	 * bit; bit 30 is used as the "dummy" bit. So, the maximum size of tableau
	 * is 2^30.
	 */
	private int tindex;

	public BTGraphNode(long fp, int index) {
		super(fp);
		this.tindex = index;
	}

	public final int getIndex() {
		return (this.tindex & 0x3FFFFFFF);
	}

	public final void setIndex(int index) {
		this.tindex = (this.tindex & 0xC0000000) | index;
	}

	public final boolean isDone() {
		return this.tindex < 0;
	}

	public final void setDone() {
		this.tindex |= 0x80000000;
	}

	public static BTGraphNode makeDummy(long fp) {
		return new BTGraphNode(fp, 0x40000000);
	}

	public final boolean isDummy() {
		return (this.tindex & 0x40000000) > 0;
	}


	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (stateFP ^ (stateFP >>> 32));
		result = prime * result + getIndex();
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		BTGraphNode other = (BTGraphNode) obj;
		if (stateFP != other.stateFP) {
			return false;
		}
		if (getIndex() != other.getIndex()) {
			return false;
		}
		return true;
	}

	public final TBGraphNode getTNode(TBGraph tableau) {
		return tableau.getNode(this.getIndex());
	}

	public final String nodeInfo() {
		return "<" + this.stateFP + "," + this.getIndex() + ">";
	}

	/**
	 * This method assumes that the visited field of all the nodes is set to the
	 * same value. It flips the visited field. We use the high-order bit of
	 * this.number as the visited bit.
	 */
	protected final void toString(StringBuffer buf, boolean unseen) {
		if (this.getVisited() == unseen) {
			this.flipVisited();
			buf.append("(" + this.stateFP + "," + this.getIndex() + ") --> ");
			int size = this.nextSize();
			if (size != 0) {
				BTGraphNode node = (BTGraphNode) this.nextAt(0);
				buf.append("(" + node.stateFP + "," + node.getIndex() + ")");
			}
			for (int i = 1; i < size; i++) {
				buf.append(", ");
				BTGraphNode node = (BTGraphNode) this.nextAt(i);
				buf.append("(" + node.stateFP + "," + node.getIndex() + ")");
			}
			buf.append("\n");
			for (int i = 0; i < size; i++) {
				this.nextAt(i).toString(buf, unseen);
			}
		}
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/ObligationNumberMessage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;

/**
 * Represents a message from TLAPM that has one field, "count"
 * containing the number of obligations to be checked or proved.
 * 
 * @author <NAME>
 *
 */
public class ObligationNumberMessage extends TLAPMMessage
{
    /**
     * Number of obligations in the message.
     */
    private int count;

    /**
     * Field giving the number of obligations in the message.
     */
    public static final String COUNT_FIELD = "count";

    public static ObligationNumberMessage getObNumMessage(Set fieldPairs, String moduleName)
    {
        ObligationNumberMessage message = new ObligationNumberMessage();

        for (Iterator it = fieldPairs.iterator(); it.hasNext();)
        {
            Map.Entry nextEntry = (Map.Entry) it.next();
            String fieldName = (String) nextEntry.getKey();
            String fieldValue = (String) nextEntry.getValue();
            if (fieldName != null && fieldValue != null)
            {
                if (fieldName.equals(COUNT_FIELD))
                {
                    try
                    {
                        message.count = Integer.parseInt(fieldValue);
                    } catch (NumberFormatException e)
                    {
                        ProverUIActivator.getDefault().logError("Count field in message cannot be parsed to an int."
                                + "The message contains the fields " + fieldPairs, e);
                    }
                }
            }
        }

        return message;
    }

    /**
     * Returns the number of obligations in the message.
     * This is the number of obligations to be proved or checked.
     * 
     * @return the count
     */
    public int getCount()
    {
        return count;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/launch/IModelConfigurationConstants.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.launch;

/**
 * @author <NAME>
 */
public interface IModelConfigurationConstants extends IConfigurationConstants {
    /**
     * Comments
     */
    public static final String MODEL_COMMENTS = "modelComments";
    /**
     * number showing if one closed formula is used
     */
    public static final String MODEL_BEHAVIOR_SPEC_TYPE = "modelBehaviorSpecType";
    /**
     * formula which points behavior specification
     */
    public static final String MODEL_BEHAVIOR_CLOSED_SPECIFICATION = "modelBehaviorSpec";
    /**
     * formula which points init part of the specification
     */
    public static final String MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_INIT = "modelBehaviorInit";
    /**
     * formula which points next part of the specification
     */
    public static final String MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_NEXT = "modelBehaviorNext";
    /**
     * formula which points fairness part of the specification
     */
    public static final String MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_FAIRNESS = "modelBehaviorFairness";
    /**
     * no specification option
     */
    public static final String MODEL_BEHAVIOR_NO_SPEC = "modelBehaviorNoSpec";
    /**
     * Variables
     */
    public static final String MODEL_BEHAVIOR_VARS = "modelBehaviorVars";

    /**
     * flag for checking deadlock
     */
    public static final String MODEL_CORRECTNESS_CHECK_DEADLOCK = "modelCorrectnessCheckDeadlock";
    /**
     * invariants list
     */
    public static final String MODEL_CORRECTNESS_INVARIANTS = "modelCorrectnessInvariants";
    /**
     * property lists
     */
    public static final String MODEL_CORRECTNESS_PROPERTIES = "modelCorrectnessProperties";

    /**
     * This property is set only if, when creating the model, the Properties
     * part should be expanded when first opened.
     */
    public static final String MODEL_PROPERTIES_EXPAND = "modelPropertiesExpand";
    /**
     * action constraints list
     */
    public static final String MODEL_PARAMETER_ACTION_CONSTRAINT = "modelParameterActionConstraint";
    /**
     * constraint 
     */
    public static final String MODEL_PARAMETER_CONSTRAINT = "modelParameterContraint";
    /**
     * constant list 
     */
    public static final String MODEL_PARAMETER_CONSTANTS = "modelParameterConstants";
    /**
     * definitions list
     */
    public static final String MODEL_PARAMETER_DEFINITIONS = "modelParameterDefinitions";
    /**
     * new definitions list
     */
    public static final String MODEL_PARAMETER_NEW_DEFINITIONS = "modelParameterNewDefinitions";
    /**
     * advanced model values not used in constant definitions
     */
    public static final String MODEL_PARAMETER_MODEL_VALUES = "modelParameterModelValues";
    /**
     * view
     */
    public static final String MODEL_PARAMETER_VIEW = "modelParameterView";
    /**
     * post condition
     */
    public static final String MODEL_PARAMETER_POST_CONDITION = "modelParameterPostCondition";
    /**
     * alias
     */
    public static final String MODEL_PARAMETER_ALIAS  = "modelParameterAlias";
    /**
     * constant expression to be evaluated
     */
    public static final String MODEL_EXPRESSION_EVAL = "modelExpressionEval";
    /**
     * Extra modules to extended by TE.tla.
     */
    public static final String TRACE_EXPLORE_EXTENDS = "traceExploreExtends";
    
    /**
     * a bitwise OR'd value representing which of the closeable tabs should be open on a model editor opening
     */
    public static final String EDITOR_OPEN_TABS = "modelEditorOpenTabs";
    
    /**
     * values to use with the {@link #EDITOR_OPEN_TABS} attribute
     */
	public static final int EDITOR_OPEN_TAB_NONE = 0;
	public static final int EDITOR_OPEN_TAB_ADVANCED_MODEL = 1 << 1;
	public static final int EDITOR_OPEN_TAB_ADVANCED_TLC = 1 << 2;
	public static final int EDITOR_OPEN_TAB_RESULTS = 1 << 3;
    
    /**
     * an integer representing the model version - we'll probably use YYYYMMDD
     */
    public static final String MODEL_VERSION = "modelVersion";
    
    /**
     * values to use with the {@link #MODEL_VERSION} attribute
     */
    public static final int VERSION_160 = 20190710;
    // this value needn't be cemented before release, as long as kept consistently increasing during development
    public static final int VERSION_161 = 20191005;
    
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/MemBasedSet.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

public abstract class MemBasedSet {

	protected int size;

	protected int[] elems;

	public MemBasedSet(final int minCapacity) {
		this.size = 0;
		this.elems = new int[minCapacity];
	}
	
	protected int[] ensureCapacity(final int minCapacity) {
		// If the internal storage reaches its capacity, double the size of
		// the internal storage. This strategy is great for as long as size
		// is smaller than 2^31. Once size is >= 2^31, doubling it means it
		// becomes negative resulting in a NegativeArraySizeException. Additionally
		// if size gets larger and larger, an OutOfMemory exception becomes 
		// more likely when MemIntStacks memory requirements get doubled.
		// From the literature and popular implementations (e.g. Java's ArrayList),
		// a growth factor of 1.5 seems to be practical.
		final int newSize = (int) ((this.size * 3L) / 2) + 1; // multiply with *long* 3L to stay positive
		// If newSize is negative (happens when size become too large for
		// int), just increase the array by MIN_CAPACITY. This obviously
		// doesn't prevent a NegativeArraySizeException either, but it
		// postpones it to the moment when the int-sized array will be
		// completely full. At this point, nothing can be done except using
		// two MemIntStack instances which requires changes in the places
		// where MemIntStack is used or swapping MemIntStack to disk (which -
		// from looking at the ctor's parameters - appears to be the preferred
		// solution of the original MemIntStack authors).
		//
		// Performance obviously goes south the moment the array is 
		// increased in MIN_CAPACITY steps. It's a trade off between risking
		// an OutOfMemory exception and performance.
		return new int[Math.max(newSize, this.size + minCapacity)];
	}

	/**
	 * Return the number of items on the stack.
	 */
	public final long size() {
		return this.size;
	}

	public final boolean hasElements() {
		return this.size > 0;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/org/apache/commons/math3/util/FastMath.java<|end_filename|>
package org.apache.commons.math3.util;

public class FastMath {

	public static double sqrt(int d) {
		// The original implementation of FastMath.java in Apache Commons Math delegates
		// to Math.sqrt too. However, its FastMath has many more methods in that we drag
		// in many dependencies. We don't want nor need those dependencies.
		return Math.sqrt(d);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/Tokenize.java<|end_filename|>
/***************************************************************************
* CLASS Tokenize                                                           *
*                                                                          *
* The main methods of this class are                                       *
*                                                                          *
*    TLAExpr TokenizeExpr(PcalCharReader charReader)                       *
*                                                                          *
*       It returns a TLAExpr obtained by reading characters from           *
*       charReader.  It stops reading characters after it has read the     *
*       first token that follows the expression.  Upon return,             *
*                                                                          *
*           Tokenize.Delimiter                                             *
*              is the string that equals that following token.             *
*           Tokenize.DelimiterLine, Tokenize.DelimiterCol                  *
*              are the string's line and column numbers (first = 0)        *
*                                                                          *
*       It would be nicer if Tokenize simply left the reader               *
*       positioned before that following token.  However, this             *
*                                                                          *
*       Note: If there are line breaks between the position at which       *
*       this is called and the first token of the expression, then         *
*       these will produce null lines in the output.  I think that         *
*       will produce the proper translated output, but I'm not             *
*       positive.                                                          *
*                                                                          *
*    String  GetAlgorithmToken(PcalCharReader charReader)                  *
*       This returns the next token from charReader, ignoring TLA+         *
*       comments.  It is used for parsing the algorithm.                   *
*                                                                          *
* This class was written by modifying tlatex.TokenizeSpec.  The major      *
* changes are that it uses pcal.PcalBuiltInSymbols instead of              *
* tlatex.BuiltInSymbols (which defines ";" as an additional built-in       *
* token), CommentTokenOut was modified to throw away comments, and         *
* TokenOut was modified to end the parsing when the end of the expression  *
* is detected (and to detect some errors).                                 *
*                                                                          *
* In the +CAL grammar, an expression is ended by any of the following      *
* tokens (which follow the express, and are not part of it):               *
*                                                                          *
*   ;   variable   variables   begin   do   then   :=   ||                 *
*                                                                          *
* or by a ")" or a "," that does not match or occur inside an unmatched    *
* "(", "[", "{", or "<<" .                                                 *
*                                                                          *
* Because TokenizeExpr doesn't try to parse the expression but merely      *
* looks for a delimiter, an error in the algorithm text can cause it to    *
* gobble up a fair amount of the algorithm before it realizes that it's    *
* outside the expression.  For example, if one forgets the ";" and writes  *
*                                                                          *
*        x := x + 1                                                        *
*       if x > y + 17 then                                                 *
*                                                                          *
* then the parser keeps building the expression until it hits the "then",  *
* and reports the missing semicolon at that point.  Error reporting could  *
* be improved by being more aggressive at testing for the end of the       *
* expression.  For example, we could prohibit "if", "when", "while",       *
* "with", and "else" from appearing in an expression and test for them.    *
*                                                                          *
* Comment added by LL on 28 Feb 2006:                                      *
* Because the ParseAlgorithm.Uncomment method is now called before the     *
* algorithm is tokenized, the code here for handling comments is not       *
* needed.  However, an unmatched *) before the "end algorithm" could       *
* cause the tokenize methods in this class to encounter a comment.  An     *
* error should be reported if this happens.  This has not been done.       *
*                                                                          *
* ------------------------------------------------------------------       *
*                                                                          *
*    THE FOLLOWING IS THE DOCUMENTATION FROM tlatex.TokenizeSpec           *
*                                                                          *
* This class contains the Tokenize method that takes a CharReader for a    *
* TLA specification, or part of a specification, and tokenizes it.         *
* After tokenizing the spec, it provides the methods                       *
*                                                                          *
*    isIdent                                                               *
*    isUsedBuiltin                                                         *
*    isString                                                              *
*                                                                          *
* that tell whether a particular string appeared in the spec as an         *
* identifier, built-in operator, or TLA+ string.  These methods are used   *
* in TokenizeComment.Tokenize to try to determine if a comment token       *
* represents a specification symbol.                                       *
*                                                                          *
* The following comments are from tlatex.TokenizeSpec.  The description    *
* of TLA mode describes how tokens are parsed by the current module.       *
* However, in the current module, the parsing is normally stopped before   *
* the DONE state.                                                          *
*                                                                          *
* -----------------------------------------------------------------------  *
*                                                                          *
* The Tokenize method can be called in one of two modes:                   *
*                                                                          *
*   TLA mode    : It assumes that the input is any arbitrary portion       *
*                 of a TLA+ spec.                                          *
*   MODULE mode : It assumes that the input consists of arbitrary          *
*                 text, followed by a complete module, followed            *
*                 by arbitrary text.                                       *
*                                                                          *
* The result returned by Tokenize is an an array of arrays spec of Token   *
* objects, where spec[i][j] is token number j on line number i of the      *
* input, where the first line is numbered 0 and the first token of a line  *
* is numbered 0.                                                           *
*                                                                          *
* This is not quite a tokenizer for a parser for the following reasons:    *
*                                                                          *
*   -- Inner nested comments are thrown away.                              *
*                                                                          *
*   -- It keeps the "\" in escape sequences in strings.  For               *
*      example, when tokenizing the string "a\"b", it produces             *
*      the string with the four characters a \ " b instead                 *
*      of the three characters a " b, which is what a tool would           *
*      probably want.                                                      *
*                                                                          *
*   -- Expressions of the form "expr.WF_string" or "expr.SF_string"        *
*      are parsed as  "expr . WF_ string" instead of "expr . WF_string".   *
*      (This is a bug.)                                                    *
*                                                                          *
* The tokenizing algorithm is described below.  The description has the    *
* following BNF syntax:                                                    *
*                                                                          *
*    <Description> ::=                                                     *
*        <State_Action> | <State_Action> <Description>                     *
*                                                                          *
*    <State_Action>    ::=  <State_Name> ":" <Action_Sequence>             *
*                                                                          *
*    <Action_Sequence> ::=  <Action> | <Action> <Action_Sequence>          *
*                                                                          *
*    <Action> ::=                                                          *
*         <Precondition> <Step_Sequence> "-->" <State_Name>                *
*                                                                          *
*    <Step_Sequence> ::= <Step> | <Step> ";" <StepSequence>                *
*                                                                          *
* The algorithm has a current state, which is initially START in TLA       *
* mode and PROLOG in MODULE mode.  When in a state S, the algorithm        *
* executes the <Action_Sequence> for the <State_Action> whose              *
* <State_Name> is S. It executes an <Action_Sequence> by going through     *
* its actions in order until it finds one whose <Precondition> is true.    *
* It then executes the <Step>s in that <Action>'s <Step_Sequence>, and     *
* then sets the current state to the <Action>'s <State_Name>.  However,    *
* the special <State_Name>s DONE and ERROR indicate that the algorithm     *
* is finished, either normally or with an error.                           *
*                                                                          *
* The algorithm uses the following variables:                              *
*                                                                          *
*    token :    The part of the token found so far.                        *
*                                                                          *
*    token1, token2, token3                                                *
*    col1,   col2,   col3   :                                              *
*               Temporary variables holding tokens and their starting      *
*               columns, used in processing the prolog.                    *
*                                                                          *
*    nextChar : The next character from the input stream                   *
*                                                                          *
*    cdepth :   The number of nested comments currently in.                *
*               (Equals 0 outside a comment.)                              *
*                                                                          *
*    mdepth :   The module nesting level.  (Determined by counting         *
*               "MODULE" keywords and "===="'s.                            *
*                                                                          *
* A <Precondition> has the form [exp], where exp is an ordinary            *
* expression, except the following conventions are used in it:             *
*                                                                          *
*   (S) asserts that nextChar equals S if S is a character, or             *
*     that nextChar is an element of S if S is a set of characters.        *
*     LegalStringChar is the set of all legal non-escaped characters       *
*     in a TLA+ string.                                                    *
*                                                                          *
*   token+ is the string obtained by appending nextChar to token.          *
*                                                                          *
*   BuiltIns is the set of all strings that are recognized by              *
*     TLA+ as operators or keywords.                                       *
*                                                                          *
*   BuiltInPrefix is the set of prefixes of all strings in                 *
*     BuiltIns except all-letter strings or strings consisting             *
*     of a "\\" (a backslash) followed by a sequence of letters.           *
*                                                                          *
*   OTHER equals TRUE.                                                     *
*                                                                          *
* I write (S) instead of [(S)].                                            *
*                                                                          *
* The following notation for steps is used.                                *
*                                                                          *
*   + means to append nextChar to token and set nextChar to the            *
*     next character in the input stream.                                  *
*                                                                          *
*   - means to set nextChar to the next character in the input             *
*     stream.                                                              *
*                                                                          *
*   TokenOut(type) and TokenOut(type, subtype) output  token               *
*     as a token of the indicated type and perhaps subtype,                *
*     and reset  token  to the empty string.                               *
*                                                                          *
* Here is the algorithm.                                                   *
*                                                                          *
* PROLOG:                                                                  *
*   ("-")     token1 := token; col1 := col ;                               *
*               token := "-" ; col := ncol; -     --> PROLOG_DASH          *
*   ("\n")    - ; TokenOut(PROLOG)                --> PROLOG               *
*   ("\t")                                        --> ERROR                *
*   [OTHER]   +                                   --> PROLOG               *
*                                                                          *
* PROLOG_DASH                                                              *
*   [("-") /\  Len(token) = 3]                                             *
*            +                        --> PROLOG_DASHES                    *
*   ("-")    +                        --> PROLOG_DASH                      *
*   [OTHER]  token := token1 + token; col := col1  --> PROLOG              *
*                                                                          *
* PROLOG_DASHES                                                            *
*   ("-")    +                              --> PROLOG_DASHES              *
*   [OTHER]  token2 := token ; token := "" ;                               *
*               col2 := col ; col = ncol    --> PROLOG_SPACES              *
*                                                                          *
* PROLOG_SPACES                                                            *
*   (" ")      +                                       --> PROLOG_SPACES   *
*   (Letter)   token3 := token ; col3 := ncol ;                            *
*                 token := ""                          --> PROLOG_ID       *
*   [OTHER]    token := token1 + token2 ; col := col1  --> PROLOG          *
*                                                                          *
* PROLOG_ID                                                                *
*   (Letter)  +                                            --> PROLOG_ID   *
*   [token = "MODULE"] token := token1; col := col1 ; TokenOut(PROLOG);    *
*                      token := token2; col := col2; TokenOut(DASHES);     *
*                      token := "MODULE"; col := col3;                     *
*                      TokenOut(BUILTIN);                                  *
*                      token := "" ;                                       *
*                      mdepth := 1                           --> START     *
*   [OTHER]   token := token1 + token2 + token3; col := col1 --> PROLOG    *
*                                                                          *
* START:                                                                   *
*   (Space_Char)          -  --> START                                     *
*   (Letter)              +  --> ID                                        *
*   (Digit)               +  --> NUM_OR_ID                                 *
*   ("\\")                +  --> BS                                        *
*   ("-")                 +  --> DASH1                                     *
*   ("=")                 +  --> EQ1                                       *
*   ("(")                 -  --> LEFT_PAREN                                *
*   ("\"")                -  --> STRING                                    *
*   ("\n")                -  --> START                                     *
*   (BuiltInPrefix)       +  --> BUILT_IN                                  *
*   [("\t") /\ TLA mode]     --> DONE                                      *
*   [OTHER]                  --> ERROR                                     *
*                                                                          *
* ID:                                                                      *
*   [token = "WF_" or "SF_"]  TokenOut(BUILTIN)     --> START              *
*   (Letter or Digit)         +                     --> ID                 *
*   [token = "MODULE"]        TokenOut(BUILTIN);                           *
*                             mdepth := mdepth + 1  --> START              *
*   [token \in BuiltIns]      TokenOut(BUILTIN)     --> START              *
*   [OTHER]                   TokenOut(IDENT)       --> START              *
*                                                                          *
* NUM_OR_ID:                                                               *
*   (Digit)   +                 --> NUM_OR_ID                              *
*   (Letter)  +                 --> ID                                     *
*   [OTHER]   TokenOut(NUMBER)  --> START                                  *
*                                                                          *
* BS:                                                                      *
*   ("b", "B", "o", "O", "h", or "H") +                --> NUM_OR_BI       *
*   (Letter)                                           --> BSBUILT_IN      *
*   ("*")                             - ; token := ""  --> LINE_COMMENT    *
*   [OTHER]                                            --> BUILT_IN        *
*                                                                          *
* NUM_OR_BI                                                                *
*   (Digit)   --> NUM                                                      *
*   [OTHER]   --> BSBUILT_IN                                               *
*                                                                          *
* NUM:                                                                     *
*   (Digit)  +                      --> NUM                                *
*   (Letter /\ token[1] != '\')   + --> ID                                 *
*   (Letter)                        --> ERROR                              *
*   [OTHER]  TokenOut(NUMBER)       --> START                              *
*                                                                          *
* BSBUILT_IN:                                                              *
*   (Letter)              +                  --> BSBUILT_IN                *
*   [token \in BuiltIns]  TokenOut(BUILTIN)  --> START                     *
*   [OTHER]                                  --> ERROR                     *
*                                                                          *
* BUILT_IN:                                                                *
*   [token+ \in BuiltInPrefix]  +                  --> BUILT_IN            *
*   [OTHER]   while (token \notin BuiltIn)                                 *
*               {move last char in token back                              *
*                to the CharReader};                                       *
*             TokenOut(BUILTIN)                    --> START               *
*                                                                          *
* DASH1:                                                                   *
*   ("-")   + --> DASH2                                                    *
*   [OTHER]   --> BUILT_IN                                                 *
*                                                                          *
* DASH2:                                                                   *
*   ("-")   + --> DASH3                                                    *
*   [OTHER]   --> BUILT_IN                                                 *
*                                                                          *
* DASH3:                                                                   *
*   ("-")   + --> DASHES                                                   *
*   [OTHER]   --> ERROR                                                    *
*                                                                          *
* DASHES:                                                                  *
*   ("-")   +                --> DASHES                                    *
*   [OTHER] TokenOut(DASHES) --> START                                     *
*                                                                          *
* EQ1:                                                                     *
*   ("=")   + --> EQ2                                                      *
*   [OTHER]   --> BUILT_IN                                                 *
*                                                                          *
* EQ2:                                                                     *
*   ("=")   + --> EQ3                                                      *
*   [OTHER]   --> BUILT_IN                                                 *
*                                                                          *
* EQ3:                                                                     *
*   ("=")   + --> EQS                                                      *
*   [OTHER]   --> ERROR                                                    *
*                                                                          *
* EQS:                                                                     *
*   ("=")   +                           --> EQS                            *
*   [TLA mode]  TokenOut(END_MODULE)    --> START                          *
*   [depth > 1] TokenOut(END_MODULE) ;                                     *
*               mdepth := mdepth - 1    --> START                          *
*   [depth = 1] TokenOut(END_MODULE) ;                                     *
*               mdepth := mdepth - 1    --> EPILOG                         *
*   [OTHER]                             --> ERROR                          *
*                                                                          *
* LEFT_PAREN:                                                              *
*   ("*")   - ; ; cdepth := 1   --> COMMENT                                *
*   [OTHER] token := "("        --> BUILT_IN                               *
*                                                                          *
* (**********************************************************)             *
* (* Note that we leave in the string the "\" of an escape  *)             *
* (* character like "\n".                                   *)             *
* (**********************************************************)             *
* STRING:                                                                  *
*   ("\\")             +                     --> ESC_STRING                *
*   ("\"")             - ; TokenOut(STRING)  --> START                     *
*   (LegalStringChar)  +                     --> STRING                    *
*   [OTHER]                                  --> ERROR                     *
*                                                                          *
* ESC_STRING:                                                              *
*   ("\"", "\\", "t", "n", "f", or "r")  + --> STRING                      *
*   [OTHER]                                --> ERROR                       *
*                                                                          *
* LINE_COMMENT:                                                            *
*   ("(")                 -                           --> LINE_COM_PAREN   *
*   [("*") /\ cdepth > 0]  -                          --> LINE_COM_STAR    *
*   ("\n" or "\t")        TokenOut(COMMENT, LINE)                          *
*                           ; cdepth := 0              --> START           *
*   [OTHER]               IF cdepth = 0 THEN + ELSE -  --> LINE_COMMENT    *
*                                                                          *
* LINE_COM_PAREN:                                                          *
*   ("*") - ; cdepth := cdepth + 1                   --> LINE_COMMENT      *
*   [OTHER]  IF cdepth = 0 THEN token := token + "("                       *
*                         ELSE                       --> LINE_COMMENT      *
*                                                                          *
* LINE_COM_STAR:                                                           *
*   (")")    - ; cdepth := cdepth - 1                 --> LINE_COMMENT     *
*   [OTHER]  IF cdepth = 0 THEN token := token + "*"                       *
*                          ELSE                       --> LINE_COMMENT     *
*                                                                          *
* COMMENT:                                                                 *
*   ("*")    -                                --> COMMENT_STAR             *
*   ("("}    -                                --> COMMENT_PAREN            *
*   ("\n")   TokenOut(COMMENT, BEGIN_OR) ; -  --> OR_COMMENT               *
*   ("\t")                                    --> ERROR                    *
*   [OTHER]  IF cdepth = 1 THEN + ELSE -      --> COMMENT                  *
*                                                                          *
*                                                                          *
* COMMENT_STAR:                                                            *
*   [(")") /\ cdepth = 1] - c; depth := cdepth - 1                         *
*                          ; TokenOut(COMMENT, NORMAL)  --> START          *
*   (")")                - ; cdepth := cdepth - 1       --> COMMENT        *
*   [OTHER]              IF cdepth = 1                                     *
*                          THEN token := token + "*"                       *
*                          ELSE                       --> COMMENT          *
*                                                                          *
* COMMENT_PAREN:                                                           *
*   ("*")    - ; cdepth := cdepth + 1                --> COMMENT           *
*   [OTHER]  IF cdepth = 1 THEN token := token + "("                       *
*                          ELSE                       --> COMMENT          *
*                                                                          *
* OR_COMMENT:                                                              *
*   ("*")    -                               --> OR_COMMENT_STAR           *
*   ("("}    -                               --> OR_COMMENT_PAREN          *
*   ("\n")   TokenOut(COMMENT, OVERRUN) ; -  --> OR_COMMENT                *
*   ("\t")                                   --> ERROR                     *
*   [OTHER]  IF cdepth = 1 THEN + ELSE -      --> OR_COMMENT               *
*                                                                          *
* OR_COMMENT_STAR:                                                         *
*   [(")") /\ cdepth = 1] - ; depth := depth - 1                           *
*                          ; TokenOut(COMMENT, END_OR)  --> START          *
*   (")")                - ; cdepth := cdepth - 1       --> OR_COMMENT     *
*   [OTHER]              IF cdepth = 1                                     *
*                          THEN token := token + "*"                       *
*                          ELSE                         --> OR_COMMENT     *
*                                                                          *
* OR_COMMENT_PAREN:                                                        *
*   ("*")    - ; cdepth := cdepth + 1                  --> OR_COMMENT      *
*   [OTHER]  IF cdepth = 1 THEN token := token + "("   --> OR_COMMENT      *
*                                                                          *
* EPILOG:                                                                  *
*   ("\n")  TokenOut(EPILOG) --> EPILOG                                    *
*   ("\t")  TokenOut(EPILOG) --> DONE                                      *
*   [OTHER] +                --> EPILOG                                    *
***************************************************************************/
package pcal;
import java.util.Vector;

import pcal.exception.TokenizerException;
import tla2tex.Misc;
import tla2tex.Symbol;
import tla2tex.Token;

public class Tokenize
  { private static final int MODULE = 1 ;
    private static final int TLA =    2 ;

    public static String Delimiter ;
    public static int DelimiterLine ;
    public static int DelimiterCol ;
      /*********************************************************************
      * Upon return, this equals the token following the expression.       *
      *********************************************************************/

      /*********************************************************************
      * The hash tables above are used only to remember the keys; there    *
      * is no value attached to them.  However, the Hashtable class        *
      * stores a non-null object with each key.  This is the object we     *
      * use.                                                               *
      *********************************************************************/

    /***********************************************************************
    * The following private class variables are used in the                *
    * implementation of the Tokenize method.  They are made class          *
    * variables so they can be accessed in procedures used by              *
    * TokenizedSpec (which are defined as private class methods).          *
    *                                                                      *
    * Note: This use of static fields makes the class totally thread       *
    * unsafe.                                                              *
    ***********************************************************************/
    private static Vector vspec = null ;
          /*****************************************************************
          * vspec is a vector of vectors in which the TokenizedSpec is     *
          * constructed.  At the end, it is turned into an array.          *
          *****************************************************************/

    private static Vector linev = new Vector(30, 30) ;
          /*****************************************************************
          * Vector linev contains the tokens found so far on the current   *
          * line.                                                          *
          *****************************************************************/

    private static char nextChar ;
          /*****************************************************************
          * nextChar is the next input character to be processed.          *
          *****************************************************************/

    /**
     * This is set to -1 when the last call to getNextChar returned a `\n',
     * and to 0 otherwise.  This is used by the TokenOut method, since if
     * a token is immediately followed by a `\n' character, then 
     * reader.getLineNumber will have been incremented before TokenOut
     * is called.
     */
    private static int getLineCorrection = 0 ;
    
    private static String token  = "" ;
    private static String token1 = "" ;
    private static String token2 = "" ;
    private static String token3 = "" ;
    private static int    col1   = 0 ;
    private static int    col2   = 0 ;
    private static int    col3   = 0 ;
          /*****************************************************************
          * token is the string containing the part of the token found so  *
          * far.                                                           *
          *                                                                *
          * token1, token2, and token3 are "temporary fields" holding a    *
          * previous value of token.                                       *
          *****************************************************************/

    private static int parenDepth = 0;
      /*********************************************************************
      * The current parenthesis nesting depth, where a parenthesis is      *
      * defined as a token of type BUILTIN whose corresponding Symbol      *
      * object has symbolType Symbol.LEFT_PAREN or Symbol.RIGHT_PAREN.     *
      *********************************************************************/

    private static boolean inQuantifier = false;
      /*********************************************************************
      * Set true if a `\A' or `\E' is found when parenDepth = 0, and set   *
      * false when a `:' is found with parenDepth = 0.  A comma does not   *
      * delimit the expression if encountered with inQuantifier = true.    *
      * This prevents the comma in an expression such as `\A i, j \in S :  *
      * P' from being interpreted as the end of the expression.  (A comma  *
      * found with parenDepth > 0 does not terminate the expression.)      *
      *********************************************************************/
      
    private static int cdepth = 0 ;
          /*****************************************************************
          * The nesting depth within "(*" ... "*)" comments.               *
          *****************************************************************/

    private static int mdepth = 0 ;
          /*****************************************************************
          * The module nesting depth.                                      *
          *****************************************************************/

    private static int col ;
    private static int ncol = 0;
          /*****************************************************************
          * col is the column from which the first character of token      *
          * came.                                                          *
          *                                                                *
          * ncol is the column from which nextChar came from.              *
          *****************************************************************/

/************* made public for DEBUGGING  ****************/
    public static PcalCharReader reader ;
      /*********************************************************************
      * This is the "exposed" version of the CharReader argument to the    *
      * TokenizedSpec constructor, exposed so it can be used by the        *
      * following procedures.                                              *
      *********************************************************************/

    /***********************************************************************
    * Here are all the states for the tokenizing algorithm.                *
    ***********************************************************************/
      private static final int PROLOG             = 1 ;
      private static final int PROLOG_DASH        = 2 ;
      private static final int PROLOG_DASHES      = 3 ;
      private static final int PROLOG_SPACES      = 4 ;
      private static final int PROLOG_ID          = 5 ;
      private static final int START              = 6 ;
      private static final int ID                 = 7 ;
      private static final int NUM_OR_ID          = 8 ;
      private static final int BS                 = 9 ;
      private static final int NUM                = 10 ;
      private static final int NUM_OR_BI          = 11 ;
      private static final int BSBUILT_IN         = 12 ;
      private static final int BUILT_IN           = 13 ;
      private static final int DASH1              = 14 ;
      private static final int DASH2              = 15 ;
      private static final int DASH3              = 16 ;
      private static final int DASHES             = 17 ;
      private static final int EQ1                = 18 ;
      private static final int EQ2                = 19 ;
      private static final int EQ3                = 20 ;
      private static final int EQS                = 21 ;
      private static final int LEFT_PAREN         = 22 ;
      private static final int STRING             = 23 ;
      private static final int ESC_STRING         = 24 ;
      private static final int LINE_COMMENT       = 25 ;
      private static final int LINE_COM_PAREN     = 26 ;
      private static final int LINE_COM_STAR      = 27 ;
      private static final int COMMENT            = 28 ;
      private static final int COMMENT_STAR       = 29 ;
      private static final int COMMENT_PAREN      = 30 ;
      private static final int OR_COMMENT         = 31 ;
      private static final int OR_COMMENT_PAREN   = 32 ;
      private static final int OR_COMMENT_STAR    = 33 ;
      private static final int EPILOG             = 34 ;
      private static final int DONE               = 35 ;
      
    private static int state = 0 ;
      /*********************************************************************
      * The state in the tokenizing algorithm.                             *
      *********************************************************************/

    private static boolean exprEnd = false;
      /*********************************************************************
      * Set true when at the end of the expression.                        *
      *********************************************************************/
      
    /***********************************************************************
    * The following private methods are all procedures for use by the      *
    * TokenizedSpec constructor.                                           *
    ***********************************************************************/


    private static void skipNextChar()
      /*********************************************************************
      * Sets nextChar to the next character in the input stream, and sets  *
      * ncol to its column.                                                *
      *********************************************************************/
      { ncol = reader.getColumnNumber();
        nextChar = reader.getNextChar();
        // See declaration of getLineCorrection for an explanation of:
        if (nextChar == '\n') {
            getLineCorrection = -1 ;
        } 
        else {
            getLineCorrection = 0 ;
        }
      } ;

    private static void addNextChar()
      /*********************************************************************
      * Appends nextChar to token, sets nextChar to the next character in  *
      * the input stream, and sets ncol to its column.                     *
      *********************************************************************/
      { token = token + nextChar ;
        skipNextChar() ;
      } ;

    private static void gotoStart()
      /*********************************************************************
      * Set the state to START. Since this means that we are at or before  *
      * the beginning of the next token, we set col equal to ncol.         *
      *********************************************************************/
      { state = START ;
        col = ncol ;
      }

    private static boolean parseExpression = true ;
      /*********************************************************************
      * The Tokenize method sets this value to its isExpr argument so the  *
      * TokenOut method can use it.  (Doing it the right way and making    *
      * it an argument of TokenOut would have required modifying all the   *
      * calls of TokenOut.)                                                *
      *********************************************************************/

    private static String prevToken = " " ;
      /*********************************************************************
      * Used by TokenOut to remember the previous token for figuring out   *
      * whether the current token is a record-field name rather than an    *
      * identifier.  This is needed to prevent a +cal reservered word      *
      * like "end" from screwing up the parsing when it is used as a       *
      * record-field name.  It is initialized in InnerTokenize and         *
      * set/reset by TokenOut.                                             
     * @throws TokenizerException *
      *********************************************************************/
      
    private static void TokenOut(int type) throws TokenizerException
      /*********************************************************************
      * If parseExpression is true, then add the token to linev and reset  *
      * token to the empty string unless it is the token following the     *
      * expression.  In that case, end the parsing and set Delimiter to    *
      * the token.  If parseExpression is false, then just set Delimiter   *
      * to the token and end the parsing.                                  *
      *********************************************************************/
      { if (parseExpression)
          { if (   (type == Token.BUILTIN)
                || (type == Token.NUMBER)
                || (type == Token.STRING)
                || (type == Token.IDENT) )
              { /***********************************************************
                * Check if this is a token that delimits the expression.   *
                ***********************************************************/
                if (   (type != Token.STRING)
                          /*************************************************
                          * Must not treat a string like ";" or "end" as   *
                          * delimiter.                                     *
                          *************************************************/
 
                    && (   (   IsDelimiter(token) 
                            && /********************************************
                               * Do not treat a reserved word like `end'   *
                               * as a delimiter if it may be a record      *
                               * field.                                    *
                               ********************************************/
                               ! (    (type == Token.IDENT)
                                   && (    prevToken.equals(".")
                                        || prevToken.equals("[")
                                        || prevToken.equals(","))))
                        || (   (   (    token.equals(",") 
                                     && ! inQuantifier)
                                || token.equals(")") 
                                || token.equals("}") 
                                   /****************************************
                                   * Test for "}" added 25 Mar 2006 to     *
                                   * permit c-syntax.                      *
                                   ****************************************/
                           )       
                            && (parenDepth == 0) ) )       )
                  { /*******************************************************
                    * The current token is the next one after the end of   *
                    * the expression.  Terminate the parsing by setting    *
                    * exprEnd to true and setting Delimiter to the         *
                    * current token.                                       *
                    *******************************************************/
                    if (parenDepth != 0)
                      {TokenizingError(
                         "Expression with an unmatched (, [, {, or << " +
                         "followed by");
                      } ;
                    if (inQuantifier)
                      {TokenizingError(
                         "Expression with \\A or \\E" +
                         " but no following `:` followed by");
                      } ;
                    exprEnd = true ;
                    Delimiter = token ;
                    DelimiterCol = col ;
                    DelimiterLine = reader.getLineNumber();
                    if (nextChar == '\n') 
                      {DelimiterLine = DelimiterLine - 1 ; } ;
    
                    /*******************************************************
                    * If current line is non-empty, add it to vspec.       *
                    *******************************************************/
                    if (linev.size() > 0)
                      { startNewLine() ; }
                  } 
                else
                 { /********************************************************
                   * Adjust parenDepth if necessary.                       *
                   ********************************************************/
                   if (type == Token.BUILTIN)
                     { Symbol sym = PcalBuiltInSymbols.GetBuiltInSymbol(token);
                       if (sym.symbolType == Symbol.LEFT_PAREN)
                         { parenDepth = parenDepth + 1; } ;
                       if (sym.symbolType == Symbol.RIGHT_PAREN)
                         { parenDepth = parenDepth - 1; 
                           if (parenDepth < 0)
                             { TokenizingError("Extra (unmatching)"); };
                         }
                     };
    
                   /********************************************************
                   * Set prevToken.  We set it to " " if the current       *
                   * token is a string so that, for example, the `end' in  *
                   * `"[" end' is recognized as the +cal reserved word     *
                   * and not considered to be a record field.              *
                   ********************************************************/
                   if (type == Token.STRING)
                     { prevToken = " " ; }
                   else 
                     { prevToken = token ; } ;

                   /********************************************************
                   * Set inQuantifier if necessary.                        *
                   ********************************************************/
                   if (    (   token.equals("\\A")
                            || token.equals("\\E"))
                        && (parenDepth == 0))
                     { inQuantifier = true ;} ;
                   if (    inQuantifier
                        && token.equals(":")
                        && (parenDepth == 0))
                     { inQuantifier = false ;} ;

                   /********************************************************
                   * Add the token to the expression.                      *
                   ********************************************************/
                   if (   (! token.equals(""))
                       || (type == Token.STRING))
                     /******************************************************
                     * I don't remember why I thought that TokenOut can    *
                     * be called with a null argument other than for the   *
                     * empty STRING. But, there are no other cases of      *
                     * non-comment tokens with empty strings, so the test  *
                     * seems harmless.                                     *
                     ******************************************************/
                	   /**
                	    * Line number argument added by LL for TLA-PCal mapping.
                	    * Experiment shows that it seems to do the right thing.
                	    * See the declaration of getLineCorrection for an explanation
                	    * of its use.
                	    */
                     { linev.addElement(new TLAToken(token, col, type, 
                             reader.getLineNumber() + getLineCorrection )); } ;   
                   /********************************************************
                   * Reset token.                                          *
                   ********************************************************/
                   token = "" ;
                  }
              }
            else
              { /***********************************************************
                * This is a token type that does not belong in an expression. *
                ***********************************************************/
                TokenizingError("Illegal token in an expression");
                   ;
              }
          }
        else
          { /***************************************************************
            * parseExpression = false                                      *
            ***************************************************************/
            exprEnd = true ;
            Delimiter = token ;
            DelimiterCol = col ;
            DelimiterLine = reader.getLineNumber();
            if (nextChar == '\n') {DelimiterLine = DelimiterLine - 1 ; } ;
            token = "" ;
          }
      }

    private static boolean IsDelimiter(String tok)
      /*********************************************************************
      * True iff tok is a token that does not belong to the expression,    *
      * and hence must be the next token after the expression.             *
      *********************************************************************/
      { return (   tok.equals(";")
                || tok.equals("do")
                || tok.equals("then")
                || tok.equals(":=")
                || tok.equals("begin")
                || tok.equals("variable")
                || tok.equals("variables")
                || tok.equals("||")

         // The following are added to improve error reporting
         // and to make possible the omission of some final ";"s. 
                || tok.equals("end")
                || tok.equals("else")
                || tok.equals("elsif")
                || tok.equals("if")
                || tok.equals("either")
                || tok.equals("or")
                || tok.equals("while")
                || tok.equals("with")
                || tok.equals("call")
                || tok.equals("return")
                || tok.equals("goto")
                || tok.equals("print")
                || tok.equals("assert")
                || tok.equals("skip")
                || tok.equals("procedure")
                || tok.equals("define")
                || tok.equals("process")
                || tok.equals("fair")
               ) ;
      }

    private static void CommentTokenOut()
      /*********************************************************************
      * Add the token to linev and reset token to the empty string.        *
      *                                                                    *
      * REFINED FOR pcal TO BE A NO-OP, AND TO TAKE NO ARGUMENT, SO        *
      * COMMENT TOKENS GET THROWN AWAY. THE ARGUMENT HAS BEEN REMOVED      *
      * FROM ALL CALLS TO CommentTokenOut.                                 *
      *********************************************************************/
      { token = "" ;
      }

    private static void startNewLine()
      /*********************************************************************
      * Append linev to vspec and reset linev.  This should be called      *
      * whenever a \n character is removed from the input stream.          *
      *********************************************************************/
      { vspec.addElement(linev)    ;
        linev = new Vector(30, 30) ;
        col = 0 ;
      }

    private static void TokenizingError(String msg) throws TokenizerException 
      { throw new TokenizerException(
           msg + " `" + token + "' found at\n" + 
          "    line " + (reader.getLineNumber() + 1) + ", column " + 
               (col + 1));
      }


    public static TLAExpr TokenizeExpr(PcalCharReader charReader) throws TokenizerException
      { TLAExpr exp = InnerTokenize(charReader, true) ;
        return exp ; }

    public static String GetAlgorithmToken(PcalCharReader charReader) throws TokenizerException
      { TLAExpr exp = InnerTokenize(charReader, false) ;
        return Delimiter ; }

    public static TLAExpr InnerTokenize(PcalCharReader charReader, 
                                    boolean isExpr) throws TokenizerException 
      /*********************************************************************
      * Tokenize the input from the CharReader.  If isExpr is true, then   *
      * an expression from the input is tokenized and Delimiter is set to  *
      * the following token.  If isExpr is false, then a single            *
      * non-comment token is tokenized, Delimiter is set to that token,    *
      * and a null TLAExpr is returned.                                    *
      *********************************************************************/
      { int mode = TLA ;
        /*******************************************************************
        * Modified by LL on 1 Feb 2006 to initialize ncol and col.  This   *
        * is needed because the use of PcalCharReader.peek() between       *
        * calls to the methods in the Tokenize class can cause the         *
        * current values to be off, leading to wrong column numbers for    *
        * tokens, which can cause misalignment.                            *
        *******************************************************************/
        ncol = charReader.getColumnNumber() ;
        col  = ncol ;
        parseExpression = isExpr ;
        prevToken = " ";
        vspec = new Vector(4) ;
          // Changed by LL on 13 Dec 2011 from new Vector(1000, 1000) ;
          // I don't know why such a large vector was being used
        reader = charReader ;
           /****************************************************************
           * This "exports" the charReader for use by the class's other    *
           * (private) methods.                                            *
           ****************************************************************/

        linev = new Vector() ;
          /*****************************************************************
          * I don't know where linev is initialized, but adding this       *
          * initialization doesn't seem to make any difference.            *
          *****************************************************************/

        token = "" ;
        nextChar = reader.getNextChar();
          /*****************************************************************
          * Initialize nextChar.                                           *
          *****************************************************************/
        // See declaration of getLineCorrection for an explanation of:
        if (nextChar == '\n') {
            getLineCorrection = -1 ;
        } 
        else {
            getLineCorrection = 0 ;
        }

        parenDepth = 0 ;
        inQuantifier = false ;

        switch (mode)
          { case MODULE : state = PROLOG ; break ;
            case TLA    : state = START  ; break ;
            default     : PcalDebug.ReportBug(
                           "TokenizeSpec.Tokenize called with illegal mode") ;
          } ;

        exprEnd = false ;

        while ((state != DONE) &&  ! exprEnd)
          { /***************************************************************
            * Set linev to the vector of tokens in the current line.       *
            ***************************************************************/
            switch (state) 
              /*************************************************************
              * The following code is a direct translation of the          *
              * description given in the comments above, with only minor   *
              * optimizations that are local to a particular case clause.  *
              *************************************************************/
              { case START :
                  if (Misc.IsSpace(nextChar))
                    { skipNextChar() ;
                      gotoStart(); 
                    }
                  else if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      state = ID;  
                    }
                  else if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM_OR_ID; 
                    }
                  else if (nextChar == '\\')
                    { addNextChar();
                      state = BS;    
                    }
                  else if (nextChar == '-')
                    { addNextChar();
                      state = DASH1; 
                    }
                  else if (nextChar == '=')
                    { addNextChar();
                      state = EQ1; 
                    }                              
                  else if (nextChar == '(')   // )
                    { skipNextChar() ;
                      state = LEFT_PAREN; 
                    }
                  else if (nextChar == '"')   // " )
                    { skipNextChar();
                      state = STRING;  }
                  else if (nextChar == '\n')
                    { skipNextChar() ;
                      startNewLine() ;
                      gotoStart(); 
                    }
                  else if (PcalBuiltInSymbols.IsBuiltInPrefix("" + nextChar))
                    { addNextChar();
                      state = BUILT_IN ;
                    }
                  else if (nextChar == '\t')
                    { if (mode == MODULE) 
                        { throw new TokenizerException(
                            "Input ended before end of module");
                        } ;
                      state = DONE ;
                    }
                  else 
                    { addNextChar();
                      TokenizingError("Illegal lexeme");
                    } ;
                  break;

                case ID :
                  if (   (token.length() == 3)
                      && (token.equals("WF_") || token.equals("SF_")))
                    { TokenOut(Token.BUILTIN) ;
                      gotoStart(); 
                    }
                  else if (Misc.IsLetter(nextChar) || Misc.IsDigit(nextChar))
                    { addNextChar();
                      // state = ID ;
                    }  
                  else if (PcalBuiltInSymbols.IsBuiltInSymbol(token))
                    { if (token.equals("MODULE")) 
                        { mdepth = mdepth + 1; 
                        }
                      TokenOut(Token.BUILTIN) ;
                      gotoStart();
                    }
                  else 
                    { TokenOut(Token.IDENT) ;
                      gotoStart();
                    };
                  break;          

                case NUM_OR_ID :
                  if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM_OR_ID; 
                    }
                  else if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      state = ID; 
                    }
                  else 
                    { TokenOut(Token.NUMBER) ;
                      gotoStart();
                    }
                  break;

                case BS :
                  if (    (nextChar == 'b') 
                       || (nextChar == 'B') 
                       || (nextChar == 'o') 
                       || (nextChar == 'O') 
                       || (nextChar == 'h') 
                       || (nextChar == 'H') )
                    { addNextChar();
                      state = NUM_OR_BI ;
                    }
                  else if (Misc.IsLetter(nextChar))
                    { state = BSBUILT_IN ; 
                    }
                  else if (nextChar == '*')
                    { skipNextChar();
                      token = "" ;
                      state = LINE_COMMENT ;
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case NUM_OR_BI :
                  if (Misc.IsDigit(nextChar))
                    { state = NUM;
                    }
                  else 
                    { state = BSBUILT_IN;
                    };
                  break;

                case NUM :
                  if (Misc.IsDigit(nextChar))
                    { addNextChar();
                      state = NUM;
                    }
                  else if (Misc.IsLetter(nextChar))
                    { addNextChar();
                      if (token.charAt(0) == '\\')
                       { TokenizingError("Illegal lexeme");
                       }
                      else
                       { state = ID;
                       };
                    }
                  else 
                    { TokenOut(Token.NUMBER) ;
                      gotoStart();
                    }
                  break;

                case BSBUILT_IN :
                  if (Misc.IsLetter(nextChar) && (nextChar != '_'))
                        // added test for /= '_' on 21 Feb 2004
                        // to correct bug
                    { addNextChar();
                      state = BSBUILT_IN;
                    }
                  else if (PcalBuiltInSymbols.IsBuiltInSymbol(token))
                    { TokenOut(Token.BUILTIN) ;
                      gotoStart();
                    }
                  else 
                    { TokenizingError("Illegal lexeme ");
                    } ;
                   break;

                case BUILT_IN :
                  if (PcalBuiltInSymbols.IsBuiltInPrefix(token + nextChar))
                    { addNextChar();
                      // state = BUILT_IN;
                    }
                  else 
                    { 
                     if (! PcalBuiltInSymbols.IsBuiltInSymbol(token))
                      { 
                        reader.backspace();
                        while (! PcalBuiltInSymbols.IsBuiltInSymbol(token))
                        { reader.backspace();
                          if (token.length() == 0)
                            { TokenizingError("Illegal lexeme");
                            };
                          token = token.substring(0, token.length()-1);
                        } ;
                        // On 11 Jan 2011, LL changed
                        //
                        //     nextChar = reader.getNextChar();
                        //
                        // to the following so ncol gets set to the correct value in 
                        // case multiple reader.backspace calls occurred.  This fixed
                        // a bug that caused parsing "(\E x...)" to put the "\E" token
                        // one column too far to the right, causing it to be output
                        // as "( \Ex...)".
                        skipNextChar();
                       
                      } ;
                      TokenOut(Token.BUILTIN) ;
                      gotoStart();
                    }
                   break;

                case DASH1 :
                  if (nextChar == '-')
                    { addNextChar();
                      state = DASH2 ;
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case DASH2 :
                  if (nextChar == '-')
                    { addNextChar();
                      state = DASH3 ;
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case DASH3 :
                  if (nextChar == '-')
                    { addNextChar();
                      state = DASHES ;
                    }
                  else 
                    { TokenizingError("Illegal lexeme");
                    }
                  break;

                case DASHES :
                  if (nextChar == '-')
                    { addNextChar();
                      state = DASHES ;
                    }
                  else 
                    { TokenOut(Token.DASHES) ;
                      gotoStart();
                    }
                  break;

                case EQ1 :
                  if (nextChar == '=')
                    { addNextChar();
                      state = EQ2 ;
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case EQ2 :
                  if (nextChar == '=')
                    { addNextChar();
                      state = EQ3 ;
                    }
                  else 
                    { state = BUILT_IN ;
                    }
                  break;

                case EQ3 :
                  if (nextChar == '=')
                    { addNextChar();
                      state = EQS ;
                    }
                  else 
                    { TokenizingError("Illegal lexeme");
                    }
                  break;

                case EQS :
                  if (nextChar == '=')
                    { addNextChar();
                      state = EQS ;
                    }
                  else 
                    { mdepth = mdepth - 1 ;
                      TokenOut(Token.END_MODULE) ;
                      if ((mdepth > 0) || (mode == TLA))
                        { gotoStart();
                        }
                      else if (mdepth == 0)
                        { state = EPILOG ;
                        }
                      else 
                        { throw new TokenizerException(
                           "Extra end-of-module lexeme on line "
                           + (reader.getLineNumber() + 1));
                        }
                    }
                  break;

                case LEFT_PAREN :
                  if (nextChar == '*')
                    { skipNextChar();
                      cdepth = 1;
                      state = COMMENT ;
                    }
                  else
                    { token = "(" ;
                      state = BUILT_IN ;
                    }

                  break;

                case STRING :
                  if (nextChar == '\\')
                    { addNextChar();
                      state = ESC_STRING ;
                    }
                  else if (nextChar == '"') // " )
                    { skipNextChar();
                      TokenOut(Token.STRING) ;
                      gotoStart();
                    }
                  else if (PcalBuiltInSymbols.IsStringChar(nextChar))
                    { addNextChar();
                      state = STRING ;
                    }
                  else
                    { addNextChar();
                      TokenizingError("Illegal character in string");
                    }
                   break;

                case ESC_STRING :
                  if (   (nextChar == '\"')
                      || (nextChar == '\\')
                      || (nextChar == 't')
                      || (nextChar == 'n')
                      || (nextChar == 'f')
                      || (nextChar == 'r') )
                    { addNextChar();
                      state = STRING ;
                    }
                  else
                    { addNextChar();
                      TokenizingError(
                          "Illegal character following \\ in string");
                    }
                  break;

                case LINE_COMMENT :
                  if (nextChar == '(')   // )
                    { skipNextChar();
                      state = LINE_COM_PAREN;
                    }
                  else if ((nextChar == '*') && (cdepth > 0))
                    { skipNextChar();
                      state = LINE_COM_STAR;
                    }
                  else if ((nextChar == '\n') || (nextChar == '\t'))
                    { CommentTokenOut() ;
                      cdepth = 0 ;
                      gotoStart();
                    }
                  else
                    { if (cdepth == 0) {addNextChar();}
                        else {skipNextChar();} ;
                      state = LINE_COMMENT;
                    }
                  break;

                case LINE_COM_PAREN :
                  if (nextChar == '*')
                    { skipNextChar();
                      cdepth = cdepth + 1;
                      state = LINE_COMMENT;
                    }
                  else
                    { if (cdepth == 0) {token = token + "(";} ;
                      state = LINE_COMMENT;
                    }
                  break;

                case LINE_COM_STAR :   // (     
                  if (nextChar == ')')  
                    { skipNextChar();
                      cdepth = cdepth - 1;
                      PcalDebug.Assert(cdepth >= 0,
                                   "case LINE_COM_STAR");
                      state = LINE_COMMENT;
                    }
                  else
                    { if (cdepth == 0) {token = token + "*";} ;
                      state = LINE_COMMENT;
                    }
                  break;

                case COMMENT :
                  if (nextChar == '*')
                    { skipNextChar();
                      state = COMMENT_STAR;
                    }
                  else if (nextChar == '(')  // )
                    { skipNextChar();
                      state = COMMENT_PAREN;
                    }
                  else if (nextChar == '\n')
                    { CommentTokenOut() ;
                      skipNextChar();
                      startNewLine();
                      state = OR_COMMENT;
                    }
                  else if (nextChar == '\t')
                    { throw new TokenizerException(
                         "Input ended in the middle of a comment");
                    }
                  else
                    { if (cdepth == 1) {addNextChar();}
                        else {skipNextChar();};
                      // state = COMMENT ;
                    }

                  break;

                case COMMENT_STAR :       // (
                  if (nextChar == ')')
                    { skipNextChar();
                      cdepth = cdepth - 1;
                      if (cdepth == 0)
                        { CommentTokenOut();
                          gotoStart();
                        }
                      else
                        { state = COMMENT;
                        }
                    }
                  else
                    { if (cdepth == 1) {token = token + "*";};
                      state = COMMENT;
                    }
                  break;

                case COMMENT_PAREN :
                  if (nextChar == '*')
                    { skipNextChar();
                      cdepth = cdepth + 1;
                      state = COMMENT;
                    }
                  else
                    { if (cdepth == 1) {token = token + "(";};
                      state = COMMENT;
                    }
                  break;

                case OR_COMMENT :
                  if (nextChar == '*')
                    { skipNextChar();
                      state = OR_COMMENT_STAR;
                    }
                  else if (nextChar == '(')  // )
                    { skipNextChar();
                      state = OR_COMMENT_PAREN;
                    }
                  else if (nextChar == '\n')
                    { CommentTokenOut() ;
                      skipNextChar();
                      startNewLine();
                      state = OR_COMMENT;
                    }
                  else if (nextChar == '\t')
                    { throw new TokenizerException(
                         "Input ended in the middle of a multi-line comment");
                    }
                  else
                    { if (cdepth == 1) {addNextChar();}
                        else {skipNextChar();};
                      // state = OR_COMMENT ;
                    }
                  break;

                case OR_COMMENT_STAR :    // (
                  if (nextChar == ')')
                    { skipNextChar();
                      cdepth = cdepth - 1;
                      PcalDebug.Assert(cdepth >= 0);
                      if (cdepth == 0)
                        { CommentTokenOut();
                          gotoStart();
                        }
                      else
                        { state = OR_COMMENT;
                        }
                    }
                  else
                    { if (cdepth == 1) {token = token + "*";};
                      state = OR_COMMENT;
                    }
                  break;

                case OR_COMMENT_PAREN :
                  if (nextChar == '*')
                    { skipNextChar();
                      cdepth = cdepth + 1;
                      state = OR_COMMENT;
                    }
                  else
                    { if (cdepth == 1) {token = token + "(";};
                      state = OR_COMMENT;
                    }
                  break;

                case PROLOG :
                  if (nextChar == '-')
                    { token1 = token ;
                      col1   = col ;
                      col    = ncol ;
                      token  = "-" ;
                      skipNextChar();
                      state = PROLOG_DASH ;
                    } 
                  else if (nextChar == '\n')
                    { TokenOut(Token.PROLOG) ;
                      skipNextChar();
                      startNewLine();
                      // state = PROLOG ;
                    }
                  else if (nextChar == '\t')
                    { throw new TokenizerException(
                         "Input ended before beginning of module");
                    }
                  else
                    { addNextChar();
                      // state = PROLOG ;
                    }
                break;

                case PROLOG_DASH :
                  PcalDebug.Assert(token.length() <= 3) ;
                  if (nextChar ==   '-')
                    { addNextChar();
                      if (token.length() == 4)
                        { state = PROLOG_DASHES;
                        }
                      else
                        { // state = PROLOG_DASH
                        } ;
                    }
                  else 
                    { token = token1 + token ;
                      col   = col1 ;
                      state = PROLOG ;
                    }
                  break;

                case PROLOG_DASHES :
                  if (nextChar == '-')
                    { addNextChar();
                      // state = PROLOG_DASHES ;
                    }
                  else 
                    { token2 = token ;
                      col2   = col ;
                      token  = "" ;
                      col    = ncol;
                      state  = PROLOG_SPACES ;
                    }
                  break;

                case PROLOG_SPACES :
                  if (nextChar == ' ')
                    { addNextChar();
                      // state = PROLOG_SPACES;
                    }
                  else if (Misc.IsLetter(nextChar))  
                    { token3 = token;
                      col3   = ncol ;
                      token  = "" ;
                      state  = PROLOG_ID ;
                    }
                  else 
                    { token  = token1 + token2 ;
                      col    = col1 ;
                      state  = PROLOG ;
                    }
                  break;
	      
                case PROLOG_ID :
                  if (Misc.IsLetter(nextChar))  
                    { addNextChar();
                      // state = PROLOG_ID ;
                    }
                  else if (token.equals("MODULE"))  
                    { token = token1 ;
                      col = col1;
                      TokenOut(Token.PROLOG) ;
                      token = token2 ;
                      col = col2;
                      TokenOut(Token.DASHES) ;
                      token = "MODULE" ;
                      col = col3;
                      TokenOut(Token.BUILTIN) ;
                      token  = "" ;
                      mdepth = 1 ;
                      gotoStart();
                    }
                  else 
                    { token = token1 + token2 + token3 ;
                      col = col1;
                      state  = PROLOG ;
                    }
                  break;

                case EPILOG :
                  if (nextChar == '\n')
                    { TokenOut(Token.EPILOG) ;
                      skipNextChar();
                      startNewLine();
                      // state = EPILOG ;
                    }
                  else if (nextChar == '\t')
                    { TokenOut(Token.EPILOG) ;
                      state = DONE ;
                    }
                  else
                    { addNextChar();
                      // state = EPILOG ;
                    }
                break;

                default :
                  PcalDebug.ReportBug(
                    "Illegal state in TokenizeSpec.Tokenize");
                  // break;

              } ;  // ends switch
         } ; // ends while

        /*******************************************************************
        * Need to backspace one character because it has already read one  *
        * character further--unless nextChar = \n (and the reader is       *
        * therefore at the beginning of the next line).                    *
        *******************************************************************/
        if (nextChar != '\n')
          { reader.backspace(); } ;

        /*******************************************************************
        * Returns a normalized TLAExpr made from vspec.                    *
        *******************************************************************/
        TLAExpr rval = new TLAExpr(vspec) ;
        rval.normalize() ;
        return rval;
      }
  }


/* last modified on Sat 25 Mar 2006 at  8:18:49 PST by lamport */

/*
In the +cal grammar, an <Expr> can be followed by the following:
Modify the TokenOut method to detect the end of the expression,
which is either one of the following tokens

  ;
  variable variables begin  [when it follows "procedure <Name> =|\in "]
  begin
  do
  then
  :=
  ||

or else an unmatched ")" or a "," that does not occur inside
parentheses of some form.  (It's "call( <Expr> [, <Expr> ]^* )"
that requires this hack.)

Note: In <LHS>, we regard everything between the <Variable>
      and the := to be an <Expr>.


      
*/



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/StatisticalBlockSelector.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.TLCWorkerRMI;
import tlc2.tool.distributed.TLCWorkerSmartProxy;

public class StatisticalBlockSelector extends LimitingBlockSelector {

	/**
	 * Maximum total network overhead we are willing to take
	 */
	private final double networkOverheadLimit;

	/**
	 * @param aTLCServer
	 */
	public StatisticalBlockSelector(final TLCServer aTLCServer) {
		super(aTLCServer);
		this.networkOverheadLimit = 2.5 / 100d; 
	}

	/**
	 * @param size
	 *            The current size of the state queue.
	 * @return The intended block size
	 */
	protected long getBlockSize(final long size, final TLCWorkerRMI aWorker) {
		// has to be correct type and statistics have to be available
		if(aWorker instanceof TLCWorkerSmartProxy) {
			final TLCWorkerSmartProxy proxy = (TLCWorkerSmartProxy) aWorker;
			int blockSize = (int) Math.min(Math.max(
					Math.abs(Math.ceil(size * (proxy.getNetworkOverhead() / networkOverheadLimit))), 1), getMaximum());
			return blockSize;
		}
		
		// default return value
		return super.getBlockSize(size, aWorker);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/StringSet.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.util;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

/**
 * A StringSet object represents a set of strings.  It provides the following
 * methods: 
 * 
 *   add(elt) : Adds the element elt to the set (no-op if elt is
 *              already in the set.
 *              
 *   addAll(sset) : Adds all the elements of the StringSet sset to the 
 *                 set represented by this object.
 *   
 *   contains(elt) : Returns true iff the element is in the set.
 *   
 *   isEmpty() : True iff the set is empty
 *   
 *   toCommaSeparatedString() : Returns the comma-separated list of all the
 *                              elements of the set.
 *                              
 *   CommaSeparatedListToStringSet(str) : 
 *      Assumes str is a comma-separated list of strings, each of which
 *      does not contain a comma or a space.  There may be arbitrary amounts
 *      of space (including none) anywhere in str.  It returns the corresponding
 *      StringSet.
 *   
* There is also a constructor that turns a HashSet<String> object
 * into a StringSet.
 * 
 * Because of the way Java implements strings, a HashSet provides these 
 * functions most of the time.  However, there are some ways of creating
 * strings that produces different String objects, and hence would put
 * two different copies of the same string into a HashSet--or might fail
 * to recognize that a string is in the HashSet.  So, this method is
 * used to be safe. 
 * 
 * This method is not implemented very efficiently, and should not be 
 * where space or execution time is an issue.  The implementation is based
 * on the algorithm in module BinarySort at the end of this file.
 *   
 * @author lamport
 *
 */
public class StringSet {

    
    private Vector<String> contents = new Vector<String>() ;

    
    public void add(String str) {
       int position = 0 ;
       if (contents.size() == 0) {
           contents.add(str) ;
           return ;
       }
       
       
       position = this.binarySearch(str) ;
       
       if ((position == -1)  || ! str.equals(contents.elementAt(position))) {
           contents.add(position+1, str) ;
       }
       return ;
    }

    public void addAll(StringSet ss) {
        for (int i=0; i < ss.contents.size(); i++) {
            this.add(ss.contents.elementAt(i)) ;
        }
    }
    public boolean contains(String str) {
        int position = binarySearch(str) ;
        if (position == -1) {
            return false;
        }
        return str.equals(contents.elementAt(binarySearch(str))) ;    
    }
    
    public boolean isEmpty() {
        return contents.size() == 0 ;
    }
    
    /**
     * Returns the following value, where << is lexicographical ordering
     * of strings:
     * 
     *   IF contents.size() = 0 \/ str << contents(0) 
     *     THEN -1
     *     ELSE the largest integer i in 0..(contents.size()-1) such that contents(i) =<< str
     *     
     * It uses the algorithm BinarySearch appended at the end of this file.
     * 
     * @param str
     * @return
     */
    private int binarySearch(String str) {
        if ( (contents.size() == 0) || (str.compareTo(contents.elementAt(0)) < 0) ) {
            return -1 ;
        }
        if (contents.elementAt(contents.size()-1).compareTo(str) <= 0) {
            return contents.size() - 1 ;
        }
        int bot = 0 ;
        int top = contents.size() - 1;
        while (bot+1 < top) {
          int mid = bot + ((top - bot) / 2) ;
          if (str.compareTo(contents.elementAt(mid)) < 0) {
              top = mid ;
          }
          else {
              bot = mid ;
          }
        }
        return bot ;
    }
    
    /*
     *  The Constructors
     */
    public StringSet() {
    }
    
    public StringSet(HashSet<String>hSet) {
        Iterator iter = hSet.iterator() ;
        while (iter.hasNext()) {
            contents.add((String) iter.next()) ;
        }
    }
    
    /**
     * Returns a shallow copy of the set, which for Strings is
     * equivalent to a deep copy.
     */
    public StringSet clone() {
        StringSet result = new StringSet() ;
        for (int i=0; i < contents.size(); i++) {
            result.add(contents.elementAt(i)) ;
        }
        return result;
    }
    
    /**
     * Returns the comma-separated list of all the elements of the list.
     * It returns "" if the set is empty.
     * @return
     */
    public String toCommaSeparatedString() {
        String result = "" ;
        for (int i=0 ; i < contents.size(); i++) {
            if (result.equals("")) {
                result = contents.elementAt(i) ;
            }
            else {
                result = result + ", " + contents.elementAt(i) ;
            }
        }
        return result ;
    }
    
    public static StringSet CommaSeparatedListToStringSet(String str) {
        StringSet result = new StringSet();
        String[] elements = str.split(",") ;
        for (int i=0; i < elements.length; i++) {
            result.add(elements[i].trim()) ;
        }
        return result;      
    }
    /**
     * For debugging.
     */
    public String toString() {
        return contents.toString() ;
    }
    
    /**
     * The following method tests all possible ways of constructing a StringSet by performing
     * five add() operations to add an element in {"1", ... , "max"} and checking that
     * it produces a StringSet such that content is lexicographically ordered without
     * duplicates and the value returned by contains(s) for any of those elements is the
     * same as for an identically constructed HashSet.  It also checks that the addAll
     * method and that the empty set contains no elements.
     * 
     * Note: The first version of this test was buggy and essentially tested
     * just five different sets.  The next version was slightly less buggy, but
     * was still checking many fewer sets than it should have.
     *   
     * ONE HAS TO TEST THAT A TEST IS TESTING WHAT YOU THINK IT'S TESTING.
     */
    public static void test() { 
       int max = 12 ;
       int[] elts = new int[5] ;
        for (int i=1 ; i < max; i++) {
          elts[0] = i;
           for (int j=1 ; j < max; j++) {
              elts[1] = j;              
              for (int k=1 ; k < max; k++) {
                  elts[2] = k ;
                  for (int m=1 ; m < max; m++) {
                      elts[3] = m ;
                      for (int n=1 ; n < max; n++) {
                          elts[4] = n ;
                          innerTest(elts, max) ;
                      }
                  }
              }
           }
        }
    }
    
    public static void innerTest(int[] elts, int max) {
        int n = elts.length;
        StringSet ss = new StringSet() ;
        HashSet<String> hs = new HashSet<String>();
        StringSet ss1 = new StringSet() ;
        StringSet ss2 = new StringSet() ;
        String str = "" ;
        for (int i=0; i < n; i++) {
           ss.add(""+elts[i]);
           hs.add(""+elts[i]);
           if (i>0) {
               str = str + " , " ;
           }
           str = str + elts[i] ;
           if (i < n/2) {
               ss1.add(""+elts[i]);
           } else {
               ss2.add(""+elts[i]);
           }  
        }
        
        // Check that contents is properly ordered
        for (int t=1; t < ss.contents.size()-1; t++) {
            if (! (ss.contents.elementAt(t).compareTo(ss.contents.elementAt(t+1)) < 0)) {
                System.out.println(t+", "+(t+1)+" malordered in: " + ss.toCommaSeparatedString());
            }
        }
        // Check that ss and hs have same elements
        for (int r=1; r < n; r++) {
            if (ss.contains(""+r) != hs.contains(""+r)) {
                System.out.println("ss and hs differ on " + r + " in: " + ss.toCommaSeparatedString()) ;
            }
        }
        // Check union of "two halves" 
        StringSet ss3 = ss1.clone(); ss3.addAll(ss2) ;
        for (int z=1; z < max; z++) {
            if (ss3.contains(""+z) != (ss1.contains(""+z) || ss2.contains(""+z))) {
                System.out.println(ss3.toCommaSeparatedString() + " != " +
                   ss1.toCommaSeparatedString() + " + " + ss2.toCommaSeparatedString());
            }
        }
        // Check CommaSeparatedListToStringSet
       
        StringSet csl = CommaSeparatedListToStringSet(str);
        if (!csl.toCommaSeparatedString().equals(ss.toCommaSeparatedString())) {
            System.out.println(csl.toCommaSeparatedString() + " != " + ss.toCommaSeparatedString()) ;
        }

        // Check handling of empty set.
        StringSet ss4 = new StringSet() ;
        if (ss4.contains("1")) {
            System.out.println("The empty set is not empty") ;
        }
    }
}

// The following module has been model-checked for N = 7.
//
//----------------------------- MODULE BinarySearch -----------------------------
//(***************************************************************************)
//(* This module describes algorithm an algorithm that does the following.   *)
//(* Given an increasing sequence <<e_1, ...  , e_n>> of distinct integers   *)
//(* and an integer e , it returns                                           *)
//(*                                                                         *)
//(*    IF n = 0 \/ e < e_1                                                  *)
//(*      THEN 0                                                             *)
//(*      ELSE the largest integer i in 1..n such that e_i =< e              *)
//(*                                                                         *)
//(* (The algorithm uses binary search.)                                     *)
//(*                                                                         *)
//(* This algorithm is used as the basis of code for implementing a class of *)
//(* object representing a set, with the the two operations of adding an     *)
//(* element to the set and determining if the set contains a given element. *)
//(*                                                                         *)
//(* Note: When implementing this method in Java, I made the following       *)
//(* error.  In translating from 1-based to 0-based indexing, I failed to    *)
//(* translate the value 0 returned by the first `if' test to -1.  This      *)
//(* caused a bug that was not found by the testing I did, which was         *)
//(* perfunctory because I was implementing a correct algorithm.  There are  *)
//(* two possible lessons to be drawn from this mistake:                     *)
//(*                                                                         *)
//(*  - Since my goal was to implement binary search on Java arrays, I       *)
//(*    should have written the algorithm to search a function with domain   *)
//(*    0..(N-1) rather than a sequence of length N.                         *)
//(*                                                                         *)
//(*  - I should have been more conscientious in testing my implementation,  *)
//(*    especially in checking boundary cases.                               *)
//(***************************************************************************)
//EXTENDS Integers, Sequences, TLC
//
//CONSTANT N  \* The maximum length of input sequence on which to test the 
//            \* algorithm.
//
//TestSequences == { seq \in UNION { [1..i -> -1 .. (N+1)] : i \in 0..N } :
//                     \A j \in 1..(Len(seq)-1) : \A k \in (j+1)..Len(seq) :
//                        seq[j] < seq[k] }
//
//Max(S) == CHOOSE x \in S : \A y \in S : x >= y
//
//CorrectValue(seq, i) == IF Len(seq) = 0 \/ i < seq[1]
//                          THEN 0
//                          ELSE Max ({j \in DOMAIN seq : seq[j] =< i})
//
//(***************************************************************************
//--fair algorithm BinarySearch {
//  variables seq \in TestSequences, elt \in (-1)..(N+1) ,
//            bot = 1 , top = Len(seq), result ;
//            
//  { if ( (Len(seq) = 0) \/ (elt < seq[1]) ) { result := 0 }
//    else if (seq[Len(seq)] =< elt) { result := Len(seq) }
//    else 
//       \* while loop maintains the invariant that :
//       \*  (bot < top) /\ (seq[bot] =< elt < seq[top]) /\ 
//     { while (bot+1 < top) 
//         { with (mid = bot + ((top - bot) \div 2)) 
//            { if (elt < seq[mid]) { top := mid }
//              else {bot := mid} 
//            } 
//         } ;
//       result := bot 
//     } ;
//    assert result = CorrectValue(seq, elt)
//  }
//}
// ***************************************************************************)
//\* BEGIN TRANSLATION
//CONSTANT defaultInitValue
//VARIABLES seq, elt, bot, top, result, pc
//
//vars == << seq, elt, bot, top, result, pc >>
//
//Init == (* Global variables *)
//        /\ seq \in TestSequences
//        /\ elt \in (-1)..(N+1)
//        /\ bot = 1
//        /\ top = Len(seq)
//        /\ result = defaultInitValue
//        /\ pc = "Lbl_1"
//
//Lbl_1 == /\ pc = "Lbl_1"
//         /\ IF (Len(seq) = 0) \/ (elt < seq[1])
//               THEN /\ result' = 0
//                    /\ pc' = "Lbl_3"
//               ELSE /\ IF seq[Len(seq)] =< elt
//                          THEN /\ result' = Len(seq)
//                               /\ pc' = "Lbl_3"
//                          ELSE /\ pc' = "Lbl_2"
//                               /\ UNCHANGED result
//         /\ UNCHANGED << seq, elt, bot, top >>
//
//Lbl_2 == /\ pc = "Lbl_2"
//         /\ IF bot+1 < top
//               THEN /\ LET mid == bot + ((top - bot) \div 2) IN
//                         IF elt < seq[mid]
//                            THEN /\ top' = mid
//                                 /\ bot' = bot
//                            ELSE /\ bot' = mid
//                                 /\ top' = top
//                    /\ pc' = "Lbl_2"
//                    /\ UNCHANGED result
//               ELSE /\ result' = bot
//                    /\ pc' = "Lbl_3"
//                    /\ UNCHANGED << bot, top >>
//         /\ UNCHANGED << seq, elt >>
//
//Lbl_3 == /\ pc = "Lbl_3"
//         /\ Assert(result = CorrectValue(seq, elt), 
//                   "Failure of assertion at line 48, column 5.")
//         /\ pc' = "Done"
//         /\ UNCHANGED << seq, elt, bot, top, result >>
//
//Next == Lbl_1 \/ Lbl_2 \/ Lbl_3
//           \/ (* Disjunct to prevent deadlock on termination *)
//              (pc = "Done" /\ UNCHANGED vars)
//
//Spec == /\ Init /\ [][Next]_vars
//        /\ WF_vars(Next)
//
//Termination == <>(pc = "Done")
//
//\* END TRANSLATION
//
//=============================================================================
//\* Modification History
//\* Last modified Wed Oct 08 10:56:42 PDT 2014 by lamport
//\* Created Wed Oct 08 09:44:00 PDT 2014 by lamport


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/xml/SymbolContext.java<|end_filename|>
package tla2sany.xml;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.semantic.AssumeNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.TheoremNode;

/* TL
 * This class is used to track the occurrence of SymbolNodes
 * nodes which have a context (modules, nonleafproofs, etc.)
 * create a new instance of this class and pass it over
 * to be populated with values.
 * The oldKeys set is used in order to prevent entering the
 * same def twice
 */
public class SymbolContext {
  private java.util.Map<Integer,Element> context;
  private java.util.Set<Integer> keys; // we need this set since the generated element might spawn new keys
  private boolean top_level_entry;  // used to detect if a symbol is exported twice.
                                    // only set in put() and reset in SymbolNode.getDefinitionElement

  // flags list
  public static final int OTHER_BUG = 0;

  // some semantic objects are represented using null. this flags array
  // is used to tell nodes to expect them so xml exporting will be done properly
  private boolean[] flagArray;

  public SymbolContext() {
    context = new java.util.HashMap<Integer,Element>();
    keys = new java.util.HashSet<Integer>();
    flagArray = new boolean[1];
    top_level_entry = false;
  }

  // copy concstructor
  public SymbolContext(SymbolContext other) {
    context = other.context;
    keys = other.keys;
    flagArray = other.flagArray;
    top_level_entry = other.top_level_entry;
  }

  public void setFlag(int flag) {
    flagArray[flag] = true;
  }

  public boolean hasFlag(int flag) {
    return flagArray[flag];
  }

  public void put(SymbolNode nd, Document doc) {
    Integer k = new Integer(nd.myUID);
    if (!keys.contains(k)) {
      // first add the key as it might be mentioned again inside the definition
      keys.add(k);
      setTop_level_entry();
      context.put(k,nd.exportDefinition(doc,this));
    }
  }

  public void put(TheoremNode nd, Document doc) {
    Integer k = new Integer(nd.myUID);
    if (!keys.contains(k)) {
      // first add the key as it might be mentioned again inside the definition
      keys.add(k);
      setTop_level_entry();
      context.put(k,nd.exportDefinition(doc,this));
    }
  }

  public void put(AssumeNode nd, Document doc) {
    Integer k = new Integer(nd.myUID);
    if (!keys.contains(k)) {
      // first add the key as it might be mentioned again inside the definition
      keys.add(k);
      setTop_level_entry();
      context.put(k,nd.exportDefinition(doc,this));
    }
  }

  public Element getContextElement(Document doc) {
    Element ret = doc.createElement("context");
    for (java.util.Map.Entry<Integer, Element> entry : context.entrySet()) {
      Element e = doc.createElement("entry");
      Element id = doc.createElement("UID");
      id.appendChild(doc.createTextNode(entry.getKey().toString()));
      e.appendChild(id);
      e.appendChild(entry.getValue());
      ret.appendChild(e);
    }
    return ret;
  }

  public int getContextSize() {
    return context.size();
  }

  public boolean isTop_level_entry() { return top_level_entry; }
  public void setTop_level_entry() { top_level_entry = true; }
  public void resetTop_level_entry() { top_level_entry = false; }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/preference/ModelEditorPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.preference;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Preference pane for the Model Editor preferences page.
 */
public class ModelEditorPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
	public ModelEditorPreferencePage() {
        super(GRID);
        
        // Copy preference value to non-ui plugin.
        TLCUIActivator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
			@Override
			public void propertyChange(PropertyChangeEvent event) {
				final IPreferenceStore store = TLCActivator.getDefault().getPreferenceStore();
				if (TLCActivator.I_TLC_SNAPSHOT_KEEP_COUNT.equals(event.getProperty())) {
					store.setValue(TLCActivator.I_TLC_SNAPSHOT_KEEP_COUNT, (int)event.getNewValue());
				}
			}
		});
		setPreferenceStore(TLCUIActivator.getDefault().getPreferenceStore());
        setDescription("Model Editor preferences");
    }

	protected Control createContents(Composite parent) {
        final Control pageControl = super.createContents(parent);
        UIHelper.setHelp(pageControl, IHelpConstants.MODEL_EDITOR_PREFERENCE_PAGE);
        return pageControl;
    }

	protected void createFieldEditors() {
        addField(new BooleanFieldEditor(IModelEditorPreferenceConstants.I_MODEL_EDITOR_SHOW_ECE_AS_TAB,
                "Show Evaluate Constant Expression in its own tab", getFieldEditorParent()));
        
        final String[][] overrideDisplays = {
        		{ "Definition [Module Name]",
        			IModelEditorPreferenceConstants.I_OVERRIDDEN_DEFINITION_STYLE_MODULE_NAME },
        		{ "InstanceName!Definition",
        			IModelEditorPreferenceConstants.I_OVERRIDDEN_DEFINITION_STYLE_INSTANCE_NAME }
        };
        addField(new ComboFieldEditor(IModelEditorPreferenceConstants.I_OVERRIDDEN_DEFINITION_STYLE,
        		"Definition Override display style", overrideDisplays, getFieldEditorParent()));
    }

    public void init(IWorkbench workbench) { }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/spec/parsing.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/spec/parsing.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Parsing</title>
</head>
<!-- a comment -->

<body>
<h1>Parsing</h1>

<p>
The Toolbox parses a spec upon opening it.&nbsp;  The parse status of the currently 
open spec is shown in the lower right-hand
corner of the Toolbox window.&nbsp;  The status is either:&nbsp; <samp>Parsed</samp>, 
meaning it has no parsing
errors;&nbsp; <samp>Unparsed</samp>, meaning that the spec had no errors the last time
 it was parsed, but that
one of its files has since been modified and saved;&nbsp; or <samp>Error</samp>, 
meaning that an error
was found the last time it was parsed.
</p>

<p>
Clicking&nbsp; <samp>File/Parse Spec</samp>&nbsp;  parses the 
spec.&nbsp;  Clicking&nbsp; <samp>File/Parse Module</samp>&nbsp; parses the 
currently selected module, which 
is the one in the most recently selected module editor.&nbsp;  
Parsing the spec is equivalent to parsing its root module.&nbsp; 
Unless your spec is <font size=+1>VERY BIG</font>, you will want to parse whenever 
a module is saved.&nbsp;
See the parsing preferences listed below for how to do this.</p>

<p>
If there is a parsing error, the Toolbox pops up a Parsing Errors view.&nbsp;  For most errors, clicking on
the error takes you to its location in a module editor.&nbsp;  The Toolbox also marks the locations of the 
errors in the module editor (or editors).&nbsp;  There is a preference, described below, that controls
whether or not the Parsing Errors view 
automatically pops up.&nbsp;  If you set it not to pop up, you can open the view from the 
Toolbox's&nbsp; <samp>Window</samp>&nbsp; menu.
</p>

<h2>Parsing Preferences</h2>

<h3>Re-parse module on save</h3>

<p>
Causes a module to be reparsed when you save it from the module editor.&nbsp;  It is the default.
</p>

<h3>Re-parse specification on spec module save</h3>

<p>

Causes the entire spec to be reparsed when you save a module, if that module is part
of the spec.&nbsp;  More precisely, the spec is reparsed if the Toolbox found the module to be part of the 
spec when the spec was
last parsed.&nbsp;  This option has no effect unless the <b>Re-parse module on save</b> option is chosen.&nbsp;
It is the default.
</p>

<h3>Always pop up Parsing Errors view</h3>

<p>
It is the default.  
</p>

<hr> 
<!-- delete rest of line to comment out 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 --> 
<!-- delete rest of line to comment out -->  
<a href = "spec.html">&uarr; Managing Your Specifications</a>
<!-- --> 
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/Github179cTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.output.EC.ExitStatus;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class Github179cTest extends ModelCheckerTestCase {

	public Github179cTest() {
		super("Github179c", ExitStatus.FAILURE_SPEC_EVAL);
	}

	@Test
	public void testSpec() {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));

		assertTrue(recorder.recordedWithStringValues(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE,
				"public static tlc2.value.impl.Value tlc2.module.TLC.PrintT(tlc2.value.impl.Value)",
				"Attempted to check equality of integer 1 with non-integer:\n" + 
				"{1}"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_NESTED_EXPRESSION,
				"0. Line 16, column 9 to line 16, column 42 in Github179c\n" + 
				"1. Line 16, column 9 to line 16, column 33 in Github179c\n" + 
				"2. Line 16, column 9 to line 16, column 25 in Github179c\n" + 
				"3. Line 10, column 11 to line 12, column 39 in Github179c\n" + 
				"4. Line 10, column 24 to line 12, column 39 in Github179c\n" + 
				"5. Line 10, column 27 to line 10, column 36 in Github179c\n" + 
				"\n"));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCRegion.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TypedRegion;

/**
 * Marks a TLC output region
 * @author <NAME>
 * @version $Id$
 */
public class TLCRegion extends TypedRegion implements ITypedRegion
{
    public static final String TAG = "__tlc_tag";

    private int messageCode;
    private int severity;

    public TLCRegion(int offset, int length)
    {
        this(offset, length, TAG);
    }

    public TLCRegion(int offset, int length, String type)
    {
        super(offset, length, type);
    }

    public final int getMessageCode()
    {
        return messageCode;
    }

    public final void setMessageCode(int messageCode)
    {
        this.messageCode = messageCode;
    }

    public final int getSeverity()
    {
        return severity;
    }

    public final void setSeverity(int severity)
    {
        this.severity = severity;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/ui/handler/AddModuleHandlerTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.ui.handler;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;

import org.eclipse.core.internal.resources.LinkDescription;
import org.eclipse.core.internal.resources.Project;
import org.eclipse.core.internal.resources.ProjectDescription;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.ResourceHelper;

import junit.framework.TestCase;

@SuppressWarnings("restriction")
public class AddModuleHandlerTest extends TestCase {

	/*
	 * Test that a create module file is stored realtive to the project
	 * 
	 * see SpecTest if this fails because of non-matching paths.
	 */
	public void testCreateModuleStoreRelativePath() throws IOException, CoreException {
		// Need a per invocation temp directory to avoid writing to the same
		// .project file over and over again.
		final File tempDirectory = createTempDirectory();

		// Create...
		final File specFile = new File(tempDirectory + File.separator + "TestSpecName.tla");
		specFile.createNewFile();
		final Spec spec = Spec.createNewSpec("TestSpecName", specFile.getAbsolutePath(), false,
				new NullProgressMonitor());

		final AddModuleHandler addModuleHandler = new AddModuleHandler();
		final File moduleFileRaw = new File(tempDirectory + File.separator + "TestModuleName.tla");
		moduleFileRaw.createNewFile();
		final IFile moduleFile = addModuleHandler.createModuleFile(spec, "TestModuleName",
				new Path(moduleFileRaw.getAbsolutePath()));

		// ...check
		assertNotNull(moduleFile);
		assertTrue(moduleFile.isAccessible());
		assertTrue(moduleFile.isLinked());

		// could use non-internal alternative
		// project.getWorkspace().loadProjectDescription(path) instead, but then
		// need to known path to .project file
		assertTrue(spec.getProject() instanceof Project);
		final Project project = (Project) spec.getProject();
		final ProjectDescription description = project.internalGetDescription();
		final ProjectDescription pd = (ProjectDescription) description;
		final HashMap<IPath, LinkDescription> links = pd.getLinks();
		assertEquals(2, links.size()); // spec + module
		for (LinkDescription linkDescription : links.values()) {
			final URI uri = linkDescription.getLocationURI();
			assertTrue(uri.toASCIIString().startsWith(ResourceHelper.PARENT_ONE_PROJECT_LOC));
		}
	}

	private static File createTempDirectory() throws IOException {
		final File temp = File.createTempFile("temp", Long.toString(System.nanoTime()));

		if (!(temp.delete())) {
			throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
		}

		if (!(temp.mkdir())) {
			throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
		}

		return temp;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/configuration/Configuration.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
/* Generated By:JavaCC: Do not edit this line. Configuration.java */

/***************************************************************************
* This file was originally created by running javacc on the grammar file   *
* config.jj that specifies the parsing of the string                       *
* ConfigConstants.defaultConfig.  The current file has since been          *
* modified by DRJ (<NAME>).                                       *
*                                                                          *
* This file was modified by LL on 13 May 2008 to replace calls to          *
* System.out and System.err by calls to ToolIO.out and ToolIO.err.         *
***************************************************************************/
// Last modified on Tue 13 May 2008 at  1:08:30 PST by lamport


package tla2sany.configuration;

import java.io.File;

import tla2sany.parser.Operator;
import tla2sany.parser.Operators;
import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.AbortException;
import tla2sany.semantic.Context;
import tla2sany.semantic.Errors;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.st.Location;
import util.ToolIO;
import util.UniqueString;

public final class Configuration implements ConfigConstants {

  private static Errors         errors;
  private static java.io.Reader input;

  public static void displayDefinitions() {
    ToolIO.out.println( defaultConfig );
  }

  public static void load (Errors errs ) throws AbortException {
    /***********************************************************************
    * Called from drivers/SANY.java                                        *
    ***********************************************************************/
    Configuration Parser;
    try {
      errors = errs;
      File source = new File( "config.src" );
      String origin;

      if ( source.exists() ) {
//      java.io.OutputStream output;
        input = new java.io.FileReader( source );
        origin = " from local config.src file.";
      } else {
        input = new java.io.StringReader( defaultConfig );
        origin = " from defaults.";
      }
      Parser = new Configuration( input );

      try {
        Parser.ConfigurationUnit();
//      Operators.printTable();
      } catch (ParseException e) {
        errors.addAbort(Location.nullLoc,"\nConfiguration Parser:  Encountered errors during parse.  " 
                        + e.getMessage(),true );
      }

    } catch (java.io.FileNotFoundException e) {
      errors.addAbort(Location.nullLoc,"File not found.\n" + e,true);
    }
  } // end load()



  static final public void ConfigurationUnit() throws ParseException, AbortException {
    label_1:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case OPERATOR:
      case SYNONYM:
      case BUILTIN:
        ;
        break;
      default:
        jj_la1[0] = jj_gen;
        break label_1;
      }
      OpDefinition();
    }
  }


  static final public void OpDefinition() throws ParseException, AbortException {
  Token t;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case OPERATOR:
      jj_consume_token(OPERATOR);
      t = jj_consume_token(OPID);

      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case NUMBER:
        OpBody(t.image);
        break;
      case NOTOP:
        OpNull(t.image);
        break;
      default:
        jj_la1[1] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    case SYNONYM:
      OpSynonym();
      break;
    case BUILTIN:
      OpBuiltin();
      break;
    default:
      jj_la1[2] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

 static final public void OpBody(String s) throws ParseException {
 Token t;
 int kind, assoc;
 int low, high;
    t = jj_consume_token(NUMBER);
                low = Integer.parseInt( t.image );
    t = jj_consume_token(NUMBER);
                high = Integer.parseInt( t.image );
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LEFTASSOC:
      jj_consume_token(LEFTASSOC);
                   assoc = Operators.assocLeft;
      break;
    case RIGHTASSOC:
      jj_consume_token(RIGHTASSOC);
                    assoc = Operators.assocRight;
      break;
    case NOASSOC:
      jj_consume_token(NOASSOC);
                 assoc = Operators.assocNone;
      break;
    default:
      jj_la1[3] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case INFIX:
      jj_consume_token(INFIX);
               kind = Operators.infix;
      break;
    case PREFIX:
      jj_consume_token(PREFIX);
                kind = Operators.prefix;
      break;
    case POSTFIX:
      jj_consume_token(POSTFIX);
                 kind = Operators.postfix;
      break;
    case NFIX:
      jj_consume_token(NFIX);
              kind = Operators.nfix;
      break;
    default:
      jj_la1[4] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
     t = null;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case OPID:
      t = jj_consume_token(OPID);
      break;
    default:
      jj_la1[5] = jj_gen;
      ;
    }
   Operator op;
   if ( t == null ) {
     op = new Operator( UniqueString.uniqueStringOf(s), low, high, assoc, kind );
   } else {
     op = new Operator( UniqueString.uniqueStringOf(t.image), low, high, assoc, kind );
   }
   Operators.addOperator( UniqueString.uniqueStringOf(s), op );
  }

  static final public void OpSynonym() throws ParseException {
  Token t1, t2;
    jj_consume_token(SYNONYM);
    t1 = jj_consume_token(OPID);
    t2 = jj_consume_token(OPID);
    Operators.addSynonym( UniqueString.uniqueStringOf(t1.image), 
                          UniqueString.uniqueStringOf(t2.image) );
  }

  static final public void OpNull(String s) throws ParseException {
    Token t;
    jj_consume_token(NOTOP);
  }

  static final public void OpBuiltin() throws ParseException, AbortException {
  Token t;
  String external, internal;
  UniqueString us;
    jj_consume_token(BUILTIN);
    t = jj_consume_token(OPID);
    external = t.image; us = UniqueString.uniqueStringOf( external );
    t = jj_consume_token(RESTRICTED);
    internal = t.image;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case INFIX:
      jj_consume_token(INFIX);
      Context.addGlobalSymbol( us, new OpDefNode( us, tla2sany.semantic.ASTConstants.BuiltInKind, 2,
                        new FormalParamNode[2], false, null, null, null, new SyntaxTreeNode( us ) ),
                        errors);
      break;
    case PREFIX:
      jj_consume_token(PREFIX);
      Context.addGlobalSymbol( us, new OpDefNode( us, tla2sany.semantic.ASTConstants.BuiltInKind, 1,
                        new FormalParamNode[1], false, null, null, null, new SyntaxTreeNode( us ) ),
                        errors);
      break;
    case POSTFIX:
      jj_consume_token(POSTFIX);
      Context.addGlobalSymbol( us, new OpDefNode( us, tla2sany.semantic.ASTConstants.BuiltInKind, 1,
                        new FormalParamNode[1], false, null, null, null, new SyntaxTreeNode( us ) ),
                        errors);
      break;
    case CONSTANT:
      jj_consume_token(CONSTANT);
      Context.addGlobalSymbol( us, new OpDefNode( us, tla2sany.semantic.ASTConstants.BuiltInKind, 0,
                        new FormalParamNode[0], false, null, null, null, new SyntaxTreeNode( us ) ),
                        errors);
      break;
    case NUMBER:
      t = jj_consume_token(NUMBER);
      int n = Integer.parseInt( t.image );
      FormalParamNode fpn[] = null;
      if ( n != -1 ) fpn = new FormalParamNode[ n ];
      Context.addGlobalSymbol( us, 
                        new OpDefNode( us, tla2sany.semantic.ASTConstants.BuiltInKind, n,
                                       fpn, false, null, null, null, new SyntaxTreeNode( us ) ),
                                       errors);
      break;
    default:
      jj_la1[6] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }

  }

  static private boolean                  jj_initialized_once = false;
  static public ConfigurationTokenManager token_source;
  static ASCII_CharStream                 jj_input_stream;
  static public Token                     token, jj_nt;
  static private int                      jj_ntk;
  static private int                      jj_gen;
  static final private int[]              jj_la1 = new int[7];
  static final private int[]              jj_la1_0 = 
                                            {0x44100,0x402000,0x44100,0x38000,
                                             0x1e00,0x200000,0x400e80,};

  public Configuration(java.io.InputStream stream) {
    if (jj_initialized_once) {
      ToolIO.out.println("ERROR: Second call to constructor of static parser.  You must");
      ToolIO.out.println("       either use ReInit() or set the JavaCC option STATIC to false");
      ToolIO.out.println("       during parser generation.");
      throw new Error();
    }
    jj_initialized_once = true;
    jj_input_stream = new ASCII_CharStream(stream, 1, 1);
    token_source = new ConfigurationTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  static public void ReInit(java.io.InputStream stream) {
    jj_initialized_once = false;
    jj_input_stream.ReInit(stream, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  public Configuration(java.io.Reader stream) {
    if (jj_initialized_once) {
      ToolIO.out.println("ERROR: Second call to constructor of static parser.  You must");
      ToolIO.out.println("       either use ReInit() or set the JavaCC option STATIC to false");
      ToolIO.out.println("       during parser generation.");
      throw new Error();
    }
    jj_initialized_once = true;
    jj_input_stream = new ASCII_CharStream(stream, 1, 1);
    token_source = new ConfigurationTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  static public void ReInit(java.io.Reader stream) {
    jj_initialized_once = false;
    jj_input_stream.ReInit(stream, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  // The following method added by DRJ.  It should be in the .jcc version of this file
  static public void ReInit() {
    jj_initialized_once = false;
    jj_input_stream.ReInit(input, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }


  public Configuration(ConfigurationTokenManager tm) {
    if (jj_initialized_once) {
      ToolIO.out.println("ERROR: Second call to constructor of static parser.  You must");
      ToolIO.out.println("       either use ReInit() or set the JavaCC option STATIC to false");
      ToolIO.out.println("       during parser generation.");
      throw new Error();
    }
    jj_initialized_once = true;
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  public void ReInit(ConfigurationTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 7; i++) jj_la1[i] = -1;
  }

  static final private Token jj_consume_token(int kind) throws ParseException {
    Token oldToken;
    if ((oldToken = token).next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    if (token.kind == kind) {
      jj_gen++;
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  }

  static final public Token getNextToken() {
    if (token.next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    jj_gen++;
    return token;
  }

  static final public Token getToken(int index) {
    Token t = token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  }

  static final private int jj_ntk() {
    if ((jj_nt=token.next) == null)
      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
    else
      return (jj_ntk = jj_nt.kind);
  }

  static private java.util.Vector jj_expentries = new java.util.Vector();
  static private int[] jj_expentry;
  static private int jj_kind = -1;

  static final public ParseException generateParseException() {
    jj_expentries.removeAllElements();
    boolean[] la1tokens = new boolean[24];
    for (int i = 0; i < 24; i++) {
      la1tokens[i] = false;
    }
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 7; i++) {
      if (jj_la1[i] == jj_gen) {
        for (int j = 0; j < 32; j++) {
          if ((jj_la1_0[i] & (1<<j)) != 0) {
            la1tokens[j] = true;
          }
        }
      }
    }
    for (int i = 0; i < 24; i++) {
      if (la1tokens[i]) {
        jj_expentry = new int[1];
        jj_expentry[0] = i;
        jj_expentries.addElement(jj_expentry);
      }
    }
    int[][] exptokseq = new int[jj_expentries.size()][];
    for (int i = 0; i < jj_expentries.size(); i++) {
      exptokseq[i] = (int[])jj_expentries.elementAt(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  }

  static final public void enable_tracing() {
  }

  static final public void disable_tracing() {
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/modelexplorer/CloneModelContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.handlers.CloneForeignModelHandler;
import org.lamport.tla.toolbox.tool.tlc.handlers.CloneModelHandlerDelegate;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Contributes a list of models for cloning.
 * 
 * @author <NAME>
 */
public class CloneModelContributionItem extends CompoundContributionItem
{
    /**
     * Contrary to CloneModelHandlerDelegate.COMMAND_ID, no enabledWhen expression plugin.xml
     */
    public static final String COMMAND_ID_ALWAYS_ENABLED = CloneModelHandlerDelegate.COMMAND_ID + ".always.enabled";

    private ImageDescriptor modelIcon = TLCUIActivator.getImageDescriptor("icons/full/choice_sc_obj.gif");

	protected IContributionItem[] getContributionItems() {
        final Vector<CommandContributionItem> modelContributions = new Vector<CommandContributionItem>();

        final Spec currentSpec = ToolboxHandle.getCurrentSpec();
        if (currentSpec == null) {
        	return new IContributionItem[0];
        }
        
        final IProject specProject = currentSpec.getProject();
		try {
            // refresh local to pick up any models that have been added
            // to the file system but not recognized by the toolbox's resource
            // framework.
			// TODO decouple from UI thread or question why it has to be done
			// here. Meaning, why doesn't the resource fw handle this case
			// already?
            specProject.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
		} catch (CoreException e) {
			TLCUIActivator.getDefault().logError("Exception encountered refreshing the project.", e);
        }

		// First, search for all models for the given spec.
		final Set<String> modelNames = currentSpec.getAdapter(TLCSpec.class).getModels().keySet();
		for (final String modelName : modelNames) {
            // Next, set the command and the parameters for the command
            // that will be called when the user selects this item.
            final Map<String, String> parameters = new HashMap<String, String>();

            // fill the model name for the handler
            parameters.put(CloneModelHandlerDelegate.PARAM_MODEL_NAME, modelName);

            // create the contribution item
            final CommandContributionItemParameter param = new CommandContributionItemParameter(UIHelper
                    .getActiveWindow(), "toolbox.command.model.clone." + modelName,
                    COMMAND_ID_ALWAYS_ENABLED, parameters, modelIcon, null, null, modelName, null,
                    "Clones " + modelName, CommandContributionItem.STYLE_PUSH, null, true);

            // add contribution item to the list
            modelContributions.add(new CommandContributionItem(param));
        }
		final CommandContributionItemParameter param
			= new CommandContributionItemParameter(UIHelper.getActiveWindow(),
					"toolbox.command.model.cloneforeign", CloneForeignModelHandler.COMMAND_ID, null, null, null, null,
					"Foreign Model...", null, "Shows a chooser dialog to select a foreign model.",
					CommandContributionItem.STYLE_PUSH, null, true);
        modelContributions.add(new CommandContributionItem(param));

        return (IContributionItem[]) modelContributions.toArray(new IContributionItem[modelContributions.size()]);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/TabNavigationLocation.java<|end_filename|>
// Copyright (c) Dec 20, 2011 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.forms.editor.IFormPage;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;

/**
 * @author <NAME>
 */
public class TabNavigationLocation implements INavigationLocation {

	private IFormPage formPage;
	private Object input;
	
	public TabNavigationLocation(IFormPage aFormPage) {
		this.formPage = aFormPage;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#saveState(org.eclipse.ui.IMemento)
	 */
	public void saveState(IMemento memento) {
		// no-op because we don't support persistent navigation history
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreState(org.eclipse.ui.IMemento)
	 */
	public void restoreState(IMemento memento) {
		// no-op because we don't support persistent navigation history
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreLocation()
	 */
	public void restoreLocation() {
		ModelEditor me = (ModelEditor) formPage.getEditor();
		me.setActivePage(formPage.getIndex());
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#mergeInto(org.eclipse.ui.INavigationLocation)
	 */
	public boolean mergeInto(INavigationLocation currentLocation) {
		// merge this and the given currentLocation if they both are the same type and handle the same page
		if(currentLocation instanceof TabNavigationLocation) {
			TabNavigationLocation fpnlc = (TabNavigationLocation) currentLocation;
			return formPage == fpnlc.formPage;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#update()
	 */
	public void update() {
		// nothing to update yet
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.NavigationLocation#dispose()
	 */
	public void dispose() {
		releaseState();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.NavigationLocation#releaseState()
	 */
	public void releaseState() {
		this.input = null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.NavigationLocation#getInput()
	 */
	public Object getInput() {
		return this.input;	
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.NavigationLocation#getText()
	 */
	public String getText() {
		final String title = this.formPage.getTitle();
		return title;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.NavigationLocation#setInput(java.lang.Object)
	 */
	public void setInput(Object input) {
		this.input = input;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LiveExprNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 15:30:18 PST by lamport
//      modified on Sun Aug  5 00:00:56 PDT 2001 by yuanyu

package tlc2.tool.liveness;

import tla2sany.semantic.LevelConstants;
import tlc2.tool.ITool;
import tlc2.tool.TLCState;

/**
 * LNConj - a conjunction. (contains list of conjuncts) LNDisj - a disjunction.
 * (contains list of disjuncts) LNAll - Allways: []e LNEven - Eventually: <>e
 * LNNeg - Negation: -e LNState - State predicate. Concrete types: LNStateAST,
 * LNStateEnabled LNAction - Transition predicate. LNNext - next. ()e. Only used
 * for tableau construction. Not part of TLA
 *
 * LNState and LNAction have tags. When constructing the tableau, we will have
 * to check whether two primitives are equal to each other, to distinguish
 * atoms. We could do it just by checking the object pointers to the Act and
 * State ASTNodes. But to make it absolutely explicit, I will use integer tags.
 * These are initialized to distinct values immediately before tableau
 * construction, used during tableau construction, and not used any more.
 *
 * There's a little bit of a hierarchy for the LNState. That's because
 * LNStateAST (which has just an ASTNode for the state predicate) must be
 * evaluated differently from LNStateEnabled (which has ENABLED ast in it)
 *
 * We are going to end up evaluating LNState and LNAction when we come to
 * construct the tableau graph. That's for the EAs, the EAs, and for local
 * consistency. Therefore LNState and LNAction have appropriate eval functions.
 **/

public abstract class LiveExprNode {
	/**
	 * getLevel() = 0 --> constant getLevel() = 1 --> state expression
	 * getLevel() = 2 --> action expression getLevel() = 3 --> temporal
	 * expression
	 * @see {@link LevelConstants}
	 */
	public abstract int getLevel();

	/* Returns true iff the expression contains action. */
	public abstract boolean containAction();

	boolean isPositiveForm() {
		return true;
	}

	/**
	 * @param s1 First state
	 * @param s2 Second (successor) state
	 * @param tool (Technical Tool implementation)
	 * @return true iff both states are consistent with this {@link LiveExprNode}.
	 */
	public abstract boolean eval(ITool tool, TLCState s1, TLCState s2);

	/* The string representation. */
	public final String toString() {
		StringBuffer sb = new StringBuffer();
		this.toString(sb, "");
		return sb.toString();
	}

	public abstract void toString(StringBuffer sb, String padding);

	/**
	 * This method returns true or false for whether two LiveExprNodes are
	 * syntactically equal.
	 */
	public abstract boolean equals(LiveExprNode exp);

	/* Return A if this expression is of form []<>A. */
	public LiveExprNode getAEBody() {
		return null;
	}

	/* Return A if this expression is of form <>[]A. */
	public LiveExprNode getEABody() {
		return null;
	}

	/**
	 * Return true if this expression is a general temporal formula containing
	 * no []<>A or <>[]A.
	 */
	public boolean isGeneralTF() {
		return true;
	}

	/* This method pushes a negation all the way down to the atoms.
	 * It uses the subset of rewriting rules on p. 452 of Manna & Pnueli that apply
	 * to operators that exist in TLA.
	 * @see tlc2.tool.liveness.LiveExprNodeTest
	 */
	public LiveExprNode pushNeg() {
		// for the remaining types, simply negate:
		// Note that this causes a StackOverflow if pushing negation into ~()P to ()~P
		// (see tests in LiveExprNodeTests). This is no problem though, because LNNext
		// nodes are created after negation has been pushed as part of the conversion to
		// disjunct normal form (DNF) with LiveExprNode#toDNF.
		return new LNNeg(this);
	}

	/**
	 * This method pushes a negation all the way down to the atoms. It is
	 * currently not used.
	 */
	public LiveExprNode pushNeg(boolean hasNeg) {
		if (hasNeg) {
			return new LNNeg(this);
		}
		return this;
	}


	/**
	 * The method simplify does some simple simplifications before starting any real
	 * work. It will get rid of any boolean constants (of type LNBool).
	 * <p>
	 * MAK 04/15/2021: The comment above claims to get rid of LNBools, but this is
	 * not always true.  A property such as `<>[]TRUE => TRUE` is indeed simplified
	 * to FALSE, but a property such as `FALSE /\ P ~> Q` is not simplified
	 * to `P ~> Q`; the `(FALSE /\ P)` part is represented by an OpApplNode (SANY)
	 * instance, which is nested in a LNStateAST.  Also, the current TLC test suite
	 * has only a single test (tlc2.tool.liveness.EmptyOrderOfSolutionsTest) that
	 * fails if the simplification is skipped.  All of this isn't too interesting,
	 * however, the trivial property `<>TRUE`, obviously, cannot be and is not
	 * simplified for the LNBool to be removed (and is also not identified as a
	 * tautology in Liveness.processLiveness). Perhaps, an earlier stage of the
	 * liveness implementation made this assumption. This would explain the bug
	 * that TLC produces a bogus counterexample for `<>TRUE`, unless LNBool
	 * instances are added to the statePredicates (in addition to LNState) in
	 * TBGraphNode::new. Another example is `TRUE ~> Q` where Q is either constant-
	 * or state-level.
	 * 
	 * See Github issue #604 and the test Github604.tla
	 */
	public LiveExprNode simplify() {
		// for the remaining types, simply negate:
		return this;
	}
	
	/**
	 * The method toDNF turns a LiveExprNode into disjunctive normal form.
	 */
	public LiveExprNode toDNF() {
		// For the remaining types, there is nothing to do:
		return this;
	}

	/**
	 * This method eliminates (flattens) singleton conjunctions and
	 * disjunctions. For example, /\[single-thing] is rewritten to single-thing.
	 * Note: With the current version of toDNF, there is probably no need for
	 * calling this method.
	 */
	public LiveExprNode flattenSingleJunctions() {
		// Finally, for the remaining types, there is nothing to do:
		return this;
	}

	/**
	 * This method makes all conjunctions and disjunctions binary. This is for
	 * tableau 'triple' construction. We'll do a recursive thing to balance the
	 * binary trees. Note that there can be no LNActions.
	 */
	public LiveExprNode makeBinary() {
		return this;
	}

	/**
	 * TagExpr tags all Act and State subexpressions in an expression. It
	 * returns the maximum tag used so that the caller can proceed with other
	 * tags in its depth-first traversal.
	 */
	public int tagExpr(int tag) {
		// Non-trivially overridden in:
		// - LNState
		// - LNAction
		return tag;
	}

	/**
	 * The method extractPromises, given a formula, returns all the promises in
	 * its closure. All promises are in the form <>p. (We assume that we have
	 * pushed all negations inside. So, there are no -[]ps.) The closure of a
	 * formula says: for all subformulas of p, they are also in the closure. And
	 * some other rules, none of which have the possibility of creating a
	 * promise! So we only need look at subformulas of p.
	 */
	public void extractPromises(TBPar promises) {
		// Finally, for the remaining kinds, there is nothing to do.
		// Except for LNEven, all LiveExprNode sub-classes have either trivial overrides
		// or none at all.
		return;
	}

	public String toDotViz() {
		// By default just return the regular toString rep.
		return toString();
	}

	/**
	 * This doesn't mutate the LiveExprNode hierarchy it is called on. This is the
	 * entry point for callers. @see LiveExprNode#extractPromises(TBPar) for details
	 * what actually happens.
	 */
	public final LNEven[] extractPromises() {
		final TBPar promises = new TBPar(10);
		extractPromises(promises);
		
		final LNEven[] prms = new LNEven[promises.size()];
		for (int j = 0; j < promises.size(); j++) {
			prms[j] = (LNEven) promises.exprAt(j);
		}

		return prms;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/callable/CheckFPsCallable.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp.callable;

import java.io.IOException;
import java.util.concurrent.Callable;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.distributed.fp.FPSetRMI;

public class CheckFPsCallable implements Callable<Long> {
	private final FPSetRMI fpSetRMI;
	
	public CheckFPsCallable(FPSetRMI fpSetRMI) {
		this.fpSetRMI = fpSetRMI;
	}

	/* (non-Javadoc)
	 * @see java.util.concurrent.Callable#call()
	 */
	public Long call() throws Exception {
		try {
			return fpSetRMI.checkFPs();
		} catch (IOException e) {
			// not expected to happen.
			MP.printError(EC.GENERAL, e);
			// return max value to indicate to caller that the result is
			// incorrect.
			return Long.MAX_VALUE;
		}
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.test/src/org/lamport/tla/toolbox/tool/tlc/util/ModelHelperTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchDelegate;
import org.junit.Assert;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationConstants;

import junit.framework.TestCase;
import tlc2.model.Assignment;

/**
 * Test for toolkit methods
 */
public class ModelHelperTest extends TestCase
{

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
    }

    /**
     * Test method for {@link org.lamport.tla.toolbox.tool.tlc.util.ModelHelper#getCheckpoints(org.eclipse.debug.core.ILaunchConfiguration)}.
     */
    public void testRegexGetCheckpoints()
    {
        String input = "09-08-13-15-07-32";
        String input2 = "hello dolly";
        
        Pattern pattern = Pattern.compile("[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}");
        
        Matcher matcher = pattern.matcher(input);
        Assert.assertTrue(matcher.matches());

        Matcher matcher2 = pattern.matcher(input2);
        Assert.assertFalse(matcher2.matches());
    }
    
    public void testStripSymmetry() {
    	final List<String> serializedList = new ArrayList<String>();
    	serializedList.add("Procs;;{A, B};1;1");
    	
    	// Symmetry not stripped
    	List<Assignment> deserializeAssignmentList = ModelHelper.deserializeAssignmentList(serializedList);
    	assertEquals(1, deserializeAssignmentList.size());
    	assertTrue(deserializeAssignmentList.get(0).isSymmetricalSet());
    	
    	// Symmetry stripped
    	deserializeAssignmentList = ModelHelper.deserializeAssignmentList(serializedList, true);
    	assertEquals(1, deserializeAssignmentList.size());
    	assertFalse(deserializeAssignmentList.get(0).isSymmetricalSet());
    }
    
    public void testPrettyPrintConstants2() throws CoreException {
		final List<String> values = new ArrayList<String>();
		values.add("X;;X;1;0");
		values.add("Y;;{a1, b1};1;0");
		values.add("Z;;{s1, s2};1;1");
		values.add("W;;1;0;0");
		values.add("V;;V;1;0");
		values.add("U;;42;0;0");
		final ILaunchConfiguration config = new DummyLaunchConfig(
				IModelConfigurationConstants.MODEL_PARAMETER_CONSTANTS, values);

		final String constants = ModelHelper.prettyPrintConstants(config, "\n");
    	final String[] split = constants.split("\n");
    	assertEquals(5, split.length);
    	assertEquals("U <- 42", split[0]);
    	assertEquals("W <- 1", split[1]);
    	assertEquals("Y <- {a1, b1}", split[2]);
    	assertEquals("Z <- s{s1, s2}", split[3]);
    	assertEquals("Model values: V, X", split[4]);
    }
    
    private class DummyLaunchConfig implements ILaunchConfiguration {

    	private final Map<String, List<String>> attributes = new HashMap<String, List<String>>();
    	
    	public DummyLaunchConfig(String key, List<String> value) {
    		this.attributes.put(key, value);
    	}
    	
		public <T> T getAdapter(Class<T> adapter) {
			return null;
		}

		public boolean contentsEqual(ILaunchConfiguration configuration) {
			return false;
		}

		public ILaunchConfigurationWorkingCopy copy(String name) throws CoreException {
			return null;
		}

		public void delete() throws CoreException {
		}

		public boolean exists() {
			return false;
		}

		public boolean getAttribute(String attributeName, boolean defaultValue) throws CoreException {
			return false;
		}

		public int getAttribute(String attributeName, int defaultValue) throws CoreException {
			return 0;
		}

		public List<String> getAttribute(String attributeName, List<String> defaultValue) throws CoreException {
			return this.attributes.get(attributeName);
		}

		public Set<String> getAttribute(String attributeName, Set<String> defaultValue) throws CoreException {
			return null;
		}

		public Map<String, String> getAttribute(String attributeName, Map<String, String> defaultValue)
				throws CoreException {
			return null;
		}

		public String getAttribute(String attributeName, String defaultValue) throws CoreException {
			return null;
		}

		public Map<String, Object> getAttributes() throws CoreException {
			return null;
		}

		public String getCategory() throws CoreException {
			return null;
		}

		public IFile getFile() {
			return null;
		}

		public IPath getLocation() {
			return null;
		}

		public IResource[] getMappedResources() throws CoreException {
			return null;
		}

		public String getMemento() throws CoreException {
			return null;
		}

		public String getName() {
			return null;
		}

		public Set<String> getModes() throws CoreException {
			return null;
		}

		public ILaunchDelegate getPreferredDelegate(Set<String> modes) throws CoreException {
			return null;
		}

		public ILaunchConfigurationType getType() throws CoreException {
			return null;
		}

		public ILaunchConfigurationWorkingCopy getWorkingCopy() throws CoreException {
			return null;
		}

		public boolean hasAttribute(String attributeName) throws CoreException {
			return false;
		}

		public boolean isLocal() {
			return false;
		}

		public boolean isMigrationCandidate() throws CoreException {
			return false;
		}

		public boolean isWorkingCopy() {
			return false;
		}

		public ILaunch launch(String mode, IProgressMonitor monitor) throws CoreException {
			return null;
		}

		public ILaunch launch(String mode, IProgressMonitor monitor, boolean build) throws CoreException {
			return null;
		}

		public ILaunch launch(String mode, IProgressMonitor monitor, boolean build, boolean register)
				throws CoreException {
			return null;
		}

		public void migrate() throws CoreException {
		}

		public boolean supportsMode(String mode) throws CoreException {
			return false;
		}

		public boolean isReadOnly() {
			return false;
		}

		public void delete(int flag) throws CoreException {
		}

		public ILaunchConfiguration getPrototype() throws CoreException {
			return null;
		}

		public boolean isAttributeModified(String attribute) throws CoreException {
			return false;
		}

		public Collection<ILaunchConfiguration> getPrototypeChildren() throws CoreException {
			return new ArrayList<ILaunchConfiguration>();
		}

		public int getKind() throws CoreException {
			return 0;
		}

		public Set<String> getPrototypeVisibleAttributes() throws CoreException {
			return null;
		}

		public void setPrototypeAttributeVisibility(String attribute, boolean visible) throws CoreException {
		}

		public boolean isPrototype() {
			return false;
		}
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/FixedSizedBucketStatistics.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.util.statistics;

import java.util.NavigableMap;
import java.util.TreeMap;

public class FixedSizedBucketStatistics extends AbstractBucketStatistics implements IBucketStatistics {

	/**
	 * The amount of samples seen by this statistics. It's identical
	 * to the sum of the value of all buckets.
	 */
	private long observations;
	
	/**
	 * Instead of using an ever-growing list of samples, identical
	 * samples are counted in a bucket. E.g. the sample 5 is stored
	 * in a bucket with key 5 and a value of 2 if the sample has been
	 * seen two times.
	 * The map is thread safe, so are the values.
	 */
	private final long[] buckets;
	
	/**
	 * @param aTitle
	 *            A title for console pretty printing
	 * @param aMaxmimum
	 *            see {@link BucketStatistics#maximum}
	 */
	public FixedSizedBucketStatistics(final String aTitle, final int aMaxmimum) {
		super(aTitle);
		this.buckets = new long[aMaxmimum];
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#addSample(int)
	 */
	public void addSample(int amount) {
		if (amount < 0) {
			throw new IllegalArgumentException("Negative amount invalid");
		}
		
		// If the amount exceeds the fixed maximum, increment the overflow
		// bucket. The overflow bucket is the very last bucket. 
		final int idx = Math.min(this.buckets.length - 1, amount);
		
		this.buckets[idx]++;
		this.observations++;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.AbstractBucketStatistics#getObservations()
	 */
	public long getObservations() {
		return observations;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.statistics.IBucketStatistics#getSamples()
	 */
	public NavigableMap<Integer, Long> getSamples() {
		final NavigableMap<Integer, Long> res = new TreeMap<Integer, Long>();
		for (int i = 0; i < this.buckets.length; i++) {
			long value = this.buckets[i];
			if (value > 0) {
				res.put(i, value);
			}
		}
		return res;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/ParseError.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;


public class ParseError implements tla2sany.st.ParseError {
  private String custom;
  private String backup;
  ParseError(String a, String b) {
    custom = a;
    backup = b;
  }

  ParseError(String a) {
    custom = a;
    backup = "";
  }

  public final String reportedError() { return custom; };
  public final String defaultError() { return backup; };
}



<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/DummyFPSetConfiguration.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

@SuppressWarnings("serial")
public class DummyFPSetConfiguration extends FPSetConfiguration {
	
	/* (non-Javadoc)
	 * @see tlc2.tool.fp.FPSetConfiguration#getMemoryInBytes()
	 */
	public long getMemoryInBytes() {
		// Override super.getMemoryInBytes() to allow unit tests to pass an
		// explicit value by bypassing util.TLCRuntime.getFPMemSize(double).
		// getFPMemSize(double) sets a lower limit for the DiskFPSet size, 
		// which unit tests might have to tear down.
		return memoryInBytes;
	}
	
	public void setMemoryInFingerprintCnt(long length) {
		this.memoryInBytes = length * FPSet.LongSize;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/Vector.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.utilities;
import java.util.Enumeration;

public class Vector<E> {
  static int defaultSize = 10;
  
  protected Object info[];
  protected int size = 0;
  protected int capacity;
  protected int increment;

  public Vector() {
    info = new Object[ defaultSize ];
    capacity = defaultSize;
    increment = defaultSize;
  }

  public Vector(int initialSize ) {
    info = new Object[ initialSize ];
    capacity = initialSize;
    increment = initialSize;
  }

  public final int size() {
    return size;
  }

  /* Method replaced below
  public final String toString() {
    String ret="";

    for (int i = 0; i < size; i++) {
      ret = ret + info[i].toString();
    }

    return ret;
  }
  */

  public final void addElement( E obj ) {
    if (size == capacity) {
      Object next[] = new Object[ capacity + increment ];
      System.arraycopy( info, 0, next, 0, capacity );
      capacity+= increment;
      info = next;
    }
    info[ size ] = obj;
    size++;
  }

  @SuppressWarnings("unchecked")
  public final E firstElement() {
    return (E)info[0];
  }

  @SuppressWarnings("unchecked")
  public final E lastElement() {
    return (E)info[ size-1 ];
  }

  @SuppressWarnings("unchecked")
  public final E elementAt(int i) {
    if (i < 0 || i >= size )
      throw new ArrayIndexOutOfBoundsException();
    else
      return (E)info[ i ];
  }

  public final void removeAllElements() {
    for (int lvi = 0; lvi < size; lvi++ ) {
      info[lvi] = null;
    }
    size = 0;
  }

  public final void removeElementAt( int i ) {
    if (i < 0 || i >= size )
      throw new ArrayIndexOutOfBoundsException();
    else {
      for (int lvi = i+1; lvi < size; lvi++ )
        info[ lvi-1 ] = info [lvi];
      size--;
      info[ size ] = null;
    }
  }

  public final void insertElementAt( E obj, int i ) {
    if (i < 0 || i >= size )
      throw new ArrayIndexOutOfBoundsException();
    else if (size == capacity) {
      Object next[] = new Object[ capacity + increment ];
      System.arraycopy( info, 0, next, 0, i );
      next[i] = obj;
      System.arraycopy( info, i, next, i+1, capacity - i );
      capacity+= increment;
      info = next;
    } else {
      for ( int lvi = size; lvi > i; lvi-- )
        info[ lvi ] = info[lvi-1];
      info[ i ] = obj;
    }
    size++;
  }

  public final void setElementAt( E obj, int i ) {
    if (i < 0 || i >= size )
      throw new ArrayIndexOutOfBoundsException();
    else 
      info[ i ] = obj;
  }

  public final boolean contains (E obj) {
    for (int i = 0; i < size; i++) {
      if ( info[ i ] == obj ) return true;
    }
    return false; 
  }

  public final Enumeration<E> elements() {
    return new VectorEnumeration<E>( info, size );
  }

  public final void append( Vector<E> v ) {
    if ( v.size + size  > capacity ) {
      Object neo[] = new Object[ capacity + v.capacity ];
      capacity += v.capacity;
      System.arraycopy( info, 0, neo, 0, size );
      info = neo;
    }
    System.arraycopy( v.info, 0, info, size, v.size );
    size += v.size;
  }

  // Like the append method above, but elements of v will not be added to THIS Vector 
  // if they are already present at least once; repeated elements already in 
  // THIS Vector, however, will not be removed.
  public final void appendNoRepeats(Vector<E> v) {
    for (int i = 0; i < v.size(); i++) {
      if ( ! this.contains(v.elementAt(i)) ) this.addElement(v.elementAt(i));
    }
  }

  @Override
  public final String toString() {
    String ret;
    ret = "[ ";
    if (this.size() > 0) ret += this.elementAt(0).toString();
    for (int i = 1; i<this.size(); i++) {
      ret += ", " + this.elementAt(i).toString();
    }
    return ret + " ]";
  } // end toString()
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/preference/TranslatorPreferencePage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.preference;

import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.util.IHelpConstants;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * Currently, this preference page is not used.
 *
 */
public class TranslatorPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage
{

    /**
     * Constructor
     */
    public TranslatorPreferencePage()
    {
        super(GRID);
        setPreferenceStore(PreferenceStoreHelper.getInstancePreferenceStore());
        setDescription("PCal Translator preferences");
    }

    protected Control createContents(Composite parent)
    {
        Control pageControl = super.createContents(parent);
        UIHelper.setHelp(pageControl, IHelpConstants.TRANSLATOR_PREFERENCE_PAGE);
        return pageControl;
    }

    /**
     * Create field editors
     */
    protected void createFieldEditors()
    {

        addField(new BooleanFieldEditor(IPreferenceConstants.I_TRANSLATE_POPUP_ERRORS,
                "&Popup problem window on translator errors", getFieldEditorParent()));

        addField(new BooleanFieldEditor(IPreferenceConstants.I_TRANSLATE_MODULE_ON_MODIFY,
                "&Re-translate on module save", getFieldEditorParent()));
    }

    public void init(IWorkbench workbench)
    {

    }

    protected void initialize()
    {
        // sync the auto-build
        // getPreferenceStore().setValue(IPreferenceConstants.I_PARSE_MODULE_ON_MODIFY,
        // ResourcesPlugin.getWorkspace().isAutoBuilding());
        super.initialize();
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCRegionContainer.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.Vector;

import org.eclipse.jface.text.ITypedRegion;

/**
 * Container TLC region
 * @author <NAME>
 * @version $Id$
 */
public class TLCRegionContainer extends TLCRegion
{

    private Vector<ITypedRegion> subRegions = new Vector<ITypedRegion>();

    /**
     * Constructs the container type
     * @param offset
     * @param length
     */
    public TLCRegionContainer(int offset, int length)
    {
        super(offset, length);
    }

    public ITypedRegion[] getSubRegions()
    {
        return (ITypedRegion[]) subRegions.toArray(new ITypedRegion[subRegions.size()]);
    }

    public void setSubRegions(Vector<ITypedRegion> elements)
    {
        this.subRegions = elements;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/OperatorStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;

import tla2sany.utilities.Vector;
import util.UniqueString;

/***************************************************************************
* An OperatorStack object is a stack of stacks of OSelement objects.       *
***************************************************************************/

public class OperatorStack implements tla2sany.st.SyntaxTreeConstants {

  private Vector StackOfStack = new Vector (10);
    /***********************************************************************
    * The actual OperatorStack object.  It appears to be a vector of       *
    * vectors of OSElement objects.  A stack appears to be represented by  *
    * a vector v where v.elementAt(v.size()-1) is the top element of the   *
    * stack.                                                               *
    ***********************************************************************/

  private SyntaxTreeNode VoidSTNode = new SyntaxTreeNode( );

  private Vector CurrentTop = null;
    /***********************************************************************
    * Appears to be the stack of OSelement objects at the top of the       *
    * OperatorStack.  It equals null if OperatorStack is empty.  Does it   *
    * equal null only if OperatorStack is empty?  J-Ch says yes.           *
    ***********************************************************************/
    
  private ParseErrors PErrors;

  private Operator fcnOp;
    /***********************************************************************
    * This is a constant set when the OperatorStack object is created to   *
    * the operator entry for "[", which apparently is a dummy operator     *
    * representing function application.                                   *
    ***********************************************************************/
    
  public OperatorStack( ParseErrors pe ) {
    PErrors = pe;
    fcnOp = Operators.getOperator( UniqueString.uniqueStringOf("[") ); }

// could be optimized to reuse memory
  public final void newStack() {
    /***********************************************************************
    * Adds an empty stack to the top of the OperatorStack.                 *
    ***********************************************************************/
    CurrentTop = new Vector( 20 );
    StackOfStack.addElement( CurrentTop );
  }

// could be optimized to reuse memory
  public final void popStack() {
    /***********************************************************************
    * Removes the element at the top of the operator stack.                *
    ***********************************************************************/
    StackOfStack.removeElementAt( StackOfStack.size()-1 );
    if (StackOfStack.size() > 0 )
      CurrentTop = (Vector) StackOfStack.elementAt( StackOfStack.size() - 1 );
    else
      CurrentTop = null;
  }

//
  public final boolean empty() {
    return CurrentTop.size()==0; // CurrentTop 
  }

  public final int size() {
    return CurrentTop.size();
  }

/*
  We use the prec and succ relations, as described in the formal specs of the grammar.
  Their definition is embedded in the Operator class.
  One way to look at prec and succ is in term of their effect on the stack:
  if left \prec right, then shift; if left \succ right, then reduce.
                            ^^^^^
What do left and right mean?????? What does shift mean????????
  There are caveats in the case of prefix or postfix operators.
*/

// returns true if the top of the stack holds a prefix or infix op
// used to distinguish [] from [] - or vice versa ?
// also used to distinguish junction from \/ or /\
  final public boolean preInEmptyTop() {
    /***********************************************************************
    * Returns true iff OperatorStack is empty, the stack at the top of     *
    * OperatorStack is empty, or OSElement at the top of the stack at the  *
    * top of OperatorStack is that of a prefix or infix operator.          *
    ***********************************************************************/
    if (CurrentTop == null) return true; // empty or holding nothing - lookahead compliant
    if (CurrentTop.size() == 0)
      return true;
    else {
      Operator op  = ((OSelement) CurrentTop.elementAt( CurrentTop.size()-1 )).getOperator();
      if (op != null)
        return op.isPrefix() || op.isInfix();
      else
        return false;
    }
  }

  final private void reduceInfix( Operator op ) {
    /***********************************************************************
    * IF Len(CurrentTop) < 4                                               *
    *   THEN do nothing.                                                   *
    *   ELSE Suppose CurrentTop = <<head, op1, op2, op3>> \o rest          *
    *        and LET rightOp  == op1.node                                  *
    *                opNode   == op2.node                                  *
    *                leftNode == op3.node                                  *
    *        Set CurrentTop to <<head, OSelement(lSTN)>> \o rest, where    *
    *        lSTN = IF op represents an operator of type/kind N_Times      *
    *                 THEN IF leftOp is an operator of type/kind N_Times   *
    *                        THEN A node of type N_Times with heirs        *
    *                             leftOp.heirs \o <<opNode, rightNode>>    *
    *                        ELSE a node of type N_Times with heirs        *
    *                             <<leftOp, opNode, rightOp>>              *
    *                 ELSE a node of type N_InfixExpr with heirs           *
    *                      <<leftOp, opNode, rightOp>>                     *
    ***********************************************************************/
// System.err.println("infix reduction on " + op.toString() );
    int n = CurrentTop.size()-1;
//    SyntaxTreeNode localTN = new InfixExprNode();
    if (n>=3) {
      SyntaxTreeNode opNode  = ((OSelement) CurrentTop.elementAt( n-2)).getNode();
      SyntaxTreeNode leftOp  = ((OSelement) CurrentTop.elementAt( n-3)).getNode();
      SyntaxTreeNode rightOp = ((OSelement) CurrentTop.elementAt( n-1)).getNode();
      CurrentTop.removeElementAt(n-1);
      CurrentTop.removeElementAt(n-2);
      SyntaxTreeNode lSTN;

      if (op.isNfix() && leftOp.isKind( N_Times ) ) {
        SyntaxTreeNode children[] = (SyntaxTreeNode[])leftOp.heirs();
        SyntaxTreeNode newC[] = new SyntaxTreeNode[ children.length + 2];
        System.arraycopy(children, 0, newC, 0, children.length);
        newC[ newC.length-2 ] = opNode;
        newC[ newC.length-1 ] = rightOp;
        lSTN = new SyntaxTreeNode( N_Times, newC );
      } else if (op.isNfix()) { // first \X encountered
        lSTN = new SyntaxTreeNode(N_Times, leftOp , opNode, rightOp );
      } else { // inFix
        lSTN = new SyntaxTreeNode(N_InfixExpr, leftOp , opNode, rightOp );
      }
      CurrentTop.setElementAt(new OSelement(lSTN), n-3);
    }
  }

  final private void reducePrefix() {
    /***********************************************************************
    * IF Len(CurrentTop) < 3                                               *
    *   THEN do nothing                                                    *
    *   ELSE suppose CurrentTop = <<head, next, third>> \o rest            *
    *        LET opNode == third.node                                      *
    *        Set CurrentTop to <<head, OSelement(lSTN)>> \o rest, where    *
    *        lSTN is a node of kind N_PrefixExpr with heirs                *
    *             third, next.                                             *
    ***********************************************************************/
// Log.log(evalStackLog, "--- reduce prefix");
// System.out.print("prefix reduction ");
    int n = CurrentTop.size()-1;
//    SyntaxTreeNode localTN = new PrefixExprNode();
    if (n>=2) {
      Operator op = ((OSelement) CurrentTop.elementAt( n-2)).getOperator();
        /*******************************************************************
        * It appears that op is no longer used.                            *
        *******************************************************************/
      SyntaxTreeNode opNode = ((OSelement) CurrentTop.elementAt( n-2)).getNode();
// System.out.println( op.getIdentifier() );
//      if ( op.isInfix() )
//        ((GenOpNode)opNode).register( op.getIdentifier() + ".", STable);
//      else
//        ((GenOpNode)opNode).register( op.getIdentifier(), STable);
        SyntaxTreeNode lSTN = new SyntaxTreeNode(N_PrefixExpr,
          ((OSelement) CurrentTop.elementAt( n-2)).getNode(),
          ((OSelement) CurrentTop.elementAt( n-1)).getNode());
//      localTN.addChild( ((OSelement) CurrentTop.elementAt( n-2)).getNode() ) ;
//      localTN.addChild( ((OSelement) CurrentTop.elementAt( n-1)).getNode() ) ;
      CurrentTop.removeElementAt(n-1);
      CurrentTop.setElementAt(new OSelement(lSTN) , n-2);
    }
  }

  final private void reducePostfix() {
    /***********************************************************************
    * IF Len(CurrentTop) < 3                                               *
    *   THEN do nothing                                                    *
    *   ELSE suppose CurrentTop = <<head, next, third>> \o rest            *
    *        LET op     == next.op                                         *
    *            opNode == next.node                                       *
    *        Set CurrentTop to <<head, OSelement(lSTN)>> \o rest, where    *
    *        lSTN = IF op = fcnOp                                          *
    *                 THEN a node of kind N_FcnAppl with heirs             *
    *                      third.node \o opNode.heirs                      *
    *                 ELSE a node of kind N_PostfixExpr with heirs         *
    *                      third.node, opNode.                             *
    ***********************************************************************/
// Log.log(evalStackLog, "--- reduce postfix");
// System.out.println("postfix reduction");
    int n = CurrentTop.size()-1;
    SyntaxTreeNode lSTN;
//    SyntaxTreeNode localTN = new PostfixExprNode();
    if (n>=2) {
      Operator op = ((OSelement) CurrentTop.elementAt( n-1)).getOperator();
      SyntaxTreeNode opNode = ((OSelement) CurrentTop.elementAt( n-1)).getNode();
      if (op != fcnOp ) {
//      ((GenOpNode)opNode).register( op.getIdentifier(), STable);
        lSTN = new SyntaxTreeNode(N_PostfixExpr,
          ((OSelement) CurrentTop.elementAt( n-2)).getNode(),
          opNode);
//      localTN.addChild( ((OSelement) CurrentTop.elementAt( n-2)).getNode() ) ;
//      localTN.addChild( opNode ) ;
      } else {
// System.out.println("postfix reduction : FcnOp");
        SyntaxTreeNode eSTN = ((OSelement) CurrentTop.elementAt( n-2)).getNode();
        lSTN = new SyntaxTreeNode( eSTN.getFN(), N_FcnAppl, eSTN, (SyntaxTreeNode[]) (opNode.heirs()) );
      }
      CurrentTop.removeElementAt(n-1);
      CurrentTop.setElementAt(new OSelement(lSTN) , n-2);
    }
  }


// we follow case by case the definitions here.
// returns true if reduction succeeded, or was without effect.
  final public void reduceStack () throws ParseException {
    int n;
      /*********************************************************************
      * I presume java initializes n to 0                                  *
      *********************************************************************/
    Operator oR, oL;    // left and right operator
    Operator LastOp = null; // used to remember what we last reduced
    OSelement tm0, tm1, tm2;
    int a1, a2;

    do { // until (n != CurrentTop.size()-1);
      n = CurrentTop.size()-1; 
         // note !!! n is used as index, not size. XXX lousy identifier.
      tm0 = (OSelement)CurrentTop.elementAt( n );

      if ( ! tm0.isOperator() ) break; /* break = return here */
      oR = tm0.getOperator();
// System.out.println("tm0 est " + oR.toString() + printStack() );
      if ( oR.isPostfix() ) {
        if ( n == 0 ) {
          throw new ParseException("\n  Encountered postfix op " + 
                                   oR.getIdentifier() + " in block " + 
                                   tm0.getNode().getLocation().toString() + 
                                   " on empty stack");
        } else {
          tm1 = (OSelement)CurrentTop.elementAt( n-1 );
          if ( tm1.isOperator()) {
            oL = tm1.getOperator();
// System.out.println("tm1 est " + oL.toString() );
            if ( oL.isInfix() || oL.isPrefix() ) {
              throw new ParseException("\n  Encountered postfix op " + 
                                       oR.getIdentifier() + " in block " + 
                                       tm0.getNode().getLocation().toString() + 
                                       " following prefix or infix op " + 
                                       oL.getIdentifier() + ".");
            } else { // isPostfixOp - must reduce.
              reducePostfix();
            }
          } else { // tm1 is Expression - what's below ?
            if ( n > 1 ) {
              tm2 = (OSelement)CurrentTop.elementAt( n-2 );
              if ( tm2.isOperator() ) { 
                oL = tm2.getOperator();
                if ( Operator.succ( oL, oR ) ) { // prefix or infix ?
                   if ( oL.isInfix() ) reduceInfix( oL ); else reducePrefix();
                } else if ( ! Operator.prec( oL, oR ) ) {
                  throw new ParseException(
                           "Precedence conflict between ops " + 
                           oL.getIdentifier() + " in block " + 
                           tm0.getNode().getLocation().toString() + " and " 
                           + oR.getIdentifier() + ".");
		} else
		  break;
              } else {
                throw new ParseException(
                  "Expression at location " + 
                  tm2.getNode().getLocation().toString() +
                  " and expression at location " + 
                  tm1.getNode().getLocation().toString() +
                  " follow each other without any intervening operator.");
              }
            } else
              break; // nothing this time around.
          }
        }
      } else if ( oR.isPrefix() ) {
        if ( n == 0 ) break; // can't do anything yet
        else {
          tm1 = (OSelement)CurrentTop.elementAt( n-1 );
          if ( tm1.isOperator()) { // prefix, or infix
            oL = tm1.getOperator();
            if ( oL.isPostfix() ) {
              throw new ParseException(
                      "\n  Encountered prefix op " + oR.getIdentifier() + 
                      " in block " + tm0.getNode().getLocation().toString() + 
                      " following postfix op " + oL.getIdentifier() + ".");
            } else // nothing to do
              break;
          } else { // can't be expression 
            throw new ParseException(
                          "\n  Encountered prefix op " + oR.getIdentifier() + 
                          " in block " + 
                          tm0.getNode().getLocation().toString() + 
                          " following an expression.");
          }
        }
      } else { // oR.isInfix()
        if ( n == 0 ) {
            Operator mixR  = Operators.getMixfix( oR );
            if ( mixR == null )
              throw new ParseException(
                          "\n  Encountered infix op " + oR.getIdentifier() + 
                          " in block " + 
                          tm0.getNode().getLocation().toString() + 
                          " on empty stack.");
            else
              break;
        } else {
// System.out.println("infix case: " + oR.getIdentifier());
          tm1 = (OSelement)CurrentTop.elementAt( n-1 );
          if ( tm1.isOperator()) {
            oL = tm1.getOperator();
            if ( oL.isInfix() || oL.isPrefix() ) { 
                    // new case for mixfix XXX this is not exhaustive.
              Operator mixR  = Operators.getMixfix( oR );
              if ( mixR == null ) { // is infix
                if (oR == Operator.VoidOperator() )
                  throw new ParseException(
                         "\n  Missing expression in block " + 
                         tm1.getNode().getLocation().toString() + 
                         " following prefix or infix op " + 
                         oL.getIdentifier() + ".");
                else
                  throw new ParseException(
                              "\n  Encountered infix op " + 
                              oR.getIdentifier() + " in block " + 
                              tm1.getNode().getLocation().toString() + 
                              " following prefix or infix op " + 
                              oL.getIdentifier() + ".");
              } else if (   Operator.succ( oL, mixR ) 
                         || ( oL == mixR && oL.assocLeft() ) ) {
// System.out.println("precedence pbm detected");
                throw new ParseException(
                            "\n  Precedence conflict between ops " + 
                            oL.getIdentifier() + " in block " + 
                            tm1.getNode().getLocation().toString() + 
                            " and " + mixR.getIdentifier() + ".");
              } // else, skip
            } else // no choice
              reducePostfix();
          } else { // tm1 is Expression - what's below ?
// System.out.println("tm1 is expression");
            if ( n > 1 ) {
// System.out.println("deep stack");
              tm2 = (OSelement)CurrentTop.elementAt( n-2 );
              if ( tm2.isOperator() ) {
                oL = tm2.getOperator();
// System.out.println("tm2 is operator: " + oL.getIdentifier());
                Operator mixL = Operators.getMixfix( oL );
                if (  mixL != null && ((n==2) 
                    || 
                     ((OSelement)CurrentTop.elementAt( n-3 )).isOperator())) {
// System.out.println("identified prefix");
                  oL = mixL;
                } 
                if (  Operator.succ( oL, oR ) 
                    ||
                     ( oL == oR && oL.assocLeft() ) ) { 
                         // prefix or infix ?
// System.out.println("prefix or infix in succ oL, oR");
                   if      ( oL.isInfix() ) reduceInfix(oL);
                   else if ( oL.isPrefix() ) reducePrefix();
                   else {
                     if (   (tm2.getNode().getLocation().beginLine() < 
                                tm1.getNode().getLocation().beginLine() )
                         && (oR.getIdentifier() == 
                               UniqueString.uniqueStringOf("=") )) {
// System.out.println("Case 1");
                       throw new ParseException(
                              "\n  *** Hint *** You may have mistyped ==" + 
                              "\n  Illegal combination of operators " + 
                              oL.getIdentifier() + " in block " + 
                              tm2.getNode().getLocation().toString() + 
                              " and " + oR.getIdentifier() + ".");
		     } else if (oR == Operator.VoidOperator() ) {
// System.out.println("Case 2");
	               throw new ParseException(
                               "\n Error following expression at  " + 
                               tm2.getNode().getLocation().toString() + 
                               ", missing operator or separator.");
		     } else {
// System.out.println("Case 3");
                       throw new ParseException(
                              "\n  Illegal combination of operators " + 
                              oL.getIdentifier() + " in block " + 
                              tm2.getNode().getLocation().toString() + 
                              " and " + oR.getIdentifier() + ".");
		     }
                  }
                } else if (   !( Operator.prec( oL, oR ) 
                           || (oL==oR && oL.assocRight())) ) {
// System.out.println("prefix or infix in prec oL, oR+++ throwing exception");
                    throw new ParseException(
                            "\n  Precedence conflict between ops " + 
                            oL.getIdentifier() + " in block " + 
                            tm2.getNode().getLocation().toString() + 
                            " and " + oR.getIdentifier() + ".");
                } else {
// System.out.println("Case not handled");
                  break;
		}
              } else {
                throw new ParseException(
                        "Expression at location " + 
                        tm2.getNode().getLocation().toString() +
                        " and expression at location " + 
                        tm1.getNode().getLocation().toString() +
                        " follow each other without any " + 
                        "intervening operator.");
              }
            } else {
// System.out.println("Other case  not handled");
              break; // nothing this time around.
	    }
          }
        }
      }
    } while (n != CurrentTop.size()-1);
// System.out.println("exit at size: " + (CurrentTop.size()-1));
  }

  final public SyntaxTreeNode finalReduce() throws ParseException {

    int n=0;
    pushOnStack( null, Operator.VoidOperator() );
    reduceStack();
    if ( isWellReduced() )
      return ((OSelement) CurrentTop.elementAt(0)).getNode();
    else {
      StringBuffer msg = new StringBuffer("Couldn't properly parse expression");
      int l[];
      do {
//((OSelement)CurrentTop.elementAt(n)).getNode().printTree(new java.io.PrintWriter(System.out));  n++;
        msg.append("-- incomplete expression at ");
        msg.append( ((OSelement)CurrentTop.elementAt(n)).getNode().getLocation().toString() ) ;
        msg.append(".\n");
        n++;
      } while (n < CurrentTop.size()-1);
      PErrors.push( new ParseError( msg.toString(), "-- --" ));
      return null;
    }
  }

  public boolean isWellReduced () {
     return CurrentTop.size() == 2;
  }

  final public void pushOnStack( SyntaxTreeNode n, Operator o ) {
    /* XXX could be optimized to reuse OSelements */
    /***********************************************************************
    * Apparently, the operator argument o is null if this is not an        *
    * in/pre/postfix operator.                                             *
    ***********************************************************************/
// System.out.print("pushing");
// if ( n != null )
// System.out.print( " " + n.getImage() );
// if ( o != null )
// System.out.print(" " + o.toString() );
// System.out.println();
    CurrentTop.addElement( new OSelement( n, o) );
//    System.out.println(printStack());
  }

  public SyntaxTreeNode bottomOfStack() {
    return ((OSelement) CurrentTop.elementAt(0)).getNode();
  }

  public final void reduceRecord( SyntaxTreeNode middle, SyntaxTreeNode right ) throws ParseException {
    int index;
    OSelement oselt;
    int a1, a2;

    index = CurrentTop.size()-1;
    if (index < 0)
      throw new ParseException("\n    ``.'' has no left hand side at " + middle.getLocation().toString() + "." );
    oselt = (OSelement)CurrentTop.elementAt( index );

    if ( oselt.isOperator() ) {
      OSelement ospelt = (OSelement)CurrentTop.elementAt( index - 1 );
      if ( oselt.getOperator().isPostfix() && !ospelt.isOperator() ) {
        CurrentTop.addElement( null ); // humour reducePostfix
        reducePostfix();
        index = CurrentTop.size()-1;             // fix humoring
        CurrentTop.removeElementAt(index);
        index--;
        oselt = (OSelement)CurrentTop.elementAt( index );
      } else
        throw new ParseException("\n    ``.'' follows operator " + oselt.getNode().getLocation().toString() + "." );
    } 
    SyntaxTreeNode left = ((OSelement) CurrentTop.elementAt(index )).getNode();
    SyntaxTreeNode rcd = new SyntaxTreeNode(N_RecordComponent, left, middle, right);
    CurrentTop.setElementAt(new OSelement(rcd) , index);
}

// simple utility

  final private String printStack() {
    String str = new String( "stack dump, " + StackOfStack.size() + " levels, " + CurrentTop.size() + " in top one: ");
     for (int i = 0; i< CurrentTop.size(); i++ ) {
       SyntaxTreeNode tn = ((OSelement)CurrentTop.elementAt( i )).getNode();
       if (tn != null)
         str = str.concat(tn.getImage() + " " );
     }
   return str;     
  }

  final public OSelement topOfStack() {
    /***********************************************************************
    * Returns the top element of the top stack, or null if that stack is   *
    * empty.                                                               *
    ***********************************************************************/
    if (CurrentTop == null) {return null;} ;
    int n = CurrentTop.size() ;
    if (n == 0) {return null;} ;
    return (OSelement) CurrentTop.elementAt(n-1) ;
   }

  final public void popCurrentTop() {
    /***********************************************************************
    * Removes the element currently at the top of the CurrentTop stack.    *
    * Must not be called unless CurrentTop has at least one element.       *
    ***********************************************************************/
    CurrentTop.removeElementAt(CurrentTop.size() - 1) ;
   }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Parameters.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Parameters                                                         *
*                                                                          *
* The fields of this class consist of all the parameters used by           *
* TLATeX.  Some of them are set by program options.                        *
***************************************************************************/
package tla2tex;

import java.io.File;

public final class Parameters
{ 

  /*************************************************************************
  * Parameters Related to non-file Options                                 *
  *************************************************************************/
  
  public static boolean Debug = false ;
    /***********************************************************************
    * True if the -debug option is chosen.  At the moment, this just       *
    * causes timing information to be output.                              *
    ***********************************************************************/

  public static boolean TLAOut = false ;
    /***********************************************************************
    * True if the -tlaOut option is chosen.                                *
    ***********************************************************************/
  
  public static String TLAOutFile = "" ;
    /***********************************************************************
    * If the -tlaOut option is present, this is the file it specified.     *
    ***********************************************************************/

  public static boolean TLACommentOption = false ;
    /***********************************************************************
    * True if the -tlaComment option is chosen.                            *
    ***********************************************************************/
    
  public static boolean CommentShading = false ;
  /***********************************************************************
  * True if comments are to be shaded in the output.                     *
  ***********************************************************************/
  
  public static boolean NoPlusCalShading = false ;
  /***********************************************************************
  * True if PlusCal code should not be shaded when CommentShading is     *
  * true; meaningless otherwise.                                         *
  ***********************************************************************/
  
  public static boolean PrintProlog = true ;
    /***********************************************************************
    * True unless the -noProlog option is specified.  It determines        *
    * whether the prolog of a module (the part that appears before the     *
    * start of the module) is to be printed.                               *
    ***********************************************************************/

  public static boolean PrintEpilog = true ;
    /***********************************************************************
    * True unless the -noEpilog option is specified.  It determines        *
    * whether the epilog of a module (the part that appears after the end  *
    * of the module) is to be printed.                                     *
    ***********************************************************************/

  public static boolean PrintLineNumbers = false ;
    /***********************************************************************
    * True iff the -number option is chosen.  It determines whether the    *
    * output will print line numbers.                                      *
    ***********************************************************************/
    
  public static float PSGrayLevel = Misc.stringToFloat(".85");
    /***********************************************************************
    * The gray level of shaded comment boxes, where 0 is black and 1 is    *
    * white.  Set by the -grayLevel option.                                *
    ***********************************************************************/
    
  public static String PSCommand = "dvips" ;
    /***********************************************************************
    * The command used to create a Postscript or pdf output file.          *
    * Set by -psCommand.                                                   *
    ***********************************************************************/
    
  public static boolean PSOutput = false ;
    /***********************************************************************
    * True iff creating Postscript output file.                            *
    ***********************************************************************/
   
  /*************************************************************************
  * File parameters.                                                       *
  *************************************************************************/

  public static String WordFile = "words.all" ;
    /***********************************************************************
    * The name of the resource file containing the list of all common      *
    * English words.  This file must contain one word per line, with no    *
    * spaces.                                                              *
    ***********************************************************************/
    
  public static String LaTeXStyleFile = "tlatex.sty" ;
    /***********************************************************************
    * The style file that defines the commands used in the LaTeX output    *
    * files.  It is read in and added to the output files, so it           *
    * shouldn't use "@" in command names without an explicit               *
    * \makeatletter command.                                               *
    ***********************************************************************/

  public static String UserStyleFile = "";
    /***********************************************************************
    * If not equal to "", then it is the user-supplied package that is     *
    * used instead of LaTeXStyleFile.  Set by the -style option.           *
    ***********************************************************************/
    
  public static final String HelpFile = "help.txt";
    /***********************************************************************
    * The file containing the -help message for tlatex.TLA.                *
    ***********************************************************************/

  public static final String InfoFile = "info.txt";
    /***********************************************************************
    * The file containing the -info message for tlatex.TLA, which is more  *
    * complete than the -help message.                                     *
    ***********************************************************************/

  public static final String TeXHelpFile = "texhelp.txt";
  public static final String TeXInfoFile = "texinfo.txt";
    /***********************************************************************
    * The corresponding files for tlatex.TeX                               *
    ***********************************************************************/
    
  public static String TLAInputFile = "" ;
    /***********************************************************************
    * The name of the input file.  It is set to equal the argument with    *
    * which the program is called.  If no extension is specified, then     *
    * ".tla" added if for tlatex.TLA, and ".tex" is added for tlatex.TeX.  *
    ***********************************************************************/
    
  public static String LaTeXOutputFile = "" ;
    /***********************************************************************
    * The name of the LaTeX output file (minus the ".tex" extension) used  *
    * to typeset the spec.  It is set by the -out option; the default      *
    * value is set by the GetArguments method (of class TLA or TeX).       *
    ***********************************************************************/

  public static String LaTeXAlignmentFile = "" ;
    /***********************************************************************
    * The name of the output file (minus the ".tex" extension) used to     *
    * write the alignment output--the LaTeX file that is executed to find  *
    * the widths of the typeset output for computing alignment spacing.    *
    * It is set by the -alignOut option; the default value is set by       *
    * TLA.GetArguments.                                                    *
    ***********************************************************************/

  public static String MetaDir = "" ;

  public static String LatexOutputExt = "dvi" ;

  /*************************************************************************
  * Parameters Related to TLATeX's LaTeX-Source Input                      *
  *************************************************************************/

  public static File ParentDir = null ;
  
  public final static int MaxOutputLineLength = 78  ;
    /***********************************************************************
    * The maximum number of characters in a line of the LaTeX input files  *
    * created by TLATeX.                                                   *
    ***********************************************************************/

  public static String LaTeXCommand = "latex" ;
    /***********************************************************************
    * The command used to run LaTeX.  Set by the -latexCommand option.     *
    ***********************************************************************/
    
  public static int LaTeXptSize = 10 ;
    /***********************************************************************
    * The point-size of type to use.  Must be 10, 11, or 12.               *
    ***********************************************************************/

  public static int LaTeXtextwidth = 360 ;
    /***********************************************************************
    * The value, in points, of \textwidth for the LaTeX files.  Set by     *
    * the -textwidth option.                                               *
    ***********************************************************************/

  public static int LaTeXtextheight = 541 ;
    /***********************************************************************
    * The value, in points, of \textheight for the LaTeX files.  Set by    *
    * the -textheight option.                                              *
    ***********************************************************************/

  public static int LaTeXhoffset = 0 ;
    /***********************************************************************
    * The value, in points, of a quantity added to TeX's \hoffset          *
    * parameter.  Useful for horizontally centering the output on the      *
    * page.  Set by the -hoffset option.                                   *
    ***********************************************************************/

  public static int LaTeXvoffset = 0 ;
    /***********************************************************************
    * The value, in points, of a quantity added to TeX's \hoffset          *
    * parameter.  Useful for centering the output vertically on the page.  *
    * Set by the -voffset option.                                          *
    ***********************************************************************/

  /*************************************************************************
  * Various LaTeX commands and environments used in the LaTeX output.      *
  *************************************************************************/

  public final static float LaTeXLeftSpace(int n)
    /***********************************************************************
    * The amount of space, in points, that corresponds to n spaces in the  *
    * input file.  The definition of \PROVE in tlatex.sty depends on this  *
    * method and needs to be changed if the method changes.                *
    ***********************************************************************/
    { return Misc.stringToFloat("4.1") * n * LaTeXptSize / 10  ; }
    
  public final static float LaTeXCommentLeftSpace(int n)
    /***********************************************************************
    * The amount of space, in points, that corresponds to n spaces in a    *
    * comment in the input file.                                           *
    ***********************************************************************/
    { return Misc.stringToFloat("2.5") * n * LaTeXptSize / 10 ; }

  public final static float LaTeXVSpace(int n)
    /***********************************************************************
    * The amount of vertical space, in points, that corresponds to n       *
    * blank lines in the input file.                                       *
    ***********************************************************************/
    { return Misc.stringToFloat("8.0") * n  ; }
    
  public final static float LaTeXCommentVSpace(int n)
    /***********************************************************************
    * The amount of space, in points, that corresponds to n blank lines    *
    * in a comment in the input file.                                      *
    ***********************************************************************/
    { return Misc.stringToFloat("5.0") * n ; }

  public final static String LaTeXCommentVSpaceCmd = "\\vshade";
    /***********************************************************************
    * A command that takes an argument n and creates an n-point vertical   *
    * space between paragraphs in a comment, with proper shading.  (A      *
    * simple \vspace command would leave unshaded white space between the  *
    * paragraphs when shading.)                                            *
    ***********************************************************************/
    
  public final static String LaTeXStartLine = "\\@x";  
    /***********************************************************************
    * The command \@x{txt} starts a specification line in the -out file    *
    * that begins with txt.                                                *
    ***********************************************************************/

  public final static String LaTeXContinueLine = "\\@xx";  
    /***********************************************************************
    * The command \@xx{txt} continues a specification line of the -out or   *
    * -alignOut file with text txt.                                        *
    ***********************************************************************/

  public final static String LaTeXStartAlignLine = "\\fl";  
    /***********************************************************************
    * The command \fl{txt} starts a specification line in the -alignOut    *
    * file that begins with txt.                                           *
    ***********************************************************************/

  public final static String LaTeXAlignPoint = "\\al" ;  
    /***********************************************************************
    * The command \al{i}{j}{txt} is put in the alignment file if item j    *
    * of line i is an alignment point, with txt the following text on the  *
    * specification line.  It puts "%{i}{j}{wd}" in the alignment file,    *
    * where wd is the width of the line up to that point,                  *
    ***********************************************************************/
    
  public final static String LaTeXStringCommand  = "\\@w" ;  
    /***********************************************************************
    * The command \@w{xyz} produces "xyz", formatted as a TLA+ string.     *
    ***********************************************************************/

  public final static String LaTeXPfStepNumCommand  = "\\@pfstepnum" ;  
    /***********************************************************************
    * The command \@pfstepnum{<42>}{1a.} produces "<42>1a.", properly      *
    * formatted with space after it.                                       *
    ***********************************************************************/
    
  public final static String LaTeXSpaceCommand  = "\\@s" ;  
    /***********************************************************************
    * The command \@s{n} produces an n-point horizontal space.              *
    ***********************************************************************/
    
  public final static String LaTeXOneLineCommentCommand = "\\@y" ;  
  public final static String LaTeXZeroWidthCommentCommand = "\\@z" ;  


  public final static String LaTeXLeftDash  = "\\moduleLeftDash\\@xx" ;  
  public final static String LaTeXRightDash = "\\moduleRightDash\\@xx" ;
    /***********************************************************************
    * The LaTeX commands that make the dashes to the left and right in     *
    * the beginning of a module.                                           *
    ***********************************************************************/
  public final static String LaTeXDash      = "\\midbar\\@xx" ;  
    /***********************************************************************
    * The LaTeX commands that make the decorative horizontal bar in the    *
    * middle of a module, which appears as a sequence of dashes in the     *
    * input.                                                               *
    ***********************************************************************/
  public final static String LaTeXEndModule = "\\bottombar\\@xx" ;  
    /***********************************************************************
    * The LaTeX commands that make the module-ending horizontal bar.       *
    ***********************************************************************/
    
  public final static String LaTeXAlignLeftDash  = "\\moduleLeftDash\\cl" ;  
  public final static String LaTeXAlignRightDash = "\\moduleRightDash\\cl" ;
  public final static String LaTeXAlignDash      = "\\midbar\\cl" ;  
  public final static String LaTeXAlignEndModule = "\\bottombar\\cl" ;  
    /***********************************************************************
    * These are the same as the four previous parameters, except they are  *
    * the commands for the alignment file.                                 *
    ***********************************************************************/
    
    
  public final static String LaTeXCommentPar = "cpar" ;  
    /***********************************************************************
    * This LaTeX environment takes two arguments--a dimension d in points  *
    * and a label.  It produces a sequence of paragraphs, shaped as        *
    * follows, where [label] is the result of typesetting the label        *
    * argument in an LR box.                                               *
    *                                                                      *
    *      left |<-- d -->[label]XXXXXXXXXXXXXXX                           *
    *    margin |                XXXXXXXXXXXXXXX                           *
    *           |                XXXXXXXXXXXXXXX                           *
    *           |                                                          *
    *           |                XXXXXXXXXXXXXXX                           *
    *           |                XXXXXXXXXXXXXXX                           *
    *                                                                      *
    * However, this environment should leave no vertical space above or    *
    * below it, or between its paragraphs.  (TLATeX inserts the proper     *
    * amount of vertical space.)                                           *
    ***********************************************************************/

    
  public final static String LaTeXRightMultiLineComment = "mcom" ;
    /***********************************************************************
    * The environment that formats a multi-line comment at the end of a    *
    * line.  It takes a single argument, the width of the comment in       *
    * points.  It works in conjunction with the LaTeXEndMultiLineVSpace    *
    * command.  The actual text inside it must all be in LaTeXCommentPar   *
    * environments.                                                        *
    ***********************************************************************/

  public final static String LaTeXLeftMultiLineComment = "lcom" ;
    /***********************************************************************
    * The environment that formats a multi-line comment with nothing to    *
    * its left.  It takes a single argument, the indentation in points of  *
    * the comment's left margin from the document's left margin.  The      *
    * actual text inside it must all be in LaTeXCommentPar environments.   *
    ***********************************************************************/

  public final static String LaTeXEndMultiLineVSpace = "\\multivspace" ;
    /***********************************************************************
    * The command to produce vertical space indicated by "|"s in this      *
    * situation                                                            *
    *                                                                      *
    *     xxxx (*************)                                             *
    *     xxxx (* ccccccccc *)                                             *
    *      |   (* ccccccccc *)                                             *
    *      |   (* ccccccccc *)                                             *
    *      |   (* ccccccccc *)                                             *
    *      |   (*************)                                             *
    *                                                                      *
    * where the argument is one less than the number of "xxxx" lines.      *
    * This command must immediately follow the LaTeXRightMultiLineComment  *
    * environment that produces the comment.                               *
    ***********************************************************************/
 }  

/* last modified on Wed 19 Sep 2007 at  4:53:41 PST by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/ui/util/ParsingToolkitTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TypedRegion;
import org.lamport.tla.toolbox.tool.tlc.output.PartitionToolkit;

import junit.framework.TestCase;

/**
 * Tests of parsing toolkit
 * @author <NAME>
 * @version $Id$
 */
public class ParsingToolkitTest extends TestCase
{

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
    }

    /**
     * Test method for {@link org.lamport.tla.toolbox.tool.tlc.output.ParsingTLCOutputSink#mergePartitions(org.eclipse.jface.text.ITypedRegion[])}.
     */
    public void testMergePartitions()
    {
        assertEquals(new TypedRegion(0, 100, "type"), PartitionToolkit.mergePartitions(new ITypedRegion[] {
                new TypedRegion(0, 10, "type"), new TypedRegion(10, 80, "type"), new TypedRegion(90, 10, "type") }));
    }

    public void testMergePartitions2()
    {
        assertEquals(new TypedRegion(0, 100, "type"), PartitionToolkit
                .mergePartitions(new ITypedRegion[] { new TypedRegion(0, 100, "type") }));
    }

}


<|start_filename|>general/bugzilla/css/show_multiple.css<|end_filename|>
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This Source Code Form is "Incompatible With Secondary Licenses", as
 * defined by the Mozilla Public License, v. 2.0.
 */

hr {margin: 20px auto 40px}

.bz_private { color:darkred }

h1 {
  font-size: 2em;
  margin-bottom: 10px;
}

/* bugfields is table of all fields and values */
.bugfields {
  font-size: small;
  background: #eee;
  padding: 5px;
  border: 1px solid silver;
  width: 100%;
}

.bugfields tr {
  vertical-align: top;
}

.bugfields th {
  width: 10em;
  text-align: left;
  font-weight: normal;
  line-height: 150%;
}

.bugfields td {
  font-weight: bold;
  line-height: 150%;
}

.bugfields .rightcell {
  padding-left: 10px;
}

/* set line-height to normal for nested tables of bugfields table */
.bugfields table th, .bugfields table td {
  line-height: 100%;
  width: auto;
}

.bugfields table.timetracking th, .bugfields table.timetracking td {
  width: 10em;
}

.error {
  color: red;
  font-weight: bold;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/TLCStateInfo.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:35 PST by lamport 
//      modified on Sat Feb 17 12:07:55 PST 2001 by yuanyu 

package tlc2.tool;

// TLCStateInfo is largely obsolete and should be replaced in favor of
// TLCStateMutExt, which has support for storing the predecessor, action,
// and level (stateNum), but doesn't have to be created after the fact,
// that is from an existing TLCState trace, but gets created by Tool/
// TLCTrace. However, TLCStateInfo is used in too many places, which makes
// this particular refactoring too expensive right now.  Also, TLCStateMutExt
// doesn't get used in throughput-optimized BFS search (unless TLC runs in
// '-debugger' mode).
public class TLCStateInfo {
  private static final String INITIAL_PREDICATE_NO_ANGLE_BRACKET = "Initial predicate";

  public static final String INITIAL_PREDICATE = "<" + INITIAL_PREDICATE_NO_ANGLE_BRACKET + ">";
  
  public TLCStateInfo predecessorState;
  public long stateNumber;
  public Object info;
  public final TLCState state;
  public Long fp;

  public TLCStateInfo(final TLCState state) {
	this.state = state;
	this.stateNumber = state.getLevel();
	
	if (state.hasAction()) {
		// In simulation mode or when TLC runs with "-debugger", states have the Action
		// attached.
		this.info = toInfo(state.isInitial(), state.getAction());
	} else {
		// Traditionally (hail legacy), the name and location of the initial predicate is unknown.
		// See e.g. https://github.com/tlaplus/tlaplus/issues/305
		this.info = INITIAL_PREDICATE;
	}
  }

  public TLCStateInfo(final TLCState state, final Action action) {
	this.state = state;
	this.stateNumber = state.getLevel();
	
	this.info = toInfo(state.isInitial(), action);
  }
  
  private static String toInfo(final boolean isInitial, final Action a) {
	  if (isInitial && !a.isNamed()) {
		  // It is possible for an action to have no name, yet to have a location. Instead
		  // of showing <Action loc ...>, we show <Initial Predicate loc...> for legacy
	      // reasons.
		  return a.getLocation(INITIAL_PREDICATE_NO_ANGLE_BRACKET);
	  }
	  return a.getLocation();
  }
  
  // Legacy (DFID & MP)
  public TLCStateInfo(final TLCState state, final int stateOrdinal) {
		this.state = state;
		this.stateNumber = stateOrdinal;
		this.info = "";
  }
  
  // AliasTLCStateInfo
  protected TLCStateInfo(final TLCState s, final TLCStateInfo info) {
	  this.state = s;
	  this.info = info.info;
	  this.stateNumber = info.stateNumber;
	  this.fp = info.fp;
  }

  public final long fingerPrint() {
	  if (fp == null) {
		  fp = this.state.fingerPrint();
	  }
	  return fp.longValue();
  }

  public final String toString() {
    return this.state.toString();
  }
  
  public boolean equals(Object other) {
	  if (other instanceof TLCStateInfo) {
		  TLCStateInfo sinfo = (TLCStateInfo) other;
		  return this.state.equals(sinfo.state);
	  } else if (other instanceof TLCState) {
		  TLCState state = (TLCState) other;
		  return this.state.equals(state);
	  }
	  return false;
  }

  public int hashCode() {
	  return this.state.hashCode();
  }

  public TLCState getOriginalState() {
	return state;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/model/Formula.java<|end_filename|>
package tlc2.model;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Representation of a formula.
 * @author <NAME>
 */
public class Formula {
    /**
     * De-serialize formula list, to a list of formulas, that are selected (have a leading "1")
     * 
     * The first character of the formula is used to determine if the formula is enabled in the model 
     * editor or not. This allows the user to persist formulas, which are not used in the current model 
     */
	public static List<Formula> deserializeFormulaList(final List<String> serializedList) {
		final ArrayList<Formula> result = new ArrayList<>(serializedList.size());
		for (final String entry : serializedList) {
			if ("1".equals(entry.substring(0, 1))) {
				result.add(new Formula(entry.substring(1)));
			}
		}
		return result;
	}
	
    // DOTALL to match beyond line endings.
    private static final Pattern PATTERN = Pattern.compile("^\\s*(\\w+)\\s*==(.*)$", Pattern.DOTALL);
    
	
    private String formula;

    /**
     * Constructs a formula representation
     * @param formula
     */
	public Formula(String formulaString) {
		formula = formulaString;
	}

	/**
	 * Retrives formula
	 * 
	 * @return
	 */
	public String getFormula() {
		return formula;
	}

	@Override
	public String toString() {
		return formula;
	}

	/**
	 * @param formulaString
	 */
	public void setFormula(String formulaString) {
		formula = formulaString;
	}

	// MAK 03/2019: This methods below appear redundant to the Assignment subclass
	// but I don't have time to look into it.
    
    public boolean isNamed()  {
    	return !getLeftHandSide().equals(getFormula());
    }
    
    public String getLeftHandSide() {
		final Matcher matcher = PATTERN.matcher(this.formula);
		if (matcher.find()) {
			return matcher.group(1).trim();
		}
		return getFormula();
    }
    
    public String getRightHandSide() {
		final Matcher matcher = PATTERN.matcher(this.formula);
		if (matcher.find()) {
			return matcher.group(2).trim();
		}
		return getFormula();
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/SpecLifecycleManager.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;

/**
 * The spec life cycle manager is keeping track of the spec life cycle participants and is used to propagate events to them 
 * @author <NAME>
 * @version $Id$
 */
public class SpecLifecycleManager
{

    private static final String POINT = "org.lamport.tla.toolbox.spec";
    private static final String CLASS_ATTR_NAME = "class";

	private final List<SpecLifecycleParticipant> extensions = new CopyOnWriteArrayList<SpecLifecycleParticipant>();

    /**
     * Simple strategy calling the method
     */
    private ExtensionInvocationStrategy simpleInvocationStrategy = new ExtensionInvocationStrategy() {
        // simple strategy calling the method directly
        public boolean invoke(SpecLifecycleParticipant target, SpecEvent event)
        {
            return target.eventOccured(event);
        }
    };

    /**
     * Initializes the spec participants
     */
    public SpecLifecycleManager() {
        IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
        List<SpecLifecycleParticipant> specExtensions = new ArrayList<SpecLifecycleParticipant>();
        if (extensionRegistry != null)
        {
            IConfigurationElement[] decls = extensionRegistry.getConfigurationElementsFor(POINT);
            for (int i = 0; i < decls.length; i++)
            {
                try
                {
                	// This causes other OSGi bundles to be started 
                	// e.g. ProverUI which registers a SpecLifecycleParticipant
                    SpecLifecycleParticipant extension = (SpecLifecycleParticipant) decls[i].createExecutableExtension(CLASS_ATTR_NAME);
                    assert extension != null;
                    specExtensions.add(extension);
                    extension.initialize();
                } catch (CoreException e)
                {
                    Activator.getDefault().logError("Error retrieving the registered participants", e);
                }
            }
        }
       	extensions.addAll(specExtensions);
    }

    /**
     * Sends events ignoring veto responses
     * Shortcut for {@link SpecLifecycleManager#sendEventWithVeto(SpecEvent, false)}
     */
    public boolean sendEvent(SpecEvent event)
    {
        return sendEventWithVeto(event, false);
    }

    /**
     * Sends event to the registered participants
     * @param event
     * @param stopOnVeto
     * @return
     */
    public boolean sendEventWithVeto(SpecEvent event, boolean stopOnVeto)
    {
        boolean responseAll = true;
        boolean response;
        for (SpecLifecycleParticipant target : extensions) {
            assert target != null;
            
            // local response
            response = simpleInvocationStrategy.invoke(target, event);

            // global response
            responseAll = responseAll && response;

            // veto answer received, stop
            if (stopOnVeto && !response)
            {
                break;
            }
        }
        return responseAll;
    }

    /**
     * Distributes the terminate message  
     */
    public void terminate()
    {
    	for (SpecLifecycleParticipant extension : extensions) {
            extension.terminate();
        }
    }

    /**
     * Describers the invocation strategy
     * <br>This is the point where the indirection can be introduced for asynchronous invocation,
     * invocation with timeouts etc...  
     */
    static abstract class ExtensionInvocationStrategy
    {
        /**
         * Responsible for invocation of the eventOccured method 
         * @param target target to invoke on
         * @param event event to send
         * @return result of invocation
         */
        public abstract boolean invoke(SpecLifecycleParticipant target, SpecEvent event);
    }

	public void addSpecLifecycleParticipant(SpecLifecycleParticipant specLifecycleParticipant) {
		extensions.add(specLifecycleParticipant);
	}

	public void removeSpecLifecycleParticipant(SpecLifecycleParticipant specLifecycleParticipant) {
		extensions.remove(specLifecycleParticipant);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tla2sany/SANYTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tla2sany;

import org.junit.Before;

import util.ToolIO;

public abstract class SANYTest {
	
	@Before
	public void setup() {
		// Make tool capture the output written to ToolIO.out. Otherwise,
		// ToolIO#getAllMessages returns an empty array.
		ToolIO.setMode(ToolIO.TOOL);
		
		// Reset ToolIO for each test case. Otherwise, a test case sees the output of
		// the previous tests.
		ToolIO.reset();
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/ReadOnlyFileEditorInput.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.eclipse.core.resources.IFile;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.part.FileEditorInput;

/**
 * Read only editor input
 * @author <NAME>
 * @version $Id$
 */
public class ReadOnlyFileEditorInput extends FileEditorInput
{

    public ReadOnlyFileEditorInput(IFile file)
    {
        super(file);
    }

    public IPersistableElement getPersistable()
    {
        return null;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/NamedInputStream.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Path;

// SZ Feb 20, 2009: moved to util and reformatted

/**
 * A NamedInputStream is an InputStream together with a name.  The most
 * common such object o will be one that is the InputStream obtained by
 * reading a file named o.getName().
 *
 * It extends FileInputStream, rather than input stream, since it's not 
 * possible to change the default hierarchy. This implies that it isn't 
 * possible to use the same class for a buffer derived from an input string.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class NamedInputStream extends FileInputStream
{
    private static int numberOfReferences = 0;  
    
    private String fileName;
    private String moduleName;
    private File inputFile;

    public NamedInputStream(String file, String module, File input) throws FileNotFoundException
    {
        super(input);
        fileName = file;
        moduleName = module;
        inputFile = input;
        synchronized (NamedInputStream.class) 
        {
            if (numberOfReferences < 0) 
            {
                numberOfReferences = 0;
            }
            numberOfReferences++;
        }

    }

    public final String getName()
    {
        return fileName;
    }

    public final String getFileName()
    {
        return fileName;
    }

    public final String getModuleName()
    {
        return moduleName;
    }

    public final File sourceFile()
    {
        return inputFile;
    }
    
    /**
	 * @return The absolute, resolved path. In case a file is symlinked, resolve the
	 *         final target (doesn't work for cygwin symlinks but for mklink)
     * @throws IOException 
	 */
    public final Path getAbsoluteResolvedPath() throws IOException {
		return inputFile.toPath().toRealPath();
    }

    public final String toString()
    {
        return "[ fileName: " + fileName + ", moduleName: " + moduleName + " ]";
    }

    
    /**
     * Sanity method
     */
    public void close() throws IOException
    {
        synchronized (NamedInputStream.class) 
        {
            numberOfReferences--;
        }
        super.close();
    }
    

    /**
     * Sanity check method
     * @return
     */
    public synchronized static int getNumberOfreferences()
    {
        return numberOfReferences;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/value/impl/RandomizationBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import tlc2.TLCGlobals;
import tlc2.util.FP64;
import tlc2.value.RandomEnumerableValues;
import tlc2.value.impl.Enumerable;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.SetOfFcnsValue;
import tlc2.value.impl.SubsetValue;

@State(Scope.Benchmark)
public class RandomizationBenchmark {

	private static final Enumerable enum016;
	private static final Enumerable enum032;
	private static final Enumerable enum064;
	private static final Enumerable enum128;
	private static final Enumerable enum256;
	private static final Enumerable enum512;
	private static final Enumerable enum1024;
	private static final Enumerable enum2048;
	private static final Enumerable enum4096;
	private static final Enumerable enum8192;
	private static final Enumerable enum16384;
	private static final Enumerable enum32768;
	private static final Enumerable enumTLCBound;
	
	private static final Enumerable interval16;
	private static final Enumerable interval20;
	private static final Enumerable interval24;
	private static final Enumerable interval28;
	private static final Enumerable interval31;

	private static final int twoPow12 = (int) (Math.pow(2, 12) - 1);
	private static final int twoPow08 = (int) (Math.pow(2, 8) - 1);
	private static final int twoPow16 = (int) (Math.pow(2, 16) - 1);
	private static final Enumerable fcns008x008; // 2^24
	private static final Enumerable fcns011x011; // ~2^31
	private static final Enumerable fcns016x008;
	private static final Enumerable fcns016x016; // ~2^65
	private static final Enumerable fcns032x016;
	private static final Enumerable fcns032x032; // ~2^150
	private static final Enumerable fcns048x048; // ~2^268

	private static final SubsetValue subset2pow24; // 2^24
	private static final SubsetValue subset2pow31; // ~2^31
	private static final SubsetValue subset2pow65; // ~2^65
	private static final SubsetValue subset2pow150; // ~2^150
	private static final SubsetValue subset2pow268; // ~2^268
	
	private static ValueVec getValues(int from, int to) {
		final ValueVec vec = new ValueVec(to - from);
		for (int i = from; i <= to; i++) {
			vec.addElement(IntValue.gen(i));
		}
		return vec;
	}

	static {
		RandomEnumerableValues.setSeed(15041980L);
		RandomEnumerableValues.reset();

		FP64.Init();

		enum016 = new SetEnumValue(getValues(1, 16), true);
		enum032 = new SetEnumValue(getValues(1, 32), true);
		enum064 = new SetEnumValue(getValues(1, 64), true);
		enum128 = new SetEnumValue(getValues(1, 128), true);
		enum256 = new SetEnumValue(getValues(1, 256), true);
		enum512 = new SetEnumValue(getValues(1, 512), true);
		enum1024 = new SetEnumValue(getValues(1, 1024), true);
		enum2048 = new SetEnumValue(getValues(1, 2048), true);
		enum4096 = new SetEnumValue(getValues(1, 4096), true);
		enum8192 = new SetEnumValue(getValues(1, 8192), true);
		enum16384 = new SetEnumValue(getValues(1, 16384), true);
		enum32768 = new SetEnumValue(getValues(1, 32768), true);
		enumTLCBound = new SetEnumValue(getValues(1, TLCGlobals.setBound), true);

		interval16 = new IntervalValue(0, 2 << 16);
		interval20 = new IntervalValue(0, 2 << 20);
		interval24 = new IntervalValue(0, 2 << 24);
		interval28 = new IntervalValue(0, 2 << 28);
		interval31 = new IntervalValue(0, Integer.MAX_VALUE); // maximum possible value for internal ValueVec
		
		fcns008x008 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 8), true),
				new SetEnumValue(getValues(1, 8), true));
		fcns011x011 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 11), true),
				new SetEnumValue(getValues(1, 11), true));
		fcns016x008 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 16), true),
				new SetEnumValue(getValues(1, 8), true));
		fcns016x016 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 16), true),
				new SetEnumValue(getValues(1, 16), true));
		fcns032x016 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 32), true),
				new SetEnumValue(getValues(1, 16), true));
		fcns032x032 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 32), true),
				new SetEnumValue(getValues(1, 32), true));
		fcns048x048 = new SetOfFcnsValue(new SetEnumValue(getValues(1, 48), true),
				new SetEnumValue(getValues(1, 48), true));
		
		subset2pow24 = new SubsetValue(new IntervalValue(1, 24));
		subset2pow31 = new SubsetValue(new IntervalValue(1, 31));
		subset2pow65 = new SubsetValue(new IntervalValue(1, 65));
		subset2pow150 = new SubsetValue(new IntervalValue(1, 150));
		subset2pow268 = new SubsetValue(new IntervalValue(1, 268));
	}
	
	/* exact */
	
	@Benchmark
	public Enumerable randomSetOfSubsetExact024k008() {
		return subset2pow24.getRandomSetOfSubsets(twoPow08, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact024k012() {
		return subset2pow24.getRandomSetOfSubsets(twoPow12, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact024k016() {
		return subset2pow24.getRandomSetOfSubsets(twoPow16, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact031k008() {
		return subset2pow31.getRandomSetOfSubsets(twoPow08, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact031k012() {
		return subset2pow31.getRandomSetOfSubsets(twoPow12, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact031k016() {
		return subset2pow31.getRandomSetOfSubsets(twoPow16, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact65k008() {
		return subset2pow65.getRandomSetOfSubsets(twoPow08, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact065k012() {
		return subset2pow65.getRandomSetOfSubsets(twoPow12, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact065k016() {
		return subset2pow65.getRandomSetOfSubsets(twoPow16, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact150k008() {
		return subset2pow150.getRandomSetOfSubsets(twoPow08, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact150k012() {
		return subset2pow150.getRandomSetOfSubsets(twoPow12, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact150k016() {
		return subset2pow150.getRandomSetOfSubsets(twoPow16, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact268k008() {
		return subset2pow268.getRandomSetOfSubsets(twoPow08, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact268k012() {
		return subset2pow268.getRandomSetOfSubsets(twoPow12, 10);
	}

	@Benchmark
	public Enumerable randomSetOfSubsetExact268k016() {
		return subset2pow268.getRandomSetOfSubsets(twoPow16, 10);
	}
	
	/* probabilistic */
	
	@Benchmark
	public Enumerable randomSetOfSubset024k008() {
		return subset2pow24.getRandomSetOfSubsets(twoPow08, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset024k012() {
		return subset2pow24.getRandomSetOfSubsets(twoPow12, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset024k016() {
		return subset2pow24.getRandomSetOfSubsets(twoPow16, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset031k008() {
		return subset2pow31.getRandomSetOfSubsets(twoPow08, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset031k012() {
		return subset2pow31.getRandomSetOfSubsets(twoPow12, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset031k016() {
		return subset2pow31.getRandomSetOfSubsets(twoPow16, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset065k008() {
		return subset2pow65.getRandomSetOfSubsets(twoPow08, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset065k012() {
		return subset2pow65.getRandomSetOfSubsets(twoPow12, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset065k016() {
		return subset2pow65.getRandomSetOfSubsets(twoPow16, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset150k008() {
		return subset2pow150.getRandomSetOfSubsets(twoPow08, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset150k012() {
		return subset2pow150.getRandomSetOfSubsets(twoPow12, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset150k016() {
		return subset2pow150.getRandomSetOfSubsets(twoPow16, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset268k008() {
		return subset2pow268.getRandomSetOfSubsets(twoPow08, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset268k012() {
		return subset2pow268.getRandomSetOfSubsets(twoPow12, .1d);
	}

	@Benchmark
	public Enumerable randomSetOfSubset268k016() {
		return subset2pow268.getRandomSetOfSubsets(twoPow16, .1d);
	}
	
	/* IntervalValue */
	
	@Benchmark
	public Enumerable randomInterval016setBound() {
		return interval16.getRandomSubset(TLCGlobals.setBound);
	}
	
	@Benchmark
	public Enumerable randomInterval020setBound() {
		return interval20.getRandomSubset(TLCGlobals.setBound);
	}
	
	@Benchmark
	public Enumerable randomInterval024setBound() {
		return interval24.getRandomSubset(TLCGlobals.setBound);
	}
	
	@Benchmark
	public Enumerable randomInterval028setBound() {
		return interval28.getRandomSubset(TLCGlobals.setBound);
	}
	
	@Benchmark
	public Enumerable randomInterval031setBound() {
		return interval31.getRandomSubset(TLCGlobals.setBound);
	}
	
	@Benchmark
	public Enumerable randomIntervalt016all() {
		return interval16.getRandomSubset(interval16.size() - 1);
	}
	
	@Benchmark
	public Enumerable randomInterval020all() {
		return interval20.getRandomSubset(interval20.size() - 1);
	}
	
	@Benchmark
	public Enumerable randomInterval024all() {
		return interval24.getRandomSubset(interval24.size() - 1);
	}
	
	@Benchmark
	public Enumerable randomIntervalt016half() {
		return interval16.getRandomSubset(interval16.size() / 2);
	}
	
	@Benchmark
	public Enumerable randomInterval020half() {
		return interval20.getRandomSubset(interval20.size() / 2);
	}
	
	@Benchmark
	public Enumerable randomInterval024half() {
		return interval24.getRandomSubset(interval24.size() / 2);
	}
	
	/* SetEnumValue */
	
	@Benchmark
	public Enumerable randomSubset016() {
		return enum016.getRandomSubset(enum016.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset032() {
		return enum032.getRandomSubset(enum032.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset064() {
		return enum064.getRandomSubset(enum064.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset128() {
		return enum128.getRandomSubset(enum128.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset256() {
		return enum256.getRandomSubset(enum256.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset512() {
		return enum512.getRandomSubset(enum512.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset1024() {
		return enum1024.getRandomSubset(enum1024.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset2048() {
		return enum2048.getRandomSubset(enum2048.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset4096() {
		return enum4096.getRandomSubset(enum4096.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset8192() {
		return enum8192.getRandomSubset(enum8192.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset16384() {
		return enum16384.getRandomSubset(enum16384.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubset32768() {
		return enum32768.getRandomSubset(enum32768.size() - 1);
	}

	@Benchmark
	public Enumerable randomSubsetTLCBound() {
		return enumTLCBound.getRandomSubset(enumTLCBound.size() - 1);
	}
	
	/* randomSubset with SetOfFcns */

	@Benchmark
	public Enumerable randomSubsetFcns008x008p16() {
		return fcns008x008.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns008x008p08() {
		return fcns008x008.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns008x008p12() {
		return fcns008x008.getRandomSubset(twoPow12);
	}

	@Benchmark
	public Enumerable randomSubsetFcns011x011p16() {
		return fcns008x008.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns011x011p08() {
		return fcns011x011.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns011x011p12() {
		return fcns011x011.getRandomSubset(twoPow12);
	}
	
	@Benchmark
	public Enumerable randomSubsetFcns016x008p16() {
		return fcns011x011.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns016x008p08() {
		return fcns016x008.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns016x008p12() {
		return fcns016x008.getRandomSubset(twoPow12);
	}

	@Benchmark
	public Enumerable randomSubsetFcns016x016p16() {
		return fcns016x016.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns016x016p08() {
		return fcns016x016.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns016x016p12() {
		return fcns016x016.getRandomSubset(twoPow12);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x016p16() {
		return fcns032x016.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x016p08() {
		return fcns032x016.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x016p12() {
		return fcns032x016.getRandomSubset(twoPow12);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x032p16() {
		return fcns032x032.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x032p08() {
		return fcns032x032.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns032x032p12() {
		return fcns032x032.getRandomSubset(twoPow12);
	}

	@Benchmark
	public Enumerable randomSubsetFcns048x048p16() {
		return fcns048x048.getRandomSubset(twoPow16);
	}

	@Benchmark
	public Enumerable randomSubsetFcns048x048p08() {
		return fcns048x048.getRandomSubset(twoPow08);
	}

	@Benchmark
	public Enumerable randomSubsetFcns048x048p12() {
		return fcns048x048.getRandomSubset(twoPow12);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/Operator.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.parser;
// Last modified onFri  2 Mar 2007 at 15:40:00 PST by lamport

// import tla2sany.error.*;
/***************************************************************************
* Unused import eliminated by LL on 2 Mar 2007                             *
***************************************************************************/

import util.UniqueString;

public class Operator implements tla2sany.st.SyntaxTreeConstants {

  private UniqueString Id;
  private int Low;
  private int High;
  public int Associativity;
  public int Fix;

  private static Operator voidOperator = null;
  
  // SZ Apr 16, 2009: changed to a method in order to avoid the usage
  // of the unique string in the class loading time 
  public synchronized static Operator VoidOperator()
  {  
      if (voidOperator == null) 
      {
          voidOperator = new Operator(UniqueString.uniqueStringOf("$$_void"), 0, 0, 
                  Operators.assocNone, Operators.infix);
      }
      return voidOperator;
  }
  
  public Operator( UniqueString id, int l, int h, int a, int f) {
    Id = id; Low = l; High = h; Associativity = a; Fix = f;
  }

  public Operator clone ( UniqueString name ) {
    return new Operator( name, Low, High, Associativity, Fix);
  }

  public String toString() {
  switch ( Fix ) {
    case 0 /* Operators.nofix   */ : return Id.toString() + ", nofix";
    case 1 /* Operators.prefix  */ : return Id.toString() + ", prefix";
    case 2 /* Operators.postfix */ : return Id.toString() + ", postfix";
    case 3 /* Operators.infix   */ : return Id.toString() + ", infix";
    case 4 /* Operators.nfix    */ : return Id.toString() + ", nfix";
  }
  return null;
}

  public final boolean isPrefix() {
    return (Fix==Operators.prefix);
  }

  public final boolean isInfix() {
    return ( Fix == Operators.infix || Fix == Operators.nfix );
  }

  public final boolean isPostfix() {
    return ( Fix == Operators.postfix );
  }

  public final boolean isNfix() {
    return Fix == Operators.nfix ;
  }

  public final boolean isPrefixDecl() {
    return ( Fix == Operators.prefix && Id.toString().endsWith(".") );
  }

  public final boolean assocLeft() {
    return Associativity == Operators.assocLeft;
  }

  public final boolean assocRight() {
    return Associativity == Operators.assocRight;
  }

/*
(* Note that we can view a prefix or postfix operator as an infix          *)
(* operator with one empty argument.)  We can eliminate the side           *)
(* conditions by defining op1 \prec op2 to be true if op2 is not a postfix *)
(* or infix operator, and defining op2 \succ op1 to be true if op2 is not  *)
(* a prefix or infix operator.                                             *)
*/

  static final boolean succ( Operator left, Operator right) {
      return left.Low > right.High;
  }

  static final boolean prec( Operator left, Operator right ) {
    return left.High < right.Low;
  }

  static final boolean samePrec( Operator left, Operator right ) {
    return ( (left.High == right.High) && (left.Low == right.Low) );
  }

  public final UniqueString getIdentifier() {
    return Id;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.rss/src/org/lamport/tla/toolbox/rss/Noop.java<|end_filename|>
package org.lamport.tla.toolbox.rss;

public class Noop {
   // Make Tycho (signing) happy.
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/OpenViewHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Opens the view specified by name as parameter
 * @author <NAME>
 * @version $Id$
 */
public class OpenViewHandler extends AbstractHandler implements IHandler
{

    public static final String COMMAND_ID = "toolbox.command.openview";
    public static final String PARAM_VIEW_NAME = "toolbox.openview.name";

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        
        final String viewName = event.getParameter(PARAM_VIEW_NAME);
        if (viewName == null)
        {
            return null;
        }
        /**
         * opens a view by name
         */
        UIHelper.runUIAsync(new Runnable() 
        {
            public void run()
            {
                UIHelper.openView(viewName);
            }
        });

        return null;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/StringNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.xml.SymbolContext;
import util.UniqueString;



/**
 * This node represents a string literal in the specification--for
 * example "abc".  The only information added to the SemanticNode
 * superclass is the level information and the UniqueString
 * representation of the string.
 */

public class StringNode extends ExprNode implements ExploreNode {

  private UniqueString value;

  public StringNode(TreeNode stn, boolean strip) {
    super(StringKind, stn);

    this.value = stn.getUS();
    if (strip) {
      // Strip off quote marks from image in stn
      String str = this.value.toString();
      str = str.substring(1, str.length()-1);
      this.value = UniqueString.uniqueStringOf(str);
      /*********************************************************************
      * Setting levelChecked shouldn't be necessary.                       *
      *********************************************************************/
//      this.levelChecked = 99 ;
    }
  }

  /**
   * Returns the UniqueString representation of the string.
   */
  public final UniqueString getRep() { return this.value; }

  /* Level Checking */
  @Override
  public final boolean levelCheck(int iter) {
    levelChecked = iter;
      /*********************************************************************
      * Set it just to show that levelCHeck was called.                    *
      *********************************************************************/
    return true;
  }

//  public final int getLevel() { return ConstantLevel; }
//
//  public final HashSet getLevelParams() { return EmptySet; }
//
//  public final SetOfLevelConstraints getLevelConstraints() {
//    return EmptyLC;
//  }
//
//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    return EmptyALC;
//  }
//
//  public final HashSet getArgLevelParams() { return EmptySet; }

  /**
   * toString, levelDataToString, & walkGraph methods to implement
   * ExploreNode interface
   */
//  public final String levelDataToString() {
//    return "Level: "               + this.getLevel()               + "\n" +
//           "LevelParameters: "     + this.getLevelParams()         + "\n" +
//           "LevelConstraints: "    + this.getLevelConstraints()    + "\n" +
//           "ArgLevelConstraints: " + this.getArgLevelConstraints() + "\n" +
//           "ArgLevelParams: "      + this.getArgLevelParams()      + "\n" ;
//  }

  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;

    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    visitor.postVisit(this);
  }

  final String PrintVersion(String str) {
    StringBuffer buf = new StringBuffer(str.length()) ;
    for (int i = 0 ; i < str.length() ; i++) {
      switch (str.charAt(i)) {
        case '\"' :
          buf.append("\\\"") ;
          break ;
        case '\\' :
          buf.append("\\\\") ;
          break ;
        case '\t' :
          buf.append("\\t") ;
          break ;
        case '\n' :
          buf.append("\\n") ;
          break ;
        case '\f' :
          buf.append("\\f") ;
          break ;
        case '\r' :
          buf.append("\\r") ;
          break ;
        default :
          buf.append(str.charAt(i)) ;
          break ;
       } // switch
     }; // for
    return buf.toString();
   }

  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";
    return "\n*StringNode: " + super.toString(depth)
                             + "Value: '" + PrintVersion(value.toString()) +
                             "'" + " Length: " + value.length();
  }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
      Element e = doc.createElement("StringValue");
      Node n = doc.createTextNode(value.toString());
      e.appendChild(n);
      return appendElement(doc, "StringNode", e);
   // return appendText(doc,"StringNode",value.toString());
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LNDisj.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:38 PST by lamport
//      modified on Sun Aug  5 00:14:58 PDT 2001 by yuanyu

package tlc2.tool.liveness;

import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.util.Vect;

class LNDisj extends LiveExprNode {
	private final Vect<LiveExprNode> disjs; // The disjuncts
	private int info;

	public LNDisj(int size) {
		this.disjs = new Vect<>(size);
		this.info = 0;
	}

	public LNDisj(LiveExprNode n) {
		this.disjs = new Vect<>(1);
		this.disjs.addElement(n);
		int level = n.getLevel();
		this.info = n.containAction() ? level + 8 : level;
	}

	public LNDisj(LiveExprNode n1, LiveExprNode n2) {
		this.disjs = new Vect<>(2);
		this.disjs.addElement(n1);
		this.disjs.addElement(n2);
		boolean hasAct = n1.containAction() || n2.containAction();
		int level = Math.max(n1.getLevel(), n2.getLevel());
		this.info = hasAct ? level + 8 : level;
	}

	public LNDisj(Vect<LiveExprNode> disjs) {
		this.disjs = disjs;
		boolean hasAct = false;
		int level = 0;
		for (int i = 0; i < disjs.size(); i++) {
			LiveExprNode lexpr = (LiveExprNode) disjs.elementAt(i);
			level = Math.max(level, lexpr.getLevel());
			hasAct = hasAct || lexpr.containAction();
		}
		this.info = hasAct ? level + 8 : level;
	}

	public final int getCount() {
		return this.disjs.size();
	}

	public final LiveExprNode getBody(int i) {
		return (LiveExprNode) this.disjs.elementAt(i);
	}

	public final void addDisj(LiveExprNode elem) {
		if (elem instanceof LNDisj) {
			LNDisj elem1 = (LNDisj) elem;
			for (int i = 0; i < elem1.getCount(); i++) {
				this.addDisj(elem1.getBody(i));
			}
		} else {
			this.disjs.addElement(elem);
		}
		int level = Math.max(this.getLevel(), elem.getLevel());
		boolean hasAct = this.containAction() || elem.containAction();
		this.info = hasAct ? level + 8 : level;
	}

	public final int getLevel() {
		return (this.info & 7);
	}

	public final boolean containAction() {
		return (this.info & 8) > 0;
	}
	
	@Override
	public final boolean isPositiveForm() {
		for (int i = 0; i < disjs.size(); i++) {
			LiveExprNode lexpr = (LiveExprNode) disjs.elementAt(i);
			if (!lexpr.isPositiveForm()) {
				return false;
			}
		}
		return true;
	}

	public final boolean eval(ITool tool, TLCState s1, TLCState s2) {
		int sz = disjs.size();
		for (int i = 0; i < sz; i++) {
			LiveExprNode item = (LiveExprNode) disjs.elementAt(i);
			if (item.eval(tool, s1, s2)) {
				return true;
			}
		}
		return false;
	}

	public final void toString(StringBuffer sb, String padding) {
		int len = this.getCount();
		String padding1 = padding + "    ";
		for (int i = 0; i < len; i++) {
			if (i != 0) {
				sb.append(padding);
			}
			sb.append("\\/ (");
			this.getBody(i).toString(sb, padding1);
			sb.append(")");
			if (i != len - 1) {
				sb.append("\n");
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.LiveExprNode#toDotViz()
	 */
	public String toDotViz() {
		int len = this.getCount();
		StringBuffer sb = new StringBuffer(len);
		for (int i = 0; i < len; i++) {
			sb.append("\\/ (");
			sb.append(this.getBody(i).toDotViz());
			sb.append(")");
			if (i != len - 1) {
				sb.append("\n");
			}
		}
		return sb.toString();
	}
	public void extractPromises(TBPar promises) {
		getBody(0).extractPromises(promises);
		getBody(1).extractPromises(promises);
	}

	public int tagExpr(int tag) {
		for (int i = 0; i < getCount(); i++) {
			tag = getBody(i).tagExpr(tag);
		}
		return tag;
	}

	public final LiveExprNode makeBinary() {
		if (getCount() == 1) {
			return getBody(0).makeBinary();
		}
		int mid = getCount() / 2;
		LNDisj left = new LNDisj(0);
		LNDisj right = new LNDisj(0);
		for (int i = 0; i < getCount(); i++) {
			if (i < mid) {
				left.addDisj(getBody(i));
			} else {
				right.addDisj(getBody(i));
			}
		}
		return new LNDisj(left.makeBinary(), right.makeBinary());
	}

	public LiveExprNode flattenSingleJunctions() {
		if (getCount() == 1) {
			return getBody(0).flattenSingleJunctions();
		}
		LNDisj lnd2 = new LNDisj(getCount());
		for (int i = 0; i < getCount(); i++) {
			lnd2.addDisj(getBody(i).flattenSingleJunctions());
		}
		return lnd2;
	}

	// Apply []<>A1 \/ []<>A2 = []<>(A1 \/ A2) when possible.
	public final LiveExprNode toDNF() {
		LNDisj aeRes = new LNDisj(0);
		LNDisj res = new LNDisj(0);
		for (int i = 0; i < getCount(); i++) {
			LiveExprNode elem = getBody(i).toDNF();
			if (elem instanceof LNDisj) {
				LNDisj disj1 = (LNDisj) elem;
				for (int j = 0; j < disj1.getCount(); j++) {
					LiveExprNode elem1 = disj1.getBody(j);
					LiveExprNode elemBody = elem1.getAEBody();
					if (elemBody == null) {
						res.addDisj(elem1);
					} else {
						aeRes.addDisj(elemBody);
					}
				}
			} else {
				LiveExprNode elemBody = elem.getAEBody();
				if (elemBody == null) {
					res.addDisj(elem);
				} else {
					aeRes.addDisj(elemBody);
				}
			}
		}
		// Add aeRes to res before returning.
		if (aeRes.getCount() == 1) {
			res.addDisj(new LNAll(new LNEven(aeRes.getBody(0))));
		} else if (aeRes.getCount() > 1) {
			res.addDisj(new LNAll(new LNEven(aeRes)));
		}
		return res;
	}

	public LiveExprNode simplify() {
		LNDisj lnd1 = new LNDisj(getCount());
		for (int i = 0; i < getCount(); i++) {
			LiveExprNode elem = getBody(i).simplify();
			if (elem instanceof LNBool) {
				if (((LNBool) elem).b) {
					return LNBool.TRUE;
				}
			} else {
				lnd1.addDisj(elem);
			}
		}
		if (lnd1.getCount() == 0) {
			return LNBool.FALSE;
		}
		if (lnd1.getCount() == 1) {
			return lnd1.getBody(0);
		}
		return lnd1;
	}

	public boolean isGeneralTF() {
		for (int i = 0; i < getCount(); i++) {
			if (!getBody(i).isGeneralTF()) {
				return false;
			}
		}
		return super.isGeneralTF();
	}

	public LiveExprNode pushNeg() {
		LNConj lnc = new LNConj(getCount());
		for (int i = 0; i < getCount(); i++) {
			lnc.addConj(getBody(i).pushNeg());
		}
		return lnc;
	}

	public LiveExprNode pushNeg(boolean hasNeg) {
		if (hasNeg) {
			LNConj lnc = new LNConj(getCount());
			for (int i = 0; i < getCount(); i++) {
				lnc.addConj(getBody(i).pushNeg(true));
			}
			return lnc;
		} else {
			LNDisj lnd1 = new LNDisj(getCount());
			for (int i = 0; i < getCount(); i++) {
				lnd1.addDisj(getBody(i).pushNeg(false));
			}
			return lnd1;
		}
	}

	/**
	 * This method returns true or false for whether two LiveExprNodes are
	 * syntactically equal.
	 */
	public boolean equals(LiveExprNode exp) {
		if (exp instanceof LNDisj) {
			LNDisj exp2 = (LNDisj) exp;
			if (getCount() != exp2.getCount()) {
				return false;
			}
			for (int i = 0; i < getCount(); i++) {
				if (!getBody(i).equals(exp2.getBody(i))) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/results/ResultPageColumnListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page.results;

import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A ResultPageColumnListener is a listener that handles clicks on
 * the column headers of the "State space progress" region of the
 * Result Page.  The same class is used for all the column
 * headers, with the column number indicating which column header
 * was clicked on.
 * 
 * @author lamport
 */
class ResultPageColumnListener implements SelectionListener {
	private final int m_columnNumber;
	private final ResultPage m_resultPage;

	public ResultPageColumnListener(final int columnNumber, final ResultPage resultPage) {
		m_columnNumber = columnNumber;
		m_resultPage = resultPage;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.
	 * swt.events.SelectionEvent)
	 */
	@Override
	public void widgetDefaultSelected(final SelectionEvent se) { }

	/**
	 * This is called when the user clicks on the header of a column of the "State
	 * space progress" region of the ResultsPage. It raises a window with a graph of
	 * the specified column.
	 */
	@Override
	public void widgetSelected(final SelectionEvent se) {
		UIHelper.runUIAsync(new DataDisplay(m_columnNumber, m_resultPage));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/IBucketStatistics.java<|end_filename|>
package tlc2.util.statistics;

import java.util.NavigableMap;

/**
 * Keeps statistics about any samples added.
 */
public interface IBucketStatistics {

	/**
	 * @param amount
	 *            Add a sample to the statistics. Allowed range is 0 <= sample <=
	 *            Integer.MAX_VALUE
	 */
	void addSample(int amount);

	/**
	 * @return The sum of all values in all buckets (might exceed int)
	 */
	long getObservations();

	/**
	 * @return The median
	 */
	int getMedian();

	/**
	 * @return The mean
	 */
	double getMean();

	/**
	 * @return The minimum
	 */
	int getMin();

	/**
	 * @return The maximum
	 */
	int getMax();

	/**
	 * @return The standard deviation
	 */
	double getStdDev();

	/**
	 * @param quantile 0 <= d <= 1.0 (adjusted to closet limit if smaller or larger)
	 * @return The given percentile
	 */
	double getPercentile(double quantile);

	NavigableMap<Integer, Long> getSamples();
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Debug.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Debug                                                              *
*                                                                          *
* This class provides methods called when an error is encountered,         *
* methods for printing debugging output, and methods for measuring and     *
* reporting elapsed time.                                                  *
***************************************************************************/
package tla2tex;
import java.util.Date;
import java.util.Vector;

import util.ToolIO;

public class Debug
  { public static void ReportError(String msg)
      /*********************************************************************
      * This method is called to report an error and abort.                *
      *********************************************************************/
      { ToolIO.out.println("");
        ToolIO.out.println("TLATeX unrecoverable error:");
        ToolIO.out.println("");
        ToolIO.out.println(" -- " + msg + ".");
        ToolIO.out.println("");
        throw new TLA2TexException("TLATeX unrecoverable error:" + " -- " + msg + ".");
      };

    public static void Assert(boolean val) 
      /*********************************************************************
      * Why doesn't java provide an Assert statement?                      *
      *********************************************************************/
      { if (! val) {ReportBug("Assertion failure");};
      };

    public static void Assert(boolean val, String msg) 
      /*********************************************************************
      * An Assert with an error message.                                   *
      *********************************************************************/
      { if (! val) {ReportBug("Failure of assertion: " + msg);};
      };

    public static void ReportBug(String msg)
      /*********************************************************************
      * This method is called to report a bug in the program and abort.    *
      *********************************************************************/
      { ToolIO.out.println("");
        ToolIO.out.println("You have discovered a bug in TLATeX.");
        ToolIO.out.println("Send the following information and the");
        ToolIO.out.println("input file to the current maintainer(s).");
        ToolIO.out.println("");
        ToolIO.out.println(" -- " + msg + ".");
        ToolIO.out.println("");
        throw new Error() ;
      };


    public static void printArray(Object[] array, String name)
      /*********************************************************************
      * This method prints to standard output the contents of the array    *
      * argument, where name is the name of the array.                     *
      *********************************************************************/
      { if (array == null)
          {ToolIO.out.println(name + " == null");
           return ;} ;
        int i = 0 ;
        while (i < array.length)
          { if (array[i] == null)
              { ToolIO.out.println(name + "[" + i + "] = null") ;}
            else
              { ToolIO.out.println(name + "[" + i + "] = " 
                                        + array[i].toString()) ; }
            i = i+1;
          } ;
        if (array.length == 0)
          {ToolIO.out.println(name + " = zero-length array" ); } ;
      } ;

    public static void print2DArray(Object[][] array, String name)
      /*********************************************************************
      * This method prints to standard output the contents of the array    *
      * argument, where name is the name of the array.                     *
      *********************************************************************/
      { if (array == null)
          {ToolIO.out.println(name + " == null");
           return ;} ;
        int i = 0 ;
        while (i < array.length)
          { int j = 0 ;
            while (j < array[i].length)
             { ToolIO.out.println(name + "[" + i + "][" + j + "] = " 
                                     + array[i][j].toString()) ;
               j = j+1;
             };
            if (array[i].length == 0)
              {ToolIO.out.println(name + "[" + i + "] = null" ); } ;
            i = i+1;
          } ;
        if (array.length == 0)
          {ToolIO.out.println(name + " = zero-length array" ); } ;
      } ;

    public static void printVector(Vector vec, String name)
      /*********************************************************************
      * This method prints to standard output the contents of the vector   *
      * argument, where name is the name of the vector.                    *
      *********************************************************************/
      { if (vec == null)
          {ToolIO.out.println(name + " == null");
           return ;} ;
        int i = 0 ;
        while (i < vec.size())
          { if (vec.elementAt(i) == null)
              { ToolIO.out.println(name + "[" + i + "] = null") ;}
            else
              { ToolIO.out.println(name + "[" + i + "] = " 
                                        + vec.elementAt(i).toString()) ; }
            i = i+1;
          } ;
        if (vec.size() == 0)
          {ToolIO.out.println(name + " = zero-length vec" ); } ;
      } ;

    public static String pair(int i, int j)
      /*********************************************************************
      * Just a convenient little function.                                 *
      *********************************************************************/
      { return "(" + i + ", " + j + ")"; };

    public static void printPair(int i, int j)
      /*********************************************************************
      * Just prints "(i, j)".                                              *
      *********************************************************************/
      { ToolIO.out.println(pair(i,j)); };

    public static long now()
      /*********************************************************************
      * Returns the current time in milliseconds since January 1, 1970,    *
      * 00:00:00 GMT                                                       *
      *********************************************************************/
      {  Date date = new Date();
         return date.getTime() ;
      } ;

    public static void printElapsedTime(long start, String msg)
      /*********************************************************************
      * Print to stdout `msg' followed by the difference between the       *
      * current time and the time `start'.                                 *
      *********************************************************************/
      { printTimeDiff(now() - start, msg);
      } ;

    public static void printTimeDiff(long diff, String msg)
      /*********************************************************************
      * Print to stdout `msg' followed by the time interval diff, which    *
      * is assumed to be in milliseconds                                   *
      *********************************************************************/
      { ToolIO.out.println(msg + " " + 
          Misc.floatToString(((float)diff)/1000 , 2) + " seconds");
      } ;
  }

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/pprint/PrettyPrint.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:21:13 PST by lamport
//      modified on Wed Aug 23 13:22:02 PDT 2000 by yuanyu
//      modified on Wed Jun 16 14:36:34 EDT 1999 by tuttle

package tlc2.pprint;

import tlc2.output.EC;
import tlc2.output.MP;
import util.ToolIO;


public class PrettyPrint {

  public static String mypp(String value, int width) {
    try {
      Node   tree   = Parse.parse(value,0);
      if (tree.last() < value.length()-1) {
	return value;
      }
      String format = Format.format(tree, width, 0, "");
      return format;
    }
    catch (Exception e) {
      // Assert.printStack(e);
      return value;
    }
  }
  
  public static String pp(String value, int width) {
    return pp(value, width, "");
  }

  public static String pp(String value, int width, String padding) {
    try {
      Node   tree   = Parse.parse(value,0);
      String format = Format.format(tree,width,0,padding);
      return format;
    }
    catch (ParseException e) {
        MP.printTLCBug(EC.TLC_PP_PARSING_VALUE, new String[]{value, e.getMessage()});
        return value;
    }
    catch (FormatException e) {
        MP.printTLCBug(EC.TLC_PP_FORMATING_VALUE, new String[]{value, e.getMessage()});
        return value;
    }
  }

  /**
   * Not called from the code. Seems to be for testing only
   * @param argv
   * 
   */
  public static void main(String[] argv) {
    String value = argv[0];
    int    width = Integer.parseInt(argv[1]);
    String padding;

    if (argv.length > 2) {
      padding = argv[2];
    } else {
      padding = "";
    }

    for (int i = 0; i < width; i++) {
        ToolIO.out.print("*");
    }
    ToolIO.out.println("");
    ToolIO.out.println(pp(value,width,padding));
    for (int i = 0; i < width; i++) {
        ToolIO.out.print("*");
    }
    ToolIO.out.println("");

    return;
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAEditorActivator.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import java.util.Dictionary;
import java.util.Hashtable;

import org.eclipse.e4.ui.css.swt.theme.ITheme;
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
import org.eclipse.e4.ui.css.swt.theme.IThemeManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.rules.IPartitionTokenScanner;
import org.eclipse.jface.text.rules.ITokenScanner;
import org.eclipse.swt.widgets.Display;
import org.lamport.tla.toolbox.AbstractTLCActivator;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.tla.PCALCodeScanner;
import org.lamport.tla.toolbox.editor.basic.tla.TLACodeScanner;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

/**
 * The activator class controls the plug-in life cycle
 */
@SuppressWarnings("restriction")
public class TLAEditorActivator extends AbstractTLCActivator {
    // The plug-in ID
    public static final String PLUGIN_ID = "org.lamport.tla.toolbox.editor.basic";

    // The shared instance
    private static TLAEditorActivator plugin;
    
    private static final String DARK_THEME_ID_PREFIX = "org.eclipse.e4.ui.css.theme.e4_dark";

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
	public static TLAEditorActivator getDefault() {
        return plugin;
    }

    
    private TLAPartitionScanner partitionTokenScanner;
    private TLAColorProvider colorProvider;
    private TLACodeScanner tlaCodeScanner;
    private PCALCodeScanner pcalCodeScanner;

    private ServiceRegistration<?> themeChangeEventRegistration;
    
    private Boolean currentThemeIsDark;

    /**
     * The constructor
     */
	public TLAEditorActivator() {
    	super(PLUGIN_ID);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
	public void start(final BundleContext context) throws Exception {
    	plugin = this;
    	
        super.start(context);
        
    	final Dictionary<String, Object> serviceRegistrationProperties = new Hashtable<>();
    	serviceRegistrationProperties.put(EventConstants.EVENT_TOPIC, IThemeEngine.Events.THEME_CHANGED);
    	
    	themeChangeEventRegistration = context.registerService(EventHandler.class.getName(), new EventHandler() {
    		@Override
    		public void handleEvent(final Event event) {
    			tlaCodeScanner = null;
    			pcalCodeScanner = null;
    			setDarkThemeStatus();
    		}
    	}, serviceRegistrationProperties);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
	public void stop(final BundleContext context) throws Exception {
		themeChangeEventRegistration.unregister();
		plugin = null;
		super.stop(context);
	}

    private void setDarkThemeStatus () {
    	final BundleContext context = Activator.getDefault().getBundle().getBundleContext();
    	final ServiceReference<IThemeManager> serviceReference = context.getServiceReference(IThemeManager.class);
    	
    	if (serviceReference != null) {
            final IThemeManager manager = context.getService(serviceReference);

            if (manager != null) {
            	final Display d = Display.getDefault();
            	final IThemeEngine engine = manager.getEngineForDisplay(d);
            	final ITheme it = engine.getActiveTheme();
            	
            	if (it != null) {
            		boolean newThemeStatus = it.getId().startsWith(DARK_THEME_ID_PREFIX);
            		
            		if ((currentThemeIsDark == null) || (currentThemeIsDark.booleanValue() != newThemeStatus)) {
						if (currentThemeIsDark != null) {
							d.asyncExec(() -> {
								MessageDialog.openInformation(d.getActiveShell(), "Theme Change",
										"You will need to close any open views and editors, then re-open them, to have "
												+ "your theme change fully reflected (or restart the Toolbox.)");
							});
            			}
						
            			currentThemeIsDark = Boolean.valueOf(newThemeStatus);
            		}
            	}
            }
    	}
    }
	
	/**
	 * @return true if the current UI theme is dark
	 */
	public boolean isCurrentThemeDark() {
		return (currentThemeIsDark == null) ? false : currentThemeIsDark.booleanValue();
	}

    /**
     * @return
     */
    public IPartitionTokenScanner getTLAPartitionScanner()
    {
        if (partitionTokenScanner == null) 
        {
            partitionTokenScanner = new TLAPartitionScanner();
        }
        return partitionTokenScanner; 
    }

    /**
     * @return
     */
    public TLAColorProvider getTLAColorProvider()
    {
        if (colorProvider == null) 
        {
            colorProvider = new TLAColorProvider();
        }
        return colorProvider; 
    }

    /**
     * @return
     */
    public ITokenScanner getTLACodeScanner()
    {
        if (tlaCodeScanner== null) 
        {
            tlaCodeScanner = new TLACodeScanner();
        }
        return tlaCodeScanner; 
    }
    
    // Added for PlusCal
    public ITokenScanner getPCALCodeScanner()
    {
        if (pcalCodeScanner== null) 
        {
            pcalCodeScanner = new PCALCodeScanner();
        }
        return pcalCodeScanner; 
    }
}


<|start_filename|>general/tests/eclipse-test2.bat<|end_filename|>
echo "STARTING"
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test1
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test2
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test3
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test4
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test5
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test6
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test7
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test8
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test9
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test10
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test11
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test12
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test13
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test14
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test15
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test16
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test17
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test18
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test19
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test20
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test21
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test22
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test23
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test24
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test25
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test26
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test27
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test28
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test29
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test30
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test31
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test32
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test33
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test34
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test35
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test36
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test37
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test38
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test39
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test40
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test41
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test42
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test43
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test44
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test45
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test46
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test47
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test48
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test49
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test50
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test51
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test52
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test53
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test54
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test55
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test56
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test57
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test58
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test59
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test60
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test61
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test62
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test63
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test201
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test202
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test203
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test204
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test205
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test206
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test207
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test208
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  -mx100m tlc2.TLC -cleanup  test209
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test210
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test211
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test212
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test213
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test214
java -cp "c:/users/lamport/tla/tla2/tlatools/class"  tla2sany.SANY test215
echo "DONE"


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LiveCheck.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:44 PST by lamport
//      modified on Thu Jan 10 18:41:04 PST 2002 by yuanyu

package tlc2.tool.liveness;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import tlc2.TLC;
import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.Action;
import tlc2.tool.ITool;
import tlc2.tool.ModelChecker;
import tlc2.tool.StateVec;
import tlc2.tool.TLCState;
import tlc2.util.BitVector;
import tlc2.util.IStateWriter;
import tlc2.util.IStateWriter.Visualization;
import tlc2.util.NoopStateWriter;
import tlc2.util.SetOfStates;
import tlc2.util.statistics.IBucketStatistics;
import util.Assert;

public class LiveCheck implements ILiveCheck {

	private final String metadir;
	private final IBucketStatistics outDegreeGraphStats;
	private final ILiveChecker[] checker;
	
	public LiveCheck(ITool tool, String mdir, IBucketStatistics bucketStatistics) throws IOException {
		this(tool, Liveness.processLiveness(tool), mdir, bucketStatistics, new NoopStateWriter());
	}
	
	public LiveCheck(ITool tool, String mdir, IBucketStatistics bucketStatistics, IStateWriter stateWriter) throws IOException {
		this(tool, Liveness.processLiveness(tool), mdir, bucketStatistics, stateWriter);
	}
	
	public LiveCheck(ITool tool, OrderOfSolution[] solutions, String mdir, IBucketStatistics bucketStatistics) throws IOException {
		this(tool, solutions, mdir, bucketStatistics, new NoopLivenessStateWriter());
	}

	public LiveCheck(ITool tool, OrderOfSolution[] solutions, String mdir, IBucketStatistics bucketStatistics, IStateWriter stateWriter) throws IOException {
		metadir = mdir;
		outDegreeGraphStats = bucketStatistics;
		checker = new ILiveChecker[solutions.length];
		for (int soln = 0; soln < solutions.length; soln++) {
			final ILivenessStateWriter writer = stateWriter.isNoop() || !stateWriter.isDot()
					? new NoopLivenessStateWriter()
					: new DotLivenessStateWriter(stateWriter);
			if (!solutions[soln].hasTableau()) {
				checker[soln] = new LiveChecker(solutions[soln], soln, bucketStatistics, writer);
			} else {
				checker[soln] = new TableauLiveChecker(solutions[soln], soln, bucketStatistics, writer);
			}
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#addInitState(tlc2.tool.TLCState, long)
	 */
	public void addInitState(ITool tool, TLCState state, long stateFP) {
		for (int i = 0; i < checker.length; i++) {
			checker[i].addInitState(tool, state, stateFP);
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#addNextState(tlc2.tool.TLCState, long, tlc2.util.SetOfStates)
	 */
	public void addNextState(ITool tool, TLCState s0, long fp0, SetOfStates nextStates) throws IOException {
		for (int i = 0; i < checker.length; i++) {
			final ILiveChecker check = checker[i];
			final OrderOfSolution oos = check.getSolution();
			final int alen = oos.getCheckAction().length;

			// Check the actions *before* the solution lock is acquired. This
			// increase concurrency as the lock on the OrderOfSolution is pretty
			// coarse grained (it essentially means we lock the complete
			// behavior graph (DiskGraph) just to add a single node). The
			// drawback is obviously, that we create a short-lived BitVector
			// to hold the result and loop over actions x successors twice
			// (here and down below). This is a little price to pay for significantly
			// increased concurrency.
			//
			// The actions have to be checked here because - in the light of
			// symmetry - while we still have access to the actual successor
			// state rather than just its fingerprint that represents all states
			// in the symmetry set. Unless super-symmetry is in place (the
			// actions checks for all states in the symmetry set evaluate to the
			// same value), the "smallest" (see
			// tlc2.tool.TLCStateMut.fingerPrint()) cannot be used as a
			// replacement state to check the actions.
			// TODO: In the past (commit 768b8e8), actions were only evaluated for nodes
			// that are new (ptr == -1)
			// (see https://github.com/tlaplus/tlaplus/issues/614)
			final BitVector checkActionResults = new BitVector(alen * nextStates.size());
			for (int sidx = 0; sidx < nextStates.size(); sidx++) {
				final TLCState s1 = nextStates.next();
				oos.checkAction(tool, s0, s1, checkActionResults, alen * sidx);
			}
			nextStates.resetNext();
			check.addNextState(tool, s0, fp0, nextStates, checkActionResults, oos.checkState(tool, s0));
			
			// Write the content of the current graph to a file in GraphViz
			// format. Useful when debugging!
//			check.getDiskGraph().writeDotViz(oos, new java.io.File(
//					metadir + java.io.File.separator + "dgraph_" + i + "_" + System.currentTimeMillis() + ".dot"));
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#doLiveCheck()
	 */
	public boolean doLiveCheck() {
		for (int i = 0; i < checker.length; i++) {
			// If one of the disk graph's size has increased by the given
			// percentage, run liveness checking.
			//
			// TODO Alternatively:
			//
			// - LL suggest to dedicate a fixed fraction of model checking time
			// to liveness checking.
			//
			// - The level could be taken into account. Unless the level
			// (height) of the graph increases, no new cycle won't be found
			// anyway (all other aspects of liveness checking are checked as
			// part of regular safety checking).
			//
			// - The authors of the Divine model checker describe an algorithm
			// in http://dx.doi.org/10.1109/ASE.2003.1240299
			// that counts the "Back-level Edges" and runs liveness checking upon
			// a counter reaching a certain (user defined?!) threshold.
			//
			final AbstractDiskGraph diskGraph = checker[i].getDiskGraph();
			final long sizeAtLastCheck = diskGraph.getSizeAtLastCheck();
			final long sizeCurrently = diskGraph.size();
			final double delta = (sizeCurrently - sizeAtLastCheck) / (sizeAtLastCheck * 1.d);
			if (delta > TLCGlobals.livenessThreshold) {
				return true;
			}
		}
		return false;
	}
	
	@Override
	public int check(ITool tool, boolean forceCheck) throws Exception {
		if (forceCheck) {
			return check0(tool, false);
		}
		if (!TLCGlobals.doLiveness()) {
			// The user requested to only check liveness once, on the complete
			// state graph.
			return EC.NO_ERROR;
		}
		for (int i = 0; i < checker.length; i++) {
			// see note in doLiveCheck() above!
			final AbstractDiskGraph diskGraph = checker[i].getDiskGraph();
			final long sizeAtLastCheck = diskGraph.getSizeAtLastCheck();
			final long sizeCurrently = diskGraph.size();
			final double delta = (sizeCurrently - sizeAtLastCheck) / (sizeAtLastCheck * 1.d);
			if (delta > TLCGlobals.livenessThreshold) {
				return check0(tool, false);
			}
		}
		return EC.NO_ERROR;
	}
	
	@Override
	public int finalCheck(ITool tool) throws InterruptedException, IOException {
		// Do *not* re-create the nodePtrTable after the check which takes a
		// while for larger disk graphs.
		return check0(tool, true);
	}
	
	/**
	 * @param finalCheck
	 *            If the internal nodePtrTbl should be restored for a subsequent
	 *            liveness check. If this is the final/last check, it's pointless
	 *            to re-create the nodePtrTable.
	 */
	protected int check0(final ITool tool, final boolean finalCheck) throws InterruptedException, IOException {
		final long startTime = System.currentTimeMillis();
		
		// Sum up the number of nodes in all disk graphs to indicate the amount
		// of work to be done by liveness checking.
		long sum = 0L;
		for (int i = 0; i < checker.length; i++) {
			sum += checker[i].getDiskGraph().size();
		}
		MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS, new String[] { finalCheck ? "complete" : "current",
				Long.toString(sum), checker.length == 1 ? "" : checker.length + " branches of " });

		// Copy the array of checkers into a concurrent-enabled queue
		// that allows LiveWorker threads to easily get the next 
		// LiveChecker to work on. We don't really need the FIFO
		// ordering of the BlockingQueue, just its support for removing
		// elements concurrently.
		//
		// Logically the queue is the unit of work the group of LiveWorkers
		// has to complete. Once the queue is empty, all work is done and
		// the LiveWorker threads will terminate.
		//
		// An alternative implementation could partition the array of
		// LiveChecker a-priori and assign one partition to each thread.
		// However, that assumes the work in all partitions is evenly
		// distributed, which is not necessarily true.
		final BlockingQueue<ILiveChecker> queue = new ArrayBlockingQueue<ILiveChecker>(checker.length);
		queue.addAll(Arrays.asList(checker));

		
		/*
		 * A LiveWorker below can either complete a unit of work a) without finding a
		 * liveness violation, b) finds a violation, or c) fails to check because of an
		 * exception/error (such as going out of memory). In case an LW fails to check,
		 * we still wait for all other LWs to complete. A subset of the LWs might have
		 * found a violation. In other words, the OOM of an LW has lower precedence than
		 * a violation found by another LW. However, if any LW fails to check, we terminate
		 * model checking after all LWs completed.
		 */
		final int wNum = TLCGlobals.doSequentialLiveness() ? 1 : Math.min(checker.length, TLCGlobals.getNumWorkers());
		final ExecutorService pool = Executors.newFixedThreadPool(wNum);
		// CS is really just a container around the set of Futures returned by the pool. It saves us from
		// creating a low-level array.
		final CompletionService<Boolean> completionService = new ExecutorCompletionService<Boolean>(pool);

		for (int i = 0; i < wNum; i++) {
			completionService.submit(new LiveWorker(tool, i, wNum, this, queue, finalCheck));
		}
		// Wait for all LWs to complete.
		pool.shutdown();
		pool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); // wait forever

		// Check if any one of the LWs found a violation (ignore failures for now).
		ExecutionException ee = null;
		for (int i = 0; i < wNum; i++) {
			try {
				final Future<Boolean> future = completionService.take();
				if (future.get()) {
					MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS_END,
							TLC.convertRuntimeToHumanReadable(System.currentTimeMillis() - startTime));
					return EC.TLC_TEMPORAL_PROPERTY_VIOLATED;
				}
			} catch (final ExecutionException e) {
				// handled below!
				ee = e;
			}
		}
		// Terminate if any one of the LWs failed c)
		if (ee != null) {
			final Throwable cause = ee.getCause();
			if (cause instanceof OutOfMemoryError) {
				MP.printError(EC.SYSTEM_OUT_OF_MEMORY_LIVENESS, cause);
			} else if (cause instanceof StackOverflowError) {
				MP.printError(EC.SYSTEM_STACK_OVERFLOW, cause);
			} else if (cause != null) {
				MP.printError(EC.GENERAL, cause);
			} else {
				MP.printError(EC.GENERAL, ee);
			}
			System.exit(1);
		}
		
		// Reset after checking unless it's the final check:
		if (finalCheck == false) {
			for (int i = 0; i < checker.length; i++) {
				checker[i].getDiskGraph().makeNodePtrTbl();
			}
		}
		MP.printMessage(EC.TLC_CHECKING_TEMPORAL_PROPS_END, TLC.convertRuntimeToHumanReadable(System.currentTimeMillis() - startTime));
		
		return EC.NO_ERROR;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#checkTrace(tlc2.tool.StateVec)
	 */
	public void checkTrace(ITool tool, final Supplier<StateVec> traceSupplier) throws InterruptedException, IOException {
		final StateVec stateTrace = traceSupplier.get();
		// Add the first state to the LiveCheck as the current init state
		addInitState(tool, stateTrace.elementAt(0), stateTrace.elementAt(0).fingerPrint());
		
		// Add the remaining states...
		final SetOfStates successors = new SetOfStates(stateTrace.size() * 2);

		// For all states except last one add the successor
		// (which is the next state in stateTrace).
		for (int i = 0; i < stateTrace.size() - 1; i++) {
			// Empty out old successors.
			successors.clear();
			
			// Calculate the current state's fingerprint
			final TLCState tlcState = stateTrace.elementAt(i);
			final long fingerPrint = tlcState.fingerPrint();

			// Add state itself to allow stuttering
			successors.put(tlcState);
			
			// Add the successor in the trace
			final TLCState successor = stateTrace.elementAt(i + 1);
			successors.put(successor);
			addNextState(tool, tlcState, fingerPrint, successors);
		}
		
		// Add last state in trace for which *no* successors have been generated
		final TLCState lastState = stateTrace.elementAt(stateTrace.size() - 1);
		addNextState(tool, lastState, lastState.fingerPrint(), new SetOfStates(0));
		
		// Do *not* re-create the nodePtrTbl when it is thrown away anyway.
		final int result = check0(tool, true);
		if (result != EC.NO_ERROR) {
			throw new LiveException(result);
		}
		
		// We are done with the current subsequence of the behavior. Reset LiveCheck
		// for the next behavior simulation is going to create.
		reset();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#getMetaDir()
	 */
	public String getMetaDir() {
		return metadir;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#getOutDegreeStatistics()
	 */
	public IBucketStatistics getOutDegreeStatistics() {
		return outDegreeGraphStats;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#getChecker(int)
	 */
	public ILiveChecker getChecker(final int idx) {
		return checker[idx];
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#getNumChecker()
	 */
	public int getNumChecker() {
		return checker.length;
	}

	/* Close all the files for disk graphs. */
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#close()
	 */
	public void close() throws IOException {
		for (int i = 0; i < checker.length; i++) {
			checker[i].close();
		}
	}

	/* Checkpoint. */
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#beginChkpt()
	 */
	public synchronized void beginChkpt() throws IOException {
		for (int i = 0; i < checker.length; i++) {
			checker[i].getDiskGraph().beginChkpt();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#commitChkpt()
	 */
	public void commitChkpt() throws IOException {
		for (int i = 0; i < checker.length; i++) {
			checker[i].getDiskGraph().commitChkpt();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#recover()
	 */
	public void recover() throws IOException {
		for (int i = 0; i < checker.length; i++) {
			MP.printMessage(EC.TLC_AAAAAAA);
			checker[i].getDiskGraph().recover();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#reset()
	 */
	public void reset() throws IOException {
		for (int i = 0; i < checker.length; i++) {
			checker[i].getDiskGraph().reset();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#calculateInDegreeDiskGraphs(tlc2.util.statistics.IBucketStatistics)
	 */
	public IBucketStatistics calculateInDegreeDiskGraphs(final IBucketStatistics aGraphStats) throws IOException {
		for (int i = 0; i < checker.length; i++) {
			final AbstractDiskGraph diskGraph = checker[i].getDiskGraph();
			diskGraph.calculateInDegreeDiskGraph(aGraphStats);
		}
		return aGraphStats;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.ILiveCheck#calculateOutDegreeDiskGraphs(tlc2.util.statistics.IBucketStatistics)
	 */
	public IBucketStatistics calculateOutDegreeDiskGraphs(final IBucketStatistics aGraphStats) throws IOException {
		for (int i = 0; i < checker.length; i++) {
			final AbstractDiskGraph diskGraph = checker[i].getDiskGraph();
			diskGraph.calculateOutDegreeDiskGraph(aGraphStats);
		}
		return aGraphStats;
	}
	
	static abstract class AbstractLiveChecker implements ILiveChecker {
		
		protected final ILivenessStateWriter writer;
		
		protected final OrderOfSolution oos;

		public AbstractLiveChecker(OrderOfSolution oos, ILivenessStateWriter writer) {
			this.oos = oos;
			this.writer = writer;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.ILiveChecker#getSolution()
		 */
		public OrderOfSolution getSolution() {
			return oos;
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.ILiveChecker#close()
		 */
		public void close() throws IOException {
			if (!ModelChecker.VETO_CLEANUP) {
				this.getDiskGraph().close();
			}
			this.writer.close();
		}
	}
	
	private class LiveChecker extends AbstractLiveChecker {

		private final DiskGraph dgraph;

		public LiveChecker(OrderOfSolution oos, int soln, IBucketStatistics bucketStatistics, ILivenessStateWriter writer)
			throws IOException {
			super(oos, writer);
			this.dgraph = new DiskGraph(metadir, soln, bucketStatistics);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.LiveCheck.ILiveChecker#addInitState(tlc2.tool.TLCState, long)
		 */
		public void addInitState(ITool tool, TLCState state, long stateFP) {
			dgraph.addInitNode(stateFP, -1);
			writer.writeState(state);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.ILiveChecker#addNextState(tlc2.tool.TLCState, long, tlc2.util.SetOfStates, tlc2.util.BitVector, boolean[])
		 */
		public void addNextState(ITool tool, final TLCState s0, final long fp0,
				final SetOfStates nextStates, final BitVector checkActionResults, final boolean[] checkStateResults) throws IOException {
			int cnt = 0;
			// if there is no tableau ...
			final int succCnt = nextStates.size();
			final int alen = oos.getCheckAction().length;
			synchronized (oos) {
				final GraphNode node0 = dgraph.getNode(fp0);
				final int s = node0.succSize();
				node0.setCheckState(checkStateResults);
				for (int sidx = 0; sidx < succCnt; sidx++) {
					final TLCState successorState = nextStates.next();
					final long successor = successorState.fingerPrint();
					// Only add the transition if:
					// a) The successor itself has not been written to disk
					//    TODO Why is an existing successor ignored?
					// b) The successor is a new outgoing transition for s0 
					final long ptr1 = dgraph.getPtr(successor);
					if (ptr1 == -1 || !node0.transExists(successor, -1)) {
						// Eagerly allocate as many (N) transitions (outgoing arcs)
						// as we are maximally going to add within the for
						// loop. This reduces GraphNode's internal and
						// *performance-wise expensive* System.arraycopy calls
						// from N invocations to one (best case) or two (worst
						// case). It has been found empirically (VoteProof) that
						// the best case is used most of the time (99%).
						// It should also minimize the work created for Garbage
						// Collection to clean up even in the worst-case (two invocations)
						// when the pre-allocated memory has to be freed (see
						// realign call).
						// Rather than allocating N memory regions and freeing
						// N-1 immediately after, it now just has to free a
						// single one (and only iff we over-allocated).
						node0.addTransition(successor, -1, checkStateResults.length, alen,
								checkActionResults, sidx * alen, (succCnt - cnt++));
					} else {
						cnt++;
					}
					writer.writeState(s0, successorState, checkActionResults, sidx * alen, alen, ptr1 == -1);
				}
				nextStates.resetNext();
				// In simulation mode (see Simulator), it's possible that this
				// method is called multiple times for the same state (s0/fp0)
				// but with changing successors caused by the random successor
				// selection. If the successor is truly new (it has not been
				// added before), the GraphNode instance has to be updated
				// (creating a new record on disk). However, when the successor
				// parameter happens to pass known successors only, there is no
				// point in adding the GraphNode again. It would just waste disk
				// space.
				// The amount of successors is either 0 (no new successor has
				// been added) or used to be less than it is now.
				if ((s == 0 && s == node0.succSize()) || s < node0.succSize()) {
					node0.realign(); // see node0.addTransition() hint
					// Add a node for the current state. It gets added *after*
					// all transitions have been added because addNode
					// immediately writes the GraphNode to disk including its
					// transitions.
					dgraph.addNode(node0);
				} else {
					// Since the condition is only supposed to evaluate to false
					// when LiveCheck is used in simulation mode, mainChecker
					// has to be null.
					Assert.check(TLCGlobals.mainChecker == null, EC.GENERAL);
				}
			}
		}

		public DiskGraph getDiskGraph() {
			return dgraph;
		}
	}

	private class TableauLiveChecker extends AbstractLiveChecker {

		private final TableauDiskGraph dgraph;

		public TableauLiveChecker(OrderOfSolution oos, int soln, IBucketStatistics statistics, ILivenessStateWriter writer)
				throws IOException {
			super(oos, writer);
			this.dgraph = new TableauDiskGraph(metadir, soln, statistics);
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.LiveChecker#addInitState(tlc2.tool.TLCState, long)
		 */
		public void addInitState(final ITool tool, final TLCState state, final long stateFP) {
			// (state, tnode) is a root node if tnode is an initial tableau
			// node and tnode is consistent with state.
			int initCnt = oos.getTableau().getInitCnt();
			for (int i = 0; i < initCnt; i++) {
				TBGraphNode tnode = oos.getTableau().getNode(i);
				if (tnode.isConsistent(state, tool)) {
					dgraph.addInitNode(stateFP, tnode.getIndex());
					dgraph.recordNode(stateFP, tnode.getIndex());
					writer.writeState(state, tnode);
				}
			}
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.ILiveChecker#addNextState(tlc2.tool.TLCState, long, tlc2.util.SetOfStates, tlc2.util.BitVector, boolean[])
		 */
		public void addNextState(final ITool tool, final TLCState s0, final long fp0,
				final SetOfStates nextStates, final BitVector checkActionResults, final boolean[] checkStateResults) throws IOException {
			int cnt = 0;
			final int succCnt = nextStates.size();
			
			//TODO: See regression introduced by moving TBGraphNode#isConsistent
			//      out of the (synchronized) loop below (commit d4908d0).
			//      https://github.com/tlaplus/tlaplus/issues/614
			
			// Pre-compute the consistency of the successor states for all
			// nodes in the tableau. This is an expensive operation which is
			// also dependent on the amount of nodes in the tableau times
			// the number of successors. This used to be done within the
			// global oos lock which caused huge thread contention. This variant
			// trades speed for additional memory usage (BitVector).
			final TBGraph tableau = oos.getTableau();
			final BitVector consistency = new BitVector(tableau.size() * succCnt);
			final Enumeration<TBGraphNode> elements = tableau.elements();
			while(elements.hasMoreElements()) {
				final TBGraphNode tableauNode = elements.nextElement();
				for (int sidx = 0; sidx < succCnt; sidx++) {
					final TLCState s1 = nextStates.next();
					if(tableauNode.isConsistent(s1, tool)) {
						// BitVector is divided into a segment for each
						// tableau node. Inside each segment, addressing is done
						// via each state. Use identical addressing below
						// where the lookup is done.
						consistency.set((tableauNode.getIndex() * succCnt) + sidx);
					}
				}
				nextStates.resetNext();
			}
			
			// At this point only constant time operations are allowed =>
			// Shortly lock the graph.
			//
			// Tests revealed that "synchronized" provides better performance
			// compared to "java.util.concurrent.locks.Lock" even for high 
			// thread numbers (up to 32 threads). The actual numbers for EWD840
			// with N=11 and 32 threads were ~75% compared to ~55% thread concurrency.
			synchronized (oos) {

				// Mark the fingerprint of s in s -> t as done. Internally it creates
				// or updates a record in the TableauNodePtrTable. We can safely mark
				// s0/fp0 done even though we release the oos lock, because no other
				// worker will work on s0/fp0 ever again, which is guaranteed by safety-
				// checking.
				final int loc0 = dgraph.setDone(fp0);
				final int[] nodes = dgraph.getNodesByLoc(loc0);
				if (nodes == null) {
					// There seems to be no case where nodes can end up as null.
					// setDone(fp0) creates an int[] in dgraph and
					// getNodesByLoc(loc0) returns it.
					return;
				}
				
				final int alen = oos.getCheckAction().length;
				
				// See node0.addTransition(..) of previous case for what the
				// allocation hint is used for.
				final int allocationHint = ((nodes.length / dgraph.getElemLength()) * succCnt);
				
				for (int nidx = 2; nidx < nodes.length; nidx += dgraph.getElemLength()) {
					final int tidx0 = nodes[nidx];
					final TBGraphNode tnode0 = oos.getTableau().getNode(tidx0);
					final GraphNode node0 = dgraph.getNode(fp0, tidx0);
					final int s = node0.succSize();
					node0.setCheckState(checkStateResults);
					for (int sidx = 0; sidx < succCnt; sidx++) {
						final TLCState s1 = nextStates.next();
						final long successor = s1.fingerPrint();
						final boolean isDone = dgraph.isDone(successor);
						for (int k = 0; k < tnode0.nextSize(); k++) {
							final TBGraphNode tnode1 = tnode0.nextAt(k);
							// Check if the successor is new
							final long ptr1 = dgraph.getPtr(successor, tnode1.getIndex());
							if (consistency.get((tnode1.getIndex() * succCnt) + sidx)
									// We cannot infer from successor t being in the fingerprint graph (FG), that it is
									// also in the behavior graph (BG):
									// a) Worker A might add t to FG. B observes t in the fingerprint graph and adds
									// t to BG *incorrectly assuming it is done*.
									// b) t in FG does not imply that <<t, tnode>> in BG
									// Without a), LiveChecker.addNextState(ITool, TLCState, long, SetOfStates,
									// BitVector, boolean[]) could skip checking t \in BG.
									// In other words, t \in FG is a necessary but not a sufficient condition...
									&& (ptr1 == -1 || !node0.transExists(successor, tnode1.getIndex()))) {
								node0.addTransition(successor, tnode1.getIndex(), checkStateResults.length, alen,
										checkActionResults, sidx * alen, allocationHint - cnt);
								writer.writeState(s0, tnode0, s1, tnode1, checkActionResults, sidx * alen, alen, true);
								// Record that we have seen <successor,tnode1>. If fp1 is done, we have
								// to compute the next states for <successor, tnode1>.
								if (ptr1 == -1) {
									dgraph.recordNode(successor, tnode1.getIndex());
									if (isDone) {
										addNextState(tool, s1, successor, tnode1, oos, dgraph);
									}
								}
							}
							// Increment cnt even if addTrasition is not called. After all, 
							// the for loop has completed yet another iteration.
							cnt++;
						}
					}
					nextStates.resetNext();
					// See same case in LiveChecker#addNextState
					if ((s == 0 && s == node0.succSize()) || s < node0.succSize()) {
						node0.realign(); // see node0.addTransition() hint
						dgraph.addNode(node0);
					} else {
						// Since the condition is only supposed to evaluate to false
						// when LiveCheck is used in simulation mode, mainChecker
						// has to be null.
						Assert.check(TLCGlobals.mainChecker == null, EC.GENERAL);
					}
				}
			}
		}

		/**
		 * This method takes care of the case that a new node <<state, tableau>>
		 * in the (state X tableau) graph is generated after the state itself
		 * has been done. Done means that the state has been found during safety
		 * checking in the state graph already, except that the node <<state,
		 * tableau>> not been created.
		 * <p>
		 * In this case, we will have to generate the state graph successors of
		 * the state and create the permutation of all successors with all
		 * tableau nodes .
		 * <p>
		 * Hopefully, this case does not occur very frequently because it
		 * generates successor nodes.
		 */
		private void addNextState(final ITool tool, final TLCState s, final long fp, final TBGraphNode tnode, final OrderOfSolution oos, final TableauDiskGraph dgraph)
				throws IOException {
			final boolean[] checkStateRes = oos.checkState(tool, s);
			final int slen = checkStateRes.length;
			final int alen = oos.getCheckAction().length;
			final GraphNode node = dgraph.getNode(fp, tnode.getIndex());
			final int numSucc = node.succSize();
			node.setCheckState(checkStateRes);

			// see allocationHint of node.addTransition() invocations below
			int cnt = 0;
			
			// Add edges induced by s -> s (self-loop) coming from the tableau
			// graph:
			final int nextSize = tnode.nextSize();
			final BitVector checkActionResults = nextSize > 0 ? oos.checkAction(tool, s, s, new BitVector(alen), 0) : null;
			for (int i = 0; i < nextSize; i++) {
				final TBGraphNode tnode1 = tnode.nextAt(i);
				final int tidx1 = tnode1.getIndex();
				final long ptr1 = dgraph.getPtr(fp, tidx1);
				if (tnode1.isConsistent(s, tool) && (ptr1 == -1 || !node.transExists(fp, tidx1))) {
					node.addTransition(fp, tidx1, slen, alen, checkActionResults, 0, (nextSize - cnt));
					if (ptr1 == -1) {
						dgraph.recordNode(fp, tnode1.getIndex());
						addNextState(tool, s, fp, tnode1, oos, dgraph);
					}
				}
				cnt++;
			}

			// Add edges induced by s -> s1 (where s1 is a successor of s in the
			// state graph):
			cnt = 0;
			final Action[] actions = tool.getActions();
			for (int i = 0; i < actions.length; i++) {
				final StateVec nextStates = tool.getNextStates(actions[i], s);
				final int nextCnt = nextStates.size();
				for (int j = 0; j < nextCnt; j++) {
					final TLCState s1 = nextStates.elementAt(j);
					if (tool.isInModel(s1) && tool.isInActions(s, s1)) {
						final long fp1 = s1.fingerPrint();
						final BitVector checkActionRes = oos.checkAction(tool, s, s1, new BitVector(alen), 0);
						boolean isDone = dgraph.isDone(fp1);
						for (int k = 0; k < tnode.nextSize(); k++) {
							final TBGraphNode tnode1 = tnode.nextAt(k);
							final int tidx1 = tnode1.getIndex();
							long ptr1 = dgraph.getPtr(fp1, tidx1);
							final int total = actions.length * nextCnt * tnode.nextSize();
							if (tnode1.isConsistent(s1, tool) && (ptr1 == -1 || !node.transExists(fp1, tidx1))) {
								node.addTransition(fp1, tidx1, slen, alen, checkActionRes, 0, (total - cnt));
								writer.writeState(s, tnode, s1, tnode1, checkActionRes, 0, alen, false, Visualization.DOTTED);
								// Record that we have seen <fp1, tnode1>. If
								// fp1 is done, we have to compute the next
								// states for <fp1, tnode1>.
								if (ptr1 == -1) {
									dgraph.recordNode(fp1, tidx1);
									if (isDone) {
										addNextState(tool, s1, fp1, tnode1, oos, dgraph);
									}
								}
							}
							cnt++;
						}
					} else {
						cnt++;
					}
				}
			}
			if (numSucc < node.succSize()) {
				node.realign(); // see node.addTransition() hint
				dgraph.addNode(node);
			}
		}

		/* (non-Javadoc)
		 * @see tlc2.tool.liveness.LiveCheck.AbstractLiveChecker#getDiskGraph()
		 */
		public AbstractDiskGraph getDiskGraph() {
			return dgraph;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/CharReader.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* ABSTRACT CLASS CharReader                                                *
*                                                                          *
* Provides an input stream that can be read one character at a time.  It   *
* expands tabs into spaces.  It provides the following methods.            *
*                                                                          *
* char getNextChar()    : Returns the next input character, or '\t' if     *
*                         there is none.                                   *
*                                                                          *
* void close()          : Closes the input stream.                         *
*                                                                          *
* int getLineNumber()   : Returns the line number of the next char to be   *
*                         returned by getNextChar().                       *
*                                                                          *
* int getColumnNumber() : Returns the column number of the next char to    *
*                         be returned by getNextChar().                    *
*                                                                          *
* Lines and columns are numbered starting from 0.                          *
*                                                                          *
* IMPLEMENTED BY FileCharReader.                                           *
***************************************************************************/
package tla2tex;

public abstract class CharReader 
  /*************************************************************************
  * This class provides a method for reading characters one at a time,     *
  * using the getNextChar method.  It is to be extended by a subclass      *
  * that defines (a) the method innerGetNextLine to return the next line   *
  * of actual input, and (b) the close method.                             *
  *************************************************************************/
  { /***********************************************************************
    * The variables representing the state of the object.                  *
    ***********************************************************************/

    private String currentLine = null ;
      /*********************************************************************
      * The current line of input, or null if at the end of the input or   *
      * before initialization (see below).                                 *
      *********************************************************************/

    private boolean uninitialized = true ;
      /*********************************************************************
      * Logically, we want to initialize currentLine to                    *
      * innerGetNextLine().  However, this doesn't work because the        *
      * CharReader class initialization is performed before any subclass   *
      * initialization, and the subclass has to be initialized for         *
      * innerGetNextLine() to work.  So, currentLine is initialized by     *
      * getNextChar the first time it is called, whereupon it sets         *
      * uninitialized to false.                                            *
      *********************************************************************/

    protected int line    = 0;                
    private int column  = 0;                
    private int vcolumn = 0;
      /*********************************************************************
      * The line and column numbers of the next character to be returned   *
      * by getNextChar, where column is the actual position of the next    *
      * character in the input stream, and vcolumn is what the column      *
      * number would be if tabs had been "expanded".  When columm =        *
      * length of currentLine, the next character to be returned is '\n'.  *
      *                                                                    *
      * In Java fashion, these are numbered starting at 0.                 *
      *********************************************************************/


    public int getLineNumber() 
      /*********************************************************************
      * Returns the line number of the next character to be returned by    *
      * getNextChar.  Following Java conventions, the first line is        *
      * numbered 0.                                                        *
      *********************************************************************/
      { return line ; } ;


    public int getColumnNumber() 
      /*********************************************************************
      * Returns the virtual column number of the next character to be      *
      * returned by getNextChar.  Following Java conventions, the first    *
      * column is numbered 0.                                              *
      *********************************************************************/
      { return vcolumn ; } ;

    private boolean tabToSpaces = false ;
      /*********************************************************************
      * Equals true when a tab has been encountered in the input stream,   *
      * and the next getNextChar should return a space generated from      *
      * that tab.                                                          *
      *********************************************************************/
      
    public char getNextChar()
      /*********************************************************************
      * Returns the next character in the input stream and updates the     *
      * line and column numbers.  However, it replaces each '\t' (tab) in  *
      * the input stream with the appropriate number of spaces (assuming   *
      * the standard "tab stops").  If the current column is after the     *
      * last character on the current line, then it returns '\n'.  If the  *
      * end of the input has been reached, then it returns '\t'.  Note     *
      * that, for a nonempty input stream, the call preceding the one      *
      * that returns '\t' must return '\n'.  For an empty input stream,    *
      * the first call returns '\t'.                                       *
      *********************************************************************/
      { if (uninitialized) {currentLine   = innerGetNextLine();
                            uninitialized = false; } ;
  
        /*******************************************************************
        * If currentLine is null, then we must have reached the end of the *
        * input.                                                           *
        *******************************************************************/
        if (currentLine == null) { return '\t' ;} ;
  
        /*******************************************************************
        * If we are converting a tab to spaces, return a space.            *
        *******************************************************************/
        if (tabToSpaces)
          { vcolumn = vcolumn + 1;
            if ((vcolumn % 8) == 0) {tabToSpaces = false;};
            return ' ';
          }

        /*******************************************************************
        * If the current column is at the end of the current line, then    *
        * return '\n' after updating the line and column and reading in    *
        * the next line.                                                   *
        *********************************************************************/
        if (currentLine.length() == column) 
          { line        = line + 1 ;
            column      = 0 ;
            vcolumn     = 0 ;
            currentLine = innerGetNextLine();
            return '\n' ;
           } ;
  
        /*******************************************************************
        * We are not at the end of the input or of the line and are not    *
        * converting a tab to space.  Update column and vcolumn, and       *
        * return the next character.                                       *
        *******************************************************************/
        char readChar = currentLine.charAt(column) ;
        column = column + 1;
        vcolumn = vcolumn + 1;
        if (readChar == '\t')
          { if ((vcolumn % 8) != 0) {tabToSpaces = true;} ;
            return ' ';
          }
        return readChar ;
      } ;

    public void backspace()
      /*********************************************************************
      * Backspaces the output stream.  That is, a sequence of n            *
      * backspaces without a getNextChar makes the next getNextChar        *
      * return the character returned by the n-th preceding getNextChar.   *
      * It is not possible to backspace past the first character in a      *
      * line.  Incorrect results will occur if backspacing over a tab      *
      * character.  (This could be corrected, but it's not needed for      *
      * TLATeX, and getting it right is tricky.)                           *
      *********************************************************************/
      { if (column == 0)
         { Debug.ReportBug(
            "CharReader.backspace trying to move past beginning of line");
         };
        column = column - 1;
        vcolumn = vcolumn - 1;
      } ;

    public abstract String innerGetNextLine() ;
      /*********************************************************************
      * The method innerGetNextLine is a method constructed from some      *
      * underlying reader class that returns the next line as a string,    *
      * or null if it's at the end of the input.                           *
      *********************************************************************/
    public abstract void close() ;  
      /*********************************************************************
      * This is the close method of the underlying reader class.           *
      *********************************************************************/
}     


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/generator/PartitionedFingerPrintGenerator.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.fp.generator;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

import org.junit.Assert;

import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.MultiThreadedFPSetTest;

public class PartitionedFingerPrintGenerator extends FingerPrintGenerator {

	private long fp;
	
	private final long numOfPerThreadBuckets;
	private final long increment;

	public PartitionedFingerPrintGenerator(MultiThreadedFPSetTest test, int id, int numThreads, FPSet fpSet, CountDownLatch latch,
			long seed, long insertions, final CyclicBarrier barrier) {
		super(test, id, numThreads, fpSet, latch, seed, insertions, barrier);
		
		final long numOfTotalBuckets = fpSet.getConfiguration().getMemoryInFingerprintCnt();
		numOfPerThreadBuckets = numOfTotalBuckets / (1L * numThreads);

		final long perThreadStartBucket = numOfPerThreadBuckets * (1L * id);
		increment = (long) Math.ceil((Long.MAX_VALUE - 1L) / (numOfTotalBuckets * 1d));
		fp = increment * perThreadStartBucket;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		waitForAllThreadsStarted();
		
		long insertions = 0L;
		
		while (insertions++ < numOfPerThreadBuckets) {
			try {
				if (fp != 0L) {
					if (fpSet.put(fp) != false) {
						Assert.fail("Linear fill-up should not cause a collision");
					}
					// In case PartitionedFingerPrintGenerator and
					// FingerPrintGenerator are used in performance tests, burn
					// the same amount of cycles to obtain the next random like
					// FPG does. puts is meaningless in the scope of PFPG
					// anyway. It inserts up to a load factor of 1.
					//puts += rnd.nextLong();
					puts++;
				}
				fp += increment;
			} catch (IOException e) {
				e.printStackTrace();
				Assert.fail("Unexpected");
			}
		}
		latch.countDown();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/DotActionWriter.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import java.io.IOException;
import java.io.PrintWriter;

import tlc2.tool.Action;
import util.FileUtil;

/**
 * Writes the given action in dot notation.
 * 
 * @see https://en.wikipedia.org/wiki/DOT_(graph_description_language)
 * 
 * 
 * To ASCII-render a graph (on Debian|Ubuntu) install cpanminus, sudo cpanm Graph::Easy and run:
 * cat your.dot | graph-easy --from=dot --as_ascii
 * (https://stackoverflow.com/questions/3211801/graphviz-and-ascii-output)
 */
public class DotActionWriter {

    protected final PrintWriter writer;
    protected final String fname;
	
	public DotActionWriter(final String fname, final String strict) throws IOException {
        this.fname = fname;
        this.writer = new PrintWriter(FileUtil.newBFOS(fname));
		this.writer.append(strict + "digraph ActionGraph {\n"); // strict removes redundant edges
		// Turned off LR because top to bottom provides better results with GraphViz viewer.
//		this.writer.append("rankdir=LR;\n"); // Left to right rather than top to bottom
        
		// Spread out state nodes a bit more.
        this.writer.append("nodesep=0.35;\n");

        // Add a legend explaining the semantics of the arcs.
        //TODO penwidth should be explained too!
//        subgraph cluster_legend {
//            label = "Legend";
//            node [shape=point] {
//                d0 [style = invis];
//                d1 [style = invis];
//                p0 [style = invis];
//                p1 [style = invis];
//            }
//            d0 -> d1 [label=unseen color=green style=dotted]
//            p0 -> p1 [label=seen]
//        }
		this.writer.append("subgraph cluster_legend {\n");
		this.writer.append("label = \"Coverage\";\n");
		this.writer.append("node [shape=point] {\n");
		this.writer.append("d0 [style = invis];\n");
		this.writer.append("d1 [style = invis];\n");
		this.writer.append("p0 [style = invis];\n");
		this.writer.append("p0 [style = invis];\n");
		this.writer.append("}\n");
		this.writer.append("d0 -> d1 [label=unseen, color=\"green\", style=dotted]\n");
		this.writer.append("p0 -> p1 [label=seen]\n");
		this.writer.append("}\n");

		this.writer.flush();
	}

	public synchronized void write(final Action action, final int id) {
		// Marker the state as an initial state by using a filled style.
		write(action2dot(action), id);
	}

	public synchronized void write(final String actionName, final int id) {
		// Marker the state as an initial state by using a filled style.
		this.writer.append(Integer.toString(id));
		this.writer.append(" [shape=box,label=\"");
		this.writer.append(actionName);
		this.writer.append("\"]");
		this.writer.append("\n");
	}

	public synchronized void write(final int fromId, final int toId) {
		write(fromId, toId, 0d);
	}

	public synchronized void write(final int fromId, final int toId, final double weight) {
		// Write the transition edge.
		this.writer.append(Integer.toString(fromId));
		this.writer.append(" -> ");
		this.writer.append(Integer.toString(toId));
		// Add the transition edge label.
		if (weight == 0d) {
			this.writer.append("[color=\"green\",style=dotted]");
		} else {
			// TODO don't increase penwidth (contributes to a spaghetti ball of lines) but
			// use heatmap approach like in ModuleCoverageInformation.
			this.writer.append(String.format("[penwidth=%s]", Double.toString(weight)));
		}
		this.writer.append(";\n");
	}

	protected static String action2dot(final Action action) {
		return action.getName().toString();
	}

	public void close() {
		this.writer.append("}");
		this.writer.close();
	}

	public void writeSubGraphStart(final String key, final String label) {
		this.writer.append(String.format("subgraph cluster_%s {\ncolor=\"white\"\nlabel=\"%s\"\n", key, label));
	}

	public void writeSubGraphEnd() {
		this.writer.append("}\n");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/SyntaxTreeConstants.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// jcg wrote this.
// Last modified on Wed 15 Aug 2007 at 15:45:47 PST by lamport
// last revised February 1st 2000 by J-Ch


// List of all kinds of nodes one can find in the syntax tree,
// together with a method to generate a representation

// numbering starts at 227, previous numbers will identify tokens (with an identifier 
// generated automatically by javacc

/***************************************************************************
* The value assigned to NULL_ID must be greater than the highest token     *
* number generated by javacc in parser/TLAplusParserConstants.java.  As    *
* of 20 Apr 2007, the highest token number was 226 and NULL_ID was set     *
* equal to 227.  So, I upped the numbers by 100.                           *
***************************************************************************/
package tla2sany.st;

import util.UniqueString;

public interface SyntaxTreeConstants {

  int  NULL_ID =  327;
  int  N_ActDecl  =  328 ;
  int  N_ActionExpr  =  329 ;
  int  N_AssumeDecl  =  330 ;
  int  N_AssumeProve  =  331 ;
  int  N_Assumption  =  332 ;
  int  N_BeginModule  =  333 ;
  int  N_Body  =  334 ;
  int  N_BoundQuant  =  335 ;
  int  N_Case  =  336 ;
  int  N_CaseArm  =  337 ;
//  int  N_CaseStatement  =  338 ;    // Removed by LL 25 Jul 2007
//  int  N_ChooseStatement  =  339 ;  // Removed by LL 25 Jul 2007
  int  N_ConjItem  =  340 ;
  int  N_ConjList  =  341 ;
  int  N_ConsDecl  =  342 ;
  int  N_DisjItem  =  343 ;
  int  N_DisjList  =  344 ;
  int  N_EndModule  =  345 ;
  int  N_Except  =  346 ;
  int  N_ExceptComponent  =  347 ;
  int  N_ExceptSpec  =  348 ;
  int  N_Times =  349 ; // N_Expression
  int  N_Extends  =  350 ;
  int  N_FairnessExpr  =  351 ;
  int  N_FcnAppl  =  352 ;
  int  N_FcnConst  =  353 ;
  int  N_FieldSet  =  354 ;
  int  N_FieldVal  =  355 ;
  int  N_FunctionDefinition  =  356 ;
  int  N_FunctionParam  =  357 ;
  int  N_GeneralId  =  358 ;
  int  N_GenInfixOp  =  359 ;
  int  N_GenNonExpPrefixOp  =  360 ; // I think this is used only for unary -
  int  N_GenPostfixOp  =  361 ;
  int  N_GenPrefixOp  =  362 ;
  int  N_IdentDecl  =  363 ;
  int  N_Real       =  364; //  int  N_Identifier  =  264 ;
  int  N_IdentifierTuple  =  365 ;
  int  N_IdentLHS  =  366 ;
  int  N_IdPrefix  =  367 ;
  int  N_IdPrefixElement  =  368 ;
  int  N_IfThenElse  =  369 ;
  int  N_InfixDecl  =  370 ;
  int  N_InfixExpr  =  371 ;
  int  N_InfixLHS  =  372 ;
  int  N_InfixOp  =  373 ;
  int  N_InnerProof  =  374 ;
  int  N_Instance  =  375 ;
  int  N_NonLocalInstance  =  376 ;
  int  N_Integer  =  377 ;
//  int  N_LeafProof  =  378 ;          // Removed by LL 25 Jul 2007
  int  N_LetDefinitions  =  379 ;
  int  N_LetIn  =  380 ;
  int  N_MaybeBound  =  381 ;
  int  N_Module  =  382 ;
  int  N_ModuleDefinition  =  383 ;
  int  N_NonExpPrefixOp  =  384 ;
  int  N_Number  =  385 ;
  int  N_NumberedAssumeProve  =  386 ;
  int  N_OpApplication  =  387 ;
  int  N_OpArgs  =  388 ;
  int  N_OperatorDefinition  =  389 ;
  int  N_OtherArm  =  390 ;
  int  N_ParamDecl  =  391 ;
  int  N_ParamDeclaration  =  392 ;
  int  N_ParenExpr  =  393 ;
  int  N_PostfixDecl  =  394 ;
  int  N_PostfixExpr  =  395 ;
  int  N_PostfixLHS  =  396 ;
  int  N_PostfixOp  =  397 ;
  int  N_PrefixDecl  =  398 ;
  int  N_PrefixExpr  =  399 ;
  int  N_PrefixLHS  =  400 ;
  int  N_PrefixOp  =  401 ;
  int  N_Proof  =  402 ;
//  int  N_ProofLet  =  403 ;         // Removed by LL 25 Jul 2007
//  int  N_ProofName  =  404 ;        // Removed by LL 25 Jul 2007
//  int  N_ProofStatement  =  405 ;   // Removed by LL 25 Jul 2007
  int  N_ProofStep  =  406 ;        
  int  N_QEDStep  =  407 ;
  int  N_QuantBound  =  408 ;
  int  N_RcdConstructor  =  409 ;
  int  N_RecordComponent  =  410 ;
  int  N_SetEnumerate  =  411 ;
  int  N_SetExcept  =  412 ;
  int  N_SetOfAll  =  413 ;
  int  N_SetOfFcns  =  414 ;
  int  N_SetOfRcds  =  415 ;
  int  N_SExceptSpec  =  416 ;
  int  N_SFcnDecl  =  417 ;
  int  N_String  =  418 ;
  int  N_SubsetOf  =  419 ;
  int  N_Substitution  =  420 ;
  int  N_TempDecl  =  421 ;
  int  N_Theorem  =  422 ;
  int  N_Tuple  =  423 ;
  int  N_UnboundOrBoundChoose  =  424 ;
  int  N_UnboundQuant  =  425 ;
  int  N_VariableDeclaration  =  426 ;
  int  T_IN = 427 ;
  int  T_EQUAL = 428 ;
  int  N_NewSymb = 429 ;     // Added  6 Mar 07 by LL
  int  N_Lambda  = 430 ;     // Added 27 Mar 07 by LL
  int  N_Recursive  = 431 ;  // Added 29 Mar 07 by LL
  int  N_Label  = 432 ;      // Added 21 Apr 07 by LL
  int  N_StructOp = 433 ;
    /***********************************************************************
    * This was added 11 May 07 by LL to represent something like the "<"   *
    * in "!<".  A struct op has a single child that is a SyntaxTreeNode    *
    * either formed from one of the tokens "<<", ">>", "@", or ":" or      *
    * else from a NUMBER_LITERAL token.                                    *
    ***********************************************************************/
  int  N_NumerableStep = 434 ;      // Added 23 Jul 07 by LL
  int  N_TerminalProof = 435 ;      // Added 23 Jul 07 by LL
  int  N_UseOrHide     = 436 ;      // Added 24 Jul 07 by LL
  int  N_NonExprBody   = 437 ;      // Added 24 Jul 07 by LL
  int  N_DefStep       = 438 ;      // Added 25 Jul 07 by LL
  int  N_HaveStep      = 439 ;      // Added 15 Aug 07 by LL
  int  N_TakeStep      = 440 ;      // Added 15 Aug 07 by LL
  int  N_WitnessStep   = 441 ;      // Added 15 Aug 07 by LL
  int  N_PickStep      = 442 ;      // Added 15 Aug 07 by LL
  int  N_CaseStep      = 443 ;      // Added 15 Aug 07 by LL
  int  N_AssertStep    = 444 ;      // Added 15 Aug 07 by LL
    
  UniqueString[] SyntaxNodeImage = { /* name of symbol n should be n+1 lines down*/
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("Not a node"),
    UniqueString.uniqueStringOf("N_ActDecl"),
    UniqueString.uniqueStringOf("N_ActionExpr"),
    UniqueString.uniqueStringOf("N_AssumeDecl"),
    UniqueString.uniqueStringOf("N_AssumeProve"),
    UniqueString.uniqueStringOf("N_Assumption"),
    UniqueString.uniqueStringOf("N_BeginModule"),
    UniqueString.uniqueStringOf("N_Body"),
    UniqueString.uniqueStringOf("N_BoundedQuant"),
    UniqueString.uniqueStringOf("N_Case"),
    UniqueString.uniqueStringOf("N_CaseArm"),
    UniqueString.uniqueStringOf("N_CaseStatement"),
    UniqueString.uniqueStringOf("N_ChooseStatement"),
    UniqueString.uniqueStringOf("N_ConjItem"),
    UniqueString.uniqueStringOf("N_ConjList"),
    UniqueString.uniqueStringOf("N_ConsDecl"),
    UniqueString.uniqueStringOf("N_DisjItem"),
    UniqueString.uniqueStringOf("N_DisjList"),
    UniqueString.uniqueStringOf("N_EndModule"),
    UniqueString.uniqueStringOf("N_Except"),
    UniqueString.uniqueStringOf("N_ExceptComponent"),
    UniqueString.uniqueStringOf("N_ExceptSpec"),
    UniqueString.uniqueStringOf("N_Times"), // "N_Expression"),
    UniqueString.uniqueStringOf("N_Extends"),
    UniqueString.uniqueStringOf("N_FairnessExpr"),
    UniqueString.uniqueStringOf("N_FcnAppl"),
    UniqueString.uniqueStringOf("N_FcnConst"),
    UniqueString.uniqueStringOf("N_FieldSet"),
    UniqueString.uniqueStringOf("N_FieldVal"),
    UniqueString.uniqueStringOf("N_FunctionDefinition"),
    UniqueString.uniqueStringOf("N_FunctionParam"),
    UniqueString.uniqueStringOf("N_GeneralId"),
    UniqueString.uniqueStringOf("N_GenInfixOp"),
    UniqueString.uniqueStringOf("N_GenNonExpPrefixOp"),
    UniqueString.uniqueStringOf("N_GenPostfixOp"),
    UniqueString.uniqueStringOf("N_GenPrefixOp"),
    UniqueString.uniqueStringOf("N_IdentDecl"),
    UniqueString.uniqueStringOf("N_Real"), // was N_Identifier
    UniqueString.uniqueStringOf("N_IdentifierTuple"),
    UniqueString.uniqueStringOf("N_IdentLHS"),
    UniqueString.uniqueStringOf("N_IdPrefix"),
    UniqueString.uniqueStringOf("N_IdPrefixElement"),
    UniqueString.uniqueStringOf("N_IfThenElse"),
    UniqueString.uniqueStringOf("N_InfixDecl"),
    UniqueString.uniqueStringOf("N_InfixExpr"),
    UniqueString.uniqueStringOf("N_InfixLHS"),
    UniqueString.uniqueStringOf("N_InfixOp"),
    UniqueString.uniqueStringOf("N_InnerProof"),
    UniqueString.uniqueStringOf("N_Instance"),
    UniqueString.uniqueStringOf("N_NonLocalInstance"),
    UniqueString.uniqueStringOf("N_Integer"),
    UniqueString.uniqueStringOf("N_LeafProof"),
    UniqueString.uniqueStringOf("N_LetDefinitions"),
    UniqueString.uniqueStringOf("N_LetIn"),
    UniqueString.uniqueStringOf("N_MaybeBound"),
    UniqueString.uniqueStringOf("N_Module"),
    UniqueString.uniqueStringOf("N_ModuleDefinition"),
    UniqueString.uniqueStringOf("N_NonExpPrefixOp"),
    UniqueString.uniqueStringOf("N_Number"),
    UniqueString.uniqueStringOf("N_NumberedAssumeProve"),
    UniqueString.uniqueStringOf("N_OpApplication"),
    UniqueString.uniqueStringOf("N_OpArgs"),
    UniqueString.uniqueStringOf("N_OperatorDefinition"),
    UniqueString.uniqueStringOf("N_OtherArm"),
    UniqueString.uniqueStringOf("N_ParamDecl"),
    UniqueString.uniqueStringOf("N_ParamDeclaration"),
    UniqueString.uniqueStringOf("N_ParenExpr"),
    UniqueString.uniqueStringOf("N_PostfixDecl"),
    UniqueString.uniqueStringOf("N_PostfixExpr"),
    UniqueString.uniqueStringOf("N_PostfixLHS"),
    UniqueString.uniqueStringOf("N_PostfixOp"),
    UniqueString.uniqueStringOf("N_PrefixDecl"),
    UniqueString.uniqueStringOf("N_PrefixExpr"),
    UniqueString.uniqueStringOf("N_PrefixLHS"),
    UniqueString.uniqueStringOf("N_PrefixOp"),
    UniqueString.uniqueStringOf("N_Proof"),
    UniqueString.uniqueStringOf("N_ProofLet"),
    UniqueString.uniqueStringOf("N_ProofName"),
    UniqueString.uniqueStringOf("N_ProofStatement"),
    UniqueString.uniqueStringOf("N_ProofStep"),
    UniqueString.uniqueStringOf("N_QEDStep"),
    UniqueString.uniqueStringOf("N_QuantBound"),
    UniqueString.uniqueStringOf("N_RcdConstructor"),
    UniqueString.uniqueStringOf("N_RecordComponent"),
    UniqueString.uniqueStringOf("N_SetEnumerate"),
    UniqueString.uniqueStringOf("N_SetExcept"),
    UniqueString.uniqueStringOf("N_SetOfAll"),
    UniqueString.uniqueStringOf("N_SetOfFcns"),
    UniqueString.uniqueStringOf("N_SetOfRcds"),
    UniqueString.uniqueStringOf("N_SExceptSpec"),
    UniqueString.uniqueStringOf("N_SFcnDecl"),
    UniqueString.uniqueStringOf("N_String"),
    UniqueString.uniqueStringOf("N_SubsetOf"),
    UniqueString.uniqueStringOf("N_Substitution"),
    UniqueString.uniqueStringOf("N_TempDecl"),
    UniqueString.uniqueStringOf("N_Theorem"),
    UniqueString.uniqueStringOf("N_Tuple"),
    UniqueString.uniqueStringOf("N_UnBoundedOrBoundedChoose"),
    UniqueString.uniqueStringOf("N_UnboundedQuant"),
    UniqueString.uniqueStringOf("N_VariableDeclaration"),
    UniqueString.uniqueStringOf("Token ="),    // I don't understand why this shouldn't be "Token \\in" ??
    UniqueString.uniqueStringOf("Token \\in"), // I don't understand why this shouldn't be "Token =" ??
    UniqueString.uniqueStringOf("N_NewSymb"),  // Added  8 Mar 07 by LL
    UniqueString.uniqueStringOf("N_Lambda"),   // Added 27 Mar 07 by LL
    UniqueString.uniqueStringOf("N_Recursive"),  // Added 29 Mar 07 by LL
    UniqueString.uniqueStringOf("N_Label"),      // Added 21 Apr 07 by LL
    UniqueString.uniqueStringOf("N_StructOp"),
    UniqueString.uniqueStringOf("N_NumerableStep"), // Added 23 Jul 07 by LL
    UniqueString.uniqueStringOf("N_TerminalProof"), // Added 23 Jul 07 by LL
    UniqueString.uniqueStringOf("N_UseOrHide"),     // Added 24 Jul 07 by LL
    UniqueString.uniqueStringOf("N_NonExprBody"),   // Added 24 Jul 07 by LL
    UniqueString.uniqueStringOf("N_DefStep"),       // Added 25 Jul 07 by LL
    UniqueString.uniqueStringOf("N_HaveStep"),      // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("N_TakeStep"),      // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("N_WitnessStep"),   // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("N_PickStep"),      // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("N_CaseStep"),      // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("N_AssertStep"),    // Added 15 Aug 07 by LL
    UniqueString.uniqueStringOf("Not a node")
     };
}



<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCErrorTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.output.data;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.junit.Test;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError.Order;

import tlc2.model.Formula;
import tlc2.model.TraceExpressionInformationHolder;
import util.TLAConstants;

public class TLCErrorTest {
	
	@Test
	public void testA() {
		test(Order.OneToN, Order.NToOne, 0, 1);
	}
	@Test
	public void testB() {
		test(Order.NToOne, Order.OneToN, 1, 0);
	}
	@Test
	public void testC() {
		test(Order.OneToN, Order.OneToN, 0, 1);
	}
	@Test
	public void testD() {
		test(Order.NToOne, Order.NToOne, 1, 0);
	}
	
	private static void test(final Order sortMC, final Order sortTE, final int init, final int next) {
		final String modelName = "Model_1";
		final Map<String, Formula> traceExplorerExpressions = new HashMap<String, Formula>();
		final Hashtable<String, TraceExpressionInformationHolder> traceExpressionDataTable = getTraceExpressionDataTable();
		
		// error origination for a "regular" TLC run.
		final TLCError mcError = new TLCError(sortMC);
		final TLCState mcInitState = TLCState.parseState("1: <Initial predicate>\n" + 
				"/\\ store = <<>>\n" + 
				"/\\ waitC = {}\n" + 
				"/\\ waitP = {}", modelName);
		mcError.addState(mcInitState);
		final TLCState mcNextState = TLCState.parseState("2: <p2 line 63, col 13 to line 66, col 36 of module BlockingQueue>\n" + 
				"/\\ store = <<\"data\">>\n" + 
				"/\\ waitC = {}\n" + 
				"/\\ waitP = {}", modelName);
		mcError.addState(mcNextState);
		
		// error originating from a trace expression evaluation.
		final TLCError teError = new TLCError(sortTE);
		teError.addState(TLCState.parseState("1: <Initial predicate>\n" + 
				"/\\ store = <<>>\n" + 
				"/\\ waitC = {}\n" + 
				"/\\ waitP = {}\n" + 
				"/\\ __trace_var_155717784845014000 = 1\n" + 
				"/\\ __trace_var_155717784845012000 = TRUE", modelName));
		teError.addState(TLCState.parseState("2: <next_155717784845016000 line 44, col 3 to line 67, col 2 of module TE>\n" + 
				"/\\ store = <<\"data\">>\n" + 
				"/\\ waitC = {}\n" + 
				"/\\ waitP = {}\n" + 
				"/\\ __trace_var_155717784845014000 = 2\n" + 
				"/\\ __trace_var_155717784845012000 = FALSE", modelName));
		
		// Merge teError with mcError
		teError.applyFrom(mcError, traceExplorerExpressions, traceExpressionDataTable, modelName);
		
		final List<TLCState> teStates = teError.getStates();
		assertEquals(2, teStates.size());
		
		final TLCState teInitState = teStates.get(init);
		assertTrue(teInitState.isInitialState());
		assertEquals(mcInitState.getLabel(), teInitState.getLabel());
		assertEquals(mcInitState.getStateNumber(), teInitState.getStateNumber());
		assertEquals(mcInitState.getVariableCount(1) + 2, teInitState.getVariableCount(1));
		final Map<String, TLCVariable> teInitDiff = teInitState.getDiff(mcInitState);
		assertEquals(2, teInitDiff.size());
		assertEquals(teInitDiff.get(TLAConstants.TraceExplore.POSITION).toString(), "1");
		assertEquals(teInitDiff.get("store = <<>>").toString(), "TRUE");

		final TLCState teNextState = teStates.get(next);
		assertFalse(teNextState.isInitialState());
		assertEquals(mcNextState.getLabel(), teNextState.getLabel());
		assertEquals(mcNextState.getStateNumber(), teNextState.getStateNumber());
		assertEquals(mcNextState.getVariableCount(1) + 2, teNextState.getVariableCount(1));
		final Map<String, TLCVariable> teNextDiff = teNextState.getDiff(mcNextState);
		assertEquals(2, teNextDiff.size());
		assertEquals(teNextDiff.get(TLAConstants.TraceExplore.POSITION).toString(), "2");
		assertEquals(teNextDiff.get("store = <<>>").toString(), "FALSE");
	}

	private static final Hashtable<String, TraceExpressionInformationHolder> getTraceExpressionDataTable() {
		final Hashtable<String, TraceExpressionInformationHolder> hashtable = new Hashtable<String, TraceExpressionInformationHolder>();
		hashtable.put("__trace_var_155717784845014000", new TraceExpressionInformationHolder(TLAConstants.TraceExplore.POSITION, null, "__trace_var_155717784845014000"));

		final TraceExpressionInformationHolder value = new TraceExpressionInformationHolder("store = <<>>", null, "__trace_var_155717784845012000");
		value.setLevel(1);
		hashtable.put(value.getVariableName(), value);
		
		return hashtable;
	}
	
	//*********************************************//
	
	@Test
	public void testXA() {
		testX(Order.OneToN, Order.NToOne, 0, 1);
	}
	@Test
	public void testXB() {
		testX(Order.NToOne, Order.OneToN, 2, 1);
	}
	@Test
	public void testXC() {
		testX(Order.OneToN, Order.OneToN, 0, 1);
	}
	@Test
	public void testXD() {
		testX(Order.NToOne, Order.NToOne, 2, 1);
	}
	
	private static void testX(final Order sortMC, final Order sortTE, final int init, final int next) {
		final String modelName = "Model_1";
		final Map<String, Formula> traceExplorerExpressions = new HashMap<String, Formula>();
		final Hashtable<String, TraceExpressionInformationHolder> traceExpressionDataTable = getTraceExpressionDataTableX();
		
		// error origination for a "regular" TLC run.
		final TLCError mcError = new TLCError(sortMC);
		final TLCState mcInitState = TLCState.parseState("1: <Initial predicate>\n" + "x = 0", modelName);
		mcError.addState(mcInitState);
		final TLCState mcNextState = TLCState
				.parseState("2: <Next line 6, col 9 to line 6, col 40 of module Counter>\n" + "x = 1", modelName);
		mcError.addState(mcNextState);
		final TLCState mcLoopState = TLCState
				.parseState("1: Back to state: <Next line 6, col 9 to line 6, col 40 of module Counter>", modelName);
		mcError.addState(mcLoopState);
		
		// error originating from a trace expression evaluation.
		final TLCError teError = new TLCError(sortTE);
		teError.addState(TLCState.parseState(
				"1: <Initial predicate>\n/\\ __trace_var_15571917867925000 = \"--\"\n/\\ x = 0", modelName));
		teError.addState(
				TLCState.parseState("2: <next_15571917867927000 line 34, col 2 to line 42, col 1 of module TE>\n"
						+ "/\\ __trace_var_15571917867925000 = TRUE\n/\\ x = 1", modelName));
		teError.addState(
				TLCState.parseState("3: <next_15571917867927000 line 44, col 2 to line 52, col 1 of module TE>\n"
						+ "/\\ __trace_var_15571917867925000 = FALSE\n" + "/\\ x = 0", modelName));
		teError.addState(TLCState.parseState(
				"2: Back to state: <next_15571917867927000 line 34, col 2 to line 42, col 1 of module TE>", modelName));
		
		// Merge teError with mcError
		teError.applyFrom(mcError, traceExplorerExpressions, traceExpressionDataTable, modelName);
		
		final List<TLCState> teStates = teError.getStates();
		assertEquals(3, teStates.size());
		
		final TLCState teInitState = teStates.get(init);
		assertTrue(teInitState.isInitialState());
		assertEquals(mcInitState.getLabel(), teInitState.getLabel());
		assertEquals(mcInitState.getStateNumber(), teInitState.getStateNumber());
		final Map<String, TLCVariable> teInitDiff = teInitState.getDiff(mcInitState);
		assertEquals(2, teInitDiff.size());
		assertEquals(teInitDiff.get("x' > x").toString(), "\"--\"");

		final TLCState teNextState = teStates.get(next);
		assertFalse(teNextState.isInitialState());
		assertEquals(mcNextState.getLabel(), teNextState.getLabel());
		assertEquals(mcNextState.getStateNumber(), teNextState.getStateNumber());
		final Map<String, TLCVariable> teNextDiff = teNextState.getDiff(mcNextState);
		assertEquals(2, teNextDiff.size());
		assertEquals(teNextDiff.get("x' > x").toString(), "TRUE");
	}

	private static final Hashtable<String, TraceExpressionInformationHolder> getTraceExpressionDataTableX() {
		final Hashtable<String, TraceExpressionInformationHolder> hashtable = new Hashtable<String, TraceExpressionInformationHolder>();

		final TraceExpressionInformationHolder value = new TraceExpressionInformationHolder("x' > x", null, "__trace_var_15571917867925000");
		value.setLevel(1);
		hashtable.put(value.getVariableName(), value);
		
		return hashtable;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jnlp/src/org/lamport/tla/toolbox/distributed/URLHttpServlet.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation. All rights reserved.
package org.lamport.tla.toolbox.distributed;

import java.io.IOException;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public abstract class URLHttpServlet extends HttpServlet {

	private static final long serialVersionUID = 1543293859269681164L;

	protected URL url;
	protected String addr;
	protected String remoteAddr;
	
	
	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
		// read the URL under which this servlet got accessed, assuming this is
		// the best hostname under which
		// the callee can access this host/servlet/resource
		final StringBuffer requestURL = req.getRequestURL();
		url = new URL(requestURL.toString());
		addr = url.getProtocol() + "://" + url.getAuthority();
		
		remoteAddr = req.getRemoteAddr();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/ApplicationWorkbenchAdvisor.java<|end_filename|>
package org.lamport.tla.toolbox;

import java.net.URL;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.application.IWorkbenchConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.ide.IDE;
import org.lamport.tla.toolbox.ui.intro.ToolboxIntroPart;
import org.osgi.framework.Bundle;

/**
 * This workbench advisor creates the window advisor, and specifies
 * the perspective id for the initial window.
 * @author <NAME>
 */
public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor
{

    // TODO MOVE!
    public static final String IDE_PLUGIN = "org.eclipse.ui.ide";
    public static final String PATH_OBJECT = "icons/full/obj16/";
    public static final String PATH_WIZBAN = "icons/full/wizban/";
    
    public static final String PRJ_OBJ = PATH_OBJECT + "prj_obj.gif"; 
    public static final String PRJ_OBJ_C = PATH_OBJECT + "cprj_obj.gif";
    public static final String SAVEAS_DLG = PATH_WIZBAN + "saveas_wiz.png";
    
    /**
     * Image definition from org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages#IMG_DLGBAN_SAVEAS_DLG
     */
    public static final String IMG_DLGBAN_SAVEAS_DLG = "IMG_DLGBAN_SAVEAS_DLG";

    public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
    {
        return new ApplicationWorkbenchWindowAdvisor(configurer);
    }

    public String getInitialWindowPerspectiveId()
    {
        return ToolboxIntroPart.PERSPECTIVE_ID;
    }

    /*
     * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize(org.eclipse.ui.application.IWorkbenchConfigurer)
     */
    public void initialize(IWorkbenchConfigurer configurer)
    {
        // save the positions of windows etc...
        configurer.setSaveAndRestore(true);

        super.initialize(configurer);
        
        Bundle ideBundle = Platform.getBundle(IDE_PLUGIN);
        declareWorkbenchImage(configurer, ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT, PRJ_OBJ,
                true);
        declareWorkbenchImage(configurer, ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PRJ_OBJ_C, true);
        
        declareWorkbenchImage(configurer, ideBundle, IMG_DLGBAN_SAVEAS_DLG, SAVEAS_DLG, true);
        
        // register adapter
        IDE.registerAdapters();
    }

    private void declareWorkbenchImage(IWorkbenchConfigurer configurer, Bundle ideBundle, String symbolicName,
            String path, boolean shared)
    {
        URL url = ideBundle.getEntry(path);
        ImageDescriptor desc = ImageDescriptor.createFromURL(url);
        configurer.declareImage(symbolicName, desc, shared);
    }

	/* (non-Javadoc)
	 * @see org.eclipse.ui.application.WorkbenchAdvisor#preShutdown()
	 */
	public boolean preShutdown() {
		ToolboxLifecycleParticipantManger.terminate();
		return super.preShutdown();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
	 */
	public void postStartup() {
		super.postStartup();
		ToolboxLifecycleParticipantManger.initialize();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/ParsingProverProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;
import org.lamport.tla.toolbox.tool.prover.output.IProverProcessOutputSink;

/**
 * This class receives streaming output from the TLAPM
 * and sends it to a {@link TagBasedTLAPMOutputIncrementalParser}
 * for parsing.
 * 
 * This class receives output by registering at the extension point
 * org.lamport.tla.toolbox.tool.prover.processOutputSink.
 * 
 * This class should no longer be used.
 * 
 * @deprecated
 * @author <NAME>
 *
 */
public class ParsingProverProcessOutputSink implements IProverProcessOutputSink
{

    private TagBasedTLAPMOutputIncrementalParser parser;
    private IPath name;

    /**
     * Sends text to the parser.
     */
    public void appendText(String text)
    {
        // try
        // {
        // // parser.addIncrement(text);
        //
        // } catch (BadLocationException e)
        // {
        // Activator.getDefault().logError("Error parsing the TLAPM output stream for " + name, e);
        // }
    }

    /**
     * Initializes a parser for the stream of text that will be sent
     * to this sink.
     * 
     * For now, we assume that the String modulePathString was generated by calling
     * {@link IPath#toPortableString()} and so the original {@link IPath} can
     * be retrieved by calling {@link Path#fromPortableString(String)}.
     */
    public void initializeSink(IFile moduleFile, ProverJob proverJob, IProgressMonitor monitor)
    {
        // this.parser = new TagBasedTLAPMOutputIncrementalParser(moduleFile, monitor, description);
        // this.name = moduleFile;
    }

    /**
     * Notifies the parser that
     * no more text is to be sent.
     */
    public void processFinished()
    {
        // parser.onDone();
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/nature/ParserHelper.java<|end_filename|>
package org.lamport.tla.toolbox.spec.nature;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.ModuleParserLauncher;
import org.lamport.tla.toolbox.spec.parser.SpecificationParserLauncher;

/**
 * Encapsulates parser launching methods
 * 
 * @author <NAME>
 * @version $Id$
 */
public class ParserHelper
{

    private final static ModuleParserLauncher moduleParser = new ModuleParserLauncher();
    private final static SpecificationParserLauncher launcher = new SpecificationParserLauncher(moduleParser);

    /**
     * Runs the parser on the given module
     * @param resource
     * @param monitor
     */
    public static void rebuildModule(final IResource resource, IProgressMonitor monitor)
    {
        if (resource == null)
        {
            return;
        }
        IWorkspaceRunnable run = new IWorkspaceRunnable() {

            public void run(IProgressMonitor monitor) throws CoreException
            {
                moduleParser.parseModule(resource, monitor);
            }
        };
        try
        {
            resource.getWorkspace().run(run, monitor);
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error parsing a module", e);
        }
    }

    /**
     * This will run the parse of the root file of the current spec 
     * @param monitor
     */
    public static void rebuildSpec(IProgressMonitor monitor)
    {
        final Spec spec = Activator.getSpecManager().getSpecLoaded();
        if (spec == null)
        {
            return;
        }
        IWorkspaceRunnable run = new IWorkspaceRunnable() {

            public void run(IProgressMonitor monitor) throws CoreException
            {
                // markers already removed in the parseSpecification 
                launcher.parseSpecification(spec, monitor);
            }
        };
        try
        {
            ResourcesPlugin.getWorkspace().run(run, monitor);
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error parsing a module", e);
        }
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/DoubleHashedTable.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

/**
 * This was implemented by Simon to be used (and usable) only by the 
 * ParserDependencyStorage class.  It contains two Hashtables,
 * forwardStore and backwardStore, that are supposed to be used 
 * to determine dependency between modules.  I have no idea what
 * they are supposed to mean.  But debugging reveals that both of these
 * take as keys a String that is a user module name.  Each entry is 
 * a Vector of Strings, each of which is a user module name.
 * For a spec in which Test instantiates TestA which instantiates TestB,
 * they have the following entries:
 * <pre>
 *  backwardStore: [key |-> "TestA.tla", value |-> <<"Test.tla">>],
 *                 [key |-> "TestB.tla", value |-> <<"Test.tla">>],
 *                  
 *  forwardStore: [key |-> "Test.tla", value |-> <<"TestA.tla", "TestB.tla">>]
 * </pre>
 * A little further experimentation suggests that this is true in general:
 * backward store contains an entry for every non-root module pointing to the
 * root module, and forward store contains a single entry for the root module
 * pointing to the list of imported modules.
 * @author <NAME>
 * @version $Id$
 */
public class DoubleHashedTable
{
    private static final float DEFALT_THRESHOLD = 0.75f;
    private static final int DEFAULT_SIZE = 11;

    private Hashtable forwardStore = null;
    private Hashtable backwardStore = null;

    public DoubleHashedTable()
    {
        this(DEFAULT_SIZE, DEFALT_THRESHOLD);
    }

    public DoubleHashedTable(int size)
    {
        this(size, DEFALT_THRESHOLD);
    }

    public DoubleHashedTable(int size, float threshold)
    {
        forwardStore = new Hashtable(size, threshold);
        backwardStore = new Hashtable(size, threshold);
    }

    public void clear()
    {
        forwardStore.clear();
        backwardStore.clear();
    }

    public boolean containsKey(Object key)
    {
        return forwardStore.containsKey(key);
    }

    public boolean containsValue(Object value)
    {
        return backwardStore.containsKey(value);
    }

    public List getValues(Object key)
    {
        return (List) forwardStore.get(key);
    }

    public List getKeys(Object value)
    {
        return (List) backwardStore.get(value);
    }

    /**
     * Puts a key and a list of values in to the store. <br>
     * <b>Note:</b>The method will eliminate duplicate values in the list, if any
     * @param key the key 
     * @param values list of values
     * @return the previous stored list of values
     */
    public List put(Object key, List values)
    {
        if (values == null)
        {
            values = new Vector(0);
        }

        Vector listWithoutDoublicates = new Vector(values.size());

        for (int i = 0; i < values.size(); i++)
        {
            List keys = (List) backwardStore.get(values.get(i));
            if (keys == null)
            {
                keys = new Vector();
            }
            if (!keys.contains(key))
            {
                keys.add(key);
                listWithoutDoublicates.add(values.get(i));
                backwardStore.put(values.get(i), keys);
            }
        }
        return (List) forwardStore.put(key, listWithoutDoublicates);
    }

    /**
     * Removes the key with associated values
     * @param key
     * @return
     */
    public List removeKey(Object key)
    {
        return universalRemove(key, forwardStore, backwardStore);
    }

    /**
     * Removes the value with associated keys
     * @param value
     * @return
     */
    public List removeValue(Object value)
    {
        return universalRemove(value, backwardStore, forwardStore);
    }

    /**
     * Retrieves the number of stored keys
     * @return
     */
    public int size()
    {
        return forwardStore.size();
    }
    
    
    /**
     * Removes the toRemove from direct container (as a key with all values) and as all values from from inverted container  
     * @param toRemove element to remove
     * @param directContainer container, in that the element to remove is used as a key 
     * @param invertedContainer container, in that the element to remove is used as values
     * @return a list of dependents of given value
     */
    private static List universalRemove(Object toRemove, Hashtable directContainer, Hashtable invertedContainer)
    {
        List keys = (List) directContainer.remove(toRemove);
        if (keys != null)
        {
            for (int i = 0; i < keys.size(); i++)
            {
                Object key = keys.get(i);
                List values = (List) invertedContainer.get(key);
                if (values == null || !values.contains(toRemove))
                {
                    throw new RuntimeException("DoubleHashtable integrity violated");
                } else
                {
                    values.remove(toRemove);
                }
                // no put needed
            }
        }
        return keys;

    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/gettingstarted/help.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/gettingstarted/help.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

	<title>Using Help</title>
</head>
<!-- a comment -->

<body>
<h1>Using Help</h1>

<p>
Left-clicking on the <code>Help</code> button on the top menu line of the Toolbox and 
selecting <code>Dynamic Help</code>
will raise a help view.&nbsp;  Sometimes this view will contain a
help page like this one that describes the currently selected view. 
</p>
<pre>
     <IMG SRC=useful-help.gif Align=bottom> 
</pre>
<p> If it does, there will be a <samp>See also</samp> section with links
 to relevant help pages.&nbsp;  Ignore the <samp>More results</samp> section.&nbsp;
Sometimes, clicking on <samp>Help</samp> will just show
a generic page like this:
</p>
<pre>
     <IMG SRC=default-help.gif Align=bottom> 
</pre>
<p> 
If it does this, just click on the <samp>Contents</samp> button at the bottom of 
the page, which will take you to the table of contents of all Help pages.&nbsp;  You
should be able to 
find what you need there.
</p>
<p>
You may find it convenient to move the Help view to a separate
window outside the Toolbox.&nbsp;  See <a href="views.html"><em>Managing Views</em></a>.
</p>

<p>Some pop-up dialogs and views contain a   
<IMG SRC=question-mark.gif align=bottom> button--in their lower-left corner for pop-up dialogs.&nbsp;  
Clicking on that button will raise a helpful
help window.  (For a pop-up dialog, the help window is inside the dialog. For a view, it is
in an ordinary help view.) 
</p>

<p>The <IMG SRC=left-right-arrows.gif Align=bottom> buttons at the
top right of the Help view allow you to
navigate among previously displayed help pages.</p>
<hr><a href = "gettingstarted.html">&uarr; Getting Started</a>
<!-- commented out
<dl>
<dt>Topics</dt>
<dd> <A href="help.html" target="_blank">Using Help</A></dd>
<dd> <A href="views.html" target="_blank">Managing Views</A></dd>
</dl>
 -->
</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/TLAToken.java<|end_filename|>
/***************************************************************************
* CLASS TLAToken                                                           *
*                                                                          *
* A TLAToken object represents a single token of a TLA+ expression.        *
*                                                                          *
* A TLAToken object has the following fields:                              *
*                                                                          *
*   String string : The actual input.                                      *
*   int column    : The column in the input line of its first              *
*                   character (counting from 0).                           *
*   int type      : The type of the token.  Possibilities are:             *
*                      BUILTIN, NUMBER, STRING, IDENT, ADDED               *
*                                                                          *
* The constructors are TLAToken() and TLAToken(string, column, type).      *
*                                                                          *
* The methods are                                                          *
*                                                                          *
*   getWidth() : returns width of token in input.                          *
*   toString() : for debugging                                             *
***************************************************************************/
package pcal;

import java.util.Vector;

public class TLAToken
  /*************************************************************************
  * This class defines the TLAToken object, which is an element of a       *
  * tokenized expression.                                                  *
  *************************************************************************/
  { public String string ;
      /*********************************************************************
      * The string of the token.  This is usually what the user has        *
      * typed, but it may also be something else.                          *
      *********************************************************************/

    public int column ;
      /*********************************************************************
      * The column in which the first character of the token appears in    *
      * the expression.                                                    *
      *********************************************************************/
      
    public int type ;
       /********************************************************************
       * The type of the token.  Here are the possibilities:               *
       ********************************************************************/
    
    public Region source ;
       /********************************************************************
       * The region in the file occupied by the token in the PlusCal       *
       * code.  Added 6 Dec 2011 for TLA to PlusCal mapping.               *
       ********************************************************************/    

       public static final int BUILTIN = 1 ;
         /******************************************************************
         * A built-in token.                                               *
         ******************************************************************/

       public static final int NUMBER = 2 ;
         /******************************************************************
         * A number like "2" or "\O777".                                   *
         ******************************************************************/

       public static final int STRING = 3 ;
         /******************************************************************
         * A string like "foo".  In this type, the string field does not   *
         * contain the enclosing quotes.                                   *
         ******************************************************************/

       public static final int IDENT = 4 ;
         /******************************************************************
         * An identifier, such as foo_Bar.                                 *
         ******************************************************************/

       public static final int ADDED = 5 ;
         /******************************************************************
         * A token "pc" or "stack" has this type when it has been added    *
         * by the translator, and so it should be given a subscript if     *
         * this is a multiprocess algorithm.  It doesn't matter whether    *
         * or not the translator uses this type for other tokens it        *
         * creates.                                                        *
         ******************************************************************/
       
       /**
        * A BEGIN/END_REPLACEMENT token is a zero-width token, with
        * string "", that marks the beginning/end of a region of an
        * expression obtained by substituting an expression for a token.
        * The beginning and end  of the region of the BEGIN_REPLACEMENT 
        * token both equal the begin location of the replaced token; the 
        * beginning and end of the region of the END_REPLACEMENT token
        * both equal the end region of the replaced token.
        */
//       public static final int BEGIN_REPLACEMENT = 6 ;
//       public static final int END_REPLACEMENT = 7 ;
      
    /**
     * The beginSubst and endSubst fields represent sequences of Paren objects in a TPMap, 
     * as described in module TLAtoPCal.  This means that they indicate the beginning
     * and ending of substitutions that created the expression containing the token.
     * Here is an example.  
     * 
     *    macro foo(a) {
     *     x := a + 1 
     *    }
     *    macro bar(b) {
     *      foo(b)
     *    }
     *    ...
     *    bar(3+2) ;
     *    
     * After macro expansion, the call of foo in macro bar is replaced by
     * 
     *     x := b + 1
     * 
     * and the call of bar is replaced by
     * 
     *    x := (3+2)+1
     * 
     * The token "b" in "x := b" will have 
     * 
     *    beginSubst = <<beginLoc(a)>> and endSubst = <<endLoc(a)>> 
     *    
     * where beginLoc(a) and endLoc(a) are the beginning and end locations of the 
     * token "a" in expression "x := a + 1" of macro foo.  The token "(" in 
     * "x := (3+2)+1" will have
     * 
     *    beginSubst = << beginLoc(a), beginLoc(b) >> and  endSubst = << >>
     *    
     * and the ")" token would have 
     * 
     *    beginSubst =  << >> and endSubst = << endLoc(a), endLoc(b) >>
     * 
     * (It was an arbitrary choice to add the begin/endLoc(b) elements to the 
     * beginning of the begin/endSubst sequences rather than to the end.)
     * 
     * Note that there's no need for the TPMap to have the extra Parens corresponding
     * to the location of "b".  It wouldn't be needed if  substituting an expression containing
     * more than one token for a token always adds parentheses around the substituted
     * expression.  This would imply that if some token has beginSubst equal to a sequence
     * of beginLoc locations, then some token (perhaps the same one) has a its
     * endSubst equal to the corresponding sequence of endLoc locations.  As in the,
     * example, there would be no need to keep anything but the first element of the
     * sequence, which is what is done.  However, since the {@link TLAExpr#substituteAt} 
     * method is sometimes called with an argument telling it not to  add
     * parentheses when substituting multiple tokens, I'm letting beginSubst and endSubst
     * be sequences (Vectors) of PCalLocation objects.  It would be a good idea to
     * remove redundant pairs of matching parens (the ones for "b" in the example), and
     * perhaps I'll do that.
     */
    private Vector beginSubst = new Vector(2) ; // of PCalLocation
    private Vector endSubst = new Vector(2);    // of PCalLocation
    public Vector getBeginSubst() {
        return beginSubst;
    }

    public void setBeginSubst(Vector beginSubst) {
        this.beginSubst = beginSubst;
    }

    public Vector getEndSubst() {
        return endSubst;
    }

    public void setEndSubst(Vector endSubst) {
        this.endSubst = endSubst;
    }
    

    /**
     * The isAppended flag is true iff this token is a prime ("'")
     * or one of the tokens in the "[self]" that is effectively added
     * to an expression immediately after an IDENT token by the 
     * {@link PcalTLAGen#AddSubscriptsToExpr} method.
     */
    private boolean isAppended = false ;
    public boolean isAppended() {
        return isAppended;
    }

//    public void setAppended(boolean isAppended) {
//        this.isAppended = isAppended;
//    }


    /***********************************************************************
    * Below are the methods for this object class, including the           *
    * constructors.                                                        *
    ***********************************************************************/
    /**
     * This is the old constructor, used before the addition of the TLA-PCal
     * mapping.  It should be used only to construct tokens that do not come
     * from a corresponding token in the PCal code. 
     * 
     * @param str
     * @param col
     * @param typ
     */
    public TLAToken(String str, int col, int typ)
      /*********************************************************************
      * A TLAToken constructor                                             *
      *********************************************************************/
      { string = str ;
        column = col ;
        type   = typ ;
        source = null ;
      }
    
    /**
     * The following constructor added for TLA-PCal mapping.  It 
     * sets the source field.
     * 
     * @param str
     * @param col
     * @param typ
     * @param line
     */
    public TLAToken(String str, int col, int typ, int line)
    /*********************************************************************
    * A TLAToken constructor                                             *
    *********************************************************************/
    { string = str ;
      column = col ;
      type   = typ ;
      source = new Region(line, col, str.length()) ;
    }
    
    /**
     * A constructor for cases in which the source region is known.
     * 
     * @param str
     * @param col
     * @param typ
     * @param src
     */
    public TLAToken(String str, int col, int typ, Region src) {
    	string = str ;
        column = col ;
        type   = typ ;
        source = src ;
    }
    
    /**
     * A constructor used only in {@link PcalTLAGen#AddSubscriptsToExpr}
     * or in Gen... methods that use it to construct tokens for the
     * TLAExpr argument of a call AddSubscriptsToExpr  
     * to create a token with isAppended = true.
     * 
     * @param str
     * @param col
     * @param typ
     * @param appended
     */
    public TLAToken(String str, int col, int typ, boolean appended) {
        string = str ;
        column = col ;
        type   = typ ;
        source = null ;
        isAppended = true ;
    }
    
    public TLAToken()
      /*********************************************************************
      * A default Token constructor, apparently needed for subclasses.     *
      *********************************************************************/
      { string = "" ;
        column = 0 ;
        type   = 0 ;
      } ;

    public int getWidth() 
      /*********************************************************************
      * Returns a width, which is the number of columns the token spans    *
      * in the original input stream.                                      *
      *********************************************************************/
      { if (string == null) 
          {return 0;}
        else if (type == STRING)
          {/****************************************************************
           * Have to compensate for the removal of the quotes.             *
           ****************************************************************/
            return string.length() + 2;}
        else
          {return string.length();}
      };      

   public String toString()
      /*********************************************************************
      * This is used to print a TLAToken for debugging.                    *
      *********************************************************************/
      { String typeName = "";
        switch (type) 
          { case BUILTIN    : typeName = "BUILTIN"    ; break ;
            case NUMBER     : typeName = "NUMBER"     ; break ;
            case STRING     : typeName = "STRING"     ; break ;
            case IDENT      : typeName = "IDENT"      ; break ;
//            case BEGIN_REPLACEMENT : typeName = "(map"  ; break ;
//            case END_REPLACEMENT   : typeName = "map)"  ; break ;    
          } ;
        String str = "\"" + string + "\"" ;
        if (string == null) {str = "null";};

        String result =    "[str |-> "    + str
                         + ", type |-> "  + typeName
                         + ", col |-> "   + column
                         + ", source |->" + 
            ((source == null) ? "null" : source.toString())
                         + ", beginSub |-> " + beginSubst.toString()
                         + ", endSub |-> " + endSubst.toString() + "]";
//                         + ", width |-> " + getWidth() 
//                         + ", string |-> " + string ;
        
//        if (source != null) {
//        	result = result + ", " + source.toString();
//        }
        return result; 
      };
 

   /**
    * Modified by LL on 6 Dec 2011 to set the source field too.
    * And on 14 Dec 2011 to set the beginSubst and endSubst fields.
    * 
    * @return
    */
   public TLAToken Clone()
     { 
	   TLAToken result = new TLAToken(this.string, this.column, this.type) ;
	   result.source = this.source ;
	   result.beginSubst = (Vector) this.beginSubst.clone();
	   result.endSubst = (Vector) this.endSubst.clone();
	   result.isAppended = this.isAppended;
	   return result ;
     }

  }

/* last modified on Tue 26 Jul 2005 at  0:03:08 UT by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/ITLAReserveredWords.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.tla;

import java.util.Arrays;
import java.util.HashSet;

import util.TLAConstants;

/**
 * TLA+ Reserved words

 * @author <NAME>, <a href="http://simon.zambrovski.org">http://simon.zambrovski.org</a> 
 * @version $Id: ITLAReserveredWords.java,v 1.1 2005/08/22 15:43:33 szambrovski Exp $
 */
public interface ITLAReserveredWords 
{
    public final static String ACTION       = "ACTION";
    public final static String ASSUME 		= "ASSUME";
    public final static String ASSUMPTION 	= "ASSUMPTION";
    public final static String AXIOM 		= "AXIOM";
    public final static String BY           = "BY";    
    public final static String CASE 		= "CASE";
    public final static String CHOOSE 		= "CHOOSE";
    public final static String CONSTANT		= TLAConstants.KeyWords.CONSTANT;
    public final static String CONSTANTS	= TLAConstants.KeyWords.CONSTANTS;
    public final static String COROLLARY    = "COROLLARY";  // Added 16 July 2012 by LL
    public final static String DEF          = "DEF";
    public final static String DEFINE       = "DEFINE";
    public final static String DEFS         = "DEFS";
    public final static String DOMAIN		= "DOMAIN";
    public final static String ELSE 		= "ELSE";
    public final static String ENABLED		= "ENABLED";
    public final static String EXCEPT		= "EXCEPT";
    public final static String EXTENDS 		= "EXTENDS";
    public final static String HAVE         = "HAVE";
    public final static String HIDE         = "HIDE";
    public final static String IF 			= "IF";
    public final static String IN 			= "IN";
    public final static String INSTANCE		= "INSTANCE";
    public final static String LET 			= "LET";
    public final static String LAMBDA       = "LAMBDA";
    public final static String LEMMA        = "LEMMA";
    public final static String LOCAL 		= "LOCAL";
    public final static String MODULE 		= "MODULE";
    public final static String NEW          = "NEW"; 
    public final static String OBVIOUS      = "OBVIOUS";
    public final static String OMITTED      = "OMITTED";
    public final static String ONLY 		= "ONLY";  // Added 23 May 2012 by LL
    public final static String OTHER        = "OTHER";
    public final static String PICK         = "PICK";
    public final static String PROOF        = "PROOF";
    public final static String PROPOSITION  = "PROPOSITION";
    public final static String PROVE        = "PROVE";
    public final static String QED          = "QED";
    public final static String RECURSIVE    = "RECURSIVE";
    public final static String SF_ 			= "SF_";
    public final static String STATE        = "STATE";
    public final static String SUFFICES     = "SUFFICES";
    public final static String SUBSET 		= "SUBSET";
    public final static String TAKE         = "TAKE";
    public final static String TEMPORAL     = "TEMPORAL";
    public final static String THEN 		= "THEN";
    public final static String THEOREM 		= "THEOREM";
    public final static String UNCHANGED 	= "UNCHANGED";
    public final static String UNION 		= "UNION";
    public final static String USE          = "USE";
    public final static String VARIABLE 	= TLAConstants.KeyWords.VARIABLE;
    public final static String VARIABLES 	= VARIABLE + "S";
    public final static String WF_ 			= "WF_";
    public final static String WITH 		= "WITH";
    public final static String WITNESS      = "WITNESS";
    
    public final static String TRUE         = "TRUE";
    public final static String FALSE        = "FALSE";
    
    // Added for PlusCal
    public final static String FAIR       = "fair";
    public final static String ALGORITHM  = "algorithm";
    public final static String ASSERT = "assert" ;
    public final static String AWAIT = "await" ;
    public final static String BEGIN = "begin" ;
    public final static String END = "end" ;
    public final static String CALL = "call" ;
    public final static String PDEFINE = "define" ;
    public final static String DO = "do" ;
    public final static String EITHER = "either" ;
    public final static String OR = "or" ;
    public final static String GOTO = "goto" ;
    public final static String PIF = "if" ;
    public final static String PTHEN = "then" ;
    public final static String PELSE = "else" ;
    public final static String ELSIF = "elsif" ;
    public final static String MACRO = "macro" ;
    public final static String PRINT = "print" ;
    public final static String PROCEDURE = "procedure" ;
    public final static String PROCESS = "process" ;
    public final static String RETURN = "return" ;
    public final static String SKIP = "skip" ;
    public final static String PVARIABLE = "variable" ;
    public final static String PVARIABLES = "variables" ;
    public final static String WHILE = "while" ;
    public final static String PWITH = "with" ;
    public final static String WHEN = "when" ;
    
    public final static String[] PCAL_WORDS_ARRAY = new String[] 
    {
        ASSERT,
        AWAIT,
        BEGIN,
        END,
        CALL,
        PDEFINE,
        DO,
        EITHER,
        OR,
        GOTO,
        PIF,
        PTHEN,
        PELSE,
        ELSIF,
        MACRO,
        PRINT,
        PROCEDURE,
        PROCESS,
        RETURN,
        SKIP,
        PVARIABLE,
        PVARIABLES,
        WHILE,
        PWITH,
        WHEN,
        FAIR,
        ALGORITHM 
    } ;
    
    public final static String[] ALL_WORDS_ARRAY = new String[]
    {
        ACTION,
        ASSUME,
        ASSUMPTION,
        AXIOM,
        BY,
        CASE,
        CHOOSE,
        CONSTANT,
        CONSTANTS,
        COROLLARY,
        DEF,
        DEFINE,
        DEFS,
        DOMAIN,
        ELSE,
        ENABLED,
        EXCEPT,
        EXTENDS,
        HAVE, 
        HIDE,
        IF,
        IN,
        INSTANCE,
        LAMBDA,
        LEMMA,
        LET,
        LOCAL,
        MODULE,
        NEW,
        OBVIOUS,
        OMITTED,
        ONLY,
        OTHER,
        PICK,
        PROOF,
        PROPOSITION,
        PROVE,
        QED,
        RECURSIVE,
        SF_,
        STATE,
        SUBSET,
        SUFFICES,
        TAKE,
        TEMPORAL,
        THEN,
        THEOREM,
        UNCHANGED,
        UNION,
        USE,
        VARIABLE,
        VARIABLES,
        WF_,
        WITH,
        WITNESS
};
    
    public static final String[] ALL_VALUES_ARRAY = {
        TRUE, 
        FALSE
    };
    
    public final static HashSet<String> ALL_WORDS_SET = new HashSet<>(Arrays.asList(ALL_WORDS_ARRAY));
    
}

<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/navigator/ToolboxExplorer.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.navigator;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.handler.OpenModuleHandler;
import org.lamport.tla.toolbox.ui.provider.IGroup;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Specification Explorer
 */
public class ToolboxExplorer extends CommonNavigator
{
    public final static String VIEW_ID = "toolbox.view.ToolboxExplorer";
    public static final String COMMAND_ID = "toolbox.command.cnf.open.delegate";
    
	// first level is spec and model group, second level actual specs and models,
	// third level are model snapshots which we hide by default.
    public static final int DEFAULT_EXPAND_LEVEL = 2;
    
	/**
     * Override the method to deliver the root object for the NCE activation
     */
    protected Object getInitialInput()
    {
        return Activator.getSpecManager();
    }

    /**
     * Open on double-click
     */
    protected void handleDoubleClick(DoubleClickEvent anEvent)
    {
        super.handleDoubleClick(anEvent);
        // open the model
        if (anEvent.getSelection() instanceof IStructuredSelection) {
        	IStructuredSelection iss = (IStructuredSelection) anEvent.getSelection();
        	Object firstElement = iss.getFirstElement();
        	if (firstElement instanceof Module) {
        		final Map<String, String> parameters = new HashMap<String, String>();
        		parameters.put(OpenModuleHandler.PARAM_MODULE, ((Module) firstElement).getModuleName());
				UIHelper.runCommand(OpenModuleHandler.COMMAND_ID, parameters);
        	} else if (firstElement instanceof IGroup) {
        		// No-Op
        	} else if (firstElement instanceof Spec && ((Spec) firstElement).isCurrentSpec()) {
        		// No-op, do not re-open an open spec again.
        	} else {
        		UIHelper.runCommand(ToolboxExplorer.COMMAND_ID, new HashMap<String, String>());
        	}
        }
    }

    /**
     * Finds the CommonNavigatorViewer by name
     * @param navigatorViewId
     * @return
     */
    private static CommonNavigator findCommonNavigator(String navigatorViewId)
    {
        IWorkbenchPage page = UIHelper.getActivePage();
        if (page != null)
        {
            IViewPart findView = UIHelper.getActivePage().findView(navigatorViewId);
            if (findView != null && findView instanceof CommonNavigator)
            {
                return ((CommonNavigator) findView);
            }
        }
        return null;
    }

    /**
     * Retrieves the current viewer if any
     * @return the instance of common viewer or <code>null</code>
     */
    public static CommonViewer getViewer()
    {
        CommonNavigator navigator = findCommonNavigator(ToolboxExplorer.VIEW_ID);
        if (navigator != null) 
        {
            final CommonViewer commonViewer = navigator.getCommonViewer();
            commonViewer.setAutoExpandLevel(DEFAULT_EXPAND_LEVEL);
			return commonViewer;
        }
        
        return null;
    } 

    /**
     * Refreshes the instance of the viewer if any
     */
    public static void refresh()
    {
        CommonViewer instance = getViewer();
        if (instance != null)
        {
            instance.refresh();
        }
    }
//
//    /**
//     * Sets the status of a NCE of the current viwer if any
//     */
//    private static void setToolboxNCEActive(final String extensionId, final boolean active)
//    {
//        CommonNavigator instance = findCommonNavigator(ToolboxExplorer.VIEW_ID);
//        if (instance != null) 
//        {
//            INavigatorContentService contentService = instance.getNavigatorContentService();
//            boolean isActive = contentService.getActivationService().isNavigatorExtensionActive(extensionId);
//            if (active && !isActive)
//            {
//                contentService.getActivationService().activateExtensions(new String[] { extensionId }, false);
//            } else if (!active && isActive)
//            {
//                contentService.getActivationService().deactivateExtensions(new String[] { extensionId }, false);
//            } else
//            {
//                // do nothing, just quit
//                return;
//            }
//            contentService.getActivationService().persistExtensionActivations();
//            contentService.update();
//        }
//    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/management/DiskFPSetMXBean.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp.management;

import java.io.IOException;

import tlc2.tool.fp.DiskFPSet;
import tlc2.tool.fp.FPSet;

public interface DiskFPSetMXBean {

	/**
	 * @return The version of TLC.
	 */
	String getVersion();
	
	/**
	 * @return The code revision corresponding to this version of TLC.
	 */
	String getRevision();
	
	/**
	 * @see DiskFPSet#getDiskHitCnt()
	 */
	long getDiskHitCnt();
	/**
	 * @see DiskFPSet#getDiskLookupCnt()
	 */
	long getDiskLookupCnt();
	/**
	 * @see DiskFPSet#getDiskSeekCnt()
	 */
	long getDiskSeekCnt();
	/**
	 * @see DiskFPSet#getDiskSeekCache()
	 */
	long getDiskSeekCache();
	/**
	 * @see DiskFPSet#getDiskSeekRate()
	 */
	double getDiskSeekRate();
	/**
	 *@see DiskFPSet#getDiskWriteCnt()
	 */
	long getDiskWriteCnt();

	/**
	 * @see DiskFPSet#getMemHitCnt()
	 */
	long getMemHitCnt();

	/**
	 * @see DiskFPSet#getFileCnt()
	 */
	long getFileCnt();
	/**
	 * @see DiskFPSet#getIndexCapacity()
	 */
	long getIndexCnt();

	/**
	 * ~ getMemWriteCnt()
	 */
	long getTblCnt();
	
	/**
	 * @see DiskFPSet#getBucketCapacity()
	 */
	long getBucketCapacity();
	/**
	 * @see DiskFPSet#getTblCapacity()
	 */
	long getTblCapacity();
	/**
	 * @see DiskFPSet#getOverallCapacity()
	 */
	long getOverallCapacity();

	/**
	 * @see DiskFPSet#getTblLoad()
	 */
	long getTblLoad();
	
	/**
	 * @see DiskFPSet#getGrowDiskMark()
	 */
	int getGrowDiskMark();
	/**
	 * @see DiskFPSet#getCheckPointMark()
	 */
	int getCheckPointMark();
	
	/**
	 * @return
	 */
	long getSizeOf();
	
	/**
	 * @return Accumulated time it has taken to flush {@link FPSet} to disk
	 */
	long getFlushTime();
	
	/**
	 * @see DiskFPSet#getLockCnt()
	 */
	int getLockCnt();
	
	/**
	 * @see DiskFPSet#getReaderWriterCnt()
	 */
	int getReaderWriterCnt();
	
	/**
	 * @see DiskFPSet#getLoadFactor()
	 */
	double getLoadFactor();
	
	/**
	 * @see DiskFPSet#forceFlush()
	 */
	void forceFlush();
	
	/**
	 * @see DiskFPSet#checkInvariant()
	 */
	boolean checkInvariant() throws IOException;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/StatePoolWriter.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:27 PST by lamport  
//      modified on Thu Feb  8 23:31:49 PST 2001 by yuanyu   

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCState;
import tlc2.value.ValueOutputStream;
import util.Assert;

public class StatePoolWriter extends Thread {

    private TLCState[] buf;     
    private File poolFile;           // the file to be written
    private StatePoolReader reader;  // the consumer if not null

    
  public StatePoolWriter(int bufSize) {
	  this(bufSize, null);
  }

  public StatePoolWriter(int bufSize, StatePoolReader reader) {
	  super("TLCStatePoolWriter");
    this.buf = new TLCState[bufSize];
    this.poolFile = null;
    this.reader = reader;
  }

  /*
   * This method first completes the preceding write if not started.
   * It then notifies this writer to flush enqBuf to file. In practice,
   * we expect the preceding write to have been completed. 
   */
  public final synchronized TLCState[] doWork(TLCState[] enqBuf, File file)
  throws IOException {
    if (this.poolFile != null) {
      ValueOutputStream vos = new ValueOutputStream(this.poolFile);
      for (int i = 0; i < this.buf.length; i++) {
	this.buf[i].write(vos);
      }
      vos.close();
    }
    TLCState[] res = this.buf;
    this.buf = enqBuf;
    this.poolFile = file;
    this.notify();
    return res;
  }

  /* Spin waiting for the write to complete.  */
  public final void ensureWritten() throws InterruptedException {
    synchronized(this) {
      while (this.poolFile != null) {
	this.wait();
      }
    }
  }

  public final synchronized void beginChkpt(ObjectOutputStream oos)
  throws IOException {
    boolean hasFile = (this.poolFile == null) ? false : true;
    oos.writeBoolean(hasFile);
    if (hasFile) {
      oos.writeObject(this.poolFile);
      for (int i = 0; i < this.buf.length; i++) {
	oos.writeObject(this.buf[i]);
      }
    }
  }

  /* Note this method is not synchronized.  */
  public final void recover(ObjectInputStream ois) throws IOException {    
    boolean hasFile = ois.readBoolean();
    if (hasFile) {
      try {
	this.poolFile = (File)ois.readObject();
	for (int i = 0; i < this.buf.length; i++) {
	  this.buf[i] = (TLCState)ois.readObject();
	}
      }
      catch (ClassNotFoundException e) 
      {
          Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e);
      }
    }
    else {
      this.poolFile = null;
    }
  }

  /**
   * Write "buf" to "poolFile". The objects in the queue are written
   * using Java's object serialization facilities.
   */
  public void run() {
    try {
      synchronized(this) {
	while (true) {
	  while (this.poolFile == null) {
	    this.wait();
	    // we are done without ever receiving a pool file
	    if(this.poolFile == null) {
	    	return;
	    }
	  }
	  ValueOutputStream vos = new ValueOutputStream(this.poolFile);
	  for (int i = 0; i < this.buf.length; i++) {
	    this.buf[i].write(vos);
	  }
	  vos.close();
	  this.poolFile = null;
	  this.notify();
	  if (this.reader != null) this.reader.wakeup();
	}
      }
    }
    catch (Exception e) {
      // Assert.printStack(e);
        MP.printError(EC.SYSTEM_ERROR_WRITING_POOL, e.getMessage(), e);
      System.exit(1);
    }
  }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/REPLTest.java<|end_filename|>
package tlc2;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class REPLTest {

    @Test
    public void testProcessInput() throws IOException {
        Path tempDir = Files.createTempDirectory("repltest");
        final REPL repl = new REPL(tempDir);
        String res;

        // Numeric expressions.
        res = repl.processInput("2+2");
        assertEquals("4", res);
        res = repl.processInput("4-2");
        assertEquals("2", res);
        res = repl.processInput("10 \\div 2");
        assertEquals("5", res);

        // Set expressions.
        res = repl.processInput("{1,2} \\X {3,4}");
        assertEquals("{<<1, 3>>, <<1, 4>>, <<2, 3>>, <<2, 4>>}", res);
        res = repl.processInput("{1,2} \\cup {3,4}");
        assertEquals("{1, 2, 3, 4}", res);
        res = repl.processInput("{1,2} \\cap {2,3}");
        assertEquals("{2}", res);

        // Tuple expressions.
        res = repl.processInput("Append(<<1,2>>, 3)");
        assertEquals("<<1, 2, 3>>", res);
        res = repl.processInput("Append(3, <<1,2>>)"); // error.
        assertEquals("", res);
        res = repl.processInput("Tail(<<1,2,3>>)");
        assertEquals("<<2, 3>>", res);
        res = repl.processInput("Head(<<1,2,3>>)");
        assertEquals("1", res);
        res = repl.processInput("<<1,2>> \\o <<3>>");
        assertEquals("<<1, 2, 3>>", res);

        // Other invalid expressions.
        res = repl.processInput("invalid");
        assertEquals("", res);
        res = repl.processInput("123abc");
        assertEquals("", res);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/model/TraceExpressionInformationHolder.java<|end_filename|>
package tlc2.model;

import java.util.List;

import tlc2.output.SpecWriterUtilities;
import util.TLAConstants;

/**
 * A container class for the relevant information about a
 * trace explorer expression. This class contains the expression,
 * the identifier which is defined to be the expression, the variable
 * that is declared for this expression, and the level of the expression.
 * 
 * @author <NAME>
 *
 */
public class TraceExpressionInformationHolder {
	/**
	 * @param expressions
	 * @param attributeName
	 * @return expressions.size() instances of {@code TraceExpressionInformationHolder}
	 */
	public static TraceExpressionInformationHolder[] createHolders(final List<Formula> expressions, final String attributeName) {
		final TraceExpressionInformationHolder[] holders = new TraceExpressionInformationHolder[expressions.size()];
	    int position = 0;
	    for (final Formula formula : expressions) {
			final String expression = formula.getFormula();
	
			if ((expression != null) && (expression.length() > 0)) {
	        	final String identifier
	        			= SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.TRACE_EXPR_DEF_SCHEME);
	        	if (formula.isNamed()) {
	        		final String varname = formula.getLeftHandSide();
	        		final String rightHandSide = formula.getRightHandSide();
					holders[position] = new TraceExpressionInformationHolder(rightHandSide, identifier, varname);
	        	} else  {
	        		final String varname
	        				= SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.TRACE_EXPR_VAR_SCHEME);
	        		holders[position] = new TraceExpressionInformationHolder(expression, identifier, varname);
	        	}
	        }
	
	        position++;
	    }
	    
	    return holders;
	}

	
    /*
     * The expression that the user wants to be evaluated at every
     * state of the trace. 
     */
    private String expression;
    /*
     * The identifier that is defined to be the expression.
     */
    private String identifier;
    /*
     * The variable name that is declared for this expression.
     */
    private String variableName;
    /*
     * The level of the trace expression
     */
    private int level;

    public void setExpression(String expression)
    {
        this.expression = expression;
    }

    public void setIdentifier(String identifier)
    {
        this.identifier = identifier;
    }

    public void setVariableName(String variableName)
    {
        this.variableName = variableName;
    }

    public void setLevel(int level)
    {
        this.level = level;
    }

    public TraceExpressionInformationHolder(String expression, String identifier, String variableName)
    {
        this.expression = expression;
        this.identifier = identifier;
        this.variableName = variableName;
    }

    public String getExpression()
    {
        return expression;
    }

    public String getIdentifier()
    {
        return identifier;
    }

    public String getVariableName()
    {
        return variableName;
    }

    public int getLevel()
    {
        return level;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/source/TLAPMOutputSourceRegistry.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.source;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IPath;

/**
 * Note that this class is not used. I originally created it
 * to copy the model of parsing and storing TLC's output, but we
 * have decided that for now there is no need to cache the output of
 * the prover. The parser installs markers on the appropriate resources
 * based on the output it receives. It does not need to use this registry.
 * 
 * This is a singleton registry for output from the TLAPM.
 * 
 * Listeners can register themselves to receive output by calling
 * {@link TLAPMOutputSourceRegistry#addListener(ITLAPMOutputSourceListener)}.
 * Listeners that add themselves will receive all output from the most recently
 * added {@link ITLAPMOutputSource} for which {@link ITLAPMOutputSource#getFullModulePath()}
 * is equal to {@link ITLAPMOutputSourceListener#getFullModulePath()} for equality
 * computed by {@link IPath#equals(Object)}. Such a listener will also receive all future output
 * for all {@link ITLAPMOutputSource} that also meet that condition and are added to this
 * registry after the listener is added.
 * 
 * Sources implementing {@link ITLAPMOutputSource} add themselves to the registry
 * by calling {@link TLAPMOutputSourceRegistry#addSource(ITLAPMOutputSource)}.
 * 
 * The singleton instance of this class can be accessed using {@link TLAPMOutputSourceRegistry#getInstance()}.
 * 
 * @author <NAME>
 *
 */
public class TLAPMOutputSourceRegistry
{
    // singleton instance
    private static TLAPMOutputSourceRegistry instance;

    /**
     * Container for sources, hashed by {@link IPath} pointing
     * to module for that source.
     */
    private HashMap sources;

    /**
     * Map of {@link IPath} for modules to {@link List} of
     * {@link ITLAPMOutputSourceListener} for listeners
     * that have not yet been added to a source because
     * there has not been an appropriate source added to this
     * registry.
     */
    private HashMap listenerLists;

    /**
     * Adds a source to this registry. This source will replace the most
     * recently added source such that
     * 
     * existingSource.getFullModulePath().equals(newSource.getFullModulePath()).
     * 
     * @param source
     */
    public void addSource(ITLAPMOutputSource source)
    {
        /*
         * Get all listeners that should be attached to the new source.
         * 
         * First, check if there is an existing source with listeners. If not,
         * check if there are listeners that have been added but not been connected
         * to a source.
         */
        ITLAPMOutputSource existingSource = (ITLAPMOutputSource) sources.get(source.getFullModulePath());
        if (existingSource != null)
        {
            ITLAPMOutputSourceListener[] existingListeners = existingSource.getListeners();
            for (int i = 0; i < existingListeners.length; i++)
            {
                source.addListener(existingListeners[i]);
                existingSource.removeListener(existingListeners[i]);
            }
        } else
        {

            // get listeners that have not yet been added to a source
            List list = (List) listenerLists.get(source.getFullModulePath());
            if (list != null)
            {
                for (Iterator it = list.iterator(); it.hasNext();)
                {
                    source.addListener((ITLAPMOutputSourceListener) it.next());
                    it.remove();
                }
            }
        }

        // replace the existing source, if any, with the new source
        sources.put(source.getFullModulePath(), source);
    }

    /**
     * Registers the listener.
     * 
     * Listeners that add themselves will receive all output from the most recently
     * added {@link ITLAPMOutputSource} for which {@link ITLAPMOutputSource#getFullModulePath()}
     * is equal to {@link ITLAPMOutputSourceListener#getFullModulePath()} for equality
     * computed by {@link IPath#equals(Object)}. Such a listener will also receive all future output
     * for all {@link ITLAPMOutputSource} that also meet that condition and are added to this
     * registry after the listener is added.
     * 
     * @param listener
     */
    public void addListener(ITLAPMOutputSourceListener listener)
    {

        /*
         * First, check if there is an existing source to which
         * the listener should be connected. If not, add the listener
         * to the list of listeners that will be connected to a source
         * when an appropriate one is added.
         */
        ITLAPMOutputSource source = (ITLAPMOutputSource) sources.get(listener.getFullModulePath());
        if (source != null)
        {
            source.addListener(listener);
        } else
        {
            List list = (List) listenerLists.get(listener.getFullModulePath());
            if (list == null)
            {
                list = new LinkedList();
            }

            list.add(listener);
            listenerLists.put(listener.getFullModulePath(), list);
        }
    }

    /**
     * Removes the listener from any source to which it is listening and removes
     * it from listening to any sources added in the future.
     * 
     * Does nothing if the listener has not been added using {@link TLAPMOutputSourceRegistry#addListener(ITLAPMOutputSourceListener)}.
     * 
     * @param listener
     */
    public void removeListener(ITLAPMOutputSourceListener listener)
    {
        /*
         * First, try to remove the listener from a source.
         * If no source is found, remove the listener from
         * listenerLists.
         */
        ITLAPMOutputSource source = (ITLAPMOutputSource) sources.get(listener.getFullModulePath());
        if (source != null)
        {
            source.removeListener(listener);
        } else
        {
            List list = (List) listenerLists.get(listener.getFullModulePath());
            if (list != null)
            {
                list.remove(listener);
            }
        }
    }

    private TLAPMOutputSourceRegistry()
    {
        sources = new HashMap();
        listenerLists = new HashMap();
    }

    /**
     * Singleton access method.
     * @return
     */
    public static TLAPMOutputSourceRegistry getInstance()
    {
        if (instance == null)
        {
            instance = new TLAPMOutputSourceRegistry();
        }

        return instance;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/OpenFileManager.java<|end_filename|>
// Copyright (c) Dec 08, 2016 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.ui.handler.NewSpecHandler;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;
import org.lamport.tla.toolbox.util.UIHelper;

@SuppressWarnings("restriction")
public class OpenFileManager implements Listener {
	
	@PostContextCreate
	void postContextCreate(final IApplicationContext appContext, final Display display, final IEventBroker broker) {
		// postContextCreate is registered as a LifeCycle listener via
		// ../org.lamport.tla.toolbox.product.standalone/plugin.xml. When it is
		// called, the Eclipse workbench has not been created yet. Thus, we
		// register with the IEventBroker to be notified once the workbench is
		// there. We then spawn a Runnable to let the Toolbox UI fully come up
		// before we call the open/new handler.
		broker.subscribe(UIEvents.UILifeCycle.ACTIVATE, new org.osgi.service.event.EventHandler() {
			/* (non-Javadoc)
			 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
			 */
			public void handleEvent(org.osgi.service.event.Event event) {
				// We do not want to be called again.
				broker.unsubscribe(this);
				
				UIHelper.runUIAsync(new Runnable() {
					public void run() {
						final Object argObject = appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS);
						if (argObject != null && argObject instanceof String[]) {
							final String[] args = (String[]) argObject;
							if (args.length > 0) {
								openOrCreateSpec(args[0]);
							}
						} else if (argObject != null && argObject instanceof String) {
							openOrCreateSpec((String) argObject);
						}
						
						// After we have handled the file parameter with which
						// the Toolbox got started, we now registered for
						// subsequent file open calls, see handleEvent(Event).
						display.addListener(SWT.OpenDocument, OpenFileManager.this);
					}
				});
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
	 */
	public void handleEvent(Event event) {
		final String absolutePath = event.text;
		if (absolutePath != null) {
			openOrCreateSpec(absolutePath);
		}
	}
	
	private void openOrCreateSpec(final String file) {
		// Convert relative file to absolute one if necessary.
		File absoluteFile = new File(file);
		if (!absoluteFile.isAbsolute()) {
			final String absolutePath = new File(".").getAbsolutePath();
			absoluteFile = new File(absolutePath + File.separator + file);
		}
		
		if (absoluteFile.exists() && absoluteFile.isFile()) {
			final Map<String, String> parameters = new HashMap<String, String>();

			// Try to find the corresponding spec.
			final WorkspaceSpecManager specManager = Activator.getSpecManager();
			final Spec spec = specManager.getSpecByRootModule(absoluteFile.getAbsolutePath());
			
			if (spec != null) {
				if (!spec.isCurrentSpec()) {
					// Open the spec unless it is already open.
					parameters.put(OpenSpecHandler.PARAM_SPEC, spec.getName());
					UIHelper.runCommand(OpenSpecHandler.COMMAND_ID, parameters);
				}
			} else {
				// Prompt the user to add a new spec.
				parameters.put(NewSpecHandler.PARAM_PATH, absoluteFile.getAbsolutePath());
				UIHelper.runCommand(NewSpecHandler.COMMAND_ID, parameters);
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TagBasedTLCOutputIncrementalParser.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentPartitioningChangedEvent;
import org.eclipse.jface.text.DocumentRewriteSessionType;
import org.eclipse.jface.text.GapTextStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IDocumentPartitioningListener;
import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextStore;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * Incremental parser based on TLC output in tags.
 * 
 * Implementation:
 * When instantiated, this parser creates an {@link IDocument}.
 * As text streams in, it is appended to the end of this document.
 * 
 * Attached to the document is an {@link IDocumentPartitioner}
 * and a {@link IDocumentPartitioningListener}. The partitioner
 * breaks the document into partitions based on the rules defined in
 * the class {@link TagBasedTLCOutputTokenScanner}. Currently,
 * a partition is a line containing a start tag, a line containing an
 * end tag, or any single character not in one of those lines. So
 * consider the following document:
 * 
 * @!@!@STARTMSG 2221:0 @!@!@
 * example
 * @!@!@ENDMSG 2221 @!@!@
 * 
 * The partitions would be the {@link IRegion} describing the line
 * containing "@!@!@STARTMSG 2221:0 @!@!@", an {@link IRegion} for each
 * character in "example", and an {@link IRegion} describing the line
 * containing "@!@!@ENDMSG 2221 @!@!@".
 * 
 * As text is appended to the document, the partitioning changes. The
 * {@link IDocumentPartitioningListener} attached to the document is notified
 * of these changes.
 * 
 * The {@link IDocumentPartitioningListener} used is {@link TLCOutputPartitionChangeListener}.
 * The method {@link TLCOutputPartitionChangeListener#documentPartitioningChanged(DocumentPartitioningChangedEvent)}
 * does the work in analyzing the partitions. See that method for the implementation.
 * 
 * @author <NAME>
 */
public class TagBasedTLCOutputIncrementalParser
{
	
	/**
	 * In batch mode, all lines are added to the document before the parser
	 * begins its work (see TLCOutputPartitionChangeListener). This is i.e.
	 * useful where an existing log file is processed. Conversely, incremental
	 * mode parses each line immediately when added via addIncrement/addLine.
	 * This mode should be used when {@link TagBasedTLCOutputIncrementalParser}
	 * is attached to a process sink/running TLC model checker and is supposed
	 * to show its progress.
	 */
	public enum Mode {
		BATCH, INCREMENTAL;
	}
	
    /**
     * The offset of the end of the last
     * start or end tag seen by the previous run of
     * the method {@link TLCOutputPartitionChangeListener#documentPartitioningChanged(DocumentPartitioningChangedEvent)}.
     */
    private int lastPartitionEnd;
    private final TagBasedTLCAnalyzer analyzer;
    private final CachingTLCOutputSource source;
	private final Document document;

    /**
     * The listener interested in change of partitioning, which evaluates the partitioning and produces the TLCOutput (added to the source)
     */
    class TLCOutputPartitionChangeListener implements IDocumentPartitioningListener,
            IDocumentPartitioningListenerExtension2
    {
		private final Mode mode;

		public TLCOutputPartitionChangeListener(Mode mode) {
			this.mode = mode;
		}

		/* (non-Javadoc)
         * @see org.eclipse.jface.text.IDocumentPartitioningListener#documentPartitioningChanged(org.eclipse.jface.text.IDocument)
         */
        public void documentPartitioningChanged(IDocument document)
        {
        }

        /**
         * Does the work in analyzing partitions to send output to the source.
         */
        public void documentPartitioningChanged(DocumentPartitioningChangedEvent event)
        {
            /*
             * Implementation:
             * 
             * For the purposes of this method, the parser maintains lastPartitionEnd and analyzer.
             * These are explained below:
             * 
             * -lastPartitionEnd, which represents the offset of the end of the last
             *  start or end tag seen by the previous run of this method. Initially,
             *  lastPartitionEnd = 0.
             * 
             * -TagBasedTLCAnalyzer. The analyzer maintains a stack
             *  of start and end tags and a list of partitions that are not
             *  start or end tags. The regions that are not start or end
             *  tags are called user regions. Whenever the stack is put in a state
             *  such that all start tags have a matching end tag, this should mean
             *  that there is one pair of start and end tags on the stack that contains
             *  all other start and end tags. At this point, the analyzer clears the stack
             *  and creates a region describing the pair of tags that encloses all others.
             *  This region can be obtained by calling analyzer.getTaggedRegion(). The analyzer
             *  should only clear the stack when the previous condition is true.
             * 
             * Take the following steps when this method is called:
             * 
             * 1.) Compute partitions from lastPartitionEnd to the end
             *     of the region described by event.getCoverage().
             * 2.) Clear the analyzer's list of user regions.
             * 3.) Once a portion of the document is sent to the source in
             *     the appropriate form, it should be removed from the document.
             *     This removal occurs in step 6. For this purpose, we have an
             *     integer, offsetToRemove, that initially equals 0.
             * 4.) For each partition computed in step (1), perform the following:
             *         IF (partition is a start or end tag)
             *            -IF (end of partition is greater than lastPartitionEnd)
             *                -lastPartitionEnd = end of partition
             *             END IF
             *         
             *             IF (partition is a start tag)
             *                -IF (stack is empty and list of user regions is not empty)
             *                    -merge user regions into one region and pass to source
             *                -push start tag on analyzer's stack
             *             ELSE IF (partition is an end tag)
             *                -push on analyzer's stack
             *                -IF (the analyzer's stack is empty)
             *                    -see the note towards the beginning of these
             *                     comments on how this is possible
             *                    -send a region describing the containing pair of tags
             *                     that were just removed from the analyzer's stack
             *                     to the source
             *                END IF
             *             END IF
             *             
             *         ELSE
             *            -add to analyzer's list of user regions
             *            
             *         END IF
             *         
             * 5.) IF (analyzer's stack is empty)
             *            -offsetToRemove = lastPartitionEnd
             *            -lastPartitionEnd = 0
             *     END IF
             *          
             * 6.) Remove everything in the document from the beginning to offsetToRemove if offsetToRemove > 0.
             * 
             * Note that it is possible for there to be a moment where the document does not end
             * with an end tag. In other words, this parser can receive incomplete messages. This requires
             * maintaining the lastPartitionEnd field so that the same start tag is not pushed onto the analyzer's
             * stack multiple times. The field lastPartitionEnd gives the end of the last partition that
             * is a start or end tags. It is not necessary to maintain the location of user regions because
             * they are reset in step (2).
             * 
             * We remove text from the document only when the analyzer's stack is empty (step 5). This is for the
             * following reason. The analyzer's stack contains regions that point to locations in the document.
             * They point to locations using an offset and length. The offset and length of a given region do
             * not change when the document changes. Therefore, we only want to modify the document once there
             * are no regions that need to access their locations in the document. When a region is sent to the
             * source, it no longer needs to access its location in the document because it is sent to the source
             * along with the contents of the message that it represents. However, when a region is stored in the
             * analyzer's stack, it is not stored with the contents of the message it represents, so it still
             * needs to access the document before being sent to the source. User regions are reset with
             * every call of this method, so text can be removed from the document at the end of this method
             * even if the list of regions in the analyzer is not empty.
             * 
             * 
             *             
             */

            IDocument document = event.getDocument();

            try
            {
                IRegion changedRegion = event.getCoverage();
                IDocumentPartitioner partitioner = document.getDocumentPartitioner();

                // read the new partitioning information (Step 1)
                ITypedRegion[] regions = partitioner.computePartitioning(lastPartitionEnd, changedRegion.getOffset()
                        + changedRegion.getLength() - lastPartitionEnd);

                // iterate partitions and look for the last
                // non-default (user-output) partition

                // Step 2
                analyzer.resetUserPartitions();

                // Step 3
                int offsetToRemove = 0;

                // Step 4
                for (int i = 0; i < regions.length; i++)
                {
                    // looking for non-default content type
                    if (!TagBasedTLCOutputTokenScanner.DEFAULT_CONTENT_TYPE.equals(regions[i].getType()))
                    {
                        // typed partition detected
                        int currentPartitionEnd = regions[i].getOffset() + regions[i].getLength();
                        if (currentPartitionEnd > lastPartitionEnd)
                        {
                            lastPartitionEnd = currentPartitionEnd;
                        }

                        if (TagBasedTLCOutputTokenScanner.TAG_OPEN.equals(regions[i].getType()))
                        {
                            // user partitions found, which are not belonging to the tag.
                            if (analyzer.hasUserPartitions() && !analyzer.inTag())
                            {
                                ITypedRegion mergedPartition = analyzer.getUserRegion();
                                source.onOutput(mergedPartition, document.get(mergedPartition.getOffset(),
                                        mergedPartition.getLength()));
                                // debugging
                                // PartitionToolkit.printPartition(mergedPartition, document);
                            }

                            // START_TAG
                            // just add the partition to the analyzer
                            analyzer.addTagStart(regions[i]);
                        } else if (TagBasedTLCOutputTokenScanner.TAG_CLOSED.equals(regions[i].getType()))
                        {
                            // END TAG
                            // if the end is detected, everything between the start and
                            // the end are merged to a single tag
                            analyzer.addTagEnd(regions[i]);

                            // only if there are no nested tags, retrieve the tag, else,
                            // wait until the nesting tag is closed
                            if (!analyzer.inTag())
                            {
                                ITypedRegion tag = analyzer.getTaggedRegion();

                                // add the typed coverage region
                                source.onOutput(tag, document.get(tag.getOffset(), tag.getLength()));
                            }
                        } else
                        {
                            // if the type is not default and neither START nor END, this is a bug
                            Assert.isTrue(regions[i].getLength() == 0, "Parsing bug");
                        }
                    } else
                    {
                        // if the partition has no type (default one), it is the user partition...
                        analyzer.addUserRegion(regions[i]);
                    }
                }

                // Step 5
                if (!analyzer.inTag())
                {
                    offsetToRemove = lastPartitionEnd;
                    lastPartitionEnd = 0;
                }

                // Step 6
                if (mode == Mode.INCREMENTAL && offsetToRemove > 0)
                {
					// if mode is BATCH, this call would just replace the
					// Documents complete contents wrapped in several
					// categories. Since we are going to throw the Document away
					// anyway, there is no point in removing categories.
					// Removing categories takes a long time because the
					// implementation isn't meant for a huge number of
					// categories.
                    document.replace(0, offsetToRemove, "");
                }
            } catch (BadLocationException e)
            {
                TLCUIActivator.getDefault().logError("Error removing text or retrieving text from the parser's document."
                        + "This is a bug.", e);
            }
        }
    }

    /**
     * Constructs the parser
     * @param name
     * @param prio
     * @param isTraceExplorer TODO
     */
    public TagBasedTLCOutputIncrementalParser(Model model, int prio, boolean isTraceExplorer) {
    	this(model, prio, isTraceExplorer, Mode.INCREMENTAL, LargeTextStoreDocument.SIZE_UNKNOWN);
    }
    
    public TagBasedTLCOutputIncrementalParser(Model model, int prio, boolean isTraceExplorer, Mode mode, final long size)
    {
		// create the document
        document = new LargeTextStoreDocument(size);

        this.analyzer = new TagBasedTLCAnalyzer(document);
        this.source = new CachingTLCOutputSource(model, prio);

        // set up the partitioner
        FastPartitioner partitioner = new FastPartitioner(new TagBasedTLCOutputTokenScanner(),
                TagBasedTLCOutputTokenScanner.CONTENT_TYPES);
        partitioner.connect(document);
        document.setDocumentPartitioner(partitioner);
        

        // now register the listener, responsible for evaluating the partitioning information
        document.addDocumentPartitioningListener(new TLCOutputPartitionChangeListener(mode));

        /*
         *  Register the process source
         *  
         *  There are two different source registries, one for trace exploration
         *  and one for model checking. The source must be added to the
         *  appropriate registry.
         */
        if (isTraceExplorer)
        {
            TLCOutputSourceRegistry.getTraceExploreSourceRegistry().addTLCOutputSource(this.source);
        } else
        {
        	if (mode == Mode.BATCH) {
        		// TLC always appends to the document. Therefore, we can tell the
        		// document to use a more efficient rewrite mode which reduces the time
        		// taken to execute replace operations from minutes and hours to
        		// seconds.
				// Its down side is that the ResultPage is only updated when the
				// complete log file is fully parsed, whereas in incremental
				// mode, it (potentially) updates after each line.
        		document.startRewriteSession(DocumentRewriteSessionType.STRICTLY_SEQUENTIAL);
        	}
        	
            TLCOutputSourceRegistry.getModelCheckSourceRegistry().addTLCOutputSource(this.source);
        }
    }

    /**
     * add the increment
     * 
     * The argument should be a relatively short string, i.e. no more
     * than what TLC prints out in a single instant.
     * 
     * It is also better if when at least one TLC end tag is part
     * of the string passed to this method, the string terminates with
     * a TLC end tag.
     * 
     * @param text
     * @throws BadLocationException
     */
    public void addIncrement(String text) throws BadLocationException
    {
		// don't waste time, skip empty or new lines
		if (text == null || text.length() == 0 || text.equals("\n")) {
			return;
		} else if(text.charAt(text.length() - 1) != 10) { // 10 ascii for '\n'
			// e.g. when a model check gets interrupted
			throw new BadLocationException("Input does not end with newline: " + text);
			//text = text + (char) 10;
		}

		document.replace(document.getLength(), 0, text);
    }
    
    /**
	 * Contrary to addIncrement(String), this method does not verify that the
	 * input terminates with the newline separator. It is up to the caller to
	 * only provide valid input.
	 */
    public void addLine(String text) throws BadLocationException
    {
		// don't waste time, skip empty or new lines
		if (text == null || text.length() == 0 || text.equals("\n")) {
			return;
		}

		document.replace(document.getLength(), 0, text);
    }

	IDocument getDocument() {
		return document;
	}
	
	TagBasedTLCAnalyzer getTagAnalyzer() {
		return analyzer;
	}

    /**
     * Finish
     */
    public void done()
    {
		if (this.document.getActiveRewriteSession() != null) {
			this.document.stopRewriteSession(this.document.getActiveRewriteSession());
		}
        this.source.onDone();
    }

    /**
     * Return the source
     */
    public ITLCOutputSource getSource()
    {
        return this.source;
    }

	public void clear() throws BadLocationException {
		this.document.replace(0, this.document.getLength(), "");
		if (this.document.getActiveRewriteSession() != null) {
			this.document.stopRewriteSession(this.document.getActiveRewriteSession());
		}
	}

	/**
	 * {@link Document} targets source code documents of a few thousand lines.
	 * It quickly becomes inefficient for large inputs like e.g. a TLC log file
	 * can be.
	 * <p>
	 * {@link LargeTextStoreDocument} thus drastically increases the min and max
	 * sizes of the {@link Document}'s underlying {@link ITextStore}.
	 * Experiments revealed that this optimization significantly increases the
	 * {@link TagBasedTLCOutputIncrementalParser} performance.
	 * <p>
	 * As we know the size of the log file a-prior, the {@link ITextStore}'s
	 * internal storage can be sized up-front to match the input's size.
	 * <p>
	 * Generally though, it's stupid to keep the entire log file in memory. The
	 * *incremental* parser should rather discard seen content after processing
	 * to free memory right away. However, this is larger refactoring.
	 */
	private class LargeTextStoreDocument extends Document {
		
		public static final long SIZE_UNKNOWN = -1;
		
		public LargeTextStoreDocument(long size) {
			if (size != SIZE_UNKNOWN) {
				Assert.isLegal(size >= 0, "Negative file size");
				if (size > Integer.MAX_VALUE) {
					size = Integer.MAX_VALUE - 1;
				}
				setTextStore(new GapTextStore((int) size, (int) size + 1, 0.1f));
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.uitest/src/org/lamport/tla/toolbox/ui/wizard/AddSpecWizardTest.java<|end_filename|>
package org.lamport.tla.toolbox.ui.wizard;

import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withText;

import java.io.File;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
import org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory;
import org.eclipse.swtbot.swt.finder.waits.Conditions;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.ui.PlatformUI;
import org.hamcrest.Matcher;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.lamport.tla.toolbox.test.RCPTestSetupHelper;

@RunWith(SWTBotJunit4ClassRunner.class)
public class AddSpecWizardTest {

	private static SWTWorkbenchBot bot;

	@BeforeClass
	public static void beforeClass() throws Exception {
		RCPTestSetupHelper.beforeClass();
		
		// Force shell activation to counter, no active Shell when running SWTBot tests in Xvfb/Xvnc
		// see https://wiki.eclipse.org/SWTBot/Troubleshooting#No_active_Shell_when_running_SWTBot_tests_in_Xvfb
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().forceActive();
			}
		});
		
		bot = new SWTWorkbenchBot();

		// Wait for the Toolbox shell to be available
		final Matcher<Shell> withText = withText("TLA+ Toolbox");
		bot.waitUntil(Conditions.waitForShell(withText), 30000);
		
		// Wait for the Toolbox UI to be fully started.
		final Matcher<MenuItem> withMnemonic = WidgetMatcherFactory.withMnemonic("File");
		final Matcher<MenuItem> matcher = WidgetMatcherFactory.allOf(WidgetMatcherFactory.widgetOfType(MenuItem.class),
				withMnemonic);
		bot.waitUntil(Conditions.waitForMenu(bot.shell("TLA+ Toolbox"), matcher), 30000);
	}
	
	/**
	 * Test to make sure the "Add Spec" wizard does not accept invalid spec names
	 */
	@Test
	public void doNotAcceptInvalidSpecNames() {
		
		// Open specA 
		SWTBotMenu fileMenu = bot.menu("File");
		SWTBotMenu openSpecMenu = fileMenu.menu("Open Spec");
		SWTBotMenu addNewSpecMenu = openSpecMenu.menu("Add New Spec...");
		addNewSpecMenu.click();

		// get a handle for the button before invoking the UI (widget not found exception otherwise)
		SWTBotButton button = bot.button("Finish");
		
		// create a valid path
		String path = System.getProperty("java.io.tmpdir");
		path += File.separator + "Invalid-Name.tla";
		
		// set an invalid spec name
		bot.textWithLabel("Root-module file:").setText(path);
		
		// check if the wizard can finish
		Assert.assertTrue(
				"Finish button must not be enabled with invalid spec name",
				!button.isEnabled());
		
		//TODO could change the wizard marker/error area for the correct string too
	}

	@AfterClass
	public static void sleep() {
		bot.sleep(2000);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/source/CachingTLAPMOutputSource.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.source;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.eclipse.core.runtime.IPath;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.TLAPMMessage;

/**
 * Caches parsed output data from the TLAPM for use
 * by listeners that may not register until after this
 * source has received the data.
 * 
 * @author <NAME>
 *
 */
public class CachingTLAPMOutputSource implements ITLAPMOutputSource
{
    /**
     * List of objects containing
     * {@link TLAPMMessage} output information.
     */
    private List outputData;
    /**
     * List of listeners registered to receive TLAPM
     * output information.
     */
    private Vector listeners;
    /**
     * The full path for which this source contains
     * output.
     */
    private IPath modulePath;
    /**
     * Flag indicating that this source is done
     * receiving data.
     */
    private boolean done = false;

    public CachingTLAPMOutputSource(IPath modulePath)
    {
        listeners = new Vector();
        outputData = new LinkedList();
        this.modulePath = modulePath;
    }

    public void newData(TLAPMMessage data)
    {
        // cache the data for listeners added later
        outputData.add(data);

        // inform existing listeners
        for (Iterator it = listeners.iterator(); it.hasNext();)
        {
            ITLAPMOutputSourceListener listener = (ITLAPMOutputSourceListener) it.next();
            listener.newData(data);
        }
    }

    /**
     * Adds the listener to the list of listeners
     * to be notified of new data and informs the listener
     * of all existing data.
     * 
     * Does nothing if the listener is already connected
     * to this source.
     */
    public void addListener(ITLAPMOutputSourceListener listener)
    {
        if (!listeners.contains(listener))
        {
            listeners.add(listener);

            // inform the listener of data that has
            // already been added
            for (Iterator it = outputData.iterator(); it.hasNext();)
            {
                listener.newData((TLAPMMessage) it.next());
            }
        }
    }

    public IPath getFullModulePath()
    {
        return modulePath;
    }

    public ITLAPMOutputSourceListener[] getListeners()
    {
        return (ITLAPMOutputSourceListener[]) listeners.toArray(new ITLAPMOutputSourceListener[listeners.size()]);
    }

    public void removeListener(ITLAPMOutputSourceListener listener)
    {
        listeners.remove(listener);
    }

    public void onDone()
    {
        done = true;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test-model/UserModuleOverride.java<|end_filename|>
import tlc2.value.impl.BoolValue;
import tlc2.value.impl.Value;

// manually compiled with Java 1.8
public class UserModuleOverride {
    public static Value Get() {
        return BoolValue.ValTrue;
    }

    public static Value Get2(Value v1) {
        return BoolValue.ValFalse;
    }


    public static Value Get3() {
        return BoolValue.ValFalse;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools.consumer.distributed/src/org/lamport/tla/distributed/consumer/faulty/FaultyTLCWorkerConsumer.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.distributed.consumer.faulty;

import java.net.URI;

import tlc2.ITLCWorker;

/**
 * @author <NAME>
 * 
 * <p> If DS does not pass an ITLCWorker, make sure that: 
 *  <ul>
 *   <li>The DS framework (org.eclipse.equinox.ds) is installed in active</li>
 *   <li>org.lamport.tlatools.impl.distributed is installed and active</li>
 *  </ul>
 * </p>
 */
public class FaultyTLCWorkerConsumer extends FaultyConsumer {

	/**
	 * TLCServer address to connect to.
	 * 
	 * //TODO refactor to read/obtain URI from ECF discovery
	 * //TODO port number currently hard coded in TLCServer/TLCWorker 
	 */
	private final URI uri = URI
			.create(System.getProperty(FaultyTLCWorkerConsumer.class.getName()
					+ ".uri", "rmi://localhost:10997"));

	/**
	 * @see OSGi-INF/component.xml
	 * @param anITLCWorker
	 *            passed by OSGi Declarative Services
	 */
	public void setITLCWorker(final ITLCWorker anITLCWorker) {
		// Fork out to a separate thread to not block the DeclarativeService forever
		executor.execute(new Runnable() {

			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {

				while(true) {

					// connect and wait for some states to be calculated (for three minutes max)
					anITLCWorker.connect(uri);
					long seconds = sleep();
					
					// disconnect from server and sleep before reconnecting again 
					System.err.println("Forcefully disconnecting TLCWorkers from TLCServer after " + seconds + "s" + "\n\n");
					anITLCWorker.disconnect();
					sleep();
				}
			}
		});
	}

	/**
	 * @see OSGi-INF/component.xml
	 * @param anITLCWorker passed by OSGi Declarative Services
	 */
	public void unsetITLCWorker(final ITLCWorker anITLCWorker) {
		anITLCWorker.disconnect();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/handler/AbstractPDFViewerRunnable.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.toolbox.tool.tla2tex.handler;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.tool.tla2tex.TLA2TeXActivator;
import org.lamport.tla.toolbox.tool.tla2tex.preference.ITLA2TeXPreferenceConstants;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

public abstract class AbstractPDFViewerRunnable  implements EventHandler, IPartListener, Runnable {

	protected IFile outputFile;
	protected IProgressMonitor monitor;
	protected String outputFileName;
	
	private final ProducePDFHandler handler;
	protected final IResource specFile;
	protected IWorkbenchPart part;
	
	public AbstractPDFViewerRunnable(ProducePDFHandler handler, IWorkbenchPartSite site, IResource aSpecFile) {
		Assert.isNotNull(handler);
		Assert.isNotNull(site);
		Assert.isNotNull(aSpecFile);
		this.handler = handler;
		this.specFile = aSpecFile;
		
		final boolean autoRegenerate = TLA2TeXActivator.getDefault().getPreferenceStore()
				.getBoolean(ITLA2TeXPreferenceConstants.AUTO_REGENERATE);
		if (autoRegenerate) {
			// Subscribe to the event bus with which the TLA Editor save events are
			// distributed. In other words, every time the user saves a spec, we
			// receive an event and provided the spec corresponds to this PDF, we
			// regenerate it.
			// Don't subscribe in EmbeddedPDFViewerRunnable#though, because it is run
			// repeatedly and thus would cause us to subscribe multiple times.
			final IEventBroker eventService = site.getService(IEventBroker.class);
			Assert.isTrue(eventService.subscribe(TLAEditor.SAVE_EVENT, this));
			
			// Register for part close events to deregister the event handler
			// subscribed to the event bus. There is no point in regenerating
			// the PDF if no PDFEditor is open anymore.
			final IPartService partService = site.getService(IPartService.class);
			partService.addPartListener(this);
		}
	}

	public void setFile(String outputFileName) throws CoreException {
        this.outputFileName = outputFileName;
		this.outputFile = (IFile) ResourceHelper.getResourceByName(outputFileName);
	}

	public void setMonitor(IProgressMonitor monitor) {
		this.monitor = monitor;
	}

	protected void preUpdate() {
		// No-op
	}
	
	/* EventHandler */
	
	/* (non-Javadoc)
	 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
	 */
	public void handleEvent(final Event event) {
		// Listen for TLAEditor/save to regenerate the PDF and refresh the
		// editor iff the event DATA corresponds to this.specFile. There might
		// be several PDFs open each responsible for a certain spec.
		if (TLAEditor.SAVE_EVENT.equals(event.getTopic())) {
			final Object property = event.getProperty(IEventBroker.DATA);
			if (property instanceof IFile && this.specFile.equals(property)) {
				preUpdate();
				handler.runPDFJob(this, specFile);
			}
		}
	}
	
	/* IPartListener */

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
	 */
	public void partClosed(IWorkbenchPart aPart) {
		// Listen for PDFEditor close events to de-register this event listener
		// from receiving further TLAEditor/save events. If the user closes the
		// PDFEditor, it implicitly means she's no longer interested in the PDF.
		if (aPart == part) {
			final IEventBroker service = aPart.getSite().getService(IEventBroker.class);
			service.unsubscribe(this);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
	 */
	public void partActivated(IWorkbenchPart part) {
		// no-op
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
	 */
	public void partBroughtToTop(IWorkbenchPart part) {
		// no-op
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
	 */
	public void partDeactivated(IWorkbenchPart part) {
		// no-op
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
	 */
	public void partOpened(IWorkbenchPart part) {
		// no-op
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ArgLevelParam.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

package tla2sany.semantic;

class ArgLevelParam {
  /*************************************************************************
  * ArgLevelParam objects are used only to implement the elements of the   *
  * set of that name in the specification LevelSpec.tla of level           *
  * checking.  If the ArgLevelParam object alp is in the HashSet of        *
  * objects returned by getArgLevelParams for an expression, then the      *
  * operator alp.op appears somewhere in the expression as a               *
  * subexpression alp.op(...)  in which the alp.i-th argument's level      *
  * depends on the parameter alp.param of the current context.             *
  *************************************************************************/
  SymbolNode op;
  int        i;
  SymbolNode param;

  /* Creates new ArgLevelParam */
  public ArgLevelParam(SymbolNode op, int i, SymbolNode param) {
    this.op = op;
    this.i = i;
    this.param = param;
  }

  public final boolean occur(SymbolNode[] symbols) {
    for (int i = 0; i < symbols.length; i++) {
      if (this.op == symbols[i] ||
	  this.param == symbols[i]) {
	return true;
      }
    }
    return false;
  }

  public final boolean equals(Object obj) {
    if (obj instanceof ArgLevelParam) {
      ArgLevelParam alp = (ArgLevelParam)obj;
      return ((this.op == alp.op) &&
	      (this.i == alp.i) &&
	      (this.param == alp.param));
    }
    return false;
  }

  public final int hashCode() {
    return this.op.hashCode() + this.i + this.param.hashCode();
  }

  public final String toString() {
    return "<" + this.op + ", " + this.i + ", " + this.param + ">";
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jclouds/src/org/lamport/tla/toolbox/jcloud/Application.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2017 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.jcloud;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Properties;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.lamport.tla.toolbox.tool.tlc.job.ITLCJobStatus;
import org.lamport.tla.toolbox.tool.tlc.job.TLCJobFactory;

import tlc2.TLCGlobals;
import util.ExecutionStatisticsCollector;

public class Application implements IApplication {

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
	 */
	public Object start(IApplicationContext context) throws Exception {
		Object argObject = context.getArguments().get(
				IApplicationContext.APPLICATION_ARGS);
		if (argObject == null || !(argObject instanceof String[]) || ((String[]) argObject).length < 1) {
			//TODO print usage
			System.exit(1);
		}
		
		final String[] args = (String[]) argObject;
		final String modelDirectory = args[0];
		
		final Properties props = initializeFromFile(modelDirectory);
		// By default send mail to the root account (might be overwritten below).
		// Without specifying any email address, MailSender will not set up
		// /mnt/tlc/MC.out and most of CloudDistributedTLCJob's functionality will not
		// work (no TLC process output will be received).  Do not add if cloud.properties
		// file has defined it already.
		props.putIfAbsent(TLCJobFactory.MAIL_ADDRESS, "root@localhost");
		props.put(TLCJobFactory.MAIN_CLASS, tlc2.TLC.class.getName());
		
		final ExecutionStatisticsCollector udc = new ExecutionStatisticsCollector();
		if (udc.isEnabled()) {
			props.put(ExecutionStatisticsCollector.PROP, udc.getIdentifier());
		}

		// Optional parameters
		final String cloud = args.length >= 2 ? args[1] : "aws-ec2";

		if (args.length >= 3) {
			props.put(TLCJobFactory.MODEL_NAME, args[2]);
		}
		if (args.length >= 4) {
			props.put(TLCJobFactory.SPEC_NAME, args[3]);
		}
		if (args.length >= 5) {
			props.put(TLCJobFactory.MAIL_ADDRESS, args[4]);
		}

		// The parameters below are the only one currently useful with CloudDistributedTLC
		final StringBuffer tlcParams = new StringBuffer();
		
        // fp seed offset (decrease by one to map from [1, 64] interval to [0, 63] array address
        final int fpSeedOffset = 1;
        tlcParams.append("-fp ");
        tlcParams.append(String.valueOf(fpSeedOffset - 1));
    	tlcParams.append(" ");
        
        int maxSetSize = TLCGlobals.setBound;
		if (maxSetSize != TLCGlobals.setBound) {
        	tlcParams.append("-maxSetSize ");
        	tlcParams.append(String.valueOf(maxSetSize));
        	tlcParams.append(" ");
        }
        
		boolean checkDeadlock = false;
		if (!checkDeadlock) {
			tlcParams.append("-deadlock");
        	tlcParams.append(" ");
		}
		
		// https://github.com/tlaplus/tlaplus/issues/92#issuecomment-339989087
		final int coverage = Integer.getInteger("coverage", 0);
		if (coverage > 0) {
			tlcParams.append("-coverage ");
        	tlcParams.append(String.valueOf(coverage));
		}
		
		final boolean doJFR = Arrays.asList(args).contains("jfr");
		
		final TLCJobFactory factory = new CloudTLCJobFactory();
		final CloudDistributedTLCJob job = (CloudDistributedTLCJob) factory.getTLCJob(cloud, new File(modelDirectory), 1, props, tlcParams.toString());
		job.setIsCLI(true);
		job.setDoJfr(doJFR);
		final IStatus status = job.run(new MyProgressMonitor(9));
		// Show error message if any such as invalid credentials.
		if (status.getSeverity() == IStatus.ERROR || !(status instanceof ITLCJobStatus)) {
			System.err.println(status.getMessage());
			final Throwable exception = status.getException();
			if (exception instanceof CloudDistributedTLCJob.ScriptException) {
				System.err.printf("\n###############################\n\n%s\n###############################\n",
						exception.getMessage());
			}
			// Signal unsuccessful execution.
			return new Integer(1);
		}
		
		// If no error above, read the (remote) TLC process output (stdout, no stderr)
		// and print it on the local stdout.
		final InputStream output = ((ITLCJobStatus) status).getOutput();
		try {
			final BufferedReader in = new BufferedReader(
					new InputStreamReader(output));
			String line;
			while ((line = in.readLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			System.err.println(status.getMessage());
			// Signal unsuccessful execution.
			return new Integer(1);
		}
		
		if (doJFR) {
			((ITLCJobStatus) status).getJavaFlightRecording();
		}

		return IApplication.EXIT_OK;
	}

	private Properties initializeFromFile(final String modelDirectory) throws IOException, FileNotFoundException {
		final Properties props = new Properties();
		final File file = new File(modelDirectory + File.separator + "cloud.properties");
		if (file.exists()) {
			props.load(new FileInputStream(file));
		}
		return props;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.app.IApplication#stop()
	 */
	public void stop() {
		// cannot be stopped!
	}
	
	static class MyProgressMonitor implements IProgressMonitor {
		private final DateFormat formatter = new SimpleDateFormat( "YYYY-MM-dd HH:mm:ss.SSS" );
		private final int totalSteps;
		private int steps = 1;

		public MyProgressMonitor(int totalSteps) {
			this.totalSteps = totalSteps;
		}

		public void subTask(String str) {
			System.out.printf("%s (%s of %s): %s\n", formatter.format(new Date()), Integer.toString(steps),
					Integer.toString(totalSteps), str);
			steps++;
		}

		public void beginTask(String str, int totalWork) {
			subTask(str);
		}

		public void done() {}

		public void internalWorked(double work) {}

		public boolean isCanceled() {return false;}

		public void setCanceled(boolean value) {}

		public void setTaskName(String name) {}

		public void worked(int work) {}

		public void incSteps(int steps) {
			this.steps += steps;
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/evaluate-consant-expression.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/evaluate-constant-expression.html  -->


<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Evaluate Constant Expression</title>
</head>

<body>
<h1>Evaluate Constant Expression</h1>

<p>
This functionality may exist either constain on the Model Checking Results page of the Model
Editor, or on its own page, depending on how the user has configured the Toolbox
<a href="executing-tlc.html#preferences">via the preferences.</a>
</p>

<p>
Entering a constant expression in the <em>Expression</em>
field of this section, and selecting the toggle button above and to the right
of this field, will cause the value of
that expression to appear in the <em>Value</em> field when TLC is run.&nbsp;
The expression can use any constant operators defined or declared in
the spec or elsewhere in the model.&nbsp;
Used with the
<em><a href="overview-page.html#what-is-behavior">No behavior
spec</a></em> option on
the <a href="overview-page.html">Model Overview Page</a>, this
turns TLC into a mathematical calculator--one that computes arbitrary
TLA<sup>+</sup> expressions.
</p>
</body>
</html>


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/MultiThreadedLSBDiskFPSetTest.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.io.IOException;

public class MultiThreadedLSBDiskFPSetTest extends MultiThreadedFPSetTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.AbstractFPSetTest#getFPSet(long)
	 */
	@Override
	protected FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws IOException {
		fpSetConfig.setRatio(1.0d); // Tests can consume all of the available VM memory
		return new LSBDiskFPSet(fpSetConfig);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.uitest/src/org/lamport/tla/toolbox/test/RCPTestSetupHelper.java<|end_filename|>
package org.lamport.tla.toolbox.test;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.osgi.framework.Bundle;

/**
 * @see http://www.ralfebert.de/articles/swtbot/
 */
public abstract class RCPTestSetupHelper {

	public static String getAbsolutePath(final String bundle, final String fileInBundle) {
		final Bundle b = Platform.getBundle(bundle);
		final URL url = b.getEntry(fileInBundle);
		try {
			final URL resolved = FileLocator.resolve(url);
			final File f = new File(resolved.toURI());
			return f.getAbsolutePath();
		} catch (final IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void beforeClass() {
		UIThreadRunnable.syncExec(new VoidResult() {
			public void run() {
				resetWorkbench();
				resetToolbox();
				
				// close browser-based welcome screen (if open)
				SWTWorkbenchBot bot = new SWTWorkbenchBot();
				try {
					SWTBotView welcomeView = bot.viewByTitle("Welcome");
					welcomeView.close();
				} catch (WidgetNotFoundException e) {
					return;
				}
			}
		});
	}
	
    public static void afterClass() {
        UIThreadRunnable.syncExec(new VoidResult() {
            public void run() {
                resetWorkbench();
            }
        });
    }

    /**
     * Close all open windows, editors, perspectives. Open and reset default perspective.
     */
    private static void resetWorkbench() {
        try {
            IWorkbench workbench = PlatformUI.getWorkbench();
            IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
            IWorkbenchPage page = workbenchWindow.getActivePage();
            
            Shell activeShell = Display.getCurrent().getActiveShell();
            if (activeShell != null && activeShell != workbenchWindow.getShell()) {
                activeShell.close();
            }
            
            page.closeAllEditors(false);
            page.resetPerspective();
            
            String defaultPerspectiveId = workbench.getPerspectiveRegistry().getDefaultPerspective();
            workbench.showPerspective(defaultPerspectiveId, workbenchWindow);
            page.resetPerspective();
            
            page.showView("org.eclipse.ui.internal.introview");
        } catch (WorkbenchException e) {
            throw new RuntimeException(e);
        }
    }

	/**
	 * Removes all existing specs and models
	 */
	private static void resetToolbox() {
		final WorkspaceSpecManager specManager = Activator.getSpecManager();
		// assume recently opened specs means all existing specs :)
		final Spec[] specs = specManager.getRecentlyOpened();
		for (int i = 0; i < specs.length; i++) {
			specManager.removeSpec(specs[i], new NullProgressMonitor());
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ShowDeclarationsHandler.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.AnyDefNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpDeclNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolMatcher;
import tla2sany.semantic.SymbolNode;
import tla2sany.semantic.ThmOrAssumpDefNode;

/**
 * The handler for the Shows Declarations operation, which pops up a list
 * of top-level definitions and declarations of the module.  The popup has an
 * option of showing or hiding instantiated definitions--which includes all instantiations
 * that involve name changing or substitution of parameters.  It also allows the user
 * to type the prefix of what he's looking for, which does the appropriate filtering of
 * what's displayed.
 * 
 * Popping up the dialog is easy.  Handling typed input isn't.  The problem is that typing
 * ordinarily changes the selection, which triggers the selection listener's code for
 * jumping to the selected declaration.  Keeping this from happening required: (1) adding the
 * listeners in the right order so the key listener gets called first, (2) always keeping 
 * some item selected so typing doesn't necessarily cause an item to be selected, and 
 * (3) having the key listener disable other key listeners by the magical 
 * <code>e.doit = false</code> statement in it.
 * 
 * 
 * @author lamport
 *
 */
public class ShowDeclarationsHandler extends AbstractHandler implements IHandler
{

    /**  This method is called to handle the Show Declarations operation.
     * 
    * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
    */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        Shell parent = UIHelper.getShellProvider().getShell();
        ShowDeclarationsPopupDialog popup = new ShowDeclarationsPopupDialog(parent);
        popup.open();

        return null;
    }

    /**
     * The text for telling the user to choose hiding/showing instantiated definitions.
     * 
     * @param showAll
     * @return
     */
    public static String infoText(boolean showAll)
    {
        return "Type space to " + (showAll ? "hide" : "show") + " instantiated definitions";
    }

    /**
     * The text at the top of the popup.  It shows the prefix string typed if that's
     * not empty, otherwise just the standard title.
     * 
     * @param prefix
     * @return
     */
    public static String titleText(String prefix)
    {
        if (prefix == "")
        {
            return "Definitions and Declarations";
        } else
        {
            return prefix;
        }

    }

    /**
     * The class of which the pop dialog is an object.  It contains fields that the listeners
     * need to get hold of.
     * 
     * @author lamport
     */
    public static class ShowDeclarationsPopupDialog extends PopupDialog
    {
        Shell parent; // The dialog's parent shell.
        List list; // The org.eclipse.swt.widgets.List (not ordinary Java List) being displayed.
        boolean showAll = true; // True iff displaying definitions imported by instantiation.
        String filterPrefix = ""; // For filtering displayed declarations as user types prefix.

        /*
         * The TLA editor with focus and the module it's open on.  They are saved because the editor
         * no longer has focus when the popup dialog is raised.
         */
        TLAEditor editor;
        ModuleNode module;

        // int curSelection; // The currently selected item.

		private final SymbolMatcher.NameAndTypeMatcher matcher = new SymbolMatcher.NameAndTypeMatcher() {

			/* (non-Javadoc)
			 * @see tla2sany.semantic.SymbolMatcher.NameAndTypeMatcher#matchTypes()
			 */
			@Override
			public Set<Class<? extends SymbolNode>> matchTypes() {
				final Set<Class<? extends SymbolNode>> set = new HashSet<Class<? extends SymbolNode>>();
				set.add(OpDefNode.class);
				set.add(OpDeclNode.class);
				set.add(ThmOrAssumpDefNode.class);
				return set;
			}

			/* (non-Javadoc)
			 * @see tla2sany.semantic.SymbolMatcher.NameAndTypeMatcher#matches(tla2sany.semantic.SymbolNode)
			 */
			@Override
			public boolean matches(SymbolNode aSymbol) {
				if (aSymbol instanceof ThmOrAssumpDefNode || aSymbol instanceof OpDefNode) {
					if (aSymbol.getKind() == ASTConstants.ModuleInstanceKind) {
						// Do not match INSTANCE symbols, e.g.: "InChan" defined as:
						// InChan  == INSTANCE Channel WITH ...
						return false;
					}
					if (aSymbol.getKind() == ASTConstants.BuiltInKind) {
						// Do not match built-in operators.
						return false;
					}
					if (!ResourceHelper.isFromUserModule((SemanticNode) ((AnyDefNode) aSymbol).getSource())) {
						// Do not match symbols of the Standard Modules such as Sequences, FiniteSets...
						return false;
					}
					if (!showAll && (((AnyDefNode) aSymbol).getSource() != aSymbol)) {
						// Unless showAll, do not match symbols defined or declared by extended modules. 
						return false;
					}
				}
				return super.matches(aSymbol);
			}
		};
        
        /**
         * Constructs a new Show Declarations popup with indicated parent and
         * with showAll determining if instantiated definitions should be shown.
         * 
         * @param parent
         * @param showAll
         */
        public ShowDeclarationsPopupDialog(Shell parent)
        {
            super(parent, SWT.NO_TRIM, true, // takeFocusOnOpen
                    false, // persistSize
                    true, // persistLocation
                    true, // showDialogMenu
                    true, // showPersistActions
                    "Definitions and Declarations", // titleText
                    ""); // infoText
            this.parent = parent;
            this.showAll = true;
            this.setInfoText(ShowDeclarationsHandler.infoText(showAll));
            this.editor = EditorUtil.getTLAEditorWithFocus();
            if (this.editor != null)
            {
                module = ResourceHelper.getModuleNode(editor.getModuleName());
            }
        }

        /**
         * This is just to make setInfoText a public method so the handlers
         * can call it.
         */
        public void setInfoText(String str)
        {
            super.setInfoText(str);
        }

        /**
         * This is just to make setTitleText a public method so the handlers
         * can call it.
         */
        public void setTitleText(String str)
        {
            super.setTitleText(str);
        }

        /**
         *  Sets the class's <code>list</code> field, which contains the
         *  org.eclipse.swt.widgets.List object with the actual items to be displayed.
         *  It also sets the data for each item to be the node to jump to, so
         *  list.getData(list.getSelection()[0]) gets that node for the selected
         *  item.
         */
        protected void setList()
        {
            list.removeAll();
            // Get the current module.
            if (module == null)
            {
                return;
            }
            
            // Get the list of SymbolNodes to be displayed. They
            // come from the module's constant decls, variable decls,
            // opdef nodes, ThmOrAssumpDefNodes.
            final Collection<SymbolNode> symbols = module.getSymbols(matcher.setPrefix(filterPrefix.toLowerCase()));
            for (SymbolNode symbolNode : symbols) {
                list.add(symbolNode.getName().toString());
                list.setData(symbolNode.getName().toString(), symbolNode);
			}
        }

        /**
         * This is the method that puts the content into the popup's
         * dialog area.  It puts an org.eclipse.swt.widgets.List
         * (note that this isn't an ordinary Java List) there.
         * 
         */
        protected Control createDialogArea(Composite composite)
        {
            // create the list
            list = new List(composite, SWT.SINGLE | SWT.V_SCROLL | SWT.RESIZE);

            // Populate the popup's display area.
            setList();

            // list.addKeyListener(listener);

            /* 
             *  To put a Composite instead of a List in the
             *  dialog area, do something like the following:
            Composite stuff = new Composite(composite, SWT.NONE);
            stuff.setLayoutData(new GridData());
            stuff.setLayout(new FillLayout(SWT.VERTICAL));
            Button button1 = new Button(stuff, SWT.FLAT);
            button1.setText("Button 1");
            // button1.setParent(stuff);
            Button button2 = new Button(stuff, SWT.PUSH);
            button2.setText("Button 2");
            */
            list.addSelectionListener(new ShowDeclarationsSelectionListener(EditorUtil.getTLAEditorWithFocus()));

            // Adding the KeyListener after the SelectionListener is necessary for the handling
            // of keystrokes to work. If they're added in the opposite order, some keys change
            // the selection and call the SelectionListener.

            list.addKeyListener(new ShowDeclarationsKeyListener(this)); // Testing

            // System.out.println("testing showAll = " + showAll);

            // It is necessary to select an item on the list if one is to be
            // able to listen for keystrokes. Otherwise, a keystroke causes the
            // current selection to change, calling the SelectionListener's widgetSelected()
            // method.
            list.setSelection(0);
            return list;
        }
    }

    /**
     * A listener for the List put into the dialog by the createDialogArea
     * method of ShowDefinitionsPopupDialog.
     * 
     * @author lamport
     *
     */
    public static class ShowDeclarationsSelectionListener implements SelectionListener
    {
        private TLAEditor srcEditor;

        public ShowDeclarationsSelectionListener(TLAEditor editor)
        {
            super();
            this.srcEditor = editor;
        }

        /**
         * This method seems to be called on the second click
         * when double-clicking on the selection.  Or maybe not.
         */
        public void widgetDefaultSelected(SelectionEvent e)
        {
        }

        /**
         * Called when the user selects an item in the List.
         */
        public void widgetSelected(SelectionEvent e)
        {
            List list = ((List) e.widget);
            SymbolNode node = (SymbolNode) list.getData(list.getSelection()[0]);
            EditorUtil.setReturnFromOpenDecl(srcEditor);
            UIHelper.jumpToDefOrDecl(node);
        }
    }

    /**
     * The Key Listener for keyboard input to the popup dialog.  The following
     * kinds of keyboard input are handled:
     * <ul>
     * <li> Return, which is equivalent to clicking on the selected item.
     * <li> Space, which toggles between showing and hiding instantiated declarations.
     * <li> Arrow keys, which move the selection.
     * <li> Letters, numbers,  "_", "!", and other characters like "\" and "*" that can
     *      appear in the names of user-defined operators.  These characters are added 
     *      to the prefix used for filtering what is shown.
     *      (Those other characters added by LL on 29 Mar 2012.)
     * <li> Delete/backspace, which deletes one character from the filtering prefix.
     * </ul>
     * Other typed input is ignored.
     * @author lamport
     *
     */
    public static class ShowDeclarationsKeyListener implements KeyListener
    { // Shell parent;
        ShowDeclarationsPopupDialog popup;

        // boolean showAll; // a local copy of the current specs' showAllDeclarations field.

        public ShowDeclarationsKeyListener(ShowDeclarationsPopupDialog popup)
        { // this.parent = parent;
            this.popup = popup;
        }

        public void keyPressed(KeyEvent e)
        {
            char keyPressed = e.character;
            int keyCode = e.keyCode;
            List list = popup.list;
            int selection = list.getSelectionIndex();

            // This prevents the KeyEvent from changing the selection and triggering
            // execution of the SelectionListener.
            e.doit = false;

            // Check which key was pressed and handle it appropriately.
            if (keyPressed == ' ')
            {
                popup.showAll = !popup.showAll;
                popup.setList();
                popup.setInfoText(ShowDeclarationsHandler.infoText(popup.showAll));
                if (list.getItemCount() > 0)
                {
                    list.select(0);
                }
            } else if (keyCode == SWT.ARROW_DOWN || keyCode == SWT.ARROW_RIGHT)
            {
                if (list.getItemCount() == 0 || selection == -1)
                {
                    return;
                }
                list.select(Math.min(list.getItemCount(), selection + 1));
            } else if (keyCode == SWT.ARROW_UP || keyCode == SWT.ARROW_LEFT)
            {
                if (list.getItemCount() == 0 || selection == -1)
                {
                    return;
                }
                list.select(Math.max(0, selection - 1));
            } else if (keyCode == SWT.CR || keyCode == SWT.KEYPAD_CR)
            {
                SymbolNode node = (SymbolNode) list.getData(list.getSelection()[0]);
                EditorUtil.setReturnFromOpenDecl(popup.editor);
                UIHelper.jumpToDefOrDecl(node);
                popup.close();
            } else if (Character.isLetterOrDigit(keyPressed) || 
                    (keyPressed == '_') || 
                    (keyPressed == '!') ||
                    // The following added by LL on 29 Mar 2012
                    (keyPressed == '\\') ||
                    (keyPressed == '+') ||
                    (keyPressed == '-') ||
                    (keyPressed == '%') ||
                    (keyPressed == '^') ||
                    (keyPressed == '.') ||
                    (keyPressed == '<') ||
                    (keyPressed == '>') ||
                    (keyPressed == ':') ||
                    (keyPressed == '&') ||
                    (keyPressed == '|') ||
                    (keyPressed == '#') ||
                    (keyPressed == '$') ||
                    (keyPressed == '?') ||
                    (keyPressed == '@') ||
                    (keyPressed == '*') ||
                    (keyPressed == '=') ||
                    (keyPressed == '/')
                    )
            {
                popup.filterPrefix = popup.filterPrefix + keyPressed;
                popup.setList();
                popup.setTitleText(ShowDeclarationsHandler.titleText(popup.filterPrefix));
                popup.setInfoText(ShowDeclarationsHandler.infoText(popup.showAll));
                if (list.getItemCount() > 0)
                {
                    list.select(0);
                }

            } else if ((keyCode == SWT.DEL || keyCode == SWT.BS) && !popup.filterPrefix.equals(""))
            {
                popup.filterPrefix = popup.filterPrefix.substring(0, popup.filterPrefix.length() - 1);
                popup.setList();
                popup.setTitleText(ShowDeclarationsHandler.titleText(popup.filterPrefix));
                popup.setInfoText(ShowDeclarationsHandler.infoText(popup.showAll));
                if (list.getItemCount() > 0)
                {
                    list.select(0);
                }
            }
        }

        public void keyReleased(KeyEvent e)
        {
            // TODO Auto-generated method stub

        }

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/FileCharReader.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS FileCharReader EXTENDS CharReader                                  *
*                                                                          *
* This class provides a CharReader for a file, using the                   *
* java.io.BufferedReader class.  (See the CharReader class.)               *
***************************************************************************/
package tla2tex;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileCharReader extends CharReader
  { private BufferedReader bufferedReader ;
      /*********************************************************************
      * This is the BufferedReader object providing the input characters.  *
      *********************************************************************/

    public FileCharReader(String fileName) 
      /*********************************************************************
      * The class constructor.  The fileName argument is the name of the   *
      * file.  It exits TLATeX if the file cannot be found.                *
      *********************************************************************/
      { try { bufferedReader = 
                  new BufferedReader(new InputStreamReader(
                                          new FileInputStream(fileName))) ;
            }
        catch (FileNotFoundException e)
           { /**************************************************************
             * File fileName could not be found.                           *
             **************************************************************/
             Debug.ReportError("Input file " + fileName + " not found.");
           } ;
      } ;

    public String innerGetNextLine()
      /*********************************************************************
      * The abstract innerGetNextLine method of CharReader is implemented  *
      * with the readLine method of java.io.BufferedReader.  It aborts     *
      * TLATeX if there is an IOException.                                 *
      *********************************************************************/
      { try {return bufferedReader.readLine();}
        catch (IOException e)
          { Debug.ReportError("Error reading file: " + e.getMessage());
          };

        /*******************************************************************
        * The following return statement is silly, since it is never       *
        * reached.  But the compiler isn't clever enough to notice that    *
        * it's not needed.                                                 *
        *******************************************************************/
        return null ;

      } ;

    public void close()
      /*********************************************************************
      * Implements CharReader's abstract close() method.                   *
      *********************************************************************/
      { try {bufferedReader.close();}
        catch (IOException e)
          { Debug.ReportError("Error trying to close file: " + e.getMessage());
          };
      };
  }


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/Specs.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import java.util.HashSet;
import java.util.Iterator;

import tla2sany.semantic.ExprNode;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SubstInNode;
import tla2sany.semantic.SymbolNode;
import tlc2.util.Context;
import tlc2.util.List;
import tlc2.value.impl.LazyValue;

public abstract class Specs {

	/** 
	 * The level of the expression according to level checking.
	 * static method, does not change instance state 
	 */
	public static int getLevel(LevelNode expr, Context c)
	{
	    HashSet<SymbolNode> lpSet = expr.getLevelParams();
	    if (lpSet.isEmpty())
	        return expr.getLevel();
	
	    int level = expr.getLevel();
	    Iterator<SymbolNode> iter = lpSet.iterator();
	    while (iter.hasNext())
	    {
	        SymbolNode param = (SymbolNode) iter.next();
	        Object res = c.lookup(param, true);
	        if (res != null)
	        {
	            if (res instanceof LazyValue)
	            {
	                LazyValue lv = (LazyValue) res;
	                int plevel = getLevel((LevelNode) lv.expr, lv.con);
	                level = (plevel > level) ? plevel : level;
	            } else if (res instanceof OpDefNode)
	            {
	                int plevel = getLevel((LevelNode) res, c);
	                level = (plevel > level) ? plevel : level;
	            }
	        }
	    }
	    return level;
	}

	/**
	 * Static method, does not change instance state
	 * @param expr
	 * @param subs
	 * @return
	 */
	public static final ExprNode addSubsts(ExprNode expr, List subs)
	{
	    ExprNode res = expr;
	
	    while (!subs.isEmpty())
	    {
	        SubstInNode sn = (SubstInNode) subs.car();
	        res = new SubstInNode(sn.stn, sn.getSubsts(), res, sn.getInstantiatingModule(), sn.getInstantiatedModule());
	        subs = subs.cdr();
	    }
	    return res;
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/dialog/TLAPMErrorDialog.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.dialog;

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * This is a dialog for displaying TLAPM error messages.
 * TLAPM error messages have a message and a URL for submitting
 * that message to the TLAPM developers. This dialog will display
 * the message and display the URL as a link.
 * 
 * @author <NAME>
 *
 */
public class TLAPMErrorDialog extends Dialog
{

    /**
     * The text widget displaying the warning
     * message.
     */
    private Text dialogText;
    /**
     * The message to be displayed in the dialog.
     */
    private String message;
    /**
     * The title of the dialog.
     */
    private String title;
    /**
     * The image for the dialog.
     */
    private Image image;
    /**
     * The url of for submitting the error
     * to the TLAPM developers.
     */
    private String url;

    /**
     * Creates a new dialog that can be opened in the shell returned
     * by the given shell provider. This dialog will display the
     * given message when opened. See {@link #open()}.
     * 
     * @param parentShell
     * @param message
     */
    protected TLAPMErrorDialog(IShellProvider parentShell, String message)
    {
        super(parentShell);
        setShellStyle(SWT.OK | SWT.APPLICATION_MODAL);
        setBlockOnOpen(true);
        this.message = message;
    }

    /**
     * This method overrides the method in {@link Dialog} in order
     * to return the {@link Composite} that contains the widgets for
     * displaying the image (if there is one) and the message text.
     */
    protected Control createDialogArea(Composite parent)
    {

        // create the composite that will contain the image and message
        // for the dialog
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        composite.setLayout(new GridLayout(2, false));

        // creates the widget displaying the image, if there is one
        if (image != null)
        {
            Label imageLabel = new Label(composite, SWT.NULL);
            image.setBackground(imageLabel.getBackground());
            imageLabel.setImage(image);
            /*
             * The following sets the alignment and spacing of the image label within
             * the dialog. It was copied from the createMessageArea method for IconAndMessageDialog.
             */
            GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING).applyTo(imageLabel);
        }

        // creates the widget displaying the message
        dialogText = new Text(composite, SWT.MULTI | SWT.WRAP);
        dialogText.setText(message);
        dialogText.setEditable(false);

        /*
         * The following sets the alignment and spacing of the dialog text within
         * the dialog. It was copied from the createMessageArea method for IconAndMessageDialog.
         */
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).hint(
                convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT).applyTo(
                dialogText);

        /*
         * The following creates the composite that will hold two widgets:
         * 
         * 1.) A label telling the user to submit the above message to
         * the given url.
         * 2.) A hyperlink widget that the user can click on to open
         * a browser to the given url.
         * 
         * We put these in a separate composite so that we can lay them out
         * with different widget columns than the outer composite. If we made the
         * hyperlink and label widgets direct children of the outer composite, then
         * they would have to be put into the columns of the outer composite which
         * can look a bit strange.
         */
        Composite linkComposite = new Composite(composite, SWT.NONE);
        GridData gd = new GridData();
        gd.horizontalSpan = 2;
        linkComposite.setLayoutData(gd);
        linkComposite.setLayout(new GridLayout(2, false));

        Label label = new Label(linkComposite, SWT.WRAP);
        label.setText("Please submit the above message to the TLAPM developers using the following link : ");
        // create the hyperlink for submitting the message
        Hyperlink link = new Hyperlink(linkComposite, SWT.WRAP);
        link.setForeground(JFaceColors.getHyperlinkText(UIHelper.getCurrentDisplay()));
        link.setUnderlined(true);
        link.setHref(url);
        link.setText(url);
        // adds a listener to the hyperlink that opens the link in
        // an external browser when it is clicked on
        link.addHyperlinkListener(new HyperlinkAdapter() {
            public void linkActivated(HyperlinkEvent e)
            {
                try
                {
                    IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
                    IWebBrowser browser = browserSupport.getExternalBrowser();

                    browser.openURL(new URL(url));
                } catch (PartInitException e1)
                {
                    ProverUIActivator.getDefault().logError("Error opening browser to url : " + url, e1);
                } catch (MalformedURLException e1)
                {
                    ProverUIActivator.getDefault().logError("Malformed URL : " + url, e1);
                }
            }
        });

        return composite;
    }

    /**
     * Convenience method for opening an error dialog displaying the
     * given title and message in the currently active shell. The image
     * for this dialog will be the swt error image as returned by
     * UIHelper.getSWTImage(SWT.ICON_ERROR).
     * 
     * @param message
     */
    public static void open(String message, String title, String url)
    {
        TLAPMErrorDialog dialog = new TLAPMErrorDialog(UIHelper.getShellProvider(), message);
        dialog.setTitle(title);
        dialog.setImage(UIHelper.getSWTImage(SWT.ICON_ERROR));
        dialog.setURL(url);

        dialog.open();
    }

    /**
     * Sets the title for the dialog.
     * 
     * @param title
     */
    public void setTitle(String title)
    {
        this.title = title;
    }

    /**
     * Sets the image that will be displayed next to the message
     * in the dialog.
     * 
     * @param image
     */
    public void setImage(Image image)
    {
        this.image = image;
    }

    public void setURL(String url)
    {
        this.url = url;
    }

    /**
     * This method was mostly copied from {@link MessageDialog}. Apparently
     * this is the way to set the title for a dialog.
     */
    protected void configureShell(Shell shell)
    {
        super.configureShell(shell);
        if (title != null)
        {
            shell.setText(title);
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCOutputSourceRegistry.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.ui.progress.IProgressConstants;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.ITLCOutputListener;
import org.lamport.tla.toolbox.tool.tlc.output.LogFileReader;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCModelLaunchDataProvider;
import org.lamport.tla.toolbox.tool.tlc.output.data.TraceExplorerDataProvider;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * The TLC process can produce some output, which needs to be processed by a consumer. The TLC Output Source ({@link ITLCOutputSource})
 * is the abstract representation of the source of the output. In order to process the output from the source, the TLC Output
 * listener is introduced ({@link ITLCOutputListener}). One source can have multiple listeners, and there can be several sources
 * of the output for launches of the same model over time. 
 * <br><br>
 * The consumer of the output must implement the {@link ITLCOutputListener} interface. Its instance has the following life cycle 
 * during the work with the registry:
 * <ul>
 *   <li>The consumer is passed as to the registry during the call of {@link TLCOutputSourceRegistry#connect(ITLCOutputListener)}</li> 
 *   <li>The registry will call {@link ITLCOutputListener#getModel()} and eventually select among one of the sources available</li>
 *   <li>If the source is selected, {@link ITLCOutputSource#addTLCOutputListener(ITLCOutputListener)} is called by the registry on it, 
 *   passing the consumer listener instance</li>
 *   <li>After the end of the with the source, the consumer is disconnected by calling {@link TLCOutputSourceRegistry#disconnect(ITLCOutputListener)}</li>
 * </ul>
 * <br><br>
 * A new source of the TLC output is added by calling {@link TLCOutputSourceRegistry#addTLCOutputSource(ITLCOutputSource)} method. The source 
 * is identified by the name and priority. The methods {@link ITLCOutputSource#getModel()} and {@link ITLCOutputSource#getSourcePrio()}
 * are used to obtain this information. If any listener have been registered, which are interested in the certain TLC Output (the values of 
 * {@link ITLCOutputListener#getModel()} and {@link ITLCOutputSource#getModel()}) are equal, then these will be registered by the
 * new source. The priority resolves the case if a new source for the same name arrives. Currently, high priority is used for the source attached
 * to the running process, low priority is used for the file source. 
 * 
 * There should be at most two instances of this class, one for output sources from running TLC for model checking and one for running TLC
 * for trace exploration. The flag isTraceExploreInstance indicates which type of instance it is, and the methods
 * {@link TLCOutputSourceRegistry#getModelCheckSourceRegistry()} and {@link TLCOutputSourceRegistry#getTraceExploreSourceRegistry()}
 * provide access to each instance.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class TLCOutputSourceRegistry
{
    private static final boolean DO_DEBUG = Boolean.getBoolean(TLCOutputSourceRegistry.class.getName() + ".debug");
    // instance for output sources from model checking
    private static TLCOutputSourceRegistry modelCheckInstance;
    // instance for output sources from trace exploration
    private static TLCOutputSourceRegistry traceExploreInstance;
    // container for sources, hashed by the source name
    private Map<Model, ITLCOutputSource> sources;
    // container for data providers, hashed by the process name
    private Map<Model, TLCModelLaunchDataProvider> providers;
    // flag indicating if this is a trace explorer instance
    // true indicates that this is a trace explorer instance
    private boolean isTraceExploreInstance;

    /**
     * Adds a source. If the source with the same identity is already present,
     * reconnect the the listeners, iff there are any at place and the prio of the new source is higher
     * that the one of the old one.
     * @param source new source
     * @see ITLCOutputSource#getModel()
     * @see ITLCOutputSource#getSourcePrio()
     */
    public synchronized void addTLCOutputSource(ITLCOutputSource source)
    {
        Assert.isNotNull(source);

        // TLCUIActivator.getDefault().logDebug("adding source " + source.getSourceName() + " " + source.getSourcePrio());

        ITLCOutputSource existingSource = this.sources.get(source.getModel());

        // a new source for a given name arrives which has a higher priority
        // re-register the listeners
        if (existingSource != null && source.getSourcePrio() >= existingSource.getSourcePrio())
        {
            ITLCOutputListener[] registered = existingSource.getListeners();
            for (int i = 0; i < registered.length; i++)
            {
                existingSource.removeTLCOutputListener(registered[i]);
                source.addTLCOutputListener(registered[i]);
                registered[i].onNewSource();
            }
        } else
        {
            if (existingSource == null)
            {
                // the source didn't exist, but there is a data provider interested in this source
                TLCModelLaunchDataProvider provider = providers.get(source
                        .getModel());
                if (provider != null)
                {
                    source.addTLCOutputListener(provider);
                }
            }
        }
        this.sources.put(source.getModel(), source);

        printStats();
    }

    /**
     * Remove a source and the date provider associated with that source, if it
     * exists.
     */
    private synchronized void removeTLCStatusSource(Model model)
    {
        this.sources.remove(model);
        this.providers.remove(model);
        printStats();
    }
    
    /**
     * Remove a source and the date provider associated with that source, if it
     * exists.
     */
    public synchronized void removeTLCStatusSource(Model[] models)
    {
    	for (int i = 0; i < models.length; i++) {
			removeTLCStatusSource(models[i]);
		}
    }

    /**
     * Connect the source to the listener
     * @param an instance of ITLCOutputListener interested in the receiving of TLC output from source 
     * with {@link ITLCOutputSource#getModel()} equals to {@link ITLCOutputListener#getModel()}  
     * @return status of connection: <code>true</code> if successfully connected, <code>false</code> otherwise
     */
    public synchronized boolean connect(ITLCOutputListener listener)
    {
        Assert.isNotNull(listener);
        Model model = listener.getModel();

        // try to obtain a source
        ITLCOutputSource source = this.sources.get(model);
        if (source == null)
        {
            // no source found, so no live TLC process
            // also not a source for trace explorer output, so
            // can look for the log file
            if (model == null) {
				// Config can be null after startup following a hard crash when
				// the Toolbox restores the ModelEditor but no spec is currently
				// open/loaded. In this case fail gracefully rather than hang
				// the Toolbox.
            	return false;
            }
            IFile logFile = model.getOutputLogFile(isTraceExploreInstance);
            // log file found
			if ((logFile != null) && logFile.exists()) {
                // initialize the reader and read the content
                // this will create the parser
                // the parser will create a source and register in the registry
                final LogFileReader logFileReader = new LogFileReader(model, logFile, isTraceExploreInstance);

                // retrieve the source
                source = logFileReader.getSource();
                source.addTLCOutputListener(listener);

                // read in the data
                final Job job = new WorkspaceJob("Logfile reader...") {
					public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
						try {
							logFileReader.read(monitor);
						} catch (BadLocationException e) {
							return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
						} catch (IOException e) {
							return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
						}
						return Status.OK_STATUS;
					}
				};
				job.setPriority(Job.SHORT);
				job.setUser(true);
				job.schedule();

                // from now on we should have a source for this model
                Assert.isTrue(this.sources.get(model) != null);
            } else
            {
                // no log file
                if (DO_DEBUG)
                {
                    TLCUIActivator.getDefault().logDebug("No source for " + model.getName() + " found.");
                }
                return false;
            }

        } else
        {
            source.addTLCOutputListener(listener);
        }

        printStats();
        return true;
    }

    /**
     * Disconnect the source from the listener
     */
    public synchronized void disconnect(ITLCOutputListener listener)
    {
        Assert.isNotNull(listener);

        ITLCOutputSource source = this.sources.get(listener.getModel());
        if (source != null)
        {
            source.removeTLCOutputListener(listener);
        }

        printStats();
    }

    /**
     * Retrieves the data provider for the given configuration.
     * 
     * Architecture TODO: it is unclear what we are gaining by keeping the same instance of a launch data provider
     * 	attached to an instance of Model for the lifespan of the app (except in the following cases:
     * 		. the model is deleted
     * 		. loading existing output from the filesystem for the model
     * )
     * 
     * @return a data provider for the current model
     */
    public synchronized TLCModelLaunchDataProvider getProvider(Model model)
    {
        Assert.isNotNull(model);
        TLCModelLaunchDataProvider provider = providers.get(model);
        if (provider == null)
        {
            if (isTraceExploreInstance)
            {
                provider = new TraceExplorerDataProvider(model);
            } else
            {
                provider = new TLCModelLaunchDataProvider(model);
            }
            providers.put(model, provider);
        }
        return provider;
    }
    
    public synchronized boolean hasProvider(Model model)
    {
    	return providers.containsKey(model);
    }

    /**
     * Clients should not invoke this constructor directly, but use {@link TLCOutputSourceRegistry#getModelCheckSourceRegistry()}
     * or {@link TLCOutputSourceRegistry#getTraceExploreSourceRegistry()} instead.
     */
    private TLCOutputSourceRegistry()
    {
        this.sources = new HashMap<Model, ITLCOutputSource>();
        this.providers = new HashMap<Model, TLCModelLaunchDataProvider>();
    }

    /**
     * Access method for model check source registry instance
     * @return a working copy of the registry
     */
    public static TLCOutputSourceRegistry getModelCheckSourceRegistry()
    {
        if (modelCheckInstance == null)
        {
            modelCheckInstance = new TLCOutputSourceRegistry();
            modelCheckInstance.isTraceExploreInstance = false;
        }
        return modelCheckInstance;
    }

    /**
     * Access method for trace explore source registry instance
     */
    public static TLCOutputSourceRegistry getTraceExploreSourceRegistry()
    {
        if (traceExploreInstance == null)
        {
            traceExploreInstance = new TLCOutputSourceRegistry();
            traceExploreInstance.isTraceExploreInstance = true;
        }
        return traceExploreInstance;
    }

    /**
     * Debugging
     */
    private void printStats()
    {
        if (DO_DEBUG)
        {
            String type = "model checking";
            if (isTraceExploreInstance)
            {
                type = "trace exploration";
            }
            TLCUIActivator.getDefault().logDebug("TLCOutputSourceRegistry for " + type + " maintains " + sources.size()
                    + " sources.");
            Set<Model> keySet = sources.keySet();
            for (Model model : keySet) {
            	ITLCOutputSource source = sources.get(model);
            	TLCUIActivator.getDefault().logDebug("The source " + model.getName() + " has " + source.getSourcePrio() + " prio and "
            			+ source.getListeners().length + " listeners");
			}
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/April29dTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.junit.Ignore;
import org.junit.Test;

import tlc2.TLC;
import tlc2.output.EC;
import tlc2.tool.AbstractChecker;
import tlc2.tool.liveness.GraphNode.Transition;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

/**
 * @see April29Test
 */
public class April29dTest extends ModelCheckerTestCase {

	public April29dTest() {
		super("April29dMC", "symmetry");
	}
	
	@Test
	@Ignore("Ignored for as long as symmetry is incorrectly handled by TLC with liveness checking.")
	public void testSpec() throws IOException {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertFalse(recorder.recorded(EC.GENERAL));
		
		// Verify the nodes and arcs in the behavior graph in terms of nodes and arcs.
		final ILiveCheck liveCheck = (ILiveCheck) getField(AbstractChecker.class, "liveCheck",
				getField(TLC.class, "instance", tlc));
		assertEquals(1, liveCheck.getNumChecker());
		
		final ILiveChecker checker = liveCheck.getChecker(0);
		final DiskGraph graph = (DiskGraph) checker.getDiskGraph();
		graph.makeNodePtrTbl();
		assertEquals(2, graph.size()); // two nodes

		final LongVec initNodes = graph.getInitNodes();
		assertEquals(2, initNodes.size()); // <<fp,tidx>>, thus a single init state
		
		final int slen = checker.getSolution().getCheckState().length;
		assertEquals(0, slen);
		final int alen = checker.getSolution().getCheckAction().length;
		assertEquals(3, alen);
		
		final GraphNode init = graph.getNode(initNodes.elementAt(0));
		Set<Transition> transitions = init.getTransition(slen, alen);
		assertEquals(2, transitions.size()); // One self-loop and one successor
		
		// Remove self loop from init's transitions. The remaining transitions are
		// the true successors (here just a single).
		final List<Transition> outs = new ArrayList<Transition>();
		for (Transition t : transitions) {
			if (t.getFP() != init.stateFP) {
				outs.add(t);
			}
		}
		assertEquals(1, outs.size());
		
		final GraphNode successor = graph.getNode(outs.get(0).getFP());
		transitions = successor.getTransition(slen, alen);
		assertEquals(2, transitions.size());
		
		// Verify both outgoing transitions are self loops with the expected
		// action predicates. transitions is a Set and thus adding equal
		// instance does not increase the set's size.
		BitVector bv = new BitVector(alen + slen);
		bv.set(0);
		bv.set(2);
		transitions.add(new Transition(successor.stateFP, -1, bv));
		bv = new BitVector(alen + slen);
		bv.set(2);
		transitions.add(new Transition(successor.stateFP, -1, bv));
		assertEquals(2, transitions.size());

		// Assert TLC has found a temporal violation and a counter example
		assertFalse(recorder.recorded(EC.TLC_TEMPORAL_PROPERTY_VIOLATED));
		assertFalse(recorder.recorded(EC.TLC_COUNTER_EXAMPLE));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/DivergenceTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

import tla2sany.drivers.SANY;
import util.TestPrintStream;
import util.ToolIO;


//TODO The asserts below could be strengthened if the error message about the divergence would include the actual hash mismatch.

// Plz can haz https://openjdk.java.net/jeps/355 ?
public class DivergenceTest extends PCalTest {
	@Test
	public void divergenceTest00() throws IOException {
		final String filename = "divergenceTest001" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION\n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" +
				"           \\/ Terminating\n" +
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertNoSubstring("!! WARNING " + filename);
	}

	@Test
	public void divergenceTest01() throws IOException {
		final String filename = "divergenceTest01" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (chksum(PCal) \\in STRING /\\ chksum(TLA+) \\in STRING)\n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" +
				"           \\/ Terminating\n" +
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertNoSubstring("!! WARNING " + filename);
	}

	@Test
	public void divergenceTest01fair() throws IOException {
		final String filename = "divergenceTest01" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--fair algorithm a\n" + // Divergence because "fair" was added after the translation.
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (checksum(PlusCal) = \"4860ac97\" /\\ chksum(TLA+) \\in STRING)\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The PlusCal algorithm in module %s has changed since its last translation.",
				filename));
	}
	
	@Test
	public void divergenceTest01unfair() throws IOException {
		final String filename = "divergenceTest01" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" + // Divergence because "fair" was removed after the translation.
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (checksum(PlusCal) = \"7c28162a\" /\\ chksum(TLA+) \\in STRING)\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The PlusCal algorithm in module %s has changed since its last translation.",
				filename));
	}
	
	@Test
	public void divergenceTestIndentation() throws IOException {
		final String filename = "divergenceTest01" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\nvariable f;" + 
				"begin\n" +
				"  f := /\\ TRUE\n" + 
				"    /\\ TRUE;\n" +  // Divergence because indentation was changed after the translation.
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (checksum(PlusCal) = \"996afab0\" /\\ chksum(TLA+) \\in STRING)\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The PlusCal algorithm in module %s has changed since its last translation.",
				filename));
	}

	@Test
	public void divergenceTest02() throws IOException {
		final String filename = "divergenceTest02" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  print \"msg\";\n" + // PlusCal diverged
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (chksum(PCal) = \"4860ac97\" /\\ chksum(TLA+) = \"af3d9146\")\n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" +
				"           \\/ Terminating\n" +
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The PlusCal algorithm in module %s has changed since its last translation.",
				filename));
	}

	@Test
	public void divergenceTest03() throws IOException {
		final String filename = "divergenceTest03" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION (checksum(PlusCal) = \"4860ac97\" /\\ ChkSum(tla+) = \"af3d9146\")\n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" + // TLA+ diverged.
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The TLA+ translation in module %s has changed since its last translation.",
				filename));
	}

	@Test
	public void divergenceTest04() throws IOException {
		final String filename = "divergenceTest04" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  print \"msg\";\n" + // PlusCal diverged
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION   (checksum(PlusCal) = \"4860ac97\" /\\ ChkSum(tla+) = \"af3d9146\")  \n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" + // TLA+ diverged.
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertSubstring(String.format(
				"!! WARNING: The PlusCal algorithm and its TLA+ translation in module %s filename since the last translation.",
				filename));
	}
	@Test
	public void divergenceTest05() throws IOException {
		final String filename = "divergenceTest04" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  print \"msg\";\n" + // PlusCal diverged
				"end algorithm; *)\n" +
				"\\* BEGIN TRANSLATION   (checksum(PlusCal) \\in  STRING /\\ ChkSum(tla+) \\in STRING)  \n" +
				"VARIABLE pc\n" +
				"\n" +
				"vars == << pc >>\n" +
				"\n" +
				"Init == /\\ pc = \"Lbl_1\"\n" +
				"\n" +
				"Lbl_1 == /\\ pc = \"Lbl_1\"\n" +
				"         /\\ TRUE\n" +
				"         /\\ pc' = \"Done\"\n" +
				"\n" +
				"(* Allow infinite stuttering to prevent deadlock on termination. *)\n" +
				"Terminating == pc = \"Done\" /\\ UNCHANGED vars\n" +
				"\n" +
				"Next == Lbl_1\n" + // TLA+ diverged.
				"\n" +
				"Spec == Init /\\ [][Next]_vars\n" +
				"\n" +
				"Termination == <>(pc = \"Done\")\n" +
				"\n" +
				"\\* END TRANSLATION\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertNoSubstring(String.format(
				"!! WARNING:",
				filename));
	}

	@Test
	public void divergenceTest06() throws IOException {
		final String filename = "divergenceTest05" + System.currentTimeMillis();
		final String absolutePath = writeFile(System.getProperty("java.io.tmpdir") + File.separator + filename,
				"---- MODULE " + filename + " ----\n" +
				"\n" +
				"(*\n" +
				"--algorithm a\n" +
				"begin\n" +
				"  skip;\n" +
				"end algorithm; *)\n" +
				"\n=========================");
		// Parse with SANY and check for errors (collects parse errors into ToolIO.out)
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		SANY.SANYmain(new String[] { absolutePath });
		testPrintStream.assertSubstring("Semantic processing of module " + filename);
		testPrintStream.assertNoSubstring("!! WARNING " + filename);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/dialog/ErrorViewTraceFilterDialog.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.dialog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariable;

/**
 * The genesis of this dialog is https://github.com/tlaplus/tlaplus/issues/274 and then further modified to support
 * https://github.com/tlaplus/tlaplus/issues/360
 */
public class ErrorViewTraceFilterDialog extends Dialog {
	public enum MutatedFilter {
		NO_FILTER, CHANGED_ALL_FRAMES, CHANGED_CHANGED_FRAMES;
	}
	
	
	private static final String[] MUTATED_VARIABLE_SELECTIONS = { "Show all variables",
																  "Show only changed variables",
																  "Show only changed variables in changed frames" };
	
	
	private CheckboxTableViewer tableViewer;
	
	private final List<TLCVariable> variables;
	private final HashSet<TLCVariable> selection;
	
	private Combo mutatedVariablesCombo;
	private MutatedFilter selectedFilter;
	
	/**
	 * @param parentShell
	 * @param variableList a copy of this list will be made
	 */
	public ErrorViewTraceFilterDialog(final Shell parentShell, final List<TLCVariable> variableList) {
		super(parentShell);
		
		variables = new ArrayList<>(variableList);
		selection = new HashSet<>();
	}
	
	public Set<TLCVariable> getSelection() {
		return selection;
	}
	
	public void setSelection(final Set<TLCVariable> newSelection) {
		selection.clear();
		
		if ((newSelection == null) || (newSelection.size() == 0)) {
			return;
		}
		
		selection.addAll(newSelection);
		if (tableViewer != null) {
			tableViewer.setAllChecked(false);
			selection.stream().forEach((element) -> tableViewer.setChecked(element, true));
		}
	}
	
	public MutatedFilter getMutatedFilterSelection() {
		return selectedFilter;
	}
	
    @Override
    protected final Control createDialogArea(final Composite parent) {
    	final Composite container = (Composite) super.createDialogArea(parent);
    	GridLayout gl = new GridLayout(2, false);
    	gl.verticalSpacing = 9;
    	container.setLayout(gl);

    	
    	
    	Label l = new Label(container, SWT.LEFT);
    	l.setText("Selected variables and expressions will be hidden from the error trace.");
    	l.setFont(JFaceResources.getFontRegistry().get(JFaceResources.DIALOG_FONT));
    	GridData gd = new GridData();
    	gd.horizontalSpan = 2;
    	l.setLayoutData(gd);
    	

    	
    	tableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE);
    	tableViewer.setContentProvider(new ArrayContentProvider());
    	tableViewer.setLabelProvider(new ColumnLabelProvider() {
    		@Override
    		public String getText(final Object element) {
    			return ((TLCVariable)element).getName();
    		}
    	});
    	tableViewer.setInput(variables);
		selection.stream().forEach((element) -> tableViewer.setChecked(element, true));
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	gd.minimumWidth = 333;
    	tableViewer.getTable().setLayoutData(gd);
    	
    	
    	final Composite buttonPane = new Composite(container, SWT.NONE);
    	gl = new GridLayout(1, false);
    	buttonPane.setLayout(gl);
    	
    	Button b = new Button(buttonPane, SWT.PUSH);
    	b.setText("Select All");
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	b.setLayoutData(gd);
    	b.addSelectionListener(new SelectionAdapter() {
    		@Override
    		public void widgetSelected(final SelectionEvent se) {
    			tableViewer.setAllChecked(true);
    		}
    	});
    	
    	b = new Button(buttonPane, SWT.PUSH);
    	b.setText("Deselect All");
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	b.setLayoutData(gd);
    	b.addSelectionListener(new SelectionAdapter() {
    		@Override
    		public void widgetSelected(final SelectionEvent se) {
    			tableViewer.setAllChecked(false);
    		}
    	});
    	
    	
    	final Composite mutatedVariablesComboPane = new Composite(container, SWT.NONE);
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	gd.horizontalSpan = 2;
    	mutatedVariablesComboPane.setLayoutData(gd);
    	gl = new GridLayout(2, false);
    	mutatedVariablesComboPane.setLayout(gl);
    	
    	l = new Label(mutatedVariablesComboPane, SWT.LEFT);
    	l.setText("Filter by change:");
    	l.setFont(JFaceResources.getFontRegistry().get(JFaceResources.DIALOG_FONT));
    	
    	mutatedVariablesCombo = new Combo(mutatedVariablesComboPane, SWT.READ_ONLY);
    	mutatedVariablesCombo.setItems(MUTATED_VARIABLE_SELECTIONS);
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	mutatedVariablesCombo.setLayoutData(gd);
    	mutatedVariablesCombo.setText(MUTATED_VARIABLE_SELECTIONS[0]);
    	
        return container;
    }

    @Override
    protected void okPressed() {
    	selection.clear();
    	
		Arrays.stream(tableViewer.getCheckedElements()).forEach((element) -> selection.add((TLCVariable)element));
		selectedFilter = MutatedFilter.values()[mutatedVariablesCombo.getSelectionIndex()];
		
        super.okPressed();
    }
    
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
    }
    
	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText("Error Trace Filter");
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCFunctionVariableValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.List;

/*************************************************************
 * Represents a function as a list of TLCFcnElementVariable objects
 * 
 * @author <NAME>
 */
public class TLCFunctionVariableValue extends TLCVariableValue implements TLCMultiVariableValue {

    private static final String[] DELIMETERS = { "(", " @@", ")" };
    private final TLCFcnElementVariableValue[] elements;
    
    /**
     * @param fcnElements
     */
	public TLCFunctionVariableValue(List fcnElements) {
		this.value = fcnElements;
		this.elements = innerGetFcnElements();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#getValue()
	 */
	public Object getValue() {
		return elements;
	}

	public TLCFcnElementVariableValue[] getFcnElements() {
		return elements;
	}

	public TLCFcnElementVariableValue[] innerGetFcnElements() {
		return (TLCFcnElementVariableValue[]) ((List) this.value)
				.toArray(new TLCFcnElementVariableValue[((List) this.value).size()]);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#toSimpleString()
	 */
	public String toSimpleString() {
		return arrayToSimpleStringBuffer(getFcnElements(), DELIMETERS).toString();
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCMultiVariableValue#asList()
	 */
	public List<TLCVariableValue> asList() {
		return (List<TLCVariableValue>) this.value;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#innerDiff(org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue)
	 */
	protected void innerDiff(TLCVariableValue other) {
		/*
		 * FUNCTIONS We mark a record element as added or deleted if its
		 * label does not appear in one of the elements of the other record.
		 * We mark the element as changed, and call setInnerDiffInfo on the
		 * elements' values if elements with same label but different values
		 * appear in the two records.
		 */
		if (!(other instanceof TLCFunctionVariableValue)) {
			return;
		}

		setFcnElementArrayDiffInfo(this.elements, ((TLCFunctionVariableValue) other).elements);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/OrderOfSolution.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:49 PST by lamport
//      modified on Fri Jul 14 15:40:49 PDT 2000 by yuanyu

package tlc2.tool.liveness;

import java.io.PrintStream;

import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.util.BitVector;

/*
 * Roughly speaking, each temporal formula maps 1:1 to OrderOfSolution. Say TLC is set to check
 * the three temporal formulas A, B, C, there will be three OrderOfSolution instances 
 * (one for each of formula). More precisely, each conjunct is represented by an OOS.
 * 
 * For details, see page 405 to 408 of "Temporal verification of Reactive Systems * safety *"
 * by Manna and Pnueli (abbreviated to "MP book" in most of TLC's code comments).
 *  
 * Note that TLC does *not* check if A, B or C are identical formulas. If TLC is set to
 * check A, A, A (it will still create three OrderOfSolutions). It is up to the
 * user to prevent this.
 */
public class OrderOfSolution {
	/**
	 * The algorithm will decompose the fairness spec /\ ~check into a
	 * disjunction of conjuncts of the following form: (<>[]a /\ []<>b /\ tf1)
	 * \/ (<>[]c /\ []<>d /\ tf2) .. For efficiency, we will identify disjuncts
	 * that have the same tableau (tf), and OrderOfSolution groups them
	 * together: (<>[]a/\[]<>b \/ <>[]c/\[]<>d) /\ tf Each conjunct
	 * (<>[]a/\[]<>b) is represented by a PossibleErrorModel. The solution then
	 * proceeds: construct the behaviour graph using the tableau, compute
	 * strongly connected components, and see if it meets any one of the
	 * disjunctions. Also, it's likely that a single order of solution will have
	 * lots of duplication in its <>[] and []<> spread over its disjunctions and
	 * conjunctions. To avoid waste, we use a lookup table: checkState,
	 * checkAction: when examining each state and its transitions, these are the
	 * things we have to remember before throwing it away. The possible error
	 * model stores indexes into checkState and checkAction arrays, under EA/AE,
	 * state/action. The field promises are all the promises contained in the
	 * closure.
	 */

	/*
	 * The size of the tableau graph is a function of the amount of disjuncts
	 * in the temporal formulas.
	 */
	private final TBGraph tableau; // tableau graph
	
	/**
	 * A promise &#966; that a property expressed by a formula will eventually hold.
	 * 
	 * @see Page 409ff of Manna & Pnueli
	 * "Temporal Verification of Reactive Systems: Safety"
	 * <p>
	 * @see https://books.google.de/books?id=lfIGCAAAQBAJ&lpg=PR5&ots=_YBX09o5tM
	 *      &dq=manna%20pnueli%20temporal%20verification%20of%20reactive%
	 *      20systems%20safety%20doi&pg=PA409
	 */
	private final LNEven[] promises; // promises in the tableau
	private LiveExprNode[] checkState; // state subformula
	private LiveExprNode[] checkAction; // action subformula
	private PossibleErrorModel[] pems;

	public OrderOfSolution(final LNEven[] livenessEventually) {
		this(null, livenessEventually);
	}

	public OrderOfSolution(final TBGraph aTableau, final LNEven[] livenessEventually) {
		tableau = aTableau;
		promises = livenessEventually;
	}

	public final void printPromises(PrintStream ps) {
		for (int i = 0; i < this.getPromises().length; i++) {
			ps.println(this.getPromises()[i].toString());
		}
	}

	public final String toString() {
		if (this.getPems().length == 0) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		this.toString(sb);
		return sb.toString();
	}

	public final void toString(StringBuffer sb) {
		String padding = "";
		int plen = this.getPems().length;

		if (this.hasTableau()) {
			if (plen == 1 && this.getPems()[0].isEmpty()) {
				this.getTableau().tf.toString(sb, "   ");
				return;
			} else {
				sb.append("/\\ ");
				this.getTableau().tf.toString(sb, "   ");
				sb.append("\n/\\ ");
				padding = "   ";
			}
		}

		if (plen == 1) {
			this.getPems()[0].toString(sb, padding, checkState, this.getCheckAction());
		} else {
			sb.append("\\/ ");
			String padding1 = padding + "   ";
			this.getPems()[0].toString(sb, padding1, checkState, this.getCheckAction());
			for (int i = 1; i < plen; i++) {
				sb.append(padding + "\\/ ");
				this.getPems()[i].toString(sb, padding1, checkState, this.getCheckAction());
			}
		}
	}

	public TBGraph getTableau() {
		return tableau;
	}

	public boolean hasTableau() {
		return tableau != null;
	}

	public LNEven[] getPromises() {
		return promises;
	}

	public LiveExprNode[] getCheckState() {
		return checkState;
	}
	
	public boolean[] checkState(ITool tool, final TLCState state) {
		final boolean[] result = new boolean[checkState.length];
		for (int i = 0; i < checkState.length; i++) {
			result[i] = checkState[i].eval(tool, state, null);
		}
		return result;
	}

	void setCheckState(LiveExprNode[] checkState) {
		this.checkState = checkState;
	}

	// legacy LiveCheck1
	public boolean[] checkAction(ITool tool, final TLCState state0, final TLCState state1) {
		final boolean[] result = new boolean[checkAction.length];
		for (int i = 0; i < checkAction.length; i++) {
			result[i] = checkAction[i].eval(tool, state0, state1);
		}
		return result;
	}
	
	public BitVector checkAction(ITool tool, final TLCState state0, final TLCState state1, final BitVector result, final int offset) {
		for (int i = 0; i < checkAction.length; i++) {
			if (checkAction[i].eval(tool, state0, state1)) {
				result.set(offset + i);
			}
		}
		return result;
	}
	
	public LiveExprNode[] getCheckAction() {
		return checkAction;
	}

	void setCheckAction(LiveExprNode[] checkAction) {
		this.checkAction = checkAction;
	}

	public PossibleErrorModel[] getPems() {
		return pems;
	}

	void setPems(PossibleErrorModel[] pems) {
		this.pems = pems;
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/statistics/management/BucketStatisticsMXBean.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util.statistics.management;

import tlc2.util.statistics.BucketStatistics;

public interface BucketStatisticsMXBean {

	public abstract String getObjectName();

	/**
	 * @see BucketStatistics#getObservations()
	 */
	public abstract long getObservations();

	/**
	 * @see BucketStatistics#getMedian()
	 */
	public abstract int getMedian();

	/**
	 * @see BucketStatistics#getMean()
	 */
	public abstract double getMean();

	/**
	 * @see BucketStatistics#getMin()
	 */
	public abstract int getMin();

	/**
	 * @see BucketStatistics#getMax()
	 */
	public abstract int getMax();

	/**
	 * @see BucketStatistics#getStdDev()
	 */
	public abstract double getStdDev();

	/**
	 * @see BucketStatistics#getPercentile(double)
	 */
	public abstract double get75Percentile();

	/**
	 * @see BucketStatistics#getPercentile(double)
	 */
	public abstract double get95Percentile();

	/**
	 * @see BucketStatistics#getPercentile(double)
	 */
	public abstract double get98Percentile();

	/**
	 * @see BucketStatistics#getPercentile(double)
	 */
	public abstract double get99Percentile();

	/**
	 * @see BucketStatistics#getPercentile(double)
	 */
	public abstract double get999Percentile();
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/NodeTable.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:49 PST by lamport
//      modified on Sun Jul 29 23:09:54 PDT 2001 by yuanyu

package tlc2.tool.liveness;

public final class NodeTable {
	private int count;
	private int length;
	private int thresh;
	private Object[] elems;
	private boolean isBT;

	public NodeTable(int size, boolean isBT) {
		this.count = 0;
		this.length = size;
		this.thresh = size / 2;
		this.elems = new Object[size];
		this.isBT = isBT;
	}

	/* Double the table when the table is full by the threshhold. */
	private final void grow() {
		Object[] oldElems = this.elems;
		this.count = 0;
		this.length = 2 * this.length + 1;
		this.thresh = this.length / 2;
		this.elems = new Object[this.length];
		for (int i = 0; i < oldElems.length; i++) {
			Object elem = oldElems[i];
			if (elem != null) {
				if (this.isBT) {
					this.putBTNodes(elem);
				} else {
					this.putBENode((BEGraphNode) elem);
				}
			}
		}
	}

	public final int size() {
		return this.count;
	}

	public final int putBENode(BEGraphNode node) {
		if (count >= thresh) {
			this.grow();
		}
		long k = node.stateFP;
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			BEGraphNode node1 = (BEGraphNode) this.elems[loc];
			if (node1 == null) {
				this.elems[loc] = node;
				this.count++;
				return loc;
			} else if (node1.stateFP == k) {
				this.elems[loc] = node;
				return loc;
			}
			loc = (loc + 1) % this.length;
		}
	}

	public final BEGraphNode getBENode(long k) {
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			BEGraphNode node = (BEGraphNode) this.elems[loc];
			if (node == null) {
				return null;
			}
			if (node.stateFP == k) {
				return node;
			}
			loc = (loc + 1) % this.length;
		}
	}

	private final int putBTNodes(Object nodes) {
		long k = ((nodes instanceof BTGraphNode) ? ((BTGraphNode) nodes).stateFP : ((BTGraphNode[]) nodes)[0].stateFP);
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (this.elems[loc] != null) {
			loc = (loc + 1) % this.length;
		}
		this.elems[loc] = nodes;
		this.count++;
		return loc;
	}

	public final int putBTNode(BTGraphNode node) {
		if (this.count >= this.thresh) {
			this.grow();
		}
		long k1 = node.stateFP;
		int k2 = node.getIndex();
		int loc = ((int) k1 & 0x7FFFFFFF) % this.length;
		while (true) {
			Object elem = this.elems[loc];
			if (elem == null) {
				this.elems[loc] = node;
				this.count++;
				return loc;
			} else if (elem instanceof BTGraphNode) {
				BTGraphNode btnode = (BTGraphNode) elem;
				if (btnode.stateFP == k1) {
					if (btnode.isDummy()) {
						this.elems[loc] = node;
						// this.count++;
					} else if (btnode.getIndex() != k2) {
						BTGraphNode[] newElem = new BTGraphNode[2];
						newElem[0] = btnode;
						newElem[1] = node;
						this.elems[loc] = newElem;
						// this.count++;
					}
					return loc;
				}
			} else {
				BTGraphNode[] nodes = (BTGraphNode[]) elem;
				if (nodes[0].stateFP == k1) {
					for (int i = 0; i < nodes.length; i++) {
						if (nodes[i].getIndex() == k2) {
							return loc;
						}
					}
					BTGraphNode[] newElem = new BTGraphNode[nodes.length + 1];
					for (int i = 0; i < nodes.length; i++) {
						newElem[i] = nodes[i];
					}
					newElem[nodes.length] = node;
					this.elems[loc] = newElem;
					// this.count++;
					return loc;
				}
			}
			loc = (loc + 1) % this.length;
		}
	}

	/* This method gets all the nodes with state fingerprint k. */
	public final BTGraphNode[] getBTNode(long k) {
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			Object elem = this.elems[loc];
			if (elem == null) {
				return null;
			}
			if (elem instanceof BTGraphNode) {
				BTGraphNode btnode = (BTGraphNode) elem;
				if (btnode.stateFP == k) {
					if (btnode.isDummy()) {
						return null;
					}
					BTGraphNode[] nodes = new BTGraphNode[1];
					nodes[0] = btnode;
					return nodes;
				}
			} else {
				BTGraphNode[] nodes = (BTGraphNode[]) elem;
				if (nodes[0].stateFP == k) {
					return nodes;
				}
			}
			loc = (loc + 1) % this.length;
		}
	}

	public final BTGraphNode[] getBTNodeWithHint(long k, int hintLoc) {
		Object elem = this.elems[hintLoc];
		if (elem != null) {
			if (elem instanceof BTGraphNode) {
				BTGraphNode btnode = (BTGraphNode) elem;
				if (btnode.stateFP == k) {
					if (btnode.isDummy()) {
						return null;
					}
					BTGraphNode[] nodes = new BTGraphNode[1];
					nodes[0] = btnode;
					return nodes;
				}
			} else {
				BTGraphNode[] nodes = (BTGraphNode[]) elem;
				if (nodes[0].stateFP == k) {
					return nodes;
				}
			}
		}
		return getBTNode(k);
	}

	/**
	 * This method gets the node with state fingerprint k1 and tableau node
	 * index k2. It returns null if there is no such node.
	 */
	public final BTGraphNode getBTNode(long k1, int k2) {
		int loc = ((int) k1 & 0x7FFFFFFF) % this.length;
		while (true) {
			Object elem = this.elems[loc];
			if (elem == null) {
				return null;
			}
			if (elem instanceof BTGraphNode) {
				BTGraphNode node = (BTGraphNode) elem;
				if (node.stateFP == k1) {
					if (node.isDummy() || node.getIndex() != k2) {
						return null;
					}
					return node;
				}
			} else {
				BTGraphNode[] nodes = (BTGraphNode[]) elem;
				if (nodes[0].stateFP == k1) {
					for (int i = 0; i < nodes.length; i++) {
						BTGraphNode node = nodes[i];
						if (node.getIndex() == k2) {
							return node;
						}
					}
					return null;
				}
			}
			loc = (loc + 1) % this.length;
		}
	}

	/**
	 * This method returns true iff we have already done the nodes in
	 * elems[idx]. So, if there is a new node being added to elems[idx], we must
	 * get this new node done.
	 */
	public final boolean isDone(int loc) {
		Object elem = this.elems[loc];
		if (elem == null) {
			return false;
		}
		if (elem instanceof BTGraphNode) {
			return ((BTGraphNode) elem).isDone();
		}
		return ((BTGraphNode[]) elem)[0].isDone();
	}

	public final void setDone(long k) {
		if (this.count >= this.thresh) {
			this.grow();
		}
		if (!this.isBT) {
			return;
		}
		int loc = ((int) k & 0x7FFFFFFF) % this.length;
		while (true) {
			Object elem = this.elems[loc];
			if (elem == null) {
				this.elems[loc] = BTGraphNode.makeDummy(k);
				this.count++;
				return;
			}
			if (elem instanceof BTGraphNode) {
				BTGraphNode node = (BTGraphNode) elem;
				if (node.stateFP == k) {
					node.setDone();
					return;
				}
			} else {
				BTGraphNode[] nodes = (BTGraphNode[]) elem;
				if (nodes[0].stateFP == k) {
					((BTGraphNode[]) elem)[0].setDone();
					return;
				}
			}
			loc = (loc + 1) % this.length;
		}
	}

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/StatePrinter.java<|end_filename|>
package tlc2.output;

import tlc2.TLCGlobals;
import tlc2.tool.TLCState;
import tlc2.tool.TLCStateInfo;

/**
 * Helper for printing states
 * @author <NAME>
 * @version $Id$
 */
public class StatePrinter
{
	/**
	 * Prints a single state out of a larger error trace, when the error is not
	 * related to invalidation of an invariant. This would be used if, for
	 * example, TLC finds a step where not all variables have defined values.
	 * @param currentState The single state in the trace.
	 * @param num The index of the state in the trace, counting from one.
	 */
    public static void printRuntimeErrorStateTraceState(TLCState currentState, int num)
    {
        MP.printState(EC.TLC_STATE_PRINT1, new String[] { String.valueOf(num), currentState.toString() }, currentState, num);
    }

    /**
     * Prints a single state for error reporting purposes, for example if the
     * state is invalid in some way. Not to be used when printing states just
     * because an invariant has been violated.
     * @param currentState The state to print.
     */
    public static void printStandaloneErrorState(TLCState currentState)
    {
        MP.printState(EC.TLC_STATE_PRINT1, new String[] { "", currentState.toString() }, currentState, -1);
    }

    /**
     * Prints a single state out of a larger state trace, for use when an
     * invariant is violated.
     * @param currentStateInfo
     */
    public static void printInvariantViolationStateTraceState(TLCStateInfo currentStateInfo) {
    	if (currentStateInfo.predecessorState == null) {
    		// It's an initial state
			StatePrinter.printInvariantViolationStateTraceState(currentStateInfo, null, (int) currentStateInfo.stateNumber);
    	} else {
			StatePrinter.printInvariantViolationStateTraceState(currentStateInfo, currentStateInfo.predecessorState.state, (int) currentStateInfo.stateNumber);
    	}
    }
    
    /**
     * Prints a single state out of a larger state trace, for use when an
     * invariant is violated.
     * If the {@link TLCGlobals#printDiffsOnly} flag is set, will print state
     * diffs instead of full state.
     * @param currentStateInfo Information about the single state in the trace.
     * @param previousState The previous state in the trace for diff printing.
     * @param num The index of the state in the trace, counting from one.
     */
    public static void printInvariantViolationStateTraceState(TLCStateInfo currentStateInfo, TLCState previousState, int num)
    {
        final String stateString =
        		null != previousState && TLCGlobals.printDiffsOnly
        		? currentStateInfo.state.toString(previousState)
        		: currentStateInfo.state.toString();
 
		// Fingerprint can't be calculated when state is incomplete; just use a random value.
        final String fingerprint =
        		currentStateInfo.state.allAssigned()
        		? String.valueOf(currentStateInfo.fingerPrint())
        		: "-1";

		// Metadata is the state number/ordinal and action name/location that is printed
		// above the actual state (values to variables).
        final String[] metadata = new String[] {
				String.valueOf(num),
				currentStateInfo.info.toString(),
				stateString,
				fingerprint
        };

		MP.printState(EC.TLC_STATE_PRINT2, metadata, currentStateInfo, num);
    }

    /**
     * Prints a marker for a stuttering state that concludes a liveness
     * counterexample error trace.
     * @param num The index of the state in the trace, counting from one.
     */
    public static void printStutteringState(int num)
    {
        MP.printState(EC.TLC_STATE_PRINT3, new String[] { String.valueOf(num + 1) }, (TLCState) null, num + 1);
    }

    /**
     * Prints a marker for a loopback (lasso) state that concludes a liveness
     * counterexample error trace.
     * @param currentStateInfo Info about the loopback state.
     * @param stateNum The index of the state in the trace, counting from one.
     */
	public static void printBackToState(final TLCStateInfo currentStateInfo, final int stateNum) {
		if (TLCGlobals.tool) {
			//TODO If the unit test suite runs with -tool mode always turned on, many tests fail because of a NPE.  The NPE results
			//from null passed here as TLCState, which eventually causes the NPE in tlc2.tool.TLCStateInfo.toString().  When I changed
			//this from printState to printMessage, nothing obvious broke. However, I suspect some corner case in the Toolbox breaks,
			//which is why I decided not to touch this. 
			MP.printState(EC.TLC_BACK_TO_STATE, new String[] { Integer.toString(stateNum), currentStateInfo.info.toString() }, (TLCState)null, stateNum);
		} else {
			MP.printMessage(EC.TLC_BACK_TO_STATE, new String[] {Integer.toString(stateNum), currentStateInfo.info.toString()});
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/expression/MarkerPropertyTester.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.expression;

import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.tool.tlc.TLCActivator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;

/**
 * Test if the marker exists 
 * @author <NAME>
 * @version $Id$
 */
public class MarkerPropertyTester extends PropertyTester
{
    /**
     * args: {markerId, attributeName}
     * expectedValue: {value of the attribute}  
     * 
     */
    public boolean test(Object receiver, String property, Object[] args, Object expectedValue)
    {
        if ("hasMarker".equals(property))
        {
            if (args.length > 0 && args[0] instanceof String)
            {
                // first attribute is the marker id
                String markerId = (String) args[0];
                String attributeName = null;
                
                if (args.length > 1 && args[1] instanceof String) 
                {
                    // second attribute is the attribute name
                    attributeName = (String) args[1];
                }
                
                if (receiver != null && receiver instanceof Model)
                {
                	// safeguard against non-existent files.
					// This might e.g. happen if another handler's changes
					// modifies the current selection before this property
					// tester is executed
                	final Model model = (Model) receiver;
                	final IFile file = model.getLaunchConfiguration().getFile();
                	if(!file.exists()) {
                		return false;
                	}
                	
                    try
                    {
						IMarker[] foundMarkers = file.findMarkers(markerId,
                                true, IResource.DEPTH_INFINITE);

                        
                        
                        // attribute name was not null, checking the value, if multiple markers are present,
                        // check the all of them
                        if (attributeName != null) 
                        {
                            // if there are markers, check the attributes
                            for (int i = 0; i < foundMarkers.length; i++)
                            {
                                Object value = foundMarkers[i].getAttribute(attributeName);
                                if (value == null || !value.equals(expectedValue)) 
                                {
                                    return false;
                                }
                            }
                            // either no markers at all (false), or all values are valid (true)
                            return foundMarkers.length > 0;
                        } else 
                        {
                            boolean result;
                            // no attribute to check, just check the presence of the markers
                            int expectedCount = -1;
                            if (expectedValue != null && expectedValue instanceof Integer)
                            {
                                expectedCount = ((Integer)expectedValue).intValue();
                            }
                            if (expectedCount == -1)
                            {
                                // just test if there are markers present
                                result = foundMarkers.length > 0;
                            } else
                            {
                                // compare with the number 
                                result = foundMarkers.length == expectedCount;
                            }
                            return result;
                        }

                    } catch (CoreException e)
                    {
                        TLCActivator.logError("Error testing markers", e);
                    }
                }
            }
        }
        return false;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/TLCServerRMI.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:34 PST by lamport
//      modified on Mon Jan  8 23:35:23 PST 2001 by yuanyu

package tlc2.tool.distributed;

import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;

import tlc2.tool.distributed.fp.FPSetRMI;
import tlc2.tool.distributed.fp.IFPSetManager;

/**
 * @version $Id$
 */
public interface TLCServerRMI extends Remote {
	public void registerWorker(TLCWorkerRMI worker)
			throws IOException;
	
	public void registerFPSet(FPSetRMI fpSet, String hostname) throws RemoteException;

	public Boolean getCheckDeadlock() throws RemoteException;

	public Boolean getPreprocess() throws RemoteException;

	public IFPSetManager getFPSetManager() throws RemoteException;

	public long getIrredPolyForFP() throws RemoteException;
	
	/**
	 * @return true iff server is done computing states
	 */
	public boolean isDone() throws RemoteException;
	
	/**
	 * @return The name and (potentially) path to the specification file 
	 * @throws RemoteException
	 */
	public String getSpecFileName() throws RemoteException;

	/**
	 * @return The name and (potentially) path to the configuration file
	 * @throws RemoteException
	 */
	public String getConfigFileName() throws RemoteException;
	
	/**
	 * Reads the given file from the server stripping the path the just the file name.
	 * @param file A full qualified or relative (to server spec dir) file name.
	 * @return the file requested
	 * @throws RemoteException
	 */
	public byte[] getFile(final String file) throws RemoteException;
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/modelexplorer/SavedModuleContributionItem.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.lamport.tla.toolbox.tool.tlc.handlers.OpenSavedModuleHandler;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.tool.tlc.util.ModelHelper;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import util.TLAConstants;

/**
 * This class is used to populate a menu with items that represent the versions
 * of modules saved in a run of TLC. Selecting an item opens the module in a
 * read-only editor as a page in the model editor.
 * 
 * @author <NAME>
 * 
 */
public class SavedModuleContributionItem extends CompoundContributionItem
{

    public SavedModuleContributionItem()
    {
        // TODO Auto-generated constructor stub
    }

    public SavedModuleContributionItem(String id)
    {
        super(id);
        // TODO Auto-generated constructor stub
    }

    protected IContributionItem[] getContributionItems()
    {
        /*
         * Does nothing if the active editor is not a model editor. The
         * following code gets the config file for the active model editor (if
         * it is the active editor), gets the model folder for that config,
         * iterates through all members of the model folder, adding a
         * contribution item for each member that has extension .tla and is not
         * TE.tla or MC.tla.
         */
        IEditorPart editor = UIHelper.getActiveEditor();
        if (editor instanceof ModelEditor)
        {
            IFolder modelFolder = ((ModelEditor) editor).getModel().getTargetDirectory();
            if (modelFolder != null && modelFolder.exists())
            {
                try
                {
                    /*
                     * The collection of command contribution items that will
                     * populate the menu and contain the command to be run when
                     * selected.
                     */
                    final List<IContributionItem> contributions = new ArrayList<IContributionItem>();

                    // get all resources in the model folder
                    IResource[] members = modelFolder.members();
                    for (int i = 0; i < members.length; i++)
                    {
                        /*
                         * We add to the menu an option to open every file that
                         * has exists, has extension .tla, and is not the TE or
                         * MC file.
                         * 
                         * On Nov 2011, DR added a null check to members[i].getFileExtension() which
                         * can return null for directories.
                         */
                        if (members[i].exists() && members[i].getFileExtension() != null
                                && members[i].getFileExtension().equals(ResourceHelper.TLA_EXTENSION)
                                && !members[i].getName().equals(TLAConstants.Files.MODEL_CHECK_TLA_FILE)
                                && !members[i].getName().equals(ModelHelper.TE_FILE_TLA))
                        {
                            Map<String, String> parameters = new HashMap<String, String>(1);
                            parameters.put(OpenSavedModuleHandler.PARAM_MODULE_PATH, members[i].getRawLocation()
                                    .toPortableString());
                            contributions.add(new CommandContributionItem(new CommandContributionItemParameter(UIHelper
                                    .getActiveWindow(), "toolbox.command.model.open.savedModule.",
                                    OpenSavedModuleHandler.COMMAND_ID, parameters, null, null, null, members[i]
                                            .getName(), null, "Opens the version saved in the last run of TLC.",
                                    SWT.PUSH, null, true)));
                        }
                    }

                    return (IContributionItem[]) contributions.toArray(new IContributionItem[contributions.size()]);
                } catch (CoreException e)
                {
                    TLCUIActivator.getDefault().logError("Error getting members of model folder " + modelFolder, e);
                }
            }
        }
        return new IContributionItem[0];
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/LimitingBlockSelector.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.TLCWorkerRMI;

public class LimitingBlockSelector extends BlockSelector {

	private int maximum;

	/**
	 * Limits the block size to 8192
	 * @param aTLCServer
	 */
	LimitingBlockSelector(final TLCServer aTLCServer) {
		this(aTLCServer, 8192);
	}
	
	LimitingBlockSelector(final TLCServer aTLCServer, final int aMaximum) {
		super(aTLCServer);
		this.maximum = aMaximum;
	}

	/**
	 * Limits the block size to a defined maximum if the dynamically calculated
	 * block size exceeds it
	 */
	protected long getBlockSize(final long size, final TLCWorkerRMI aWorker) {
		final long blockSize = super.getBlockSize(size, aWorker);
		if(blockSize > maximum) {
			return maximum;
		}
		return blockSize;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.selector.IBlockSelector#setMaxTXSize(int)
	 */
	public void setMaxTXSize(int aMaximum) {
		maximum = aMaximum;
	}
	
	protected int getMaximum() {
		return maximum;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/pprint/FormatException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:20:50 PST by lamport
//      modified on Fri Jun 11 17:50:09 PDT 1999 by yuanyu
//      modified on Thu Jun 10 14:52:19 EDT 1999 by tuttle

package tlc2.pprint;

public class FormatException extends Exception {

  FormatException(String s) {
    super(s);
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/InternTable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Wed Jul 11 00:00:55 PDT 2001 by yuanyu
package util;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import tlc2.output.EC;
import tlc2.tool.distributed.InternRMI;

/**
 * Storage for the UniqueStrings.  It stores them in a hash table using
 * simple linear hashing.
 * @see {@link UniqueString} for more information 
 * @author <NAME>, <NAME>
 */
public final class InternTable implements Serializable
{

    private int count;  // The number of entries in the table.
    private int length; // The length of the table.
    private int thresh; // The maximum number of entries before the table
                        // needs to be grown.
    private UniqueString[] table;  // The array that holds the entries.

    // SZ 10.04.2009: removed unused variable
    // made token counter to instance variable, since there is only one instance of the InternTable
    private int tokenCnt = 0; // the token counter

     private InternRMI internSource = null;

    public InternTable(int size)
    {
        this.table = new UniqueString[size];
        this.count = 0;
        this.length = size;
        this.thresh = this.length / 2;
    }
    
    private void grow()
    {
        UniqueString[] old = this.table;
        this.count = 0;
        this.length = 2 * this.length + 1;
        this.thresh = this.length / 2;
        this.table = new UniqueString[this.length];
        for (int i = 0; i < old.length; i++)
        {
            UniqueString var = old[i];
            if (var != null)
                this.put(var);
        }
    }

    private void put(UniqueString var)
    {
        // The following statement was added on 14 Feb 2012 by M.K.  
        // It calls the grow() method to enlarge the hash table storing
        // UniqueStrings.  This put() method is called both by the 
        // grow() method, and by the recover() method,
        // which is used to recreate the hash table when restarting from
        // a checkpoint.  The second use was apparently forgotten by Yuan Yu 
        // in the original code, which never called the grow() method,
        // causing TLC to hang when restarting from a checkpoint
        // for a spec in which the table had grown.  Amazingly, this was
        // never discovered in approximately 10 years of use.
        if (this.count >= this.thresh)
            this.grow();
        
        int loc = (var.hashCode() & 0x7FFFFFFF) % length;
        while (true)
        {
            UniqueString ent = this.table[loc];
            if (ent == null)
            {
                this.table[loc] = var;
                this.count++;
                return;
            }
            loc = (loc + 1) % length;
        }
    }

    /**
     * If there exists a UniqueString object obj such that obj.getTok()
     * equals id, then get(id) returns obj; otherwise, it returns null.
     */
    public UniqueString get(int id)
    {
        for (int i = 0; i < this.table.length; i++)
        {
            UniqueString var = this.table[i];
            if (var != null && var.getTok() == id)
            {
                return var;
            }
        }
        return null;
    }

    /**
     * Create the unique string based on the token
     */
//    private UniqueString create(String str)
//    {
//        return new UniqueString(str, ++tokenCnt);
//    }

	private UniqueString create(String str) {
		if (this.internSource == null) {
			return new UniqueString(str, ++tokenCnt);
		}
		try {
			return this.internSource.intern(str);
		} catch (Exception e) {
			Assert.fail("Failed to intern " + str + ".");
		}
		return null; // make compiler happy
	}

    public UniqueString put(String str)
    {
        synchronized (InternTable.class)
        {
            if (this.count >= this.thresh)
                this.grow();
            int loc = (str.hashCode() & 0x7FFFFFFF) % length;
            while (true)
            {
                UniqueString ent = this.table[loc];
                if (ent == null)
                {
                    UniqueString var = this.create(str);
                    this.table[loc] = var;
                    this.count++;
                    return var;
                }
                if (ent.toString().equals(str))
                {
                    return ent;
                }
                loc = (loc + 1) % length;
            }
        }
    }

    public void beginChkpt(String filename) throws IOException
    {
        BufferedDataOutputStream dos = new BufferedDataOutputStream(this.chkptName(filename, "tmp"));
        dos.writeInt(tokenCnt);
        for (int i = 0; i < this.table.length; i++)
        {
            UniqueString var = this.table[i];
            if (var != null)
                var.write(dos);
        }
        dos.close();
    }

    public void commitChkpt(String filename) throws IOException
    {
        File oldChkpt = new File(this.chkptName(filename, "chkpt"));
        File newChkpt = new File(this.chkptName(filename, "tmp"));
        if ((oldChkpt.exists() && !oldChkpt.delete()) || !newChkpt.renameTo(oldChkpt))
        {
            throw new IOException("InternTable.commitChkpt: cannot delete " + oldChkpt);
        }
    }

    public synchronized void recover(String filename) throws IOException
    {
        BufferedDataInputStream dis = new BufferedDataInputStream(this.chkptName(filename, "chkpt"));
        tokenCnt = dis.readInt();
        try
        {
            while (!dis.atEOF())
            {
                UniqueString var = UniqueString.read(dis);
                this.put(var);
            }
        } catch (EOFException e)
        {
            Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e.getMessage());
        }
        dis.close();
    }

    private String chkptName(String filename, String ext)
    {
        return filename + FileUtil.separator + "vars." + ext;
    }

	public void setSource(InternRMI source) {
		this.internSource = source;
	}

	public UniqueString find(final String str) {
        for (int i = 0; i < this.table.length; i++)
        {
            UniqueString var = this.table[i];
            if (var != null && str.equals(var.toString()))
            {
                return var;
            }
        }
        return null;
	}

	public final Map<String, UniqueString> toMap() {
		final Map<String, UniqueString> map = new HashMap<String, UniqueString>();
		for (int i = 0; i < this.table.length; i++) {
			UniqueString var = this.table[i];
			if (var != null) {
				map.put(var.toString(), var);
			}
		}
		return map;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/output/BroadcastMessagePrinterRecorder.java<|end_filename|>
package tlc2.output;

import java.util.HashSet;
import java.util.Set;

/**
 * Pushes recorded events to recorders which subscribe to this broadcaster.
 */
public class BroadcastMessagePrinterRecorder implements IMessagePrinterRecorder {
	
	/**
	 * The list of recorders subscribed to this broadcaster.
	 */
	private Set<IMessagePrinterRecorder> subscribers = new HashSet<IMessagePrinterRecorder>();
	
	@Override
	public void record(int code, Object... objects) {
		for (IMessagePrinterRecorder recorder : this.subscribers)
		{
			recorder.record(code, objects);
		}
	}
	
	/**
	 * Subscribes a recorder to this broadcaster.
	 * This function is idempotent; recorders cannot be subscribed twice.
	 */
	public void subscribe(final IMessagePrinterRecorder recorder)
	{
		this.subscribers.add(recorder);
	}
	
	/**
	 * Unsubscribes a recorder from this broadcaster.
	 * @param recorder The recorder the unsubscribe.
	 */
	public void unsubscribe(final IMessagePrinterRecorder recorder)
	{
		this.subscribers.remove(recorder);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/source/ITLAPMOutputSourceListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.source;

import org.eclipse.core.runtime.IPath;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.TLAPMMessage;

/**
 * Interface for listening to data from TLAPM
 * output through the {@link TLAPMOutputSourceRegistry}
 * This interface is not used.
 * 
 * @author <NAME>
 *
 */
public interface ITLAPMOutputSourceListener
{

    /**
     * Passes new {@link ITLAPMData} to the listener.
     * 
     * @param data
     */
    public void newData(TLAPMMessage data);

    /**
     * The full file system path for which this
     * listener wants to receive TLAPM output.
     * 
     * @return
     */
    public IPath getFullModulePath();

    /**
     * Called to dispose of the listener when
     * it is no longer needed.
     */
    public void dispose();

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/FrontEnd.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

/***************************************************************************
* This module seems not to be used anywhere.  Almost all its methods have  *
* null implementations.                                                    *
***************************************************************************/


import tla2sany.parser.ParseException;
import tla2sany.st.TreeNode;
import util.FilenameToStream;
import util.NamedInputStream;

public class FrontEnd implements ASTConstants {
  /**
   * This class contains the methods by which a tool calls the Front End
   * to parse input and to create a semantic tree, and for various other
   * interactions.  The canonical code to produce a semantic analysis of
   * the module specified by file name M is:                            
   *                                                                    
   *    // First define ntfs to be a NameToFileIStream object.  (This   
   *    // object has no fields, and is used to pass a toStream method a
   *    // an argument to the parseAll method.)                         
   *    StringToNamedInputStream ntfs = new NameToFileIStream();               
   *                                                                    
   *    // Next set astn to an array of CST nodes of parsed             
   *    // modules--the last element of the array being the CST node    
   *    // for module M, and the other elements being for modules       
   *    // extended or instantiated (perhaps indirectly) by M.          
   *    TreeNode[] astn =                                                
   *          parseAll(NameToFileIStream.toStream(M), // the input stream
   *                   SemanticNode.ModuleKind,       // it's a module
   *                   ntfs)                                         
   *                                                                    
   *    // Successively analyze each of the modules in the context      
   *    // produced by analyzing the previous ones.                     
   *    Context ctxt = Context.InitialContext ;  // the initial context
   *    SemanticNode node ;   
   *    for (int i = 0; i < astn.length; i++){                          
   *      // Set node to the result of analyzing astn[i] in the        
   *      // context ctxt                                               
   *      node = semanticAnalysis(astn[i], ctxt);     
   *    }
   *
   *    ModuleNode node = (ModuleNode)node;
   *    // node is now the ModuleNode corresponding to module M.        
   */

  /**
   * This method calls the parser to parse the NamedInputStream
   * istream as a CST node of type cstNodeType.  Initially, this might
   * be implemented only when cstNodeType specifies a module node.  If
   * the parser encounters an EXTENDS or INSTANCE statement with a
   * module name "Foo", it uses cobj.toIStream("Foo") as the
   * NamedInputStream that should contain module "Foo".
   *                                                                  
   * The method returns an array of TreeNode's.  The last is the CSTNod
   * obtained by parsing istream as a node of type cstNodeType.  The  
   * first elements of the array are module nodes obtained by parsing 
   * the extended or instantiated modules.  These are listed in "logic
   * order"--that is, if module M1 extends or instances module M2, the
   * the TreeNode of M2 precedes that of M1 in the array.              
   *                                                                  
   * A tool, such as a specification browser, might need to know about
   * all the included modules as well as the module that constitutes the
   * specification.
   */
  public static TreeNode[] parseAll(NamedInputStream nis, int nkind,
				    FilenameToStream cobj)
  throws ParseException {
    return null;
  }

  /**
   * This method parses just the single stream to create a TreeNode.
   * It does not look for any of the modules that appear in EXTENDS or
   * INSTANCE statements.  This method is included for completeness.
   * It's not clear what tool would use it.  (Perhaps an interactive
   * editor that wants to do a quick check of what the user has just
   * typed?)
   */
  public static TreeNode parseOne(NamedInputStream nis, int nkind)
    throws ParseException {
    return null;
  }

  /**
   * This method returns a SemanticNode.  The SemanticNode is the 
   * meaning of the TreeNode cst, interpreted in the context ctxt, to  
   * produce a node whose kind field is nkind.  The context ctxt is
   * updated to include the context information from analyzing cst.
   * The precise meaning of this new context is not yet specified in      
   * general.  However, when nkind specifies a module node, and ctxt is
   * the context obtained by a series of calls of semanticAnalysis for
   * module nodes, then the returned Context is ctxt augmented by the 
   * assignment of the name of the module cst to the returned SemNode.
   */
  public static SemanticNode semanticAnalysis(TreeNode cst, int nkind,
					      Context ctxt)
    throws ParseException {
    return null;
  }

  /* Returns a new, unused tool id.  */
  private static int idCnt = 0;

  public static int getToolId() { return idCnt++; }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MemFPSet.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.RemoteException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCTrace;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;

/**
 * A <code>MemFPSet</code> is a subclass of <code>FPSet</code> and a
 * memory-based fingerprint set implementations. 
 * As required by <code>FPSet</code>, this class must guarantee that
 * its methods are thread-safe.
 */

public class MemFPSet extends FPSet {
  private String metadir;
  private String filename;

  /**
   * The load factor and initial capacity for the hashtable.
   */
  private static final int MaxLoad = 20;
  private static final int LogInitialCapacity = 16;

  /* The hash table used to represent the set.  */
  private long[][] table;

  /* The total number of entries in the set.   */
  private long count;

  /* Rehashes the table when count exceeds this threshold.  */
  private long threshold;
    
  /**
   * The bit-mask used in hashing fingerprints.  Relies on two assumptions:
   *  (1) table.length is a power of 2.
   *  (2) fingerprints are so random that extracting parts of their bits
   *      makes a good hash function.
   */
  private int mask;

  public MemFPSet() throws RemoteException {
	  this(new FPSetConfiguration());
  }
  
  /* Constructs a new, empty FPSet.  */
  public MemFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
	super(fpSetConfig);
    int initialCapacity = 1 << LogInitialCapacity;
    this.count = 0;
    this.threshold = (initialCapacity * MaxLoad);
    this.table = new long[initialCapacity][];
    this.mask = initialCapacity - 1;
  }

  public final FPSet init(int numThreads, String metadir, String filename) {
    this.metadir = metadir;
    this.filename = filename;
	return this;
  }
    
  /**
   * Returns the number of fingerprints in this set.
   * @return  the number of fingerprints in this set.
   */
  public final synchronized long size() { return this.count; }

  public final synchronized long sizeof() {
    long size = 28; // 8 (ptr table) + 8 (long count) + 8 (long threshold) + 4 (int mask)
    size += 16 + (this.table.length * 8); // for this.table
    for (int i = 0; i < this.table.length; i++) {
      if (this.table[i] != null) {
	size += 16 + (this.table[i].length * 8);
      }
    }
    return size;
  }

  /**
   * Tests if the specified fingerprint is in this set.  As a side
   * effect, updates the set to contain the fingerprint.
   * 
   * @param   fp    the fingerprint.
   * @return  <code>true</code> if the specified fingerprint is 
   in this set; <code>false</code> otherwise.
   * <p>
   */
  public synchronized boolean put(long fp) {
    int index = (int)(fp & this.mask);
    long[] list = this.table[index];

    // Test if the fingerprint is already in the hashtable.
    if (list != null) {
      int listlen = list.length;
      for (int i = 0; i < listlen; i++) {
	if (list[i] == fp) return true;
      }
    }

    if (count >= threshold) {
      // If the threshold is exceeded, rehash the table and
      // recompute the index.
      rehash();
      index = (int)(fp & this.mask);
      list = this.table[index];
    } 

    // Creates the new entry.
    int len = (list == null ? 0 : list.length);
    long[] newList = new long[len+1];
    if (list != null) System.arraycopy(list, 0, newList, 0, len);
    newList[len] = fp;
    this.table[index] = newList;
	    
    this.count++;
    return false;
  }

  public synchronized boolean contains(long fp) {
    int index = (int)(fp & this.mask);
    long[] list = this.table[index];

    // Test if the fingerprint is already in the hashtable.
    if (list != null) {
      int listlen = list.length;
      for (int i = 0; i < listlen; i++) {
	if (list[i] == fp) return true;
      }
    }
    return false;
  }

  /**
   * Rehashes the contents of the hashtable into a hashtable with a
   * larger capacity. This method is called automatically when the
   * number of items in the hashtable exceeds this hashtable's
   * capacity and load factor.
   */
  private final void rehash() {
    long min = this.count, max = 0;
    long[][] oldTable = this.table;
    int oldCapacity = oldTable.length;
    long[][] newTable = new long[oldCapacity * 2][];
    final int onebitmask = oldCapacity;

    for (int i = 0; i < oldCapacity; i++) {
      long[] list = oldTable[i];
      if (list != null) {
	// The entries in list will be distributed over two arrays in
	// the new hash table.
	// count how big each list will be
	int cnt0 = 0;
	int cnt1 = 0;
	int listlen = list.length;
	if (listlen < min) min = listlen;
	if (listlen > max) max = listlen;
	for (int j = 0; j < listlen; j++) {
	  if ((list[j] & onebitmask) == 0)
	    cnt0++;
	  else
	    cnt1++;
	}
        	    
	// handle special cases if either list is empty
	if (cnt0 == 0) {
	  newTable[i + oldCapacity] = list;
	}
	else if (cnt1 == 0) {
	  newTable[i] = list;
	}
	else {
	  // allocate two new arrays
	  long[] list0 = new long[cnt0]; 
	  long[] list1 = new long[cnt1]; 
            	  
	  // copy the entries from the old list into the two new ones
	  for (int j = 0; j < listlen; j++) {
	    if ((list[j] & onebitmask) == 0) 
	      list0[--cnt0] = list[j];
	    else
	      list1[--cnt1] = list[j];
	  }
            	    
	  // install new arrays in new table
	  newTable[i] = list0;
	  newTable[i + oldCapacity] = list1;
	}
      }
    }
    this.threshold *= 2;
    this.table = newTable;
    this.mask = newTable.length - 1;
  }

  public final void exit(boolean cleanup) throws IOException {
	super.exit(cleanup);
    if (cleanup) {
      // Delete the metadata directory:
      File file = new File(this.metadir);
      FileUtil.deleteDir(file, true);
    }
    String hostname = InetAddress.getLocalHost().getHostName();    
    MP.printMessage(EC.TLC_FP_COMPLETED, hostname);
    System.exit(0);    
  }

  public final long checkFPs() {
    long dis = Long.MAX_VALUE;
    for (int i = 0; i < this.table.length; i++) {
      long[] bucket = this.table[i];
      if (bucket != null) {
	for (int j = 0; j < bucket.length; j++) {
	  for (int k = j+1; k < bucket.length; k++) {
	    dis = Math.min(dis, Math.abs(bucket[j]-bucket[k]));
	  }
	  for (int k = i+1; k < this.table.length; k++) {
	    long[] bucket1 = this.table[k];
	    if (bucket1 != null) {
	      for (int m = 0; m < bucket1.length; m++) {
		long x = bucket[j];
		long y = bucket1[m];
		long dis1 = (x > y) ? x-y : y-x;
		if (dis1 >= 0) {
		  dis = Math.min(dis, dis1);
		}
	      }
	    }
	  }
	}
      }
    }
    return dis;
  }

  // Checkpoint.
  public final void beginChkpt(String fname) throws IOException {
    BufferedDataOutputStream dos =
      new BufferedDataOutputStream(this.chkptName(fname, "tmp"));
    for (int i = 0; i < this.table.length; i++) {
      long[] bucket = this.table[i];
      if (bucket != null) {
	for (int j = 0; j < bucket.length; j++) {
	  dos.writeLong(bucket[j]);
	}
      }
    }
    dos.close();
  }
      
  final public void commitChkpt(String fname) throws IOException {
    File oldChkpt = new File(this.chkptName(fname, "chkpt"));
    File newChkpt = new File(this.chkptName(fname, "tmp"));
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemFPSet.commitChkpt: cannot delete " + oldChkpt);
    }
  }
  
  public final void recover(String fname) throws IOException {
    BufferedDataInputStream dis = 
      new BufferedDataInputStream(this.chkptName(fname, "chkpt"));
    try {
      while (!dis.atEOF()) {
          Assert.check(!this.put(dis.readLong()), EC.TLC_FP_NOT_IN_SET);
      }
    }
    catch (EOFException e) {
      Assert.fail(EC.SYSTEM_DISK_IO_ERROR_FOR_FILE, "checkpoints");
    }
    dis.close();
  }
  
  final public void beginChkpt() throws IOException {
    this.beginChkpt(this.filename);
  }

  final public void commitChkpt() throws IOException {
    this.commitChkpt(this.filename);
  }
    
  final public void recover(TLCTrace trace) throws IOException {
    this.recover(this.filename);
  }

  public final void recoverFP(long fp) throws IOException {
    Assert.check(!this.put(fp), EC.TLC_FP_NOT_IN_SET);
  }
  
  final private String chkptName(String fname, String ext) {
    return this.metadir + FileUtil.separator + fname + ".fp." + ext;
  }

}


<|start_filename|>general/tests/test2.bat<|end_filename|>
echo "STARTING"
java -mx100m tlc2.TLC -cleanup  test1
java -mx100m tlc2.TLC -cleanup  test2
java -mx100m tlc2.TLC -cleanup  test3
java -mx100m tlc2.TLC -cleanup  test4
java -mx100m tlc2.TLC -cleanup  test5
java -mx100m tlc2.TLC -cleanup  test6
java -mx100m tlc2.TLC -cleanup  test7
java -mx100m tlc2.TLC -cleanup  test8
java -mx100m tlc2.TLC -cleanup  test9
java -mx100m tlc2.TLC -cleanup  test10
java -mx100m tlc2.TLC -cleanup  test11
java -mx100m tlc2.TLC -cleanup  test12
java -mx100m tlc2.TLC -cleanup  test13
java -mx100m tlc2.TLC -cleanup  test14
java -mx100m tlc2.TLC -cleanup  test15
java -mx100m tlc2.TLC -cleanup  test16
java -mx100m tlc2.TLC -cleanup  test17
java -mx100m tlc2.TLC -cleanup  test18
java -mx100m tlc2.TLC -cleanup  test19
java -mx100m tlc2.TLC -cleanup  test20
java -mx100m tlc2.TLC -cleanup  test21
java -mx100m tlc2.TLC -cleanup  test22
java -mx100m tlc2.TLC -cleanup  test23
java -mx100m tlc2.TLC -cleanup  test24
java -mx100m tlc2.TLC -cleanup  test25
java -mx100m tlc2.TLC -cleanup  test26
java -mx100m tlc2.TLC -cleanup  test27
java -mx100m tlc2.TLC -cleanup  test28
java -mx100m tlc2.TLC -cleanup  test29
java -mx100m tlc2.TLC -cleanup  test30
java -mx100m tlc2.TLC -cleanup  test31
java -mx100m tlc2.TLC -cleanup  test32
java -mx100m tlc2.TLC -cleanup  test33
java -mx100m tlc2.TLC -cleanup  test34
java -mx100m tlc2.TLC -cleanup  test35
java -mx100m tlc2.TLC -cleanup  test36
java -mx100m tlc2.TLC -cleanup  test37
java -mx100m tlc2.TLC -cleanup  test38
java -mx100m tlc2.TLC -cleanup  test39
java -mx100m tlc2.TLC -cleanup  test40
java -mx100m tlc2.TLC -cleanup  test41
java -mx100m tlc2.TLC -cleanup  test42
java -mx100m tlc2.TLC -cleanup  test43
java -mx100m tlc2.TLC -cleanup  test44
java -mx100m tlc2.TLC -cleanup  test45
java -mx100m tlc2.TLC -cleanup  test46
java -mx100m tlc2.TLC -cleanup  test47
java -mx100m tlc2.TLC -cleanup  test48
java -mx100m tlc2.TLC -cleanup  test49
java -mx100m tlc2.TLC -cleanup  test50
java -mx100m tlc2.TLC -cleanup  test51
java -mx100m tlc2.TLC -cleanup  test52
java -mx100m tlc2.TLC -cleanup  test53
java -mx100m tlc2.TLC -cleanup  test54
java -mx100m tlc2.TLC -cleanup  test55
java -mx100m tlc2.TLC -cleanup  test56
java -mx100m tlc2.TLC -cleanup  test57
java -mx100m tlc2.TLC -cleanup  test58
java -mx100m tlc2.TLC -cleanup  test59
java -mx100m tlc2.TLC -cleanup  test60
java -mx100m tlc2.TLC -cleanup  test61
java -mx100m tlc2.TLC -cleanup  test62
java -mx100m tlc2.TLC -cleanup  test63
java -mx100m tlc2.TLC -cleanup  test201
java -mx100m tlc2.TLC -cleanup  test202
java -mx100m tlc2.TLC -cleanup  test203
java -mx100m tlc2.TLC -cleanup  test204
java -mx100m tlc2.TLC -cleanup  test205
java -mx100m tlc2.TLC -cleanup  test206
java -mx100m tlc2.TLC -cleanup  test207
java -mx100m tlc2.TLC -cleanup  test208
java -mx100m tlc2.TLC -cleanup  test209
java tla2sany.SANY test210
java tla2sany.SANY test211
java tla2sany.SANY test212
java tla2sany.SANY test213
java tla2sany.SANY test214
java tla2sany.SANY test215
echo "DONE"


<|start_filename|>tlatools/org.lamport.tlatools/src/org/apache/commons/math3/exception/util/LocalizedFormats.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.math3.exception.util;

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * Enumeration for localized messages formats used in exceptions messages.
 * <p>
 * The constants in this enumeration represent the available
 * formats as localized strings. These formats are intended to be
 * localized using simple properties files, using the constant
 * name as the key and the property value as the message format.
 * The source English format is provided in the constants themselves
 * to serve both as a reminder for developers to understand the parameters
 * needed by each format, as a basis for translators to create
 * localized properties files, and as a default format if some
 * translation is missing.
 * </p>
 * @since 2.2
 */
public enum LocalizedFormats implements Localizable {

    // CHECKSTYLE: stop MultipleVariableDeclarations
    // CHECKSTYLE: stop JavadocVariable

    ARGUMENT_OUTSIDE_DOMAIN("Argument {0} outside domain [{1} ; {2}]"),
    ARRAY_SIZE_EXCEEDS_MAX_VARIABLES("array size cannot be greater than {0}"),
    ARRAY_SIZES_SHOULD_HAVE_DIFFERENCE_1("array sizes should have difference 1 ({0} != {1} + 1)"),
    ARRAY_SUMS_TO_ZERO("array sums to zero"),
    ASSYMETRIC_EIGEN_NOT_SUPPORTED("eigen decomposition of assymetric matrices not supported yet"),
    AT_LEAST_ONE_COLUMN("matrix must have at least one column"),
    AT_LEAST_ONE_ROW("matrix must have at least one row"),
    BANDWIDTH("bandwidth ({0})"),
    BESSEL_FUNCTION_BAD_ARGUMENT("Bessel function of order {0} cannot be computed for x = {1}"),
    BESSEL_FUNCTION_FAILED_CONVERGENCE("Bessel function of order {0} failed to converge for x = {1}"),
    BINOMIAL_INVALID_PARAMETERS_ORDER("must have n >= k for binomial coefficient (n, k), got k = {0}, n = {1}"),
    BINOMIAL_NEGATIVE_PARAMETER("must have n >= 0 for binomial coefficient (n, k), got n = {0}"),
    CANNOT_CLEAR_STATISTIC_CONSTRUCTED_FROM_EXTERNAL_MOMENTS("statistics constructed from external moments cannot be cleared"),
    CANNOT_COMPUTE_0TH_ROOT_OF_UNITY("cannot compute 0-th root of unity, indefinite result"),
    CANNOT_COMPUTE_BETA_DENSITY_AT_0_FOR_SOME_ALPHA("cannot compute beta density at 0 when alpha = {0,number}"),
    CANNOT_COMPUTE_BETA_DENSITY_AT_1_FOR_SOME_BETA("cannot compute beta density at 1 when beta = %.3g"),
    CANNOT_COMPUTE_NTH_ROOT_FOR_NEGATIVE_N("cannot compute nth root for null or negative n: {0}"),
    CANNOT_DISCARD_NEGATIVE_NUMBER_OF_ELEMENTS("cannot discard a negative number of elements ({0})"),
    CANNOT_FORMAT_INSTANCE_AS_3D_VECTOR("cannot format a {0} instance as a 3D vector"),
    CANNOT_FORMAT_INSTANCE_AS_COMPLEX("cannot format a {0} instance as a complex number"),
    CANNOT_FORMAT_INSTANCE_AS_REAL_VECTOR("cannot format a {0} instance as a real vector"),
    CANNOT_FORMAT_OBJECT_TO_FRACTION("cannot format given object as a fraction number"),
    CANNOT_INCREMENT_STATISTIC_CONSTRUCTED_FROM_EXTERNAL_MOMENTS("statistics constructed from external moments cannot be incremented"),
    CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR("cannot normalize a zero norm vector"),
    CANNOT_RETRIEVE_AT_NEGATIVE_INDEX("elements cannot be retrieved from a negative array index {0}"),
    CANNOT_SET_AT_NEGATIVE_INDEX("cannot set an element at a negative index {0}"),
    CANNOT_SUBSTITUTE_ELEMENT_FROM_EMPTY_ARRAY("cannot substitute an element from an empty array"),
    CANNOT_TRANSFORM_TO_DOUBLE("Conversion Exception in Transformation: {0}"),
    CARDAN_ANGLES_SINGULARITY("Cardan angles singularity"),
    CLASS_DOESNT_IMPLEMENT_COMPARABLE("class ({0}) does not implement Comparable"),
    CLOSE_VERTICES("too close vertices near point ({0}, {1}, {2})"),
    CLOSEST_ORTHOGONAL_MATRIX_HAS_NEGATIVE_DETERMINANT("the closest orthogonal matrix has a negative determinant {0}"),
    COLUMN_INDEX_OUT_OF_RANGE("column index {0} out of allowed range [{1}, {2}]"),
    COLUMN_INDEX("column index ({0})"), /* keep */
    CONSTRAINT("constraint"), /* keep */
    CONTINUED_FRACTION_INFINITY_DIVERGENCE("Continued fraction convergents diverged to +/- infinity for value {0}"),
    CONTINUED_FRACTION_NAN_DIVERGENCE("Continued fraction diverged to NaN for value {0}"),
    CONTRACTION_CRITERIA_SMALLER_THAN_EXPANSION_FACTOR("contraction criteria ({0}) smaller than the expansion factor ({1}).  This would lead to a never ending loop of expansion and contraction as a newly expanded internal storage array would immediately satisfy the criteria for contraction."),
    CONTRACTION_CRITERIA_SMALLER_THAN_ONE("contraction criteria smaller than one ({0}).  This would lead to a never ending loop of expansion and contraction as an internal storage array length equal to the number of elements would satisfy the contraction criteria."),
    CONVERGENCE_FAILED("convergence failed"), /* keep */
    CROSSING_BOUNDARY_LOOPS("some outline boundary loops cross each other"),
    CROSSOVER_RATE("crossover rate ({0})"),
    CUMULATIVE_PROBABILITY_RETURNED_NAN("Cumulative probability function returned NaN for argument {0} p = {1}"),
    DIFFERENT_ROWS_LENGTHS("some rows have length {0} while others have length {1}"),
    DIFFERENT_ORIG_AND_PERMUTED_DATA("original and permuted data must contain the same elements"),
    DIGEST_NOT_INITIALIZED("digest not initialized"),
    DIMENSIONS_MISMATCH_2x2("got {0}x{1} but expected {2}x{3}"), /* keep */
    DIMENSIONS_MISMATCH_SIMPLE("{0} != {1}"), /* keep */
    DIMENSIONS_MISMATCH("dimensions mismatch"), /* keep */
    DISCRETE_CUMULATIVE_PROBABILITY_RETURNED_NAN("Discrete cumulative probability function returned NaN for argument {0}"),
    DISTRIBUTION_NOT_LOADED("distribution not loaded"),
    DUPLICATED_ABSCISSA_DIVISION_BY_ZERO("duplicated abscissa {0} causes division by zero"),
    EDGE_CONNECTED_TO_ONE_FACET("edge joining points ({0}, {1}, {2}) and ({3}, {4}, {5}) is connected to one facet only"),
    ELITISM_RATE("elitism rate ({0})"),
    EMPTY_CLUSTER_IN_K_MEANS("empty cluster in k-means"),
    EMPTY_INTERPOLATION_SAMPLE("sample for interpolation is empty"),
    EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY("empty polynomials coefficients array"), /* keep */
    EMPTY_SELECTED_COLUMN_INDEX_ARRAY("empty selected column index array"),
    EMPTY_SELECTED_ROW_INDEX_ARRAY("empty selected row index array"),
    EMPTY_STRING_FOR_IMAGINARY_CHARACTER("empty string for imaginary character"),
    ENDPOINTS_NOT_AN_INTERVAL("endpoints do not specify an interval: [{0}, {1}]"),
    EQUAL_VERTICES_IN_SIMPLEX("equal vertices {0} and {1} in simplex configuration"),
    EULER_ANGLES_SINGULARITY("Euler angles singularity"),
    EVALUATION("evaluation"), /* keep */
    EXPANSION_FACTOR_SMALLER_THAN_ONE("expansion factor smaller than one ({0})"),
    FACET_ORIENTATION_MISMATCH("facets orientation mismatch around edge joining points ({0}, {1}, {2}) and ({3}, {4}, {5})"),
    FACTORIAL_NEGATIVE_PARAMETER("must have n >= 0 for n!, got n = {0}"),
    FAILED_BRACKETING("number of iterations={4}, maximum iterations={5}, initial={6}, lower bound={7}, upper bound={8}, final a value={0}, final b value={1}, f(a)={2}, f(b)={3}"),
    FAILED_FRACTION_CONVERSION("Unable to convert {0} to fraction after {1} iterations"),
    FIRST_COLUMNS_NOT_INITIALIZED_YET("first {0} columns are not initialized yet"),
    FIRST_ELEMENT_NOT_ZERO("first element is not 0: {0}"),
    FIRST_ROWS_NOT_INITIALIZED_YET("first {0} rows are not initialized yet"),
    FRACTION_CONVERSION_OVERFLOW("Overflow trying to convert {0} to fraction ({1}/{2})"),
    FUNCTION_NOT_DIFFERENTIABLE("function is not differentiable"),
    FUNCTION_NOT_POLYNOMIAL("function is not polynomial"),
    GCD_OVERFLOW_32_BITS("overflow: gcd({0}, {1}) is 2^31"),
    GCD_OVERFLOW_64_BITS("overflow: gcd({0}, {1}) is 2^63"),
    HOLE_BETWEEN_MODELS_TIME_RANGES("{0} wide hole between models time ranges"),
    ILL_CONDITIONED_OPERATOR("condition number {1} is too high "),
    INCONSISTENT_STATE_AT_2_PI_WRAPPING("inconsistent state at 2\u03c0 wrapping"),
    INDEX_LARGER_THAN_MAX("the index specified: {0} is larger than the current maximal index {1}"),
    INDEX_NOT_POSITIVE("index ({0}) is not positive"),
    INDEX_OUT_OF_RANGE("index {0} out of allowed range [{1}, {2}]"),
    INDEX("index ({0})"), /* keep */
    NOT_FINITE_NUMBER("{0} is not a finite number"), /* keep */
    INFINITE_BOUND("interval bounds must be finite"),
    ARRAY_ELEMENT("value {0} at index {1}"), /* keep */
    INFINITE_ARRAY_ELEMENT("Array contains an infinite element, {0} at index {1}"),
    INFINITE_VALUE_CONVERSION("cannot convert infinite value"),
    INITIAL_CAPACITY_NOT_POSITIVE("initial capacity ({0}) is not positive"),
    INITIAL_COLUMN_AFTER_FINAL_COLUMN("initial column {1} after final column {0}"),
    INITIAL_ROW_AFTER_FINAL_ROW("initial row {1} after final row {0}"),
    @Deprecated
    INPUT_DATA_FROM_UNSUPPORTED_DATASOURCE("input data comes from unsupported datasource: {0}, supported sources: {1}, {2}"),
    INSTANCES_NOT_COMPARABLE_TO_EXISTING_VALUES("instance of class {0} not comparable to existing values"),
    INSUFFICIENT_DATA("insufficient data"),
    INSUFFICIENT_DATA_FOR_T_STATISTIC("insufficient data for t statistic, needs at least 2, got {0}"),
    INSUFFICIENT_DIMENSION("insufficient dimension {0}, must be at least {1}"),
    DIMENSION("dimension ({0})"), /* keep */
    INSUFFICIENT_OBSERVED_POINTS_IN_SAMPLE("sample contains {0} observed points, at least {1} are required"),
    INSUFFICIENT_ROWS_AND_COLUMNS("insufficient data: only {0} rows and {1} columns."),
    INTEGRATION_METHOD_NEEDS_AT_LEAST_TWO_PREVIOUS_POINTS("multistep method needs at least {0} previous steps, got {1}"),
    INTERNAL_ERROR("internal error, please fill a bug report at {0}"),
    INVALID_BINARY_DIGIT("invalid binary digit: {0}"),
    INVALID_BINARY_CHROMOSOME("binary mutation works on BinaryChromosome only"),
    INVALID_BRACKETING_PARAMETERS("invalid bracketing parameters:  lower bound={0},  initial={1}, upper bound={2}"),
    INVALID_FIXED_LENGTH_CHROMOSOME("one-point crossover only works with fixed-length chromosomes"),
    INVALID_IMPLEMENTATION("required functionality is missing in {0}"),
    INVALID_INTERVAL_INITIAL_VALUE_PARAMETERS("invalid interval, initial value parameters:  lower={0}, initial={1}, upper={2}"),
    INVALID_ITERATIONS_LIMITS("invalid iteration limits: min={0}, max={1}"),
    INVALID_MAX_ITERATIONS("bad value for maximum iterations number: {0}"),
    NOT_ENOUGH_DATA_REGRESSION("the number of observations is not sufficient to conduct regression"),
    INVALID_REGRESSION_ARRAY("input data array length = {0} does not match the number of observations = {1} and the number of regressors = {2}"),
    INVALID_REGRESSION_OBSERVATION("length of regressor array = {0} does not match the number of variables = {1} in the model"),
    INVALID_ROUNDING_METHOD("invalid rounding method {0}, valid methods: {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}), {11} ({12}), {13} ({14}), {15} ({16})"),
    ITERATOR_EXHAUSTED("iterator exhausted"),
    ITERATIONS("iterations"), /* keep */
    LCM_OVERFLOW_32_BITS("overflow: lcm({0}, {1}) is 2^31"),
    LCM_OVERFLOW_64_BITS("overflow: lcm({0}, {1}) is 2^63"),
    LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE("list of chromosomes bigger than maxPopulationSize"),
    LOESS_EXPECTS_AT_LEAST_ONE_POINT("Loess expects at least 1 point"),
    LOWER_BOUND_NOT_BELOW_UPPER_BOUND("lower bound ({0}) must be strictly less than upper bound ({1})"), /* keep */
    LOWER_ENDPOINT_ABOVE_UPPER_ENDPOINT("lower endpoint ({0}) must be less than or equal to upper endpoint ({1})"),
    MAP_MODIFIED_WHILE_ITERATING("map has been modified while iterating"),
    MULTISTEP_STARTER_STOPPED_EARLY("multistep integrator starter stopped early, maybe too large step size"),
    EVALUATIONS("evaluations"), /* keep */
    MAX_COUNT_EXCEEDED("maximal count ({0}) exceeded"), /* keep */
    MAX_ITERATIONS_EXCEEDED("maximal number of iterations ({0}) exceeded"),
    MINIMAL_STEPSIZE_REACHED_DURING_INTEGRATION("minimal step size ({1,number,0.00E00}) reached, integration needs {0,number,0.00E00}"),
    MISMATCHED_LOESS_ABSCISSA_ORDINATE_ARRAYS("Loess expects the abscissa and ordinate arrays to be of the same size, but got {0} abscissae and {1} ordinatae"),
    MUTATION_RATE("mutation rate ({0})"),
    NAN_ELEMENT_AT_INDEX("element {0} is NaN"),
    NAN_VALUE_CONVERSION("cannot convert NaN value"),
    NEGATIVE_BRIGHTNESS_EXPONENT("brightness exponent should be positive or null, but got {0}"),
    NEGATIVE_COMPLEX_MODULE("negative complex module {0}"),
    NEGATIVE_ELEMENT_AT_2D_INDEX("element ({0}, {1}) is negative: {2}"),
    NEGATIVE_ELEMENT_AT_INDEX("element {0} is negative: {1}"),
    NEGATIVE_NUMBER_OF_SUCCESSES("number of successes must be non-negative ({0})"),
    NUMBER_OF_SUCCESSES("number of successes ({0})"), /* keep */
    NEGATIVE_NUMBER_OF_TRIALS("number of trials must be non-negative ({0})"),
    NUMBER_OF_INTERPOLATION_POINTS("number of interpolation points ({0})"), /* keep */
    NUMBER_OF_TRIALS("number of trials ({0})"),
    NOT_CONVEX("vertices do not form a convex hull in CCW winding"),
    NOT_CONVEX_HYPERPLANES("hyperplanes do not define a convex region"),
    ROBUSTNESS_ITERATIONS("number of robustness iterations ({0})"),
    START_POSITION("start position ({0})"), /* keep */
    NON_CONVERGENT_CONTINUED_FRACTION("Continued fraction convergents failed to converge (in less than {0} iterations) for value {1}"),
    NON_INVERTIBLE_TRANSFORM("non-invertible affine transform collapses some lines into single points"),
    NON_POSITIVE_MICROSPHERE_ELEMENTS("number of microsphere elements must be positive, but got {0}"),
    NON_POSITIVE_POLYNOMIAL_DEGREE("polynomial degree must be positive: degree={0}"),
    NON_REAL_FINITE_ABSCISSA("all abscissae must be finite real numbers, but {0}-th is {1}"),
    NON_REAL_FINITE_ORDINATE("all ordinatae must be finite real numbers, but {0}-th is {1}"),
    NON_REAL_FINITE_WEIGHT("all weights must be finite real numbers, but {0}-th is {1}"),
    NON_SQUARE_MATRIX("non square ({0}x{1}) matrix"),
    NORM("Norm ({0})"), /* keep */
    NORMALIZE_INFINITE("Cannot normalize to an infinite value"),
    NORMALIZE_NAN("Cannot normalize to NaN"),
    NOT_ADDITION_COMPATIBLE_MATRICES("{0}x{1} and {2}x{3} matrices are not addition compatible"),
    NOT_DECREASING_NUMBER_OF_POINTS("points {0} and {1} are not decreasing ({2} < {3})"),
    NOT_DECREASING_SEQUENCE("points {3} and {2} are not decreasing ({1} < {0})"), /* keep */
    NOT_ENOUGH_DATA_FOR_NUMBER_OF_PREDICTORS("not enough data ({0} rows) for this many predictors ({1} predictors)"),
    NOT_ENOUGH_POINTS_IN_SPLINE_PARTITION("spline partition must have at least {0} points, got {1}"),
    NOT_INCREASING_NUMBER_OF_POINTS("points {0} and {1} are not increasing ({2} > {3})"),
    NOT_INCREASING_SEQUENCE("points {3} and {2} are not increasing ({1} > {0})"), /* keep */
    NOT_MULTIPLICATION_COMPATIBLE_MATRICES("{0}x{1} and {2}x{3} matrices are not multiplication compatible"),
    NOT_POSITIVE_DEFINITE_MATRIX("not positive definite matrix"), /* keep */
    NON_POSITIVE_DEFINITE_MATRIX("not positive definite matrix: diagonal element at ({1},{1}) is smaller than {2} ({0})"),
    NON_POSITIVE_DEFINITE_OPERATOR("non positive definite linear operator"), /* keep */
    NON_SELF_ADJOINT_OPERATOR("non self-adjoint linear operator"), /* keep */
    NON_SQUARE_OPERATOR("non square ({0}x{1}) linear operator"), /* keep */
    DEGREES_OF_FREEDOM("degrees of freedom ({0})"), /* keep */
    NOT_POSITIVE_DEGREES_OF_FREEDOM("degrees of freedom must be positive ({0})"),
    NOT_POSITIVE_ELEMENT_AT_INDEX("element {0} is not positive: {1}"),
    NOT_POSITIVE_EXPONENT("invalid exponent {0} (must be positive)"),
    NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE("number of elements should be positive ({0})"),
    BASE("base ({0})"), /* keep */
    EXPONENT("exponent ({0})"), /* keep */
    NOT_POSITIVE_LENGTH("length must be positive ({0})"),
    LENGTH("length ({0})"), /* keep */
    NOT_POSITIVE_MEAN("mean must be positive ({0})"),
    MEAN("mean ({0})"), /* keep */
    NOT_POSITIVE_NUMBER_OF_SAMPLES("number of sample is not positive: {0}"),
    NUMBER_OF_SAMPLES("number of samples ({0})"), /* keep */
    NOT_POSITIVE_PERMUTATION("permutation k ({0}) must be positive"),
    PERMUTATION_SIZE("permutation size ({0}"), /* keep */
    NOT_POSITIVE_POISSON_MEAN("the Poisson mean must be positive ({0})"),
    NOT_POSITIVE_POPULATION_SIZE("population size must be positive ({0})"),
    POPULATION_SIZE("population size ({0})"), /* keep */
    NOT_POSITIVE_ROW_DIMENSION("invalid row dimension: {0} (must be positive)"),
    NOT_POSITIVE_SAMPLE_SIZE("sample size must be positive ({0})"),
    NOT_POSITIVE_SCALE("scale must be positive ({0})"),
    SCALE("scale ({0})"), /* keep */
    NOT_POSITIVE_SHAPE("shape must be positive ({0})"),
    SHAPE("shape ({0})"), /* keep */
    NOT_POSITIVE_STANDARD_DEVIATION("standard deviation must be positive ({0})"),
    STANDARD_DEVIATION("standard deviation ({0})"), /* keep */
    NOT_POSITIVE_UPPER_BOUND("upper bound must be positive ({0})"),
    NOT_POSITIVE_WINDOW_SIZE("window size must be positive ({0})"),
    NOT_POWER_OF_TWO("{0} is not a power of 2"),
    NOT_POWER_OF_TWO_CONSIDER_PADDING("{0} is not a power of 2, consider padding for fix"),
    NOT_POWER_OF_TWO_PLUS_ONE("{0} is not a power of 2 plus one"),
    NOT_STRICTLY_DECREASING_NUMBER_OF_POINTS("points {0} and {1} are not strictly decreasing ({2} <= {3})"),
    NOT_STRICTLY_DECREASING_SEQUENCE("points {3} and {2} are not strictly decreasing ({1} <= {0})"), /* keep */
    NOT_STRICTLY_INCREASING_KNOT_VALUES("knot values must be strictly increasing"),
    NOT_STRICTLY_INCREASING_NUMBER_OF_POINTS("points {0} and {1} are not strictly increasing ({2} >= {3})"),
    NOT_STRICTLY_INCREASING_SEQUENCE("points {3} and {2} are not strictly increasing ({1} >= {0})"), /* keep */
    NOT_SUBTRACTION_COMPATIBLE_MATRICES("{0}x{1} and {2}x{3} matrices are not subtraction compatible"),
    NOT_SUPPORTED_IN_DIMENSION_N("method not supported in dimension {0}"),
    NOT_SYMMETRIC_MATRIX("not symmetric matrix"),
    NON_SYMMETRIC_MATRIX("non symmetric matrix: the difference between entries at ({0},{1}) and ({1},{0}) is larger than {2}"), /* keep */
    NO_BIN_SELECTED("no bin selected"),
    NO_CONVERGENCE_WITH_ANY_START_POINT("none of the {0} start points lead to convergence"), /* keep */
    NO_DATA("no data"), /* keep */
    NO_DEGREES_OF_FREEDOM("no degrees of freedom ({0} measurements, {1} parameters)"),
    NO_DENSITY_FOR_THIS_DISTRIBUTION("This distribution does not have a density function implemented"),
    NO_FEASIBLE_SOLUTION("no feasible solution"),
    NO_OPTIMUM_COMPUTED_YET("no optimum computed yet"), /* keep */
    NO_REGRESSORS("Regression model must include at least one regressor"),
    NO_RESULT_AVAILABLE("no result available"),
    NO_SUCH_MATRIX_ENTRY("no entry at indices ({0}, {1}) in a {2}x{3} matrix"),
    NAN_NOT_ALLOWED("NaN is not allowed"),
    NULL_NOT_ALLOWED("null is not allowed"), /* keep */
    ARRAY_ZERO_LENGTH_OR_NULL_NOT_ALLOWED("a null or zero length array not allowed"),
    COVARIANCE_MATRIX("covariance matrix"), /* keep */
    DENOMINATOR("denominator"), /* keep */
    DENOMINATOR_FORMAT("denominator format"), /* keep */
    FRACTION("fraction"), /* keep */
    FUNCTION("function"), /* keep */
    IMAGINARY_FORMAT("imaginary format"), /* keep */
    INPUT_ARRAY("input array"), /* keep */
    NUMERATOR("numerator"), /* keep */
    NUMERATOR_FORMAT("numerator format"), /* keep */
    OBJECT_TRANSFORMATION("conversion exception in transformation"), /* keep */
    REAL_FORMAT("real format"), /* keep */
    WHOLE_FORMAT("whole format"), /* keep */
    NUMBER_TOO_LARGE("{0} is larger than the maximum ({1})"), /* keep */
    NUMBER_TOO_SMALL("{0} is smaller than the minimum ({1})"), /* keep */
    NUMBER_TOO_LARGE_BOUND_EXCLUDED("{0} is larger than, or equal to, the maximum ({1})"), /* keep */
    NUMBER_TOO_SMALL_BOUND_EXCLUDED("{0} is smaller than, or equal to, the minimum ({1})"), /* keep */
    NUMBER_OF_SUCCESS_LARGER_THAN_POPULATION_SIZE("number of successes ({0}) must be less than or equal to population size ({1})"),
    NUMERATOR_OVERFLOW_AFTER_MULTIPLY("overflow, numerator too large after multiply: {0}"),
    N_POINTS_GAUSS_LEGENDRE_INTEGRATOR_NOT_SUPPORTED("{0} points Legendre-Gauss integrator not supported, number of points must be in the {1}-{2} range"),
    OBSERVED_COUNTS_ALL_ZERO("observed counts are all 0 in observed array {0}"),
    OBSERVED_COUNTS_BOTTH_ZERO_FOR_ENTRY("observed counts are both zero for entry {0}"),
    BOBYQA_BOUND_DIFFERENCE_CONDITION("the difference between the upper and lower bound must be larger than twice the initial trust region radius ({0})"),
    OUT_OF_BOUNDS_QUANTILE_VALUE("out of bounds quantile value: {0}, must be in (0, 100]"),
    OUT_OF_BOUNDS_CONFIDENCE_LEVEL("out of bounds confidence level {0}, must be between {1} and {2}"),
    OUT_OF_BOUND_SIGNIFICANCE_LEVEL("out of bounds significance level {0}, must be between {1} and {2}"),
    SIGNIFICANCE_LEVEL("significance level ({0})"), /* keep */
    OUT_OF_ORDER_ABSCISSA_ARRAY("the abscissae array must be sorted in a strictly increasing order, but the {0}-th element is {1} whereas {2}-th is {3}"),
    OUT_OF_PLANE("point ({0}, {1}, {2}) is out of plane"),
    OUT_OF_RANGE_ROOT_OF_UNITY_INDEX("out of range root of unity index {0} (must be in [{1};{2}])"),
    OUT_OF_RANGE("out of range"), /* keep */
    OUT_OF_RANGE_SIMPLE("{0} out of [{1}, {2}] range"), /* keep */
    OUT_OF_RANGE_LEFT("{0} out of ({1}, {2}] range"),
    OUT_OF_RANGE_RIGHT("{0} out of [{1}, {2}) range"),
    OUTLINE_BOUNDARY_LOOP_OPEN("an outline boundary loop is open"),
    OVERFLOW("overflow"), /* keep */
    OVERFLOW_IN_FRACTION("overflow in fraction {0}/{1}, cannot negate"),
    OVERFLOW_IN_ADDITION("overflow in addition: {0} + {1}"),
    OVERFLOW_IN_SUBTRACTION("overflow in subtraction: {0} - {1}"),
    OVERFLOW_IN_MULTIPLICATION("overflow in multiplication: {0} * {1}"),
    PERCENTILE_IMPLEMENTATION_CANNOT_ACCESS_METHOD("cannot access {0} method in percentile implementation {1}"),
    PERCENTILE_IMPLEMENTATION_UNSUPPORTED_METHOD("percentile implementation {0} does not support {1}"),
    PERMUTATION_EXCEEDS_N("permutation size ({0}) exceeds permuation domain ({1})"), /* keep */
    POLYNOMIAL("polynomial"), /* keep */
    POLYNOMIAL_INTERPOLANTS_MISMATCH_SEGMENTS("number of polynomial interpolants must match the number of segments ({0} != {1} - 1)"),
    POPULATION_LIMIT_NOT_POSITIVE("population limit has to be positive"),
    POWER_NEGATIVE_PARAMETERS("cannot raise an integral value to a negative power ({0}^{1})"),
    PROPAGATION_DIRECTION_MISMATCH("propagation direction mismatch"),
    RANDOMKEY_MUTATION_WRONG_CLASS("RandomKeyMutation works only with RandomKeys, not {0}"),
    ROOTS_OF_UNITY_NOT_COMPUTED_YET("roots of unity have not been computed yet"),
    ROTATION_MATRIX_DIMENSIONS("a {0}x{1} matrix cannot be a rotation matrix"),
    ROW_INDEX_OUT_OF_RANGE("row index {0} out of allowed range [{1}, {2}]"),
    ROW_INDEX("row index ({0})"), /* keep */
    SAME_SIGN_AT_ENDPOINTS("function values at endpoints do not have different signs, endpoints: [{0}, {1}], values: [{2}, {3}]"),
    SAMPLE_SIZE_EXCEEDS_COLLECTION_SIZE("sample size ({0}) exceeds collection size ({1})"), /* keep */
    SAMPLE_SIZE_LARGER_THAN_POPULATION_SIZE("sample size ({0}) must be less than or equal to population size ({1})"),
    SIMPLEX_NEED_ONE_POINT("simplex must contain at least one point"),
    SIMPLE_MESSAGE("{0}"),
    SINGULAR_MATRIX("matrix is singular"), /* keep */
    SINGULAR_OPERATOR("operator is singular"),
    SUBARRAY_ENDS_AFTER_ARRAY_END("subarray ends after array end"),
    TOO_LARGE_CUTOFF_SINGULAR_VALUE("cutoff singular value is {0}, should be at most {1}"),
    TOO_LARGE_TOURNAMENT_ARITY("tournament arity ({0}) cannot be bigger than population size ({1})"),
    TOO_MANY_ELEMENTS_TO_DISCARD_FROM_ARRAY("cannot discard {0} elements from a {1} elements array"),
    TOO_MANY_REGRESSORS("too many regressors ({0}) specified, only {1} in the model"),
    TOO_SMALL_COST_RELATIVE_TOLERANCE("cost relative tolerance is too small ({0}), no further reduction in the sum of squares is possible"),
    TOO_SMALL_INTEGRATION_INTERVAL("too small integration interval: length = {0}"),
    TOO_SMALL_ORTHOGONALITY_TOLERANCE("orthogonality tolerance is too small ({0}), solution is orthogonal to the jacobian"),
    TOO_SMALL_PARAMETERS_RELATIVE_TOLERANCE("parameters relative tolerance is too small ({0}), no further improvement in the approximate solution is possible"),
    TRUST_REGION_STEP_FAILED("trust region step has failed to reduce Q"),
    TWO_OR_MORE_CATEGORIES_REQUIRED("two or more categories required, got {0}"),
    TWO_OR_MORE_VALUES_IN_CATEGORY_REQUIRED("two or more values required in each category, one has {0}"),
    UNABLE_TO_BRACKET_OPTIMUM_IN_LINE_SEARCH("unable to bracket optimum in line search"),
    UNABLE_TO_COMPUTE_COVARIANCE_SINGULAR_PROBLEM("unable to compute covariances: singular problem"),
    UNABLE_TO_FIRST_GUESS_HARMONIC_COEFFICIENTS("unable to first guess the harmonic coefficients"),
    UNABLE_TO_ORTHOGONOLIZE_MATRIX("unable to orthogonalize matrix in {0} iterations"),
    UNABLE_TO_PERFORM_QR_DECOMPOSITION_ON_JACOBIAN("unable to perform Q.R decomposition on the {0}x{1} jacobian matrix"),
    UNABLE_TO_SOLVE_SINGULAR_PROBLEM("unable to solve: singular problem"),
    UNBOUNDED_SOLUTION("unbounded solution"),
    UNKNOWN_MODE("unknown mode {0}, known modes: {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}) and {11} ({12})"),
    UNKNOWN_PARAMETER("unknown parameter {0}"),
    UNMATCHED_ODE_IN_EXPANDED_SET("ode does not match the main ode set in the extended set"),
    CANNOT_PARSE_AS_TYPE("string \"{0}\" unparseable (from position {1}) as an object of type {2}"), /* keep */
    CANNOT_PARSE("string \"{0}\" unparseable (from position {1})"), /* keep */
    UNPARSEABLE_3D_VECTOR("unparseable 3D vector: \"{0}\""),
    UNPARSEABLE_COMPLEX_NUMBER("unparseable complex number: \"{0}\""),
    UNPARSEABLE_REAL_VECTOR("unparseable real vector: \"{0}\""),
    UNSUPPORTED_EXPANSION_MODE("unsupported expansion mode {0}, supported modes are {1} ({2}) and {3} ({4})"),
    UNSUPPORTED_OPERATION("unsupported operation"), /* keep */
    ARITHMETIC_EXCEPTION("arithmetic exception"), /* keep */
    ILLEGAL_STATE("illegal state"), /* keep */
    USER_EXCEPTION("exception generated in user code"), /* keep */
    URL_CONTAINS_NO_DATA("URL {0} contains no data"),
    VALUES_ADDED_BEFORE_CONFIGURING_STATISTIC("{0} values have been added before statistic is configured"),
    VECTOR_LENGTH_MISMATCH("vector length mismatch: got {0} but expected {1}"),
    VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT("vector must have at least one element"),
    WEIGHT_AT_LEAST_ONE_NON_ZERO("weigth array must contain at least one non-zero value"),
    WRONG_BLOCK_LENGTH("wrong array shape (block length = {0}, expected {1})"),
    WRONG_NUMBER_OF_POINTS("{0} points are required, got only {1}"),
    NUMBER_OF_POINTS("number of points ({0})"), /* keep */
    ZERO_DENOMINATOR("denominator must be different from 0"), /* keep */
    ZERO_DENOMINATOR_IN_FRACTION("zero denominator in fraction {0}/{1}"),
    ZERO_FRACTION_TO_DIVIDE_BY("the fraction to divide by must not be zero: {0}/{1}"),
    ZERO_NORM("zero norm"),
    ZERO_NORM_FOR_ROTATION_AXIS("zero norm for rotation axis"),
    ZERO_NORM_FOR_ROTATION_DEFINING_VECTOR("zero norm for rotation defining vector"),
    ZERO_NOT_ALLOWED("zero not allowed here");

    // CHECKSTYLE: resume JavadocVariable
    // CHECKSTYLE: resume MultipleVariableDeclarations


    /** Source English format. */
    private final String sourceFormat;

    /** Simple constructor.
     * @param sourceFormat source English format to use when no
     * localized version is available
     */
    LocalizedFormats(final String sourceFormat) {
        this.sourceFormat = sourceFormat;
    }

    /** {@inheritDoc} */
    public String getSourceString() {
        return sourceFormat;
    }

    /** {@inheritDoc} */
    public String getLocalizedString(final Locale locale) {
        try {
            final String path = LocalizedFormats.class.getName().replaceAll("\\.", "/");
            ResourceBundle bundle =
                    ResourceBundle.getBundle("assets/" + path, locale);
            if (bundle.getLocale().getLanguage().equals(locale.getLanguage())) {
                // the value of the resource is the translated format
                return bundle.getString(toString());
            }

        } catch (MissingResourceException mre) { // NOPMD
            // do nothing here
        }

        // either the locale is not supported or the resource is unknown
        // don't translate and fall back to using the source format
        return sourceFormat;

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/MemObjectQueue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:34 PST by lamport
//      modified on Mon Dec 18 22:56:08 PST 2000 by yuanyu

package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import tlc2.output.EC;
import util.Assert;
import util.FileUtil;

/**
 * 
 * @version $Id$
 */
public final class MemObjectQueue {
  private final static int InitialSize = 4096;
  private final static int GrowthFactor = 2;

  /* Fields  */
  private int len;
  private Object[] states;
  private int start = 0;
  private String diskdir;
    
  public MemObjectQueue(String metadir) {
    this.states = new Object[InitialSize];
    this.start = 0;
    this.diskdir = metadir;
  }
    
  public final void enqueue(Object state) {
    if (this.len == this.states.length) {
      // grow the array
      int newLen = Math.max(1, this.len * GrowthFactor);
      Object[] newStates = new Object[newLen];
      int copyLen = this.states.length - this.start;
      System.arraycopy(this.states, this.start, newStates, 0, copyLen);
      System.arraycopy(this.states, 0, newStates, copyLen, this.start);
      this.states = newStates;
      this.start = 0;
    }
    int last = (this.start + this.len) % this.states.length;
    this.states[last] = state;
    this.len++;
  }
    
  public final Object dequeue() {
    if (this.len == 0) return null;
    Object res = this.states[this.start];
    this.states[this.start] = null;
    this.start = (this.start + 1) % this.states.length;
    this.len--;
    return res;
  }

  // Checkpoint.
  public final void beginChkpt() throws IOException {
    String filename = this.diskdir + FileUtil.separator + "queue.tmp";
    ObjectOutputStream oos = FileUtil.newOBFOS(filename);
    oos.writeInt(this.len);
    int index = this.start;
    for (int i = 0; i < this.len; i++) {
      oos.writeObject(this.states[index++]);
      if (index == this.states.length) index = 0;
    }
    oos.close();
  }

  public final void commitChkpt() throws IOException {
    String oldName = this.diskdir + FileUtil.separator + "queue.chkpt";
    File oldChkpt = new File(oldName);
    String newName = this.diskdir + FileUtil.separator + "queue.tmp";
    File newChkpt = new File(newName);
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemStateQueue.commitChkpt: cannot delete " + oldChkpt);
    }
  }
  
  public final void recover() throws IOException {
    String filename = this.diskdir + FileUtil.separator + "queue.chkpt";
    ObjectInputStream ois = FileUtil.newOBFIS(filename);
    this.len = ois.readInt();
    try {
      for (int i = 0; i < this.len; i++) {
	this.states[i] = ois.readObject();
      }
    }
    catch (ClassNotFoundException e) {
        ois.close();
        Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e.getMessage());
    } finally 
    {
        ois.close();
    }
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/NewModelHandlerSelectedDelegate.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.HandlerUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer.ModelContentProvider;
import org.lamport.tla.toolbox.tool.tlc.ui.modelexplorer.ModelContentProvider.Group;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Delegates the model creation for the spec selected from the toolbox explorer
 */
public class NewModelHandlerSelectedDelegate extends AbstractHandler implements IHandler
{
	/* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
	public Object execute(ExecutionEvent event) throws ExecutionException {
		/*
		 * Try to get the spec from active navigator if any
		 */
		final ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
		if (selection != null && selection instanceof IStructuredSelection
				&& ((IStructuredSelection) selection).size() == 1) {
			Object selected = ((IStructuredSelection) selection).getFirstElement();
			if (selected instanceof ModelContentProvider.Group) {
				// Convert the group to its corresponding spec
				selected = ((Group) selected).getSpec();
			}

			if (selected instanceof Spec) {
				final Map<String, String> parameters = new HashMap<String, String>();
				// fill the spec name for the handler
				parameters.put(NewModelHandler.PARAM_SPEC_NAME, ((Spec) selected).getName());
				// delegate the call to the new model handler
				UIHelper.runCommand(NewModelHandler.COMMAND_ID, parameters);
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	public boolean isEnabled() {
		final ISelection selection = getSelection();
		if (selection instanceof IStructuredSelection) {
			final IStructuredSelection iss = (IStructuredSelection) selection;
			final Object selected = iss.getFirstElement();
			if (selected instanceof Spec && ((Spec) selected).isCurrentSpec()) {
				return true;
			} else if (selected instanceof ModelContentProvider.Group) {
				final ModelContentProvider.Group group = (Group) selected;
				return group.getSpec().isCurrentSpec();
			}
		}
		return false;
	}
	
	private static ISelection getSelection() {
		try {
			IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
			if (ww != null) {
				ISelectionService service = ww.getSelectionService();
				if (service != null) {
					return service.getSelection();
				}
			}
		} catch(IllegalStateException e) {
			return null;
		}
		return null;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/generator/FingerPrintGenerator.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp.generator;

import java.io.IOException;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

import org.junit.Assert;

import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.MultiThreadedFPSetTest;

public class FingerPrintGenerator implements Runnable {

	protected final long totalInsertions;
	protected final long perThreadInsertions;
	protected final long seed;
	protected final Random rnd;
	protected final FPSet fpSet;
	protected final CountDownLatch latch;
	protected final CyclicBarrier barrier;
	protected final int id;
	protected final int numThreads;
	protected final MultiThreadedFPSetTest test;
	protected long puts = 0L;
	protected long collisions = 0L;

	public FingerPrintGenerator(MultiThreadedFPSetTest test, int id, int numThreads, FPSet fpSet, CountDownLatch latch,
			long seed, long totalInsertions, final CyclicBarrier barrier) {
		this.test = test;
		this.id = id;
		this.numThreads = numThreads;
		this.fpSet = fpSet;
		this.latch = latch;
		this.barrier = barrier;
		this.seed = seed;
		this.rnd = new Random(seed);
		this.totalInsertions = totalInsertions;
		this.perThreadInsertions = (long) Math.floor(totalInsertions / numThreads);
	}

	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		waitForAllThreadsStarted();
		
		long predecessor = 0L;
		// Reduce number of FPSet#size invocation by counting puts/collisions.
		// FPSet#size can cause an FPSet to synchronize all its writers slowing
		// down execution.
		while (puts + collisions < perThreadInsertions || fpSet.size() < totalInsertions) {
			try {
				// make sure set still contains predecessor
				if (predecessor != 0L) {
					Assert.assertTrue(fpSet.contains(predecessor));
				}

				predecessor = rnd.nextLong();

				// Periodically verify the FPSet's content. This causes a
				// drastic slow down.
//				if (fpSet.size() % 10000 == 0) {
//					final Random verify = new Random(seed);
//					long fp = verify.nextLong();
//					while (fp != predecessor) {
//						Assert.assertTrue(fpSet.contains(fp));
//						fp = verify.nextLong();
//					}
//				}
//				
				boolean put = fpSet.put(predecessor);
				if (put == false) {
					puts++;
				} else {
					collisions++;
				}
			} catch (IOException e) {
				e.printStackTrace();
				Assert.fail("Unexpected");
			}
		}
		latch.countDown();
	}

	public int getId() {
		return id;
	}

	/**
	 * @return the puts
	 */
	public long getPuts() {
		return puts;
	}

	/**
	 * @return the collisions
	 */
	public long getCollisions() {
		return collisions;
	}

	protected void waitForAllThreadsStarted() {
		try {
			barrier.await();
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} catch (BrokenBarrierException e1) {
			e1.printStackTrace();
		}
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/MultiThreadedFPSetTest.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import tlc2.TLCGlobals;
import tlc2.tool.fp.generator.BatchedFingerPrintGenerator;
import tlc2.tool.fp.generator.FingerPrintGenerator;
import tlc2.tool.fp.generator.LongVecFingerPrintGenerator;
import tlc2.tool.fp.generator.PartitionedFingerPrintGenerator;
import tlc2.util.IdThread;

public abstract class MultiThreadedFPSetTest extends AbstractFPSetTest {

	private static final int NUM_THREADS = Integer.getInteger(MultiThreadedFPSetTest.class.getName() + ".numThreads",
			Runtime.getRuntime().availableProcessors());
	private static final long INSERTIONS = Long.getLong(MultiThreadedFPSetTest.class.getName() + ".insertions",
			Integer.MAX_VALUE + 2L);

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	@Before
	public void printStats() throws Exception {
		System.out.println("Insertions: " + df.format(INSERTIONS)
				+ " (approx: " + df.format(INSERTIONS * FPSet.LongSize >> 20) + " GiB)");
		System.out.println("Thread count: " + NUM_THREADS);
	}
	
	/**
	 * Test filling a {@link FPSet} with random fingerprints using multiple
	 * threads in ordered batches
	 */
	@Test
	public void testMaxFPSetSizeRndBatched() throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		doTest(BatchedFingerPrintGenerator.class);
	}
	
	/**
	 * Test filling a {@link FPSet} with random fingerprints using multiple
	 * threads in ordered LongVecs using putBlock/containsBlock
	 */
	@Test
	public void testMaxFPSetSizeRndBlock() throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		doTest(LongVecFingerPrintGenerator.class);
	}
	
	/**
	 * Test filling a {@link FPSet} with max int + 2L random using multiple
	 * threads
	 */
	@Test
	public void testMaxFPSetSizeRnd() throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		doTest(FingerPrintGenerator.class);
	}
	
	/**
	 * Test filling a {@link FPSet} with multiple threads. Each thread accesses
	 * a disjunct partition of the key space and fills it up linearly. This
	 * prevents hash collisions as well as lock contention. Essentially, this is
	 * the best case scenario. It ignores INSERTIONS for now.
	 */
	@Test
	public void testMaxFPSetSizePartitioned() throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		doTest(PartitionedFingerPrintGenerator.class);
	}
	
	/**
	 * @param fpgClass
	 * @throws IOException
	 * @throws InterruptedException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	protected FPSet doTest(Class<? extends FingerPrintGenerator> fpgClass) throws IOException, InterruptedException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// Skip the test if the property
		// -Dtlc2.tool.fp.MultiThreadedFPSetTest.excludes contains the simple
		// name of the test. I.e.
		// ...excludes=_BatchedFingerPrintGenerator_LongVecFingerPrintGenerator_PartitionedFingerPrintGenerator
		// to skip all but FingerPrintGenerator test. Note that the name has to
		// be prefixed with "_" to make it possible to skip
		// "FingerPrintGenerator" itself.
		Assume.assumeFalse(System.getProperty(MultiThreadedFPSetTest.class.getName() + ".excludes", "")
				.contains("_" + fpgClass.getSimpleName()));
		System.out.println("Running test: " + fpgClass.getSimpleName());
		
		TLCGlobals.setNumWorkers(NUM_THREADS);
		final FPSet fpSet = getFPSetInitialized(NUM_THREADS);
		fpSet.incWorkers(NUM_THREADS);
		final CountDownLatch latch = new CountDownLatch(NUM_THREADS);

		final Constructor<?> constructor = fpgClass.getConstructor(new Class[] { MultiThreadedFPSetTest.class,
				int.class, int.class, FPSet.class, CountDownLatch.class, long.class, long.class, CyclicBarrier.class });
		
		// Take timestamp after instantiating FPSet to not measure zero'ing/initializing FPSet.  
		startTimestamp = System.currentTimeMillis();

		final Timer timer = new Timer();
		final CyclicBarrier barrier = new CyclicBarrier(NUM_THREADS, new Runnable() {
			public void run() {
				// Start a periodic task to report progress. Do not do it as part of the
				// FPGs below. It can drastically slow down an FPG selected to be the
				// reporter.
				final TimerTask reporter = new TimerTask() {
					public void run() {
						final long currentSize = fpSet.size();
						final long insertions = currentSize - previousSize;
						if (fpSet instanceof FPSetStatistic) {
							FPSetStatistic fpSetStatistics = (FPSetStatistic) fpSet;
							System.out.println(System.currentTimeMillis() + " s (epoch); " + df.format(insertions) + " insertions/min; " + pf.format(fpSetStatistics.getLoadFactor()) + " load factor");
						} else {
							System.out.println(System.currentTimeMillis() + " s (epoch); " + df.format(insertions) + " insertions/min");
						}
						previousSize = currentSize;
					}
				};
				// Take timestamp after instantiating FPSet to not measure zero'ing/initializing FPSet.  
				startTimestamp = System.currentTimeMillis();
				timer.scheduleAtFixedRate(reporter, 1L, 60 * 1000);
			}
		});
		
		long seed = RNG_SEED;
		final FingerPrintGenerator[] fpgs = new FingerPrintGenerator[NUM_THREADS];
		for (int i = 0; i < fpgs.length; i++) {
			fpgs[i] = (FingerPrintGenerator) constructor.newInstance(
					this, i, fpgs.length, fpSet, latch, seed++, INSERTIONS, barrier);
			Thread thread = new IdThread(fpgs[i], "Producer#" + i, i);
			thread.start();
		}

		// wait for runnables/fpg to tear down the latch
		latch.await();
		endTimeStamp = new Date();
		
		// Cancel reporting task.
		timer.cancel();
		
		long overallPuts = 0L;
		long overallCollisions = 0L;
		
		// print stats
		for (int i = 0; i < fpgs.length; i++) {
			final FingerPrintGenerator fpg = fpgs[i];
			long puts = fpg.getPuts();
			long collisions = fpg.getCollisions();
			System.out.println(String.format("Producer: %s, puts: %s, puts/collisions: %s", fpg.getId(), puts,
					(collisions == 0 ? "none" : (double) (puts / collisions))));
			overallPuts += puts;
			overallCollisions += collisions;
		}
		System.out.println(String.format("Total puts: %s, total collisions: %s, total load factor: %s, duration: %s ms.", overallPuts,
				overallCollisions, df.format(((FPSetStatistic) fpSet).getLoadFactor()), endTimeStamp.getTime() - startTimestamp));
		printInsertionSpeed(fpSet, startTimestamp, endTimeStamp.getTime());
		
		// Do not compare fpSet.size() to insertions as several FPGs might race
		// with the FPG that inserts the INSERTIONS element. Hence we count the
		// overallPuts externally and compare it to the size of the fpSet.
		// Additionally we assert that the fpSet has at least the seen
		// INSERTIONS elements and that maximally NUM_THREADS extra elements are
		// in the fpSet.
		assertEquals(overallPuts, fpSet.size());
		assertTrue(fpSet.size() >= INSERTIONS);
		assertTrue(fpSet.size() <= INSERTIONS + NUM_THREADS);
		
		// Check a DiskFPSet's invariant that after flush all fingerprints in
		// the file are a) monotonically increasing and b) there are no duplicates.
		assertTrue(fpSet.checkInvariant());
		
		return fpSet;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/NewModelHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationConstants;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationDefaults;
import org.lamport.tla.toolbox.tool.tlc.launch.TLCModelLaunchDelegate;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ISectionConstants;
import org.lamport.tla.toolbox.tool.tlc.util.ModelHelper;
import org.lamport.tla.toolbox.tool.tlc.util.ModelNameValidator;
import org.lamport.tla.toolbox.util.UIHelper;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SubstInNode;
import tlc2.model.Assignment;

/**
 * Handler for creation of new models
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class NewModelHandler extends AbstractHandler implements IModelConfigurationConstants
{
    public static final String COMMAND_ID = "toolbox.tool.tlc.commands.model.new";
    public static final String PARAM_SPEC_NAME = "toolbox.tool.tlc.commands.model.new.param";
    // public static final String PARAM_SPEC_NAME = "specName";

    /**
     *  This method is called when the TLC Model Checker / New Model command 
     *  is executed.  The last thing it does is call the Eclipse magic that
     *  calls the appropriate methods to open the model pages.  Thus, any
     *  initial settings of values in the model is done here by setting
     *  the appropriate attributes of the model.
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        String parameter = event.getParameter(PARAM_SPEC_NAME);
        Spec spec = null;
        if (parameter != null)
        {
            spec = ToolboxHandle.getSpecByName(parameter);
        } else
        {
            spec = ToolboxHandle.getCurrentSpec();
        }
        if (spec == null)
        {
            // no spec
        	TLCUIActivator.getDefault().logWarning("BUG: no spec");
            return null;
        }

        // project
        IProject specProject = spec.getProject();

        // root module
        // IResource specRootModule = spec.getRootFile();

        // spec object
        SpecObj specObject = spec.getRootModule();
        if (specObject == null)
        {
        	TLCUIActivator.getDefault().logWarning("BUG: no specObject");
            return null;
        }

        // get the launch manager
        ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();

        // get the launch type (model check)
        ILaunchConfigurationType launchConfigurationType = launchManager
                .getLaunchConfigurationType(TLCModelLaunchDelegate.LAUNCH_CONFIGURATION_TYPE);

		final InputDialog dialog = new InputDialog(UIHelper.getShellProvider().getShell(), "New model...",
				"Please input the name of the model to create", spec.getAdapter(TLCSpec.class).getModelNameSuggestion(),
				new ModelNameValidator(spec));

        dialog.setBlockOnOpen(true);
        if (dialog.open() != Window.OK) {
        	return null;
        }
        final String modelName = dialog.getValue();

        // get the root module
        ModuleNode moduleNode = specObject.getExternalModuleTable().getRootModule();

        // get the list of constants
        final List<Assignment> constants = ModelHelper.createConstantsList(moduleNode);

        // if defaultInitValue is a constant, initialize it
        // to be a model value. (Should perhaps be changed to do this
        // only if the root module or some extended module has an algorithm?)
        Iterator<Assignment> iter = constants.iterator();
        boolean done = false;
        while ((!done) && iter.hasNext())
        {
            Assignment assign = iter.next();
            if (assign.getLabel().equals("defaultInitValue") && (assign.getParams().length == 0))
            {
                assign.setRight("defaultInitValue");
                done = true;
            }
        }

        try
        {
            // create new launch instance
            ILaunchConfigurationWorkingCopy launchCopy = launchConfigurationType.newInstance(specProject, specProject
                    .getName()
                    + Model.SPEC_MODEL_DELIM + modelName);

            launchCopy.setAttribute(SPEC_NAME, spec.getName());
            // it is easier to do launchCopy.getProject().getPersistentProperty(SPEC_ROOT_FILE)
            // launchCopy.setAttribute(SPEC_ROOT_FILE, specRootModule.getLocation().toOSString());
            launchCopy.setAttribute(MODEL_NAME, modelName);

            if (constants.size() == 0)
            {
                launchCopy.setAttribute(MODEL_PARAMETER_CONSTANTS, (List<String>) null);
            } else
            {
                launchCopy.setAttribute(MODEL_PARAMETER_CONSTANTS, ModelHelper.serializeAssignmentList(constants));
            }

            // Initialize the Specification field of the model to be the
            // temporal formula Spec if Spec is defined by the current
            // specification to be a temporal formula. Otherwise, initialize
            // that field to be a specification with initial predicate field
            // Init and next-state action Next if those names are defined to
            // be operators of the appropriate level.
            //
            // Also, if Spec is found and Termination is defined to be a
            // temporal formula, then add it to the list of temporal properties,
            // except not checked. It is checked iff the root file
            // contains a PlusCal spec and the termination option has been
            // selected in the PlusCal options statement within the root file.
            // (It should probably also be set if the -termination option is
            // set in the preferences, but few users will set that preference.)
            OpDefNode[] defs = moduleNode.getOpDefs();
            boolean foundSpec = false;
            boolean foundInit = false;
            boolean foundNext = false;
            boolean foundTermination = false;
            // Following added by LL on 23 Jan 2011. If true, it sets
            // checking of termination detection true if fountTermination = true.
            boolean checkTermination = false;
            for (int i = 0; i < defs.length; i++)
            {
                if (defs[i].getNumberOfArgs() == 0)
                {
                    // Only look at operators with no arguments.
                    if (defs[i].getName().toString().equals("Spec") && (defs[i].getLevel() == LevelNode.TemporalLevel))
                    {
                        foundSpec = true;

                    } else if (defs[i].getName().toString().equals("Init")
                            && (defs[i].getLevel() == LevelNode.VariableLevel))
                    {
                        foundInit = true;
                    } else if (defs[i].getName().toString().equals("Next")
                            && (defs[i].getLevel() == LevelNode.ActionLevel))
                    {
                        foundNext = true;

                    } else if (defs[i].getName().toString().equals("Termination")
                            && (defs[i].getLevel() == LevelNode.TemporalLevel))
                    {
                        foundTermination = true;

                        // The following code added by LL on 23 Jan 2011
                        // to set checkTermination true iff the root module
                        // contains "PlusCal options ( ... termination "
                        // I don't really understand it, but I copied it from
                        // the code in PCalPropertyTester that searches for
                        // "--algorithm" in a module to determine if the module
                        // has a PlusCal algorithm
                        IFile ifile = spec.getRootFile();
                        FileEditorInput fileEditorInput = new FileEditorInput(ifile);
                        FileDocumentProvider fileDocumentProvider = new FileDocumentProvider();
                        try
                        {
                            fileDocumentProvider.connect(fileEditorInput);
                            IDocument document = fileDocumentProvider.getDocument(fileEditorInput);
                            FindReplaceDocumentAdapter searchAdapter = new FindReplaceDocumentAdapter(document);
                            IRegion matchRegionx = searchAdapter.find(0,
                                    "PlusCal[\\s]*options[\\s]*\\([^\\)]*termination", true, true, false, true);
                            if (matchRegionx != null)
                            {
                                checkTermination = true;
                                Activator.getDefault().logDebug("Set checkTermination true for " + ifile.getName());
                            } else
                            {
                                // search for "termination" option in properties added by LL
                                // on 24 Jan 2011. This code was copied with little understanding from
                                // the constructor of the TranslatorJob class.
                                IPreferenceStore projectPreferenceStore = PreferenceStoreHelper
                                        .getProjectPreferenceStore(ifile.getProject());
                                String paramString = projectPreferenceStore
                                        .getString(IPreferenceConstants.PCAL_CAL_PARAMS);
                                checkTermination = (paramString.indexOf("-termination") != -1);
                                TLCUIActivator.getDefault().logDebug("checkTermination = " + checkTermination);
                            }
                        } catch (CoreException e)
                        {
                            // I have no idea what can cause this exception, but if an
                            // exception occurs, we just don't set checkTermination true.
                        } catch (BadLocationException e)
                        {
                            // I have no idea what can cause this exception, but if an
                            // exception occurs, we just don't set checkTermination true.
                        } finally
                        {
                            /*
                             * The code I copied this from says:
                             * 
                             * The document provider is not needed. Always disconnect it to avoid a memory leak.
                             * 
                             * Keeping it connected only seems to provide synchronization of
                             * the document with file changes. That is not necessary in this context.
                             */
                            fileDocumentProvider.disconnect(fileEditorInput);
                        }
                        // end code added by LL on 23 Jan 2011

                    }
                }
            }
            if (foundSpec)
            {
                launchCopy.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_CLOSED_SPECIFICATION, "Spec");
                launchCopy.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_SPEC_TYPE,
                        IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_SPEC_CLOSED);
                if (foundTermination)
                {
                    Vector<String> vec = new Vector<String>();
                    vec.add((checkTermination ? "1" : "0") + "Termination");
                    // The first character should be 1 or 0 depending
                    // on whether or not the box enabling the property should be checked.
                    launchCopy.setAttribute(IModelConfigurationConstants.MODEL_CORRECTNESS_PROPERTIES, vec);
                }
            } else if (foundInit || foundNext)
            {
                launchCopy.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_SPEC_TYPE,
                        IModelConfigurationDefaults.MODEL_BEHAVIOR_TYPE_SPEC_INIT_NEXT);
                if (foundInit)
                {
                    launchCopy.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_INIT,
                            "Init");
                }
                if (foundNext)
                {
                    launchCopy.setAttribute(IModelConfigurationConstants.MODEL_BEHAVIOR_SEPARATE_SPECIFICATION_NEXT,
                            "Next");
                }
            }
            // The following code added by LL on 10 Apr 2011 to add overriding for constant 
            // definitions of the form
            //
            //      Foo == CHOOSE v : v \notin exp  or  Foo == CHOOSE V : ~(v \in exp)
            // 
            Vector<String> overrides = new Vector<String>();
            for (int i = 0; i < defs.length; i++)
            {
                OpDefNode node = defs[i];
                ExprNode nodeBody = node.getBody();
                // Need to skip over any SubstInNodes at top of definition body's tree.
                while (nodeBody instanceof SubstInNode) {
                    nodeBody = ((SubstInNode) nodeBody).getBody();
                }
                if (nodeBody instanceof OpApplNode)
                {
                    OpApplNode nodeBodyA = (OpApplNode) nodeBody;
                    if (nodeBodyA.getOperator().getName().toString().equals("$UnboundedChoose"))
                    {
                        // The OpDefNode node's body has the form CHOOSE v : ...
                        FormalParamNode chooseParam = nodeBodyA.getUnbdedQuantSymbols()[0];
                        ExprOrOpArgNode chooseBody = nodeBodyA.getArgs()[0];
                        if (chooseBody instanceof OpApplNode)
                        {
                            OpApplNode chooseBodyA = (OpApplNode) chooseBody;
                            boolean toOverride = false;
                            String topOpName = chooseBodyA.getOperator().getName().toString();
                            if (topOpName.equals("\\notin"))
                            {
                                // this is CHOOSE v : exp \notin exp . Set to override iff
                                // exp is the CHOOSE's bound variable
                                ExprOrOpArgNode leftArg = chooseBodyA.getArgs()[0];
                                if (leftArg instanceof OpApplNode)
                                {
                                    OpApplNode leftArgA = (OpApplNode) leftArg;
                                    if (leftArgA.getOperator() == chooseParam)
                                    {
                                        toOverride = true;
                                    }
                                }
                            } else if (topOpName.equals("\\lnot"))
                            {
                                // This is CHOOSE v : ~(exp). Set to override iff
                                // exp is v \in ...
                                ExprOrOpArgNode notArg = chooseBodyA.getArgs()[0];
                                if (notArg instanceof OpApplNode)
                                {
                                    OpApplNode notArgA = (OpApplNode) notArg;
                                    if (notArgA.getOperator().getName().equals("\\in"))
                                    {
                                        // This is CHOOSE v : ~(expa \in expb). Set to override
                                        // iff expa equals v.
                                        ExprOrOpArgNode leftArg = notArgA.getArgs()[0];
                                        if (leftArg instanceof OpApplNode)
                                        {
                                            OpApplNode leftArgA = (OpApplNode) leftArg;
                                            if (leftArgA.getOperator() == chooseParam)
                                            {
                                                toOverride = true;
                                            }
                                        }
                                    }
                                }
                            }
                            if (toOverride)
                            {
                                String defName = node.getName().toString();
                                overrides.addElement(defName + ";;" + defName + ";1;0");
                            }
                        }
                    }
                }
            }
            if (overrides.size() != 0)
            {
                launchCopy.setAttribute(MODEL_PARAMETER_DEFINITIONS, overrides);
            }

            // End code for adding overrides.

            ILaunchConfiguration launchSaved = launchCopy.doSave();

            // create parameters for the handler
            final Map<String, String> parameters = new HashMap<String, String>();
            parameters.put(OpenModelHandler.PARAM_MODEL_NAME, modelName);
            
            final List<String> expand = new ArrayList<>();
            expand.add(ISectionConstants.SEC_COMMENTS);
            if (foundSpec && foundTermination) {
            	expand.add(ISectionConstants.SEC_WHAT_TO_CHECK_PROPERTIES);
            }
            if (!constants.isEmpty()) {
            	expand.add(ISectionConstants.SEC_WHAT_IS_THE_MODEL);
            }

			parameters.put(OpenModelHandler.PARAM_EXPAND_SECTIONS,
					String.join(OpenModelHandler.PARAM_EXPAND_SECTIONS_DELIM, expand));

            // runs the command and opens the module [should be model?] in the editor
            //
            // Attempted explanation by LL:
            // It appears that through some multiple levels of Eclipse-induced
            // indirection, this causes the ModelEditor.openPages() method to
            // be called, which is what actually creates the model pages and
            // puts them on the screen. See the commands for UIHelper.runCommand.
            //
            UIHelper.runCommand(OpenModelHandler.COMMAND_ID, parameters);

            return launchSaved;

        } catch (CoreException e)
        {
            TLCUIActivator.getDefault().logError("Error creating a model", e);
        }

        return null;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/MethodValue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Wed 12 Jul 2017 at 16:10:00 PST by <NAME>
//      modified on Mon 30 Apr 2007 at 13:21:00 PST by lamport
//      modified on Fri Sep 22 13:18:45 PDT 2000 by yuanyu

package tlc2.value.impl;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.EvalControl;
import tlc2.tool.EvalException;
import tlc2.tool.FingerprintException;
import tlc2.tool.impl.Tool;
import tlc2.value.IValue;
import tlc2.value.Values;
import util.Assert;
import util.Assert.TLCRuntimeException;
import util.WrongInvocationException;

public class MethodValue extends OpValue implements Applicable {

	public static Value get(final Method md) {
		return get(md, 0);
	}
	
	public static Value get(final Method md, int minLevel) {
		final MethodValue mv = new MethodValue(md, minLevel);
		// Eagerly evaluate the constant operator if possible (zero arity) to only
		// evaluate once at startup and not during state exploration.
		final int acnt = md.getParameterTypes().length;
    	final boolean isConstant = (acnt == 0) && Modifier.isFinal(md.getModifiers());
    	return isConstant ? mv.apply(Tool.EmptyArgs, EvalControl.Clear) : mv;
	}
	
  private final MethodHandle mh;
  private final Method md;
  private final int minLevel;

  /* Constructor */
	private MethodValue(final Method md, final int minLevel) {
		this.md = md;
		this.minLevel = minLevel;
		try {
			final int parameterCount = this.md.getParameterCount();
			if (parameterCount > 0) {
				// With more than one argument, we want to setup the method handle to use a
				// spreader which essentially converts the Value[] into something that is
				// accepted by the method handle. Without a spreader, passing a Value[] to
				// MethodHandle#invoke does not work. Instead one has to use MethodHandle#invokeWithArguments.
				// MethodHandle#invokeWithArguments internally creates a spreader on the fly
				// which turns out to be costly (for the spec MongoRepl of the performance
				// tests it resulted in a 20% performance drop).
				this.mh = MethodHandles.publicLookup().unreflect(md).asSpreader(IValue[].class, parameterCount);
			} else {
				this.mh = MethodHandles.publicLookup().unreflect(md); 
			}
		} catch (IllegalAccessException e) {
			throw new TLCRuntimeException(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE, MP.getMessage(
					EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE, new String[] { md.toString(), e.getMessage() }));
		}
	}

  @Override
  public final byte getKind() { return METHODVALUE; }

  @Override
  public final IValue initialize() {
	  this.deepNormalize();
	  // Do not call fingerprint as a MethodValue has no fingerprint.
	  return this;
  }
  
  @Override
  public final int compareTo(Object obj) {
    try {
      Assert.fail("Attempted to compare operator " + this.toString() +
      " with value:\n" + obj == null ? "null" : Values.ppr(obj.toString()), getSource());
      return 0;       // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  public final boolean equals(Object obj) {
    try {
      Assert.fail("Attempted to check equality of operator " + this.toString() +
      " with value:\n" + obj == null ? "null" : Values.ppr(obj.toString()), getSource());
      return false;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final boolean member(Value elem) {
    try {
      Assert.fail("Attempted to check if the value:\n" + elem == null ? "null" : Values.ppr(elem.toString()) +
      "\nis an element of operator " + this.toString(), getSource());
      return false;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final boolean isFinite() {
    try {
      Assert.fail("Attempted to check if the operator " + this.toString() +
      " is a finite set.", getSource());
      return false;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value apply(Value arg, int control) {
    try {
      throw new WrongInvocationException("It is a TLC bug: Should use the other apply method.");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value apply(Value[] args, int control) {
    try {
      Value res = null;
      try
      {
    	  if (args.length == 0) {
    		  res = (Value) this.mh.invokeExact();
    	  } else {
    		  res = (Value) this.mh.invoke(args);
    	  }
      } catch (Throwable e)
      {
          if (e instanceof InvocationTargetException)
          {
              Throwable targetException = ((InvocationTargetException)e).getTargetException();
              throw new EvalException(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE, new String[]{this.md.toString(), targetException.getMessage()});
          } else if (e instanceof NullPointerException) {
              throw new EvalException(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE, new String[]{this.md.toString(), e.getMessage()});
          } else if (e instanceof EvalException) {
        	  // Do not wrap an EvalException below.
        	  throw (EvalException) e;
          } else
          {
              String message = e.getMessage();
              if (message == null) {
				  // Try to pass some information along (i.e. the full stack-trace) in cases where
				  // message is null.
		          final StringWriter sw = new StringWriter();
            	  e.printStackTrace(new PrintWriter(sw));
            	  message = sw.toString();
              }
			Assert.fail(EC.TLC_MODULE_VALUE_JAVA_METHOD_OVERRIDE, new String[]{this.md.toString(), message});
          }
      }
      return res;
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value select(Value arg) {
    try {
      throw new WrongInvocationException("It is a TLC bug: Attempted to call MethodValue.select().");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value takeExcept(ValueExcept ex) {
    try {
      Assert.fail("Attempted to appy EXCEPT construct to the operator " +
      this.toString() + ".", getSource());
      return null;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value takeExcept(ValueExcept[] exs) {
    try {
      Assert.fail("Attempted to apply EXCEPT construct to the operator " +
      this.toString() + ".", getSource());
      return null;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value getDomain() {
    try {
      Assert.fail("Attempted to compute the domain of the operator " +
      this.toString() + ".", getSource());
      return SetEnumValue.EmptySet;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final int size() {
    try {
      Assert.fail("Attempted to compute the number of elements in the operator " +
      this.toString() + ".", getSource());
      return 0;   // make compiler happy
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  /* Should never normalize an operator. */
  @Override
  public final boolean isNormalized() {
    try {
      throw new WrongInvocationException("It is a TLC bug: Attempted to normalize an operator.");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final Value normalize() {
    try {
      throw new WrongInvocationException("It is a TLC bug: Attempted to normalize an operator.");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  @Override
  public final boolean isDefined() { return true; }

  @Override
  public final IValue deepCopy() { return this; }

  @Override
  public final boolean assignable(Value val) {
    try {
      throw new WrongInvocationException("It is a TLC bug: Attempted to initialize an operator.");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }

  /* String representation of the value.  */
  @Override
  public final StringBuffer toString(StringBuffer sb, int offset, boolean ignored) {
    try {
      return sb.append("<Java Method: " + this.md + ">");
    }
    catch (RuntimeException | OutOfMemoryError e) {
      if (hasSource()) { throw FingerprintException.getNewHead(this, e); }
      else { throw e; }
    }
  }
  
  public final int getMinLevel() {
	  return minLevel;
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ProofNode.java<|end_filename|>
// Copyright (c) 2007 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import tla2sany.st.TreeNode;

/***************************************************************************
* This abstract class represents a proof.  It just provides a way of       *
* giving a single superclass name to the two classes that extend it:       *
* LeafProofNode and NonLeafProofNode.                                      *
***************************************************************************/
public abstract class ProofNode extends LevelNode {
  ProofNode(int kind, TreeNode stn) { super(kind, stn); }

}

/***************************************************************************
* For want of a better place, here is an explanation of how SUFFICES is    *
* handled.                                                                 *
*                                                                          *
* The handling of SUFFICES steps.                                          *
*                                                                          *
* Let S be an expression or an ASSUME/PROVE. Let stepid be a step name,    *
* which can be either <i> or <i>j (or something equivalent to one of       *
* them).  The proof step                                                   *
*                                                                          *
*     stepid S                                                             *
*                                                                          *
* generates a TheoremNode whose body is the node generated by S, which     *
* is either an ExprNode or an AssumeProveNode.  The isSuffices() method    *
* of the TheoremNode returns false.                                        *
*                                                                          *
* The proof step                                                           *
*                                                                          *
*   stepid SUFFICES S                                                      *
*                                                                          *
* generates a TheoremNode whose body is either an ExprNode or an           *
* AssumeProveNode.  If S is an expression, then the body is effectively    *
* $Suffices(S), where $Suffices is a dummy built-in operator.  The         *
* isSuffices() method of the TheoremNode returns true.                     *
*                                                                          *
* If stepid is the step number <i>j, this step effectively adds the        *
* definition                                                               *
*                                                                          *
*    <i>j == body                                                          *
*                                                                          *
* where body is the body of the TheoremNode.  (That is, it equals S        *
* except for a SUFFICES in which S is an expression.)  This definition     *
* is represented by a ThmOrAssumpNode whose isSuffices() method equals     *
* the isSuffices() method of the TheoremNode.                              *
*                                                                          *
* A use of the name <i>j produces an OpApplNode whose operator is (the     *
* ThmOrAssumpNode of) the 0-argument user-defined operator <i>j.  For a    *
* SUFFICES step or if S is an ASSUME/PROVE, this can be used only as a     *
* fact (in a USE or BY).  A selector like <i>j!... names a subexpression   *
* of the body of the definition as usual, except for one case.  For        *
*                                                                          *
*    <i>j SUFFICES ASSUME A1, ... , An PROVE P                             *
*                                                                          *
* the selector <i>j!1 names the ASSUME/PROVE. That is, it generates an     *
* AssumeProveNode.  Thus, if S is either an expression or an ASSUME/PROVE, *
* in                                                                       *
*                                                                          *
*    <i>j SUFFICES S                                                       *
*                                                                          *
* the selector <i>j!1 names S.                                             *
*                                                                          *
* ------------------                                                       *
* Here is a detailed explanation of the four possible cases (with or       *
* without SUFFICES, and S an expression or an ASSUME/PROVE).               *
*                                                                          *
* <1>1. 4 = exp                                                            *
*                                                                          *
* This produces a TheoremNode whose theoremExprOrAssumeProve field is the  *
* ExprNode for 4=exp (and whose isSuffices() method returns false).  It    *
* also essentially defines                                                 *
*                                                                          *
*   <1>1 == 4 = exp                                                        *
*                                                                          *
* (the definition represented by a ThmOrAssumpDefNode) so any use of <1>1  *
* produces an OpApplNode with no arguments whose getOperator() method      *
* returns the ThmOrAssumpDefNode for the user-defined operator <1>1.       *
*                                                                          *
* The expression <1>1!2 generates an OpApplNode whose operator is $Nop     *
* and whose single argument is the ExprNode generated by exp.              *
*                                                                          *
* ------                                                                   *
*                                                                          *
* <1>2. SUFFICES 4 = exp                                                   *
*                                                                          *
* This produces a TheoremNode whose theoremExprOrAssumeProve field is the  *
* OpApplNode whose operator is $Suffices and whose single argument is the  *
* ExprNode for 4=exp (an OpApplNode whose operator is =) and whose         *
* isSuffices() method returns true.  It also essentially defines           *
*                                                                          *
*    <1>2 == $Suffices(4 = exp)                                            *
*                                                                          *
* where $Suffices is a dummy built-in operator.                            *
*                                                                          *
* The name <1>2 can be used by itself only as a fact (in a BY or USE).     *
* When used as a fact, it generates an OpApplNode with no arguments        *
* whose getOperator() method returns the ThmOrAssumpDefNode for the        *
* user-defined operator <1>2.  The isSuffices() method of this             *
* ThmOrAssumpDefNode returns true.                                         *
*                                                                          *
* The expression <1>2!1 generates an OpApplNode whose operator is $Nop     *
* and whose single argument is the ExprNode generated by 4=exp.            *
*                                                                          *
* The expression <1>2!1!2 generates an OpApplNode whose operator is $Nop   *
* and whose single argument is the ExprNode generated by exp.              *
*                                                                          *
* -------                                                                  *
*                                                                          *
* <1>3. ASSUME A1, A2 PROVE P                                              *
*                                                                          *
* This produces a TheoremNode whose theoremExprOrAssumeProve field is an   *
* AssumeProveNode and whose isSuffices() method returns false.  It also    *
* essentially defines                                                      *
*                                                                          *
*   <1>3 == ASSUME A1, A2 PROVE P                                          *
*                                                                          *
* where the definition is represented by a ThmOrAssumpDefNode whose        *
* isSuffices() method returns false.                                       *
*                                                                          *
* The name <1>3 can be used by itself only as a fact (in a BY or USE).     *
* When used as a fact, it generates an OpApplNode with no arguments        *
* whose getOperator() method returns the ThmOrAssumpDefNode for the        *
* user-defined operator <1>3.                                              *
*                                                                          *
* The expression <1>3!1 produces an OpApplNode whose operator is $Nop      *
* and whose single argument is the ExprNode generated by A1.               *
*                                                                          *
* ---------                                                                *
*                                                                          *
* <1>4. SUFFICES ASSUME A1, A2 PROVE P                                     *
*                                                                          *
* This produces a TheoremNode whose theoremExprOrAssumeProve field is an   *
* AssumeProveNode and whose isSuffices() method returns true.  It also     *
* essentially defines                                                      *
*                                                                          *
*   <1>4 == ASSUME A1, A2 PROVE P                                          *
*                                                                          *
* where the definition is represented by a ThmOrAssumpDefNode whose        *
* isSuffices() method returns true.                                        *
*                                                                          *
* The name <1>4 can be used by itself only as a fact (in a BY or USE).     *
* When used as a fact, it generates an OpApplNode with no arguments        *
* whose getOperator() method returns the ThmOrAssumpDefNode for the        *
* user-defined operator <1>4.                                              *
*                                                                          *
* The name <1>4!1 can be used only as a fact (in a BY or USE).  The fact   *
* it generates is an AssumeProveNode.                                      *
*                                                                          *
* The expression <1>4!1!2 produces an OpApplNode whose operator is $Nop    *
* and whose single argument is the ExprNode generated by A2.               *
***************************************************************************/


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/LongArrayTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import util.TLCRuntime;

public class LongArrayTest {
	
	@Before
	public void setup() {
		Assume.assumeTrue(TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86_64);
	}

	@Test
	public void testGetAndSet() throws IOException {
		final int elements = 100;

		final LongArray array = new LongArray(elements);
		array.zeroMemory();
		
		for (long i = 0L; i < elements; i++) {
			assertEquals(0L, array.get(i));
		}

		
		for (long i = 0L; i < elements; i++) {
			array.set(i, i);
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(i, array.get(i));
		}

		
		for (long i = 0L; i < elements; i++) {
			array.set(i, Long.MAX_VALUE - i);
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(Long.MAX_VALUE - i, array.get(i));
		}
		

		for (long i = 0L; i < elements; i++) {
			array.set(i, Long.MIN_VALUE + i);
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(Long.MIN_VALUE + i, array.get(i));
		}
	}
	
	@Test
	public void testOutOfRangePositive() throws IOException {
		final LongArray array = new LongArray(1);
		try {
			array.get(1);
		} catch (AssertionError e) {
			return;
		}
		fail();
	}
	
	@Test
	public void testOutOfRangeNegative() throws IOException {
		final LongArray array = new LongArray(1);
		try {
			array.get(-1);
		} catch (AssertionError e) {
			return;
		}
		fail();
	}
	
	@Test
	public void testGetAndTrySet() throws IOException {
		final int elements = 100;

		final LongArray array = new LongArray(elements);
		array.zeroMemory();
		
		// Assert zero successful
		for (long i = 0L; i < elements; i++) {
			assertEquals(0L, array.get(i));
		}

		// trySet linear elements.
		for (long i = 0L; i < elements; i++) {
			assertTrue(array.trySet(i, 0, i));
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(i, array.get(i));
		}

		// Replace with largest possible values
		for (long i = 0L; i < elements; i++) {
			array.trySet(i, i, Long.MAX_VALUE - i);
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(Long.MAX_VALUE - i, array.get(i));
		}
		

		// Replace with smallest possible values
		for (long i = 0L; i < elements; i++) {
			array.trySet(i, Long.MAX_VALUE - i, Long.MIN_VALUE + i);
		}
		for (long i = 0L; i < elements; i++) {
			assertEquals(Long.MIN_VALUE + i, array.get(i));
		}
	}
	
	@Test
	public void testZeroMemory() throws IOException {
		for (int k = 1; k < 8; k++) {
			for (int i = 1; i < 128; i++) {
				final LongArray array = new LongArray(i);
				array.zeroMemory(k);
				for (int j = 0; i < j; i++) {
					assertEquals(0L, array.get(j));
				}
				for (int j = 0; i < j; i++) {
					array.set(j, -1L);
				}
			}
		}
	}
	
	@Test
	public void testSwap() throws IOException {
		final int elements = 10321;

		final LongArray array = new LongArray(elements);
		array.zeroMemory();
		
		for (long i = 0L; i < elements; i++) {
			long value = Long.MAX_VALUE - i;
			array.set(i, value);
		}
		
		for (int i = 0; i < (elements / 2); i++) {
			array.swapCopy(i, (elements - 1) - i);
		}
		
		for (long i = 0L; i < elements; i++) {
			assertEquals(Long.MAX_VALUE - (elements -1) + i, array.get(i));
		}
	}
	
	@Test
	public void testSwapRandom() throws IOException {
		final int elements = 21383;
		
		final List<Long> vals = new ArrayList<Long>();
		final Random rnd = new Random();
		
		for (int i = 0; i < elements; i++) {
			vals.add(rnd.nextLong());
		}
		
		final LongArray array = new LongArray(elements);
		array.zeroMemory();
		
		for (int i = 0; i < elements; i++) {
			array.set(i, vals.get(i));
		}
		
		for (int i = 0; i < (elements / 2); i++) {
			array.swapCopy(i, (elements - 1) - i);
		}
		
		Collections.reverse(vals);
		
		for (int i = 0; i < elements; i++) {
			assertEquals((long) vals.get(i), array.get(i));
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/Region.java<|end_filename|>
/**
 * A Region represents a portion of the .tla file between two
 * Locations: begin and end.
 */

package pcal;

import java.io.Serializable;

import tla2sany.st.Location;

public class Region implements Serializable {

    /**
	 * @see TLAtoPCalMapping#serialVersionUID
	 */
	private static final long serialVersionUID = 5596444966456185518L;
	
	private PCalLocation begin ;
	private PCalLocation end ;

	/**
     * The simple constructor.
     * @param begin
     * @param end
     */
	public Region(PCalLocation begin, PCalLocation end) {
		this.begin = begin;
		this.end = end;
	}
	
	/**
	 * Constructs a region within a single line, from
	 * column bcol to column bcol+width;
	 * @param line
	 * @param bcol
	 * @param width
	 */
	public Region(int line, int bcol, int width)  {
		this.begin = new PCalLocation(line, bcol) ;
		this.end = new PCalLocation(line, bcol+width);
	}

	public PCalLocation getBegin() {
		return begin;
	}
	public void setBegin(PCalLocation begin) {
		this.begin = begin;
	}
	public PCalLocation getEnd() {
		return end;
	}
	public void setEnd(PCalLocation end) {
		this.end = end;
	}
	
	public String toString() {
	  return "[" + begin.toString() + "-" + end.toString() + "]";
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((begin == null) ? 0 : begin.hashCode());
		result = prime * result + ((end == null) ? 0 : end.hashCode());
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Region other = (Region) obj;
		if (begin == null) {
			if (other.begin != null)
				return false;
		} else if (!begin.equals(other.begin))
			return false;
		if (end == null) {
			if (other.end != null)
				return false;
		} else if (!end.equals(other.end))
			return false;
		return true;
	}

	public Location toLocation() {
		return new Location(begin.getLine() + 1, begin.getColumn() + 1,
				end.getLine() + 1, end.getColumn() + 1);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/module/Strings.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Sat 23 February 2008 at  9:58:18 PST by lamport
//      modified on Thu Dec  7 13:47:27 PST 2000 by yuanyu

package tlc2.module;

import tlc2.output.EC;
import tlc2.tool.EvalException;
import tlc2.value.Values;
import tlc2.value.impl.ModelValue;
import tlc2.value.impl.StringValue;
import tlc2.value.impl.UserObj;
import tlc2.value.impl.UserValue;
import tlc2.value.impl.Value;

public class Strings extends UserObj
{
	public static final long serialVersionUID = 20160822L;

    private static Value SetString = new UserValue(new Strings());

    public static Value STRING()
    {
        return SetString;
    }

    @Override
    public final int compareTo(Value val)
    {
        if ((val instanceof UserValue) && (((UserValue) val).userObj instanceof Strings))
        {
            return 0;
        }
        if (val instanceof ModelValue)
            return 1;
        throw new EvalException(EC.TLC_MODULE_COMPARE_VALUE, new String[] { "STRING", Values.ppr(val.toString()) });
    }

    @Override
    public final boolean member(Value val)
    {
        if (val instanceof StringValue)
            return true;
        if (val instanceof ModelValue)
            return ((ModelValue) val).modelValueMember(this);
        throw new EvalException(EC.TLC_MODULE_CHECK_MEMBER_OF, new String[] { Values.ppr(val.toString()), "STRING" });
    }

    @Override
    public final boolean isFinite()
    {
        return false;
    }

    @Override
    public final StringBuffer toString(StringBuffer sb, int offset, boolean swallow)
    {
        return sb.append("STRING");
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/model/MCErrorTest.java<|end_filename|>
package tlc2.model;

import static org.junit.Assert.assertEquals;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

public class MCErrorTest {
	
	@Test
	public void testGetErrorMessage()
	{
		final String expected = "this is an error message";
		MCError actual = new MCError(expected);
		assertEquals(expected, actual.getMessage());
	}
	
	@Test
	public void testUpdateStatesForTraceExpressions()
	{
		MCError error = new MCError();
		MCState[] states = new MCState[] {
				Utils.buildState(1, "init", "", "x = 1"),
				Utils.buildState(2, "next", "", "x = 2"),
				Utils.buildState(3, "next", "", "x = 3"),
				Utils.buildState(5, "next", "", "x = 4"),
				Utils.buildState(6, "next", "", "x = 5")
		};
		
		for (MCState state : states)
		{
			error.addState(state);
		}
		
		Map<String, String> map = new HashMap<String, String>();
		map.put("x", "y");
		error.updateStatesForTraceExpression(map);
		
		List<MCState> actualStates = error.getStates();
		assertEquals(states.length, actualStates.size());
		for (MCState actualState : actualStates)
		{
			MCVariable[] actualVariables = actualState.getVariables();
			assertEquals(1, actualVariables.length);
			for (MCVariable actualVariable : actualVariables)
			{
				assertEquals("x", actualVariable.getName());
				assertEquals("y", actualVariable.getSingleLineDisplayName());
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/actions/ExampleEditorAction.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.actions;

import java.util.ResourceBundle;

import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.ui.texteditor.TextEditorAction;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.util.DocumentHelper;

public class ExampleEditorAction extends TextEditorAction implements VerifyKeyListener
{

    private IStatusLineManager statusLine;

    public ExampleEditorAction(ResourceBundle bundle, String prefix, TLAEditor editor, IStatusLineManager statusLine)
    {
        super(bundle, prefix, editor);
        this.statusLine = statusLine;
    }

    /**
     * Installs this as a verify key listener on the editor's text viewer.
     */
    public void run()
    {
        ((TLAEditor) getTextEditor()).getViewer().prependVerifyKeyListener(this);
        statusLine.setMessage("Example Command");
    }

    /**
     * Listens for the first key to be pressed. If it is a digit, it
     * finds the word currently containing the caret and repeats that word
     * the number of times equal to the digit pressed.
     */
    public void verifyKey(VerifyEvent event)
    {
        // no other listeners should respond to this event
        event.doit = false;

        // the state mask indicates what modifier keys (such as CTRL) were being
        // pressed when the character was pressed
        if (event.stateMask == SWT.NONE && Character.isDigit(event.character))
        {
            // get the digit input
            int input = Character.getNumericValue(event.character);

            // get the text selection
            ISelection selection = getTextEditor().getSelectionProvider().getSelection();
            if (selection != null && selection instanceof ITextSelection)
            {
                ITextSelection textSelection = (ITextSelection) selection;

                IDocument document = getTextEditor().getDocumentProvider()
                        .getDocument(getTextEditor().getEditorInput());

                // if one or more characters are selected, do nothing
                if (textSelection.getLength() == 0 && document != null)
                {

                    // retrieve the region describing the word containing
                    // the caret
                    try
                    {
                    	IRegion region = DocumentHelper.getRegionExpandedBoth(document, textSelection.getOffset());

                        // generate the insertion string
                        String insertionText = " " + document.get(region.getOffset(), region.getLength());
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < input; i++)
                        {
                            sb.append(insertionText);
                        }
                        document.replace(region.getOffset() + region.getLength(), 0, sb.toString());
                    } catch (BadLocationException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }

        // do not listen to any other key strokes
        ((TLAEditor) getTextEditor()).getViewer().removeVerifyKeyListener(this);

        statusLine.setMessage("");
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/model.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Model Checking</title>
</head>
<!-- a comment -->

<body>
<h1>Model Checking</h1>

 <P> 
The Toolbox uses the TLC model checker to model check the current spec.&nbsp;
More precisely, TLC checks a <em>model</em> of the specification.&nbsp;
The <a href="about-models.html"><em>Models</em></A> help page explains what a model
is and how to manage models.&nbsp;  The 
<A href="creating-model.html"><em>Creating a Model</em></A> page explains how to 
create a model.&nbsp;  The <A href="executing-tlc.html"><em>Checking a Model</em></A> page 
explains how to run TLC and what to do when it reports an error.
 </P>

<p>
TLC can make use of multiple processors, getting speedups that are almost linear in
the number of processors.&nbsp;  It can use multiple processors (cores) in a single
computer, and multiple networked computers.&nbsp;  See the <a href="overview-page.html#how-to-run">How to run</a>
section of the <a href="overview-page.html">Model Overview Page</a> and
<a href="distributed-mode.html">Running TLC in Distributed Mode</a>.

</p>
<hr> 
<!-- delete rest of line to comment out --> 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href="about-models.html">Models </A></dd>
<dd> <A href="creating-model.html">Creating a Model </A></dd>
<dd> <A href="executing-tlc.html">Checking a Model </A></dd>
</dl>
<!-- --> 
<!-- delete rest of line to comment out 
<a href = ".html">&uarr; HIGHER_LEVEL_TOPIC</a>
--> 
<a href = "../contents.html">&uarr; TLA+ Toolbox User's Guide</a>
</hr>

</body>
</html>

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/BracketStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Fri  2 Mar 2007 at 15:32:46 PST by lamport

package tla2sany.parser;

import java.util.Stack;

import tla2sany.st.SyntaxTreeConstants;
// import tla2sany.error.*;
/***************************************************************************
* Use of classes from tla2sany/error eliminated by LL on 2 Mar 2007        *
* The only such use was of Log.log, which did logging for error tracing    *
* that was abandoned, and an "implements LogCategories".                   *
***************************************************************************/

public class BracketStack implements //LogCategories, 
                               SyntaxTreeConstants {

/***************************************************************************
* Implements a stack of StackElement objects, which have just a Kind       *
* and an Offset field, which are of type int.  The constructor is          *
* StackElement(int Offset, int Kind)                                       *
***************************************************************************/
  private Stack stack = new Stack( );
  private int [] classes = new int[ NULL_ID ];
    /***********************************************************************
    * This is an array of length NULL_ID = 227.  Apparently, NULL_ID is    *
    * an integer greater than the maximum `kind' field of any token, so    *
    * classes seems to be indexed by a token kind.  The array is           *
    * initialized at the beginning of the parse() method, so that it       *
    * defines classes[n] to equal null except for                          *
    *                                                                      *
    *   classes[BAND]   = 1                                                *
    *   classes[AND]    = 1                                                *
    *   classes[BOR]    = 2                                                *
    *   classes[OR]     = 2                                                *
    *   classes[PROOF]  = 3                                                *
    *   classes[LBR]    = 4                                                *
    *   classes[ASSUME] = 5                                                *
    *                                                                      *
    * Where BAND, ... , are the kind field values for the following        *
    * tokens                                                               *
    *                                                                      *
    *   BAND  : something like foo./\                                      *
    *   AND   : /\                                                         *
    *   BOR   :  something like foo.\/                                     *
    *   OR    :  \/                                                        *
    *   PROOF : PROOF or Proof                                             *
    *   LBR   :   (                                                        *
    *   ASSUME: ASSUME                                                     *
    *                                                                      *
    * The purpose of classes seems to be to act as a pseudo-kind field     *
    * for tokens so that BAND and AND have the same pseudo-kind, as do     *
    * BOR and OR.                                                          *
    ***********************************************************************/
    
  private int classIndex = 0;

  /*************************************************************************
  * The following three methods seem to be used only to create a single    *
  * BracketStack object and initialize its classes field.                  *
  *************************************************************************/
  public void newClass() { classIndex++; }
  public void registerInCurrentClass( int k ) {
    if ( classIndex == 0) classIndex++;
    classes[k] = classIndex;
  }

  BracketStack() {
    stack.push(new StackElement(0, -1 )) ;
  }

  void newReference( int o, int kind ) {
    /***********************************************************************
    * Puts on the top of a the stack a new StackElement object with        *
    * offset o and Kind classes[kind].                                     *
    ***********************************************************************/
     stack.push( new StackElement( o, classes[ kind ] )) ;
  }

   void popReference( ) {
     /**********************************************************************
     * Pops the top element off the stack.                                 *
     **********************************************************************/
     stack.pop();
  }

  boolean onReference( int o, int kind ) {
    /***********************************************************************
    * Returns true iff the top element se of the stack has se.Kind =       *
    * classes[kind] and se.Offset = o.  Throws an exception if             *
    * classes[kind] = null.                                                *
    ***********************************************************************/
    StackElement se = (StackElement)  stack.peek();
// Log.log(bracketStackLog, "--- onReference, " + o + " " + classes [ kind ] + 
//                          "  " + se.Kind + " " + se.Offset);
     /************************************************************************
     * A use of a class from tla2sany/error eliminated by LL on 2 Mar 2007   *
     ************************************************************************/
    return
      classes[ kind ] == se.Kind && se.Offset == o;
  }

  boolean belowReference( int o ) {
    /***********************************************************************
    * Returns true iff the Offset field of the top element on the stack    *
    * is greater than o.                                                   *
    *                                                                      *
    * THIS METHOD IS APPARENTLY NOT USED.                                  *
    ***********************************************************************/
    StackElement se = (StackElement)  stack.peek();
// Log.log(bracketStackLog, "--- belowReference, " + o + " " + se.Offset);
     /************************************************************************
     * A use of a class from tla2sany/error eliminated by LL on 2 Mar 2007   *
     ************************************************************************/
    return
      se.Offset > o;
  }

  boolean aboveReference( int o ) {
    StackElement se = (StackElement)  stack.peek();
// Log.log(bracketStackLog, "--- aboveReference, " + o + " " + se.Offset);
     /************************************************************************
     * A use of a class from tla2sany/error eliminated by LL on 2 Mar 2007   *
     ************************************************************************/
    return
    /***********************************************************************
    * Returns true iff the Offset field of the top element on the stack    *
    * is less than or equal to o.                                          *
    ***********************************************************************/
      se.Offset-1 < o; /* careful here. o is a beginning column, while
                          Offset is the end column of the token ...\/ ou .../\
                          on utilise - 1 pour comparer au de'but de la partie
                          significative du symbole.
                          De cette manire, le comportement ne change pas si
                          on utilise uniquement la forme non prafixe des
                         symboles */
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/expression/ParseErrorTester.java<|end_filename|>
package org.lamport.tla.toolbox.ui.expression;

import org.eclipse.core.expressions.PropertyTester;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.util.AdapterFactory;

/**
 * This is used to test whether or not the Parse Errors menu item
 * should be active.
 */
public class ParseErrorTester extends PropertyTester {

	public static final String PROPERTY_ID = "toolbox.property.hasParseErrors"; 
	
	/* (non-Javadoc)
	 * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
	 */
	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
		if (Activator.isSpecManagerInstantiated()) {
			WorkspaceSpecManager specManager = Activator.getSpecManager();
			if (specManager != null) {
				Spec loadedSpec = specManager.getSpecLoaded();
				if (loadedSpec != null) {
					return AdapterFactory.isProblemStatus(loadedSpec.getStatus());
				}
			}
		}
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/Github432Test.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Test;

import tlc2.output.EC;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class Github432Test extends ModelCheckerTestCase {
	private static final AtomicInteger TEST_COUNTER = new AtomicInteger(0);
	
	private static final String CONFIG_FILE = "Github432.cfg";
	private static final String CONFIG_FILE_BACKUP = "Github432.cfg_bak";
	
	private static final String HUMANS_TOKEN = "%1%";
	private static final String OTHERS_TOKEN = <PASSWORD>%";
	
	
	private String[] expectedWarnings;
	
	public Github432Test() {
		super("Github432");
	}

	@Override
	protected void beforeSetUp() {
		final int testNumber = TEST_COUNTER.getAndIncrement();
		final String humans;
		final String others;
		
		switch (testNumber) {
			case 0:
				humans = "Alice";
				others = "Cat, Dog";
				expectedWarnings = new String[] {"", "Humans", "has", "s"};
				break;
			case 1:
				humans = "";
				others = "Emu";
				expectedWarnings = new String[] {"s", "Humans, and Others", "have", ""};
				break;
			case 2:
				humans = "<NAME>";
				others = "";
				expectedWarnings = new String[] {"", "Others", "has", "s"};
				break;
			default:
				humans = "<NAME>";
				others = "<NAME>";
				expectedWarnings = null;
				break;
		}
		
		try {
			createConfigFile(humans, others);
		} catch (final Exception e) {
			revertConfigFile();
			
			Assert.fail(e.getMessage());
		}
	}
	
	@Override
	protected void beforeTearDown() {
		revertConfigFile();
	}
	
	@Override
	protected void assertExitStatus() {
		// We don't care - and the spec actually fails for test-b
	}
	
	private void compareToExpectedResults(final String[] array) {
		Assert.assertNotNull("Reported parameters should not be null.", array);
		Assert.assertEquals("Expected warnings should be the same cardinality of the reported parameters encountered.",
							expectedWarnings.length, array.length);
		for (int i = 0; i < array.length; i++) {
			Assert.assertEquals(expectedWarnings[i], array[i]);
		}
	}
	
	@Test
	public void testA() throws FileNotFoundException, IOException {
		if (expectedWarnings != null) {
			compareToExpectedResults((String[])recorder.getRecords(EC.TLC_SYMMETRY_SET_TOO_SMALL).get(0));
		} else {
			Assert.assertFalse(recorder.recorded(EC.TLC_SYMMETRY_SET_TOO_SMALL));
		}
	}
	
	@Test
	public void testB() throws FileNotFoundException, IOException {
		if (expectedWarnings != null) {
			compareToExpectedResults((String[])recorder.getRecords(EC.TLC_SYMMETRY_SET_TOO_SMALL).get(0));
		} else {
			Assert.assertFalse(recorder.recorded(EC.TLC_SYMMETRY_SET_TOO_SMALL));
		}
	}
	
	@Test
	public void testC() throws FileNotFoundException, IOException {
		if (expectedWarnings != null) {
			compareToExpectedResults((String[])recorder.getRecords(EC.TLC_SYMMETRY_SET_TOO_SMALL).get(0));
		} else {
			Assert.assertFalse(recorder.recorded(EC.TLC_SYMMETRY_SET_TOO_SMALL));
		}
	}
	
	@Test
	public void testD() throws FileNotFoundException, IOException {
		if (expectedWarnings != null) {
			compareToExpectedResults((String[])recorder.getRecords(EC.TLC_SYMMETRY_SET_TOO_SMALL).get(0));
		} else {
			Assert.assertFalse(recorder.recorded(EC.TLC_SYMMETRY_SET_TOO_SMALL));
		}
	}
	
	private void createConfigFile(final String humans, final String others) throws IOException {
		final File configFile = new File(BASE_DIR + TEST_MODEL + CONFIG_FILE);
		final File backup = new File(BASE_DIR + TEST_MODEL + CONFIG_FILE_BACKUP);
		
		if (backup.exists()) {
			Assert.fail("Github432 test state is incoherent: the backup file already exists at "
							+ backup.getAbsolutePath());
		}
		
		try {
			Files.move(configFile.toPath(), backup.toPath(), StandardCopyOption.ATOMIC_MOVE);
		} catch (final IOException e) {
			Assert.fail(e.getMessage());
		}
		
		try {
			try (final BufferedWriter bw = new BufferedWriter(new FileWriter(configFile))) {
				try (final BufferedReader br = new BufferedReader(new FileReader(backup))) {
					boolean humansFound = false;
					boolean othersFound = false;
					String line;
					while ((line = br.readLine()) != null) {
						int index = humansFound ? -1 : line.indexOf(HUMANS_TOKEN);
						if (index == -1) {
							index = othersFound ? -1 : line.indexOf(OTHERS_TOKEN);

							if (index == -1) {
								bw.write(line);
							} else {
								final int secondStart = index + OTHERS_TOKEN.length();
								final String convertedLine = line.substring(0, index) + others
																	+ line.substring(secondStart);
								bw.write(convertedLine);
								othersFound = true;
							}
						} else {
							final int secondStart = index + HUMANS_TOKEN.length();
							final String convertedLine = line.substring(0, index) + humans
																+ line.substring(secondStart);
							bw.write(convertedLine);
							humansFound = true;
						}
						
						bw.newLine();
					}
				}
			}
		} catch (final IOException e) {
			
			revertConfigFile();
			
			Assert.fail(e.getMessage());
		}
	}
	
	private void revertConfigFile() {
		final File backup = new File(BASE_DIR + TEST_MODEL + CONFIG_FILE_BACKUP);
		
		if (backup.exists()) {
			final File configFile = new File(BASE_DIR + TEST_MODEL + CONFIG_FILE);

			try {
				Files.move(backup.toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
			} catch (final IOException e) {
				Assert.fail(e.getMessage());
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/DotStateWriter.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import tlc2.tool.Action;
import tlc2.tool.TLCState;
import util.FileUtil;

/**
 * Writes the given state in dot notation.
 * 
 * @see https://en.wikipedia.org/wiki/DOT_(graph_description_language)
 * 
 * 
 * To ASCII-render a graph (on Debian|Ubuntu) install cpanminus, sudo cpanm Graph::Easy and run:
 * cat your.dot | graph-easy --from=dot --as_ascii
 * (https://stackoverflow.com/questions/3211801/graphviz-and-ascii-output)
 */
public class DotStateWriter extends StateWriter {

	// The Graphviz color scheme that is used for state transition edge colors. See
	// https://www.graphviz.org/doc/info/colors.html for more details on color schemes.
	private static final String dotColorScheme = "paired12";

	// A mapping of action names to their assigned color ids. Since states are fed
	// into a StateWriter incrementally, one at a time, this table is built up over
	// time, adding new actions as we find out about them.
	private final Map<String, Integer> actionToColors = new HashMap<>();
	
	// A mapping from ranks to nodes.
	private final Map<Integer, Set<Long>> rankToNodes = new HashMap<>();

	// Determines whether or not transition edges should be colorized in the state
	// graph.
	private final boolean colorize;

	// Determines whether or not transition edges should be labeled with their
	// action names.
	private final boolean actionLabels;

	// Used for assigning unique color identifiers to each action type. Incremented
	// by 1 every time a new color is assigned to an action.
	private Integer colorGen = 1;
	
	// Create a valid fname_snapshot.dot file after a state is written.
	private final boolean snapshot;
	
	public DotStateWriter(final String fname, final String strict) throws IOException {
		this(fname, strict, false, false, false);
	}
	
	/**
	 * @param fname
	 * @param colorize
	 *            Colorize state transition edges in the DOT state graph.
	 * @param actionLabels
	 *            Label transition edges in the state graph with the name of the
	 *            associated action. Can potentially add a large amount of visual
	 *            clutter for large graphs with many actions.
	 * @throws IOException
	 */
	public DotStateWriter(final String fname, final boolean colorize, final boolean actionLabels,
			final boolean snapshot) throws IOException {
		this(fname, "strict ", colorize, actionLabels, snapshot);
	}
	
	public DotStateWriter(final String fname, final String strict, final boolean colorize, final boolean actionLabels,
			final boolean snapshot) throws IOException {
		super(fname);
		this.colorize = colorize;
		this.actionLabels = actionLabels;
		this.snapshot = snapshot;
		this.writer.append(strict + "digraph DiskGraph {\n"); // strict removes redundant edges
		// Turned off LR because top to bottom provides better results with GraphViz viewer.
//		this.writer.append("rankdir=LR;\n"); // Left to right rather than top to bottom
        
		// Set the color scheme for transition edges if necessary.
		if(colorize) {
			this.writer.append(String.format("edge [colorscheme=\"%s\"]\n", dotColorScheme));	
		}
        
		// Spread out state nodes a bit more.
        this.writer.append("nodesep=0.35;\n");

		this.writer.append("subgraph cluster_graph {\n"); 
        this.writer.append("color=\"white\";\n"); // no border.
		this.writer.flush();
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IStateWriter#isDot()
	 */
	@Override
	public boolean isDot() {
		return true;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.StateWriter#writeState(tlc2.tool.TLCState)
	 */
	public synchronized void writeState(final TLCState state) {
		// Marker the state as an initial state by using a filled style.
		this.writer.append(Long.toString(state.fingerPrint()));
		this.writer.append(" [label=\"");
		this.writer.append(states2dot(state));
		this.writer.append("\",style = filled]");
		this.writer.append("\n");
		
		maintainRanks(state);
		
		if (snapshot) {
			try {
				this.snapshot();
			} catch (IOException e) {
				// Let's assume this never happens!
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	
	protected void maintainRanks(final TLCState state) {
		rankToNodes.computeIfAbsent(state.getLevel(), k -> new HashSet<Long>()).add(state.fingerPrint());
	}

	/* (non-Javadoc)
	 * @see tlc2.util.StateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.TLCState, boolean)
	 */
	public void writeState(TLCState state, TLCState successor, boolean successorStateIsNew) {
		writeState(state, successor, successorStateIsNew, Visualization.DEFAULT);
	}
	
    public void writeState(final TLCState state, final TLCState successor, final boolean successorStateIsNew, Action action)
    {
		writeState(state, successor, null, 0, 0, successorStateIsNew, Visualization.DEFAULT, action);
    }
	
	/* (non-Javadoc)
	 * @see tlc2.util.StateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.TLCState, boolean, tlc2.util.IStateWriter.Visualization)
	 */
	public void writeState(TLCState state, TLCState successor, boolean successorStateIsNew, Visualization visualization) {
		writeState(state, successor, null, 0, 0, successorStateIsNew, visualization, null);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.StateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.TLCState, tlc2.util.BitVector, int, int, boolean)
	 */
	public void writeState(TLCState state, TLCState successor, BitVector actionChecks, int from, int length, boolean successorStateIsNew) {
		writeState(state, successor, actionChecks, from, length, successorStateIsNew, Visualization.DEFAULT, null);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.StateWriter#writeState(tlc2.tool.TLCState, tlc2.tool.TLCState, java.lang.String, boolean, tlc2.util.IStateWriter.Visualization)
	 */
	private synchronized void writeState(TLCState state, TLCState successor, BitVector actionChecks, int from, int length, boolean successorStateIsNew,
			Visualization visualization, Action action) {
		final String successorsFP = Long.toString(successor.fingerPrint());
		
		// Write the transition edge.
		this.writer.append(Long.toString(state.fingerPrint()));
		this.writer.append(" -> ");
		this.writer.append(successorsFP);
		if (visualization == Visualization.STUTTERING) {
			this.writer.append(" [style=\"dashed\"];\n");
		} else {
			// Add the transition edge label.
			if(action!=null) {
				String transitionLabel = this.dotTransitionLabel(state, successor, action);
				this.writer.append(transitionLabel);	
			}
			
			this.writer.append(";\n");
			
			// If the successor is new, print the state's label. Labels are printed
			// when writeState sees the successor. It does not print the label for
			// the current state. If it would print the label for the current state,
			// the init state labels would be printed twice.
			if (successorStateIsNew) {
				// Write the successor's label.
				this.writer.append(successorsFP);
				this.writer.append(" [label=\"");
				this.writer.append(states2dot(successor));
				this.writer.append("\"]");
				this.writer.append(";\n");
			}
		}
		
		maintainRanks(state);
		
		if (snapshot) {
			try {
				this.snapshot();
			} catch (IOException e) {
				// Let's assume this never happens!
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	
	/**
	 * Given an action, returns the associated color identifier for it. The color
	 * identifier is just an integer suitable for use in a GraphViz color scheme. This
	 * method updates the (action -> color) mapping if this action has not been seen
	 * before for this DotStateWriter instance.
	 * 
	 * @param action
	 * @return the color identifier for the given action
	 */
	protected Integer getActionColor(final Action action) {
		// Return a default color if the given action is null.
		if (action == null) {
			return 1;
		} else {
			String actionName = action.getName().toString();
			// If this action has been seen before, retrieve its color.
			if (actionToColors.containsKey(actionName)) {
				return actionToColors.get(actionName);
			}
			// If this action has not been seen yet, get the next available color
			// and assign it to this action.
			else {
				this.colorGen++;
				actionToColors.put(actionName, this.colorGen);
				return this.colorGen;
			}
		}
	}
	
	/**
	 * Creates a DOT label for an edge representing a state transition. 
	 * 
	 * @param state the current state of the transition
	 * @param successor the next state of the transition
	 * @param action the action that induced the transition
	 * @return the DOT label for the edge
	 */
	protected String dotTransitionLabel(final TLCState state, final TLCState successor, final Action action) {
	    // Only colorize edges if specified. Default to black otherwise.
		final String color = colorize ? this.getActionColor(action).toString() : "black" ;
		
	    // Only add action label if specified.
		final String actionName = actionLabels ? action.getName().toString() : "" ;
		
		final String labelFmtStr = " [label=\"%s\",color=\"%s\",fontcolor=\"%s\"]";
		return String.format(labelFmtStr, actionName, color, color);
	}
	
	
	/**
	 * Creates a DOT legend that maps actions to their corresponding edge color in the state graph.
	 * 
	 * @param name the title of the legend
	 * @param actions the set of action names that will be included in the legend
	 * @return
	 */
	protected String dotLegend(final String name, final Set<String> actions) {
		final StringBuilder sb = new StringBuilder();
		sb.append(String.format("subgraph %s {", "cluster_legend"));
		sb.append("graph[style=bold];");
		sb.append("label = \"Next State Actions\" style=\"solid\"\n");
		sb.append(String.format("node [ labeljust=\"l\",colorscheme=\"%s\",style=filled,shape=record ]\n",
				dotColorScheme));
		for (String action : actions) {
			String str = String.format("%s [label=\"%s\",fillcolor=%d]", action.replaceAll("!", ":"), action,
					this.actionToColors.get(action));
			sb.append(str);
			sb.append("\n");
		}
		sb.append("}");
		return sb.toString();
	}
	
	/**
	 * Given a TLC state, generate a string representation suitable for a HTML DOT graph label.
	 */
	//TODO This cannot handle states with variables such as "active = (0 :> TRUE @@ 1 :> FALSE)". 
//	protected static String state2html(final TLCState state) {		
//		final StringBuilder sb = new StringBuilder();
//		final Map<UniqueString, Value> valMap = state.getVals();
//
//		// Generate a string representation of state.
//		for (UniqueString key : valMap.keySet()) {
//			final String valString = (key.toString() + " = " + valMap.get(key).toString());
//			sb.append(valString);
//			// New line between variables.
//			sb.append("<br/>");
//		}
//		return sb.toString();
//	}

	protected static String states2dot(final TLCState state) {
		// Replace "\" with "\\" and """ with "\"".	
		return state.toString().replace("\\", "\\\\").replace("\"", "\\\"").trim()
				.replace("\n", "\\n"); // Do not remove remaining (i.e. no danling/leading) "\n". 
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IStateWriter#close()
	 */
	public void close() {
		for (final Set<Long> entry : rankToNodes.values()) {
			this.writer.append("{rank = same; ");
			for (final Long l : entry) {
				this.writer.append(l + ";");
			}
			this.writer.append("}\n");
		}
		this.writer.append("}\n"); // closes the main subgraph.
		// We only need the legend if the edges are colored by action and there is more
		// than a single action.
		if (colorize && this.actionToColors.size() > 1) {
			this.writer.append(dotLegend("DotLegend", this.actionToColors.keySet()));
		}
		this.writer.append("}");
		super.close();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.util.IStateWriter#snapshot()
	 */
	@Override
	public void snapshot() throws IOException {
		this.writer.flush();
		
		final String snapshot = fname.replace(".dot", "_snapshot" + ".dot");
		FileUtil.copyFile(this.fname, snapshot);

		StringBuffer buf = new StringBuffer();
		for (final Set<Long> entry : rankToNodes.values()) {
			buf.append("{rank = same; ");
			for (final Long l : entry) {
				buf.append(l + ";");
			}
			buf.append("}\n");
		}
		buf.append("}\n");
		// We only need the legend if the edges are colored by action and there is more
		// than a single action.
		if (colorize && this.actionToColors.size() > 1) {
			buf.append(dotLegend("DotLegend", this.actionToColors.keySet()));
		}
		buf.append("}");

	    Files.write(Paths.get(snapshot), buf.toString().getBytes(), StandardOpenOption.APPEND);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/TLCServerThread.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:34 PST by lamport  
//      modified on Fri Mar  2 23:46:22 PST 2001 by yuanyu   
package tlc2.tool.distributed;

import java.io.EOFException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCState;
import tlc2.tool.TLCStateVec;
import tlc2.tool.WorkerException;
import tlc2.tool.distributed.selector.IBlockSelector;
import tlc2.tool.fp.FPSet;
import tlc2.tool.queue.IStateQueue;
import tlc2.tool.queue.StateQueue;
import tlc2.util.BitVector;
import tlc2.util.IdThread;
import tlc2.util.LongVec;

public class TLCServerThread extends IdThread {
	private static int COUNT = 0;
	/**
	 * Runtime statistics about states send and received by and from the remote
	 * worker. These stats are shown at the end of model checking for every
	 * worker thread.
	 */
	private int receivedStates, sentStates;
	/**
	 * {@link TLCWorker}s maintain a worker-local fingerprint cache. The hit
	 * ratio is kept here for final statistics. A negative value indicates that
	 * the statistic has not been gathered yet.
	 */
	private double cacheRateHitRatio = -1L;
	/**
	 * An {@link IBlockSelector} tunes the amount of states send to a remote
	 * worker. Depending on its concrete implementation it might employ runtime
	 * statistics to assign the ideal amount of states.
	 * 
	 * @see TLCServerThread#states
	 */
	private final IBlockSelector selector;
	/**
	 * Current unit of work or null
	 * 
	 * @see TLCServerThread#selector
	 */
	private TLCState[] states = new TLCState[0];
	/**
	 * Periodically check the remote worker's aliveness by spawning a
	 * asynchronous task that is automatically scheduled by the JVM for
	 * re-execution in the defined interval.
	 * <p>
	 * It is the tasks responsibility to detect a stale worker and disconnect
	 * it.
	 * 
	 * @see TLCServerThread#keepAliveTimer
	 */
	private final TLCTimerTask task;
	/**
	 * @see TLCServerThread#task
	 */
	private final Timer keepAliveTimer;
	/**
	 * Synchronized flag used to indicate the correct amount of workers to
	 * TCLGlobals.
	 * 
	 * Either {@link TLCServerThread#run()} or
	 * {@link TLCServerThread#keepAliveTimer} will flip to false causing
	 * subsequent calls to
	 * {@link TLCServerThread#handleRemoteWorkerLost(StateQueue)} to be a noop.
	 * 
	 * Synchronization is required because {@link TLCServerThread#run()} and
	 * {@link TLCTimerTask#run()} are executed as two separate threads.
	 */
	private final AtomicBoolean cleanupGlobals = new AtomicBoolean(true);
	/**
	 * An {@link ExecutorService} used to parallelize calls to the _distributed_
	 * fingerprint set servers ({@link FPSet}).
	 * <p>
	 * The fingerprint space is partitioned across all {@link FPSet} servers and
	 * thus can be accessed concurrently.
	 */
	private final ExecutorService executorService;
	/**
	 * An RMI proxy for the remote worker.
	 * 
	 * @see TLCServerThread#tlcServer
	 */
	private final TLCWorkerRMI worker;
	/**
	 * The {@link TLCServer} master this {@link TLCServerThread} provides the
	 * service of handling a single remote worker. A {@link TLCServer} uses n
	 * {@link TLCWorker}s to calculate the next state relation. To invoke
	 * workers concurrently, it spawns a {@link TLCServerThread} for each
	 * {@link TLCWorkerRMI} RMI proxy.
	 * <p>
	 * {@link TLCServer} and {@link TLCWorkerRMI} form a 1:n mapping and
	 * {@link TLCServerThread} is this mapping.
	 * 
	 * @see TLCServerThread#worker
	 */
	private final TLCServer tlcServer;
	/**
	 * Remote worker's address used to label local threads.
	 */
	private URI uri;

	public TLCServerThread(TLCWorkerRMI worker, URI aURI, TLCServer tlc, ExecutorService es, IBlockSelector aSelector) {
		super(COUNT++);
		this.executorService = es;
		this.tlcServer = tlc;
		this.selector = aSelector;
		this.uri = aURI;

		// Create Timer early to avoid NPE in handleRemoteWorkerLost (it tries to cancel the timer)
		keepAliveTimer = new Timer("TLCWorker KeepAlive Timer ["
				+ uri.toASCIIString() + "]", true);
		
		// Wrap the TLCWorker with a SmartProxy. A SmartProxy's responsibility
		// is to measure the RTT spend to transfer states back and forth.
		this.worker = new TLCWorkerSmartProxy(worker);

		// Prefix the thread name with a fixed string and a counter.
		// This part is used by the external Munin based statistics software to
		// gather thread contention stats.
		final String i = String.format("%03d", myGetId());
		setName(TLCServer.THREAD_NAME_PREFIX + i + "-[" + uri.toASCIIString() + "]");
		
		// schedule a timer to periodically (60s) check server aliveness
		task = new TLCTimerTask();
		keepAliveTimer.schedule(task, 10000, 60000);
	}

	/**
	 * This method gets a state from the queue, generates all the possible next
	 * states of the state, checks the invariants, and updates the state set and
	 * state queue.
	 */
	public void run() {
		TLCGlobals.incNumWorkers();
		TLCStateVec[] newStates = null;
		LongVec[] newFps = null;

		final IStateQueue stateQueue = this.tlcServer.stateQueue;
		try {
			START: while (true) {
				// blocks until more states available or all work is done
				states = selector.getBlocks(stateQueue, worker);
				if (states == null) {
					synchronized (this.tlcServer) {
						this.tlcServer.setDone();
						this.tlcServer.notify();
					}
					stateQueue.finishAll();
					return;
				}

				// without initial states no need to bother workers
				if (states.length == 0) {
					continue;
				}

				// count statistics
				sentStates += states.length;

				// real work happens here:
				// worker computes next states for states
				boolean workDone = false;
				while (!workDone) {
					try {
						final NextStateResult res = this.worker.getNextStates(states);
						newStates = res.getNextStates();
						receivedStates += newStates[0].size();
						newFps = res.getNextFingerprints();
						workDone = true;
						task.setLastInvocation(System.currentTimeMillis());
						// Read remote worker cache hits which correspond to
						// states skipped
						tlcServer.addStatesGeneratedDelta(res.getStatesComputedDelta());
					} catch (RemoteException e) {
						// If a (remote) {@link TLCWorkerRMI} fails due to the
						// amount of new states we have sent it, try to lower
						// the amount of states
						// and re-send (until we just send a single state)
						if (isRecoverable(e) && states.length > 1) {
							MP.printMessage(
									EC.TLC_DISTRIBUTED_EXCEED_BLOCKSIZE,
									Integer.toString(states.length / 2));
							// states[] exceeds maximum transferable size
							// (add states back to queue and retry)
							stateQueue.sEnqueue(states);
							// half the maximum size and use it as a limit from
							// now on
							selector.setMaxTXSize(states.length / 2);
							// go back to beginning
							continue START;
						} else { 
							// non recoverable errors, exit...
							MP.printMessage(
									EC.TLC_DISTRIBUTED_WORKER_LOST,
									getUri().toString());
							handleRemoteWorkerLost(stateQueue);
							return;
						}
					} catch (NullPointerException e) {
						MP.printMessage(EC.TLC_DISTRIBUTED_WORKER_LOST,
								// have the stack trace on a newline
								"\n" + throwableToString(e));
						handleRemoteWorkerLost(stateQueue);
						return;
					}
				}

				// add fingerprints to fingerprint manager (delegates to
				// corresponding fingerprint server)
				// (Why isn't this done by workers directly?
				// -> because if the worker crashes while computing states, the
				// fp set would be inconsistent => making it an "atomic"
				// operation)
				BitVector[] visited = this.tlcServer.fpSetManager
						.putBlock(newFps, executorService);

				// recreate newly computed states and add them to queue
				for (int i = 0; i < visited.length; i++) {
					BitVector.Iter iter = new BitVector.Iter(visited[i]);
					int index;
					while ((index = iter.next()) != -1) {
						TLCState state = newStates[i].elementAt(index);
						// write state id and state fp to .st file for
						// checkpointing
						long fp = newFps[i].elementAt(index);
						state.uid = this.tlcServer.trace.writeState(state, fp);
						// add state to state queue for further processing
						stateQueue.sEnqueue(state);
					}
				}
			}
		} catch (Throwable e) {
			TLCState state1 = null, state2 = null;
			if (e instanceof WorkerException) {
				state1 = ((WorkerException) e).state1;
				state2 = ((WorkerException) e).state2;
			}
			if (this.tlcServer.setErrState(state1, true)) {
				if (state1 != null) {
					try {
						this.tlcServer.trace.printTrace(state1, state2);
					} catch (Exception e1) {
						MP.printError(EC.GENERAL, e1);
					}
				} else {
					MP.printError(EC.GENERAL, e);
				}
				stateQueue.finishAll();
				synchronized (this.tlcServer) {
					this.tlcServer.notify();
				}
			}
		} finally {
			try {
				cacheRateHitRatio = worker.getCacheRateRatio();
			} catch (RemoteException e) {
				// Remote worker might crash after return the last next
				// state computation result but before the cache rate hit
				// ratio statistic could be read. If this is the case the
				// final statistic will be reported as negative indicating
				// that it failed to read the statistic.
				MP.printWarning(
						EC.GENERAL,
						"Failed to read remote worker cache statistic (Expect to see a negative chache hit rate. Does not invalidate model checking results)");
			}
			keepAliveTimer.cancel();
			states = new TLCState[0];
			// not calling TLCGlobals#decNumWorkers here because at this point
			// TLCServer is shutting down anyway
		}
	}

	/**
	 * A recoverable error/exception is defined to be a case where the
	 * {@link TLCWorkerRMI} can continue to work if {@link TLCServer} sends less
	 * new states to process.
	 */
	private boolean isRecoverable(final Exception e) {
		final Throwable cause = e.getCause();
		return ((cause instanceof EOFException && cause.getMessage() == null) || (cause instanceof RemoteException && cause
				.getCause() instanceof OutOfMemoryError));
	}

	private String throwableToString(final Exception e) {
		final Writer result = new StringWriter();
		final PrintWriter printWriter = new PrintWriter(result);
		e.printStackTrace(printWriter);
		return result.toString();
	}

	/**
	 * Handles the case of a disconnected remote worker
	 * 
	 * @param stateQueue
	 */
	private void handleRemoteWorkerLost(final IStateQueue stateQueue) {
		// Cancel the keepAliveTimer which might still be running if an
		// exception in the this run() method has caused handleRemoteWorkerLost
		// to be called.
		keepAliveTimer.cancel();
		
		// This call has to be idempotent, otherwise we see bugs as in 
		// Bug #234 in general/bugzilla/index.html
		//
		// Prevent second invocation of worker de-registration which stems from
		// a race condition between the TimerTask (that periodically checks
		// server aliveness) and the exception handling that kicks in when the
		// run() method catches an RMI exception.
		if (cleanupGlobals.compareAndSet(true, false)) {

			// De-register TLCServerThread at the main server thread locally
			tlcServer.removeTLCServerThread(this);
			
			// Return the undone worklist (if any)
			if (stateQueue != null) {
				stateQueue.sEnqueue(states != null ? states : new TLCState[0]);
			}
			
			// Reset states to empty array to signal to TLCServer that we are not
			// processing any new states. Otherwise statistics will incorrectly
			// count this TLCServerThread as actively calculating states.
			states = new TLCState[0];
			
			// Before decrementing the worker count, notify all waiters on
			// stateQueue to re-evaluate the while loop in isAvail(). The demise
			// of this worker (who potentially was the lock owner) might causes
			// another consumer to leave the while loop (become a consumer).
			//
			// This has to happen _prior_ to calling decNumWorkers. Otherwise
			// we decrement the total number and the active count by one
			// simultaneously, leaving isAvail without effect.
			//
			// This is to work around a design bug in
			// tlc2.tool.queue.StateQueue's impl. Other IStateQueue impls should
			// hopefully not be affected by calling notifyAll on them though.
			if (stateQueue != null) {
				synchronized (stateQueue) {
					stateQueue.notifyAll();
				}
			}
			
			TLCGlobals.decNumWorkers();
		}
	}

	/**
	 * @return The current amount of states the corresponding worker is
	 *         computing on
	 */
	public int getCurrentSize() {
		return states.length;
	}

	/**
	 * @return the url
	 */
	public URI getUri() {
		return this.uri;
	}

	/**
	 * @return the receivedStates
	 */
	public int getReceivedStates() {
		return receivedStates;
	}

	/**
	 * @return the sentStates
	 */
	public int getSentStates() {
		return sentStates;
	}
	
	/**
	 * @return The hit ratio of the worker-local fingerprint cache.
	 */
	public double getCacheRateRatio() {
		return cacheRateHitRatio;
	}

	// ************************************//

	private class TLCTimerTask extends TimerTask {
		/**
		 * Timestamp of last successful remote invocation 
		 */
		private long lastInvocation = 0L;

		/* (non-Javadoc)
		 * @see java.util.TimerTask#run()
		 */
		public void run() {
			// Check if the last invocation happened within the last minute. If
			// not, check the worker's aliveness and dispose of it if indeed
			// lost.
			long now = new Date().getTime();
			if (lastInvocation == 0 || (now - lastInvocation) > 60000) {
				try {
					if (!worker.isAlive()) {
						handleRemoteWorkerLost(tlcServer.stateQueue);
					}
				} catch (RemoteException e) {
					handleRemoteWorkerLost(tlcServer.stateQueue);
				}
			}
		}

		/**
		 * @param lastInvocation the lastInvocation to set
		 */
		public void setLastInvocation(long lastInvocation) {
			this.lastInvocation = lastInvocation;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/FPSetManager.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:13:43 PST by lamport
//      modified on Wed Jan 10 00:09:44 PST 2001 by yuanyu

package tlc2.tool.distributed.fp;

import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.rmi.RemoteException;
import java.rmi.UnmarshalException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

import tlc2.output.EC;
import tlc2.tool.distributed.fp.callable.BitVectorWrapper;
import tlc2.tool.distributed.fp.callable.CheckFPsCallable;
import tlc2.tool.distributed.fp.callable.CheckInvariantCallable;
import tlc2.tool.distributed.fp.callable.ContainsBlockCallable;
import tlc2.tool.distributed.fp.callable.PutBlockCallable;
import tlc2.util.BitVector;
import tlc2.util.LongVec;
import util.Assert;
import util.ToolIO;

/**
 * @author <NAME>
 * @version $Id$
 */
@SuppressWarnings("serial")
public abstract class FPSetManager implements IFPSetManager {
	
	private static final Random rnd = new Random();
	
	private final static Logger LOGGER = Logger.getLogger(FPSetManager.class.getName());

	protected long mask = 0x7FFFFFFFFFFFFFFFL;
	/**
	 * A list of pairs. A pair is a remote reference and its corresponding
	 * hostname. The name is cached locally to report it correctly in the error
	 * case, where it's impossible to call {@link FPSetRMI#getHostname}.
	 */
	protected List<FPSets> fpSets;
	
	protected boolean managerIsBroken = false; 

	// SZ Jul 13, 2009: moved from FPSetRMI
	public static int Port = 10998; // port # for fpset server

	public FPSetManager() {
		 this(new ArrayList<FPSets>());
	}
	
	public FPSetManager(List<FPSets> fpSets) {
		this.fpSets = fpSets;
	}

	public FPSetManager(FPSetRMI fpSet) {
		this();
		this.fpSets.add(new FPSets(fpSet, fpSet.toString()));
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#numOfServers()
	 */
	public int numOfServers() {
		return this.fpSets.size();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#numOfAliveServers()
	 */
	public int numOfAliveServers() {
		// Add all fpsets to a set to remove the duplicates. The duplicates stem
		// from reassigning alive fpsets to the slot of a dead one.
		final Set<FPSets> s = new HashSet<FPSets>();
		s.addAll(this.fpSets);
		
		int aliveServer = 0;

		final Iterator<FPSets> itr = s.iterator();
		while (itr.hasNext()) {
			if (itr.next().isAvailable()) {
				aliveServer++;
			}
		}
		return aliveServer;
	}

	/**
	 * Replace the FPSet at the given index from the list of FPSets with the
	 * next available successor in the list.
	 * 
	 * @param index Corresponds to the FPSet to be replaced
	 * @return The index of the replacement or <code>-1</code> if no functional FPSet left.
	 */
	public synchronized int reassign(final int index) {
		// Guard against invalid indices
		if (index < 0 || index >= this.fpSets.size()) {
			throw new IllegalArgumentException("index not within bounds");
		}
		
		// Avoid cycling over the list of broken FPSets if all are broken
		// anyway. This is just a performance enhancement in that it prevents
		// the code from looping over the (potentially large) list of nested
		// FPSets.
		// Since the method is synchronized, we do not need to guard
		// managerIsBroken from concurrent access.
		if (managerIsBroken) {
			return -1;
		}
		
		// The broken FPSet
		final FPSets broken = this.fpSets.get(index);
		broken.setUnavailable();

		// Calculate the index of the successor
		int next = (index + 1) % this.fpSets.size();
		
		// Loop until we wrap around which would indicate that no functional
		// FPsets are left
		while (next != index) {
			final FPSets replacement = this.fpSets.get(next);
			if (replacement.isAvailable()) {
				for (int j = index; j < next; j++) {
					this.fpSets.set(j, replacement);
				}
				return next;
			}
			next = (next + 1) % this.fpSets.size();
		}
		
		// No FPSets left that can be used.
		// Mark the FPSetManager itself as broken and cache it for subsequent
		// calls.
		managerIsBroken = true;
		
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#close(boolean)
	 */
	public void close(boolean cleanup) throws IOException {
		FPSets curr = null;
		int len = this.fpSets.size();
		int idx = 0, lidx = 0;

		for (idx = 0; idx < len; idx++) {
			curr = this.fpSets.get(idx);
			if (curr != null)
				break;
		}
		if (curr == null)
			return;

		for (lidx = len - 1; lidx > idx; lidx--) {
			FPSets last = this.fpSets.get(lidx);
			if (last != null && last != curr)
				break;
		}
		for (int i = idx + 1; i <= lidx; i++) {
			FPSets next = this.fpSets.get(i);
			if (next != null && next != curr) {
				try {
					curr.exit(cleanup);
				} catch (UnmarshalException e) {
					// happens when the DiskFPSet closes it calls System.exit
				} catch (Exception e) {
					e.printStackTrace();
				}
				curr = next;
			}
		}
		if (curr != null) {
			try {
				curr.exit(cleanup);
			} catch (UnmarshalException e) {
				// happens when the DiskFPSet closes it calls System.exit
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public String getHostName() {
		String hostname = "Unknown";
		try {
			hostname = InetAddress.getLocalHost().getHostName();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return hostname;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#put(long)
	 */
	public boolean put(long fp) {
		int fpIdx = getFPSetIndex(fp);
		while (true) {
			try {
				return this.fpSets.get(fpIdx).put(fp);
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(fpIdx).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(fpIdx) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
					return false;
				}
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#contains(long)
	 */
	public boolean contains(long fp) {
		int fpIdx = getFPSetIndex(fp);
		while (true) {
			try {
				return this.fpSets.get(fpIdx).contains(fp);
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(fpIdx).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(fpIdx) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
					return false;
				}
			}
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#getFPSetIndex(long)
	 */
	public int getFPSetIndex(long fp) {
		return (int) ((fp & mask) % numOfServers());
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#putBlock(tlc2.util.LongVec[])
	 */
	public BitVector[] putBlock(LongVec[] fps) {
		int len = this.fpSets.size();
		BitVector[] res = new BitVector[len];
		for (int i = 0; i < len; i++) {
			try {
				res[i] = this.fpSets.get(i).putBlock(fps[i]);
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(i).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(i) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
					// Indicate for all fingerprints of the lost fpset that they are
					// new. This is achieved by setting all bits in BitVector.
					res[i] = new BitVector(fps[i].size(), true);
				} else {
					// Cause for loop to retry the current fps[i] to the newly
					// assigned fingerprint set
					i -= 1;
				}
			}
		}
		return res;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#putBlock(tlc2.util.LongVec[], java.util.concurrent.ExecutorService)
	 */
	public BitVector[] putBlock(final LongVec[] fps, final ExecutorService executorService) {
		// Create a Callable for each fingerprint set
		final int len = this.fpSets.size();
		final List<Callable<BitVectorWrapper>> solvers = new ArrayList<Callable<BitVectorWrapper>>();
		for (int i = 0; i < len; i++) {
			solvers.add(new PutBlockCallable(this, fpSets, fps, i));
		}

		return executeCallablesAndCollect(executorService, solvers);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#containsBlock(tlc2.util.LongVec[])
	 */
	public BitVector[] containsBlock(LongVec[] fps) {
		int len = this.fpSets.size();
		BitVector[] res = new BitVector[len];
		for (int i = 0; i < len; i++) {
			try {
				res[i] = this.fpSets.get(i).containsBlock(fps[i]);
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(i).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(i) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
					// Indicate for all fingerprints of the lost fpset that they are
					// new. This is achieved by setting all bits in BitVector.
					res[i] = new BitVector(fps[i].size(), true);
				} else {
					// Cause for loop to retry the current fps[i] to the newly
					// assigned fingerprint set
					i -= 1;
				}
			}
		}
		return res;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#containsBlock(tlc2.util.LongVec[], java.util.concurrent.ExecutorService)
	 */
	public BitVector[] containsBlock(final LongVec[] fps, final ExecutorService executorService) {
		// Create a Callable for each fingerprint set
		final int len = this.fpSets.size();
		final List<Callable<BitVectorWrapper>> solvers = new ArrayList<Callable<BitVectorWrapper>>();
		for (int i = 0; i < len; i++) {
			solvers.add(new ContainsBlockCallable(this, fpSets, fps, i));
		}

		return executeCallablesAndCollect(executorService, solvers);
	}

	/**
	 * Executes the given solvers by using the executor service. Afterwards it
	 * waits for completion and collects the results.
	 */
	private BitVector[] executeCallablesAndCollect(final ExecutorService executorService, 
			final List<Callable<BitVectorWrapper>> solvers) {
		// Have the callables executed by the executor service
		int retry = 0;
		final CompletionService<BitVectorWrapper> ecs = new ExecutorCompletionService<BitVectorWrapper>(executorService);
		for (int i = 0; i < solvers.size(); i++) {
			final Callable<BitVectorWrapper> s = solvers.get(i);
			try {
				ecs.submit(s);
				// reset retry after successfully scheduling a callable
				retry = 0;
			} catch (RejectedExecutionException e) {
				// Throttle current execution if executor service is rejecting
				// task due to excessive task submission
				if (retry++ < 3 && !executorService.isShutdown()) {
					// Determine sleep interval [1,5] randomly to prevent all waiters
					// from retrying at the same moment.
					int sleep = 1 + rnd.nextInt(5);
					
					LOGGER.log(
							Level.FINE,
							"{0}. time throttleing task submission due to overload during FPSetManager callable execution #{1} for {2} seconds",
							new Object[] {retry, i});

					// Sleep for n seconds
					try {
						Thread.sleep(sleep * 1000L);
					} catch (InterruptedException e1) {
						// not expected to happen
						e1.printStackTrace();
					}
					
					// rewind for loop by one to have it schedule the same
					// callable again
					i -= 1;
					continue;
				} else {
					// If ExecutorService has been shut down or REE has been
					// caused for some other reason, re-throw to escalate to
					// higher level exception handling.
					throw e;
				}
			}
		}

		// Wait for completion of the executor service and convert and return
		// result
		final BitVector[] res = new BitVector[solvers.size()];
		for (int i = 0; i < res.length; i++) {
			try {
				// Callers of putBlock and containBlock expect as a post-condition:
				// for all i BitVector[i] is result of LongVec[i].
				// (The LongVec[] order has to reflect itself in the BitVector[] order)
				// Otherwise one is going to see NPEs on the caller end.
				// Thus this code uses a BitVectorWrapper which associates the
				// BitVector return with its LongVec[i] input value.
				final BitVectorWrapper indexBitVector = ecs.take().get();
				final int index = indexBitVector.getIndex();
				// Only one result for a given LongVec[i] is correct
				Assert.check(res[index] == null, EC.GENERAL);
				res[index] = indexBitVector.getBitVector();
			} catch (InterruptedException e) {
				// not expected to happen
				e.printStackTrace();
			} catch (ExecutionException e) {
				// not expected to happen
				e.printStackTrace();
			}
		}
		return res;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#checkFPs()
	 */
	public long checkFPs() {
		final int len = this.fpSets.size();
		// Instantiation of a thread pool here is fine, as long as checkFPs is only called seldomly.
		final ExecutorService executorService = Executors.newFixedThreadPool(len);
		try {
			// Start checkFP on all FPSets concurrently
			// (checkFPs scans the full set sequentially!)
			final CompletionService<Long> ecs = new ExecutorCompletionService<Long>(executorService);
			for (int i = 0; i < len; i++) {
				ecs.submit(new CheckFPsCallable(fpSets.get(i).getFpset()));
			}
			// Return minimum value
			long res = Long.MAX_VALUE;
			for (int i = 0; i < len; i++) {
				try {
					res = Math.min(res, ecs.take().get());
				} catch (InterruptedException e) {
					// not expected to happen, could return an approximation
					// if happens (but fail fast for the moment).
					e.printStackTrace();
				} catch (ExecutionException e) {
					// not expected to happen, could return an approximation
					// if happens (but fail fast for the moment).
					e.printStackTrace();
				}
			}
			return res;
		} finally {
			// Always shutdown the executor service
			executorService.shutdown();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#checkInvariant()
	 */
	public boolean checkInvariant() {
		final int len = this.fpSets.size();
		// Instantiation of a thread pool here is fine, as long as checkFPs is only called seldomly.
		final ExecutorService executorService = Executors.newFixedThreadPool(len);
		try {
			// Start checkFP on all FPSets concurrently
			// (checkFPs scans the full set sequentially!)
			final CompletionService<Boolean> ecs = new ExecutorCompletionService<Boolean>(executorService);
			for (int i = 0; i < len; i++) {
				ecs.submit(new CheckInvariantCallable(fpSets.get(i).getFpset()));
			}
			// Return minimum value
			for (int i = 0; i < len; i++) {
				try {
					if(!ecs.take().get()) {
						return false;
					}
				} catch (InterruptedException e) {
					// not expected to happen, could return an approximation
					// if happens (but fail fast for the moment).
					e.printStackTrace();
				} catch (ExecutionException e) {
					// not expected to happen, could return an approximation
					// if happens (but fail fast for the moment).
					e.printStackTrace();
				}
			}
			return true;
		} finally {
			// Always shutdown the executor service
			executorService.shutdown();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#size()
	 */
	public long size() {
		int len = this.fpSets.size();
		long res = 0;
		for (int i = 0; i < len; i++) {
			try {
				res += this.fpSets.get(i).size();
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(i).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(i) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
				}
			}
		}
		return res;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#getStatesSeen()
	 */
	public long getStatesSeen() {
		long res = 1; // the initial state
		
		int len = this.fpSets.size();
		for (int i = 0; i < len; i++) {
			try {
				res += this.fpSets.get(i).getStatesSeen();
			} catch (Exception e) {
				ToolIO.out.println("Warning: Failed to connect from "
						+ this.getHostName() + " to the fp server at "
						+ this.fpSets.get(i).getHostname() + ".\n" + e.getMessage());
				if (this.reassign(i) == -1) {
					ToolIO.out
							.println("Warning: there is no fp server available.");
				}
			}
		}
		return res;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#getMask()
	 */
	public long getMask() {
		return mask;
	}

	private final void chkptInner(String fname, boolean chkpt)
			throws InterruptedException {
		int len = this.fpSets.size();
		Checkpoint[] chkpts = new Checkpoint[len];
		FPSets curr = null;
		int cnt = 0, idx = 0, lidx = 0;

		for (idx = 0; idx < len; idx++) {
			curr = this.fpSets.get(idx);
			if (curr != null) {
				chkpts[cnt] = new Checkpoint(idx, fname, chkpt);
				chkpts[cnt].run();
				cnt++;
				break;
			}
		}
		if (curr == null)
			return;

		for (lidx = len - 1; lidx > idx; lidx--) {
			FPSets last = this.fpSets.get(lidx);
			if (last != null && last != curr)
				break;
		}

		for (int i = idx + 1; i <= lidx; i++) {
			FPSets next = this.fpSets.get(i);
			if (next != null && next != curr) {
				curr = next;
				chkpts[cnt] = new Checkpoint(i, fname, chkpt);
				chkpts[cnt].run();
				cnt++;
			}
		}

		for (int i = 0; i < cnt; i++) {
			chkpts[i].join();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#checkpoint(java.lang.String)
	 */
	public void checkpoint(String fname) throws InterruptedException, IOException {
		chkptInner(fname, true);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#commitChkpt()
	 */
	public void commitChkpt() throws IOException {
		// no-op, added due to polymorphism with NonDistribuedFPSetManager
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.IFPSetManager#recover(java.lang.String)
	 */
	public void recover(String fname) throws InterruptedException, IOException {
		chkptInner(fname, false);
	}

	final class Checkpoint extends Thread {
		int hostIndex;
		String filename;
		boolean isChkpt;

		public Checkpoint(int index, String fname, boolean chkpt) {
			this.hostIndex = index;
			this.filename = fname;
			this.isChkpt = chkpt;
		}

		public void run() {
			try {
				if (this.isChkpt) {
					fpSets.get(this.hostIndex).beginChkpt(this.filename);
					fpSets.get(this.hostIndex).commitChkpt(this.filename);
				} else {
					fpSets.get(this.hostIndex).recover(this.filename);
				}
			} catch (IOException e) {
				ToolIO.out
						.println("Error: Failed to checkpoint the fingerprint server at "
								+ fpSets.get(this.hostIndex).getHostname()
								+ ". This server might be down.");
			}
		}
	}
	
	public static class FPSets implements Serializable {
		private final String hostname;
		private final FPSetRMI fpset;
		/**
		 * Indicates that this FPSetRMI is unavailable (e.g. the node crashed)
		 * and cannot be used anymore.
		 */
		private boolean isAvailable = true;

		public FPSets(FPSetRMI fpset, String hostname) {
			this.fpset = fpset;
			this.hostname = hostname;
		}

		public void setUnavailable() {
			isAvailable = false;
		}
		
		public boolean isAvailable() {
			return isAvailable;
		}

		public void exit(boolean cleanup) throws IOException {
			fpset.exit(cleanup);
		}

		public void recover(String filename) throws IOException {
			fpset.recover(filename);
		}

		public void commitChkpt(String filename) throws IOException {
			fpset.commitChkpt(filename);
		}

		public void beginChkpt(String filename) throws IOException {
			fpset.beginChkpt(filename);
		}

		public long getStatesSeen() throws RemoteException {
			return fpset.getStatesSeen();
		}

		public long size() throws IOException {
			return fpset.size();
		}

		public BitVector containsBlock(LongVec longVec) throws IOException {
			return fpset.containsBlock(longVec);
		}

		public BitVector putBlock(LongVec longVec) throws IOException {
			return fpset.putBlock(longVec);
		}

		public boolean put(long fp) throws IOException {
			return fpset.put(fp);
		}

		public boolean contains(long fp) throws IOException {
			return fpset.contains(fp);
		}
		
		public String getHostname() {
			return hostname;
		}

		public FPSetRMI getFpset() {
			return fpset;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/parser/TLAplusParserConstants.java<|end_filename|>
/* Generated By:23&JavaCC: Do not edit this line. TLAplusParserConstants.java */
package tla2sany.parser;

public interface TLAplusParserConstants {

  int EOF = 0;
  int BEGIN_MODULE = 1;
  int BEGIN_PRAGMA = 2;
  int _BM1 = 3;
  int CASE0 = 5;
  int CASE1 = 6;
  int CASE1b = 7;
  int CASE1c = 8;
  int CASE2 = 9;
  int CASE2b = 10;
  int CASE2c = 11;
  int CASE3 = 12;
  int CASE6 = 13;
  int CASE6b = 14;
  int CASE6c = 15;
  int CASEN = 16;
  int LETTER = 17;
  int DIGIT = 18;
  int NUMBER = 19;
  int _BM2 = 20;
  int _BM0 = 34;
  int SEPARATOR = 35;
  int END_MODULE = 36;
  int ACTION = 37;
  int ASSUME = 38;
  int BOXASSUME = 39;
  int ASSUMPTION = 40;
  int CASE = 41;
  int CHOOSE = 42;
  int CONSTANT = 43;
  int ELSE = 44;
  int EXCEPT = 45;
  int EXISTS = 46;
  int EXTENDS = 47;
  int FORALL = 48;
  int IF = 49;
  int INSTANCE = 50;
  int LET = 51;
  int LETIN = 52;
  int LOCAL = 53;
  int MODULE = 54;
  int NEW = 55;
  int OTHER = 56;
  int PROPOSITION = 57;
  int SF = 58;
  int T_EXISTS = 59;
  int T_FORALL = 60;
  int THEN = 61;
  int BY = 62;
  int ONLY = 63;
  int DEFINE = 64;
  int DF = 65;
  int THEOREM = 66;
  int USE = 67;
  int HIDE = 68;
  int HAVE = 69;
  int OBVIOUS = 70;
  int OMITTED = 71;
  int LAMBDA = 72;
  int TAKE = 73;
  int PROOF = 74;
  int PROVE = 75;
  int BOXPROVE = 76;
  int QED = 77;
  int RECURSIVE = 78;
  int STATE = 79;
  int TEMPORAL = 80;
  int PICK = 81;
  int WITNESS = 82;
  int SUFFICES = 83;
  int VARIABLE = 84;
  int WF = 85;
  int WITH = 86;
  int COMMA = 87;
  int COLON = 88;
  int COLONCOLON = 89;
  int DOT = 90;
  int US = 91;
  int DEF = 92;
  int LBR = 93;
  int RBR = 94;
  int DEFBREAK = 95;
  int LSB = 96;
  int ARSB = 97;
  int RSB = 98;
  int LWB = 99;
  int RWB = 100;
  int LBC = 101;
  int RBC = 102;
  int LAB = 103;
  int ARAB = 104;
  int RAB = 105;
  int BANG = 106;
  int ARROW = 107;
  int SUBSTITUTE = 108;
  int MAPTO = 109;
  int NUMBER_LITERAL = 110;
  int STRING_LITERAL = 111;
  int BAND = 112;
  int BOR = 113;
  int op_57 = 114;
  int op_68 = 115;
  int op_69 = 116;
  int op_70 = 117;
  int op_76 = 118;
  int op_26 = 119;
  int op_29 = 120;
  int op_58 = 121;
  int CASESEP = 122;
  int op_61 = 123;
  int op_112 = 124;
  int op_113 = 125;
  int op_114 = 126;
  int op_115 = 127;
  int op_116 = 128;
  int op_1 = 129;
  int AND = 130;
  int op_3 = 131;
  int op_4 = 132;
  int OR = 133;
  int op_6 = 134;
  int op_7 = 135;
  int op_8 = 136;
  int op_9 = 137;
  int op_10 = 138;
  int op_11 = 139;
  int op_12 = 140;
  int op_13 = 141;
  int op_14 = 142;
  int op_15 = 143;
  int op_16 = 144;
  int op_17 = 145;
  int op_18 = 146;
  int op_19 = 147;
  int IN = 148;
  int op_21 = 149;
  int op_22 = 150;
  int op_23 = 151;
  int op_24 = 152;
  int op_25 = 153;
  int op_27 = 154;
  int op_30 = 155;
  int op_31 = 156;
  int op_32 = 157;
  int op_33 = 158;
  int op_34 = 159;
  int op_35 = 160;
  int op_36 = 161;
  int op_37 = 162;
  int op_38 = 163;
  int op_39 = 164;
  int op_40 = 165;
  int op_41 = 166;
  int op_42 = 167;
  int op_43 = 168;
  int op_44 = 169;
  int op_45 = 170;
  int op_46 = 171;
  int op_47 = 172;
  int op_48 = 173;
  int op_49 = 174;
  int op_50 = 175;
  int op_51 = 176;
  int op_52 = 177;
  int op_53 = 178;
  int op_54 = 179;
  int op_55 = 180;
  int op_56 = 181;
  int op_59 = 182;
  int op_62 = 183;
  int op_63 = 184;
  int op_64 = 185;
  int EQUALS = 186;
  int op_66 = 187;
  int op_67 = 188;
  int op_71 = 189;
  int op_72 = 190;
  int op_73 = 191;
  int op_74 = 192;
  int op_75 = 193;
  int op_77 = 194;
  int op_78 = 195;
  int op_79 = 196;
  int op_80 = 197;
  int op_81 = 198;
  int op_82 = 199;
  int op_83 = 200;
  int op_84 = 201;
  int op_85 = 202;
  int op_86 = 203;
  int op_87 = 204;
  int op_88 = 205;
  int op_89 = 206;
  int op_90 = 207;
  int op_91 = 208;
  int op_92 = 209;
  int op_93 = 210;
  int op_94 = 211;
  int op_95 = 212;
  int op_96 = 213;
  int op_97 = 214;
  int op_98 = 215;
  int op_100 = 216;
  int op_101 = 217;
  int op_102 = 218;
  int op_103 = 219;
  int op_104 = 220;
  int op_105 = 221;
  int op_106 = 222;
  int op_107 = 223;
  int op_108 = 224;
  int op_109 = 225;
  int op_110 = 226;
  int op_111 = 227;
  int op_117 = 228;
  int op_118 = 229;
  int op_119 = 230;
  int IDENTIFIER = 231;
  int ProofStepLexeme = 232;
  int ProofImplicitStepLexeme = 233;
  int ProofStepDotLexeme = 234;
  int BareLevelLexeme = 235;
  int UnnumberedStepLexeme = 236;

  int DEFAULT = 0;
  int PRAGMA = 1;
  int SPEC = 2;
  int IN_COMMENT = 3;
  int EMBEDDED = 4;
  int IN_EOL_COMMENT = 5;

  String[] tokenImage = {
    "<EOF>",
    "<BEGIN_MODULE>",
    "\"--->\"",
    "<_BM1>",
    "<token of kind 4>",
    "<CASE0>",
    "<CASE1>",
    "<CASE1b>",
    "<CASE1c>",
    "<CASE2>",
    "<CASE2b>",
    "<CASE2c>",
    "<CASE3>",
    "<CASE6>",
    "<CASE6b>",
    "<CASE6c>",
    "<CASEN>",
    "<LETTER>",
    "<DIGIT>",
    "<NUMBER>",
    "<_BM2>",
    "<token of kind 21>",
    "\" \"",
    "\"\\t\"",
    "\"\\n\"",
    "\"\\r\"",
    "<token of kind 26>",
    "\"\\\\*\"",
    "<token of kind 28>",
    "\"*)\"",
    "\"*)\"",
    "<token of kind 31>",
    "<token of kind 32>",
    "<token of kind 33>",
    "<_BM0>",
    "<SEPARATOR>",
    "<END_MODULE>",
    "<ACTION>",
    "\"ASSUME\"",
    "\"[]ASSUME\"",
    "<ASSUMPTION>",
    "\"CASE\"",
    "\"CHOOSE\"",
    "<CONSTANT>",
    "\"ELSE\"",
    "\"EXCEPT\"",
    "<EXISTS>",
    "\"EXTENDS\"",
    "<FORALL>",
    "\"IF\"",
    "\"INSTANCE\"",
    "\"LET\"",
    "\"IN\"",
    "\"LOCAL\"",
    "\"MODULE\"",
    "\"NEW\"",
    "\"OTHER\"",
    "<PROPOSITION>",
    "\"SF_\"",
    "\"\\\\EE\"",
    "\"\\\\AA\"",
    "\"THEN\"",
    "\"BY\"",
    "\"ONLY\"",
    "\"DEFINE\"",
    "<DF>",
    "\"THEOREM\"",
    "\"USE\"",
    "\"HIDE\"",
    "\"HAVE\"",
    "\"OBVIOUS\"",
    "\"OMITTED\"",
    "\"LAMBDA\"",
    "\"TAKE\"",
    "\"PROOF\"",
    "\"PROVE\"",
    "\"[]PROVE\"",
    "\"QED\"",
    "\"RECURSIVE\"",
    "\"STATE\"",
    "<TEMPORAL>",
    "\"PICK\"",
    "\"WITNESS\"",
    "\"SUFFICES\"",
    "<VARIABLE>",
    "\"WF_\"",
    "\"WITH\"",
    "\",\"",
    "\":\"",
    "\"::\"",
    "\".\"",
    "\"_\"",
    "\"==\"",
    "\"(\"",
    "\")\"",
    "\"-|-\"",
    "\"[\"",
    "\"]_\"",
    "\"]\"",
    "\"{|\"",
    "\"|}\"",
    "\"{\"",
    "\"}\"",
    "\"<<\"",
    "\">>_\"",
    "\">>\"",
    "\"!\"",
    "\"->\"",
    "\"<-\"",
    "\"|->\"",
    "<NUMBER_LITERAL>",
    "<STRING_LITERAL>",
    "<BAND>",
    "<BOR>",
    "\"\\\'\"",
    "\"^+\"",
    "\"^*\"",
    "\"^#\"",
    "\"-.\"",
    "\"\\\\lnot\"",
    "\"\\\\neg\"",
    "\"~\"",
    "\"[]\"",
    "\"<>\"",
    "\"ENABLED\"",
    "\"UNCHANGED\"",
    "\"SUBSET\"",
    "\"UNION\"",
    "\"DOMAIN\"",
    "\"//\"",
    "\"/\\\\\"",
    "\"/=\"",
    "\"/\"",
    "\"\\\\/\"",
    "\"\\\\approx\"",
    "\"\\\\asymp\"",
    "\"\\\\bigcirc\"",
    "\"\\\\bullet\"",
    "\"\\\\cap\"",
    "\"\\\\cdot\"",
    "\"\\\\circ\"",
    "\"\\\\cong\"",
    "\"\\\\cup\"",
    "\"\\\\div\"",
    "\"\\\\doteq\"",
    "\"\\\\equiv\"",
    "\"\\\\geq\"",
    "\"\\\\gg\"",
    "\"\\\\in\"",
    "\"\\\\intersect\"",
    "\"\\\\union\"",
    "\"\\\\land\"",
    "\"\\\\leq\"",
    "\"\\\\ll\"",
    "\"\\\\lor\"",
    "\"\\\\o\"",
    "\"\\\\odot\"",
    "\"\\\\ominus\"",
    "\"\\\\oplus\"",
    "\"\\\\oslash\"",
    "\"\\\\otimes\"",
    "\"\\\\prec\"",
    "\"\\\\preceq\"",
    "\"\\\\propto\"",
    "\"\\\\sim\"",
    "\"\\\\simeq\"",
    "\"\\\\sqcap\"",
    "\"\\\\sqcup\"",
    "\"\\\\sqsubset\"",
    "\"\\\\sqsupset\"",
    "\"\\\\sqsubseteq\"",
    "\"\\\\sqsupseteq\"",
    "\"\\\\star\"",
    "\"\\\\subset\"",
    "\"\\\\subseteq\"",
    "\"\\\\succ\"",
    "\"\\\\succeq\"",
    "\"\\\\supset\"",
    "\"\\\\supseteq\"",
    "\"\\\\uplus\"",
    "\"\\\\wr\"",
    "\"\\\\\"",
    "\"~>\"",
    "\"=>\"",
    "\"=<\"",
    "\"=|\"",
    "\"=\"",
    "\"##\"",
    "\"#\"",
    "\"^^\"",
    "\"^\"",
    "\"--\"",
    "\"-|\"",
    "\"-+->\"",
    "\"-\"",
    "\"**\"",
    "\"*\"",
    "\"++\"",
    "\"+\"",
    "\"<=>\"",
    "\"<:\"",
    "\"<=\"",
    "\"<\"",
    "\">=\"",
    "\">\"",
    "\"...\"",
    "\"..\"",
    "\"||\"",
    "\"|\"",
    "\"|-\"",
    "\"|=\"",
    "\"&&\"",
    "\"&\"",
    "\"$$\"",
    "\"$\"",
    "\"??\"",
    "\"%%\"",
    "\"%\"",
    "\"@@\"",
    "\"!!\"",
    "\":>\"",
    "\":=\"",
    "\"::=\"",
    "\"(+)\"",
    "\"(-)\"",
    "\"(.)\"",
    "\"(/)\"",
    "\"(\\\\X)\"",
    "\"\\\\notin\"",
    "\"\\\\times\"",
    "\"\\\\X\"",
    "<IDENTIFIER>",
    "<ProofStepLexeme>",
    "<ProofImplicitStepLexeme>",
    "<ProofStepDotLexeme>",
    "<BareLevelLexeme>",
    "<UnnumberedStepLexeme>",
  };

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/BCoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME>
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class BCoverageTest extends AbstractCoverageTest {

    public BCoverageTest () {
        super("B");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "2"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "5", "2", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
		assertCoverage("<Init line 4, col 1 to line 4, col 4 of module B>: 1:1\n" + 
				"  line 4, col 9 to line 4, col 17 of module B: 1\n" +
				"<A line 8, col 1 to line 8, col 1 of module B>: 1:2\n" + 
				"  line 8, col 6 to line 8, col 19 of module B: 2\n" + 
				"<B line 10, col 1 to line 10, col 1 of module B>: 0:2\n" + 
				"  line 10, col 6 to line 10, col 19 of module B: 2"); 
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/proof/IProofFoldCommandIds.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.proof;

/**
 * Ids for proof folding commands.
 * 
 * @author <NAME>
 *
 */
public interface IProofFoldCommandIds
{

    public static final String FOCUS_ON_STEP = "org.lamport.tla.toolbox.editor.basic.FocusOnStep";

    /**
     * Collapses all proofs.
     */
    public static final String FOLD_ALL_PROOFS = "org.lamport.tla.toolbox.editor.basic.FoldAllProofs";
    /**
     * Expands all proofs.
     */
    public static final String EXPAND_ALL_PROOFS = "org.lamport.tla.toolbox.editor.basic.ExpandAllProofs";
    /**
     * Expands the current subtree.
     */
    public static final String EXPAND_SUBTREE = "org.lamport.tla.toolbox.editor.basic.ExpandSubtree";
    /**
     * Collapses the current subtree.
     */
    public static final String COLLAPSE_SUBTREE = "org.lamport.tla.toolbox.editor.basic.CollapseSubtree";
    /**
     * Shows the proof of the step with the cursor and collapses all
     * subproofs.
     */
    public static final String SHOW_IMMEDIATE = "org.lamport.tla.toolbox.editor.basic.ShowImmediate";

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/LongFormDialog.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * This class really belongs in the <code>...tlc.ui</code> project, except that
 * this project has no cited dependency on that project and i'm hesitent to
 * introduce new dependencies.
 * 
 * @author <NAME>
 */
public class LongFormDialog extends Dialog {
	private final String m_title;
	private final String m_message;
	
	public LongFormDialog(final String title, final String message) {
		super(UIHelper.getShellProvider());
		
		setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); 
		
		m_title = title;
		m_message = message;
	}

	@Override
    protected Control createDialogArea(final Composite parent) {
        final Composite container = (Composite)super.createDialogArea(parent);
        container.setLayout(new GridLayout(2, false));
        
        final Display d = container.getDisplay();
        // There is no cross platform clear way to get decoration fonts; get the "system" font and fudge.
        final Font f = d.getSystemFont();
        final GC gc = new GC(container.getShell());
        gc.setFont(f);
        final Point roughTitleSize = gc.textExtent(m_title);
        gc.dispose();
        
        final Label errorIcon = new Label(container, SWT.NONE);
        errorIcon.setImage(d.getSystemImage(SWT.ICON_ERROR));
        GridData gd = new GridData();
        gd.verticalAlignment = SWT.TOP;
        errorIcon.setLayoutData(gd);
        
        final Text text = new Text(container, (SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY));
        gd = new GridData();
        gd.heightHint = 180;
        gd.minimumWidth = Math.max(300, (int)((double)roughTitleSize.x * 1.2));
        gd.horizontalAlignment = SWT.FILL;
        gd.verticalAlignment = SWT.FILL;
        gd.grabExcessHorizontalSpace = true;
        gd.grabExcessVerticalSpace = true;
        text.setLayoutData(gd);
        text.setText(m_message);
        
        container.pack();
        
        return container;
    }

	// Overridden so that we create only an "Ok" button as there is no state to cancel out of.
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
	}
	
    @Override
    protected void configureShell(final Shell newShell) {
        super.configureShell(newShell);
        newShell.setText(m_title);
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/output/internal/TraceExplorerTraceSourceOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.internal;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink;
import org.lamport.tla.toolbox.tool.tlc.util.ModelHelper;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * Clears MC_TE.out and then writes TLC output to it.
 * 
 * @author <NAME>
 *
 */
public class TraceExplorerTraceSourceOutputSink extends FileProcessOutputSink
{

    private boolean isTraceExplorerOutput;
    private boolean clearFile;

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#appendText(java.lang.String)
     */
    public synchronized void appendText(final String text)
    {
        // we dont want to do anything if this is a run of the trace explorer
        if (isTraceExplorerOutput)
        {
            return;
        }
        if (clearFile)
        {
            // // try
            // // {
            // // ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
            // // public void run(IProgressMonitor monitor) throws CoreException
            // // {
            // // // System.out.print(Thread.currentThread().getId() + " : " + message);
            // // outFile.setContents(new ByteArrayInputStream("".getBytes()), IResource.KEEP_HISTORY
            // // | IResource.FORCE | IResource.DERIVED, monitor);
            // // }
            // // }, rule, IWorkspace.AVOID_UPDATE, new NullProgressMonitor());
            // //
            // // // if the console output is active, print to it
            // // } catch (CoreException e)
            // // {
            // // TLCActivator.getDefault().logError("Error clearing the trace explorer trace source file for " + processName, e);
            // // }
            ModelHelper.createOrClearFiles(new IFile[] { this.outFile }, new NullProgressMonitor());
            clearFile = false;
        }
        super.appendText(text);
    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.output.IProcessOutputSink#initializeSink(java.lang.String, int)
     */
    public void initializeSink(Model model, int sinkType)
    {
        this.isTraceExplorerOutput = sinkType == IProcessOutputSink.TYPE_TRACE_EXPLORE;
        this.outFile = model.getTraceSourceFile();
        this.rule = ResourceHelper.getModifyRule(outFile);

        // flag the output file to be cleared before the first text is appended
        this.clearFile = true;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/data/DataTests.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.data;

import junit.framework.Test;
import junit.framework.TestSuite;

public class DataTests
{

    public static Test suite()
    {
        TestSuite suite = new TestSuite("Test for org.lamport.tla.toolbox.tool.tlc.output.data");
        // $JUnit-BEGIN$
        suite.addTestSuite(TLCVariableValueTest.class);
        // $JUnit-END$
        return suite;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/DummyDiskFPSet.java<|end_filename|>
// Copyright (c) 2011 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp;

import java.rmi.RemoteException;

/**
 * The sole purpose of this class is to broaden the visibility of
 * {@link DiskFPSet}#index for uni tests
 */
@SuppressWarnings("serial")
public class DummyDiskFPSet extends LSBDiskFPSet {

	public DummyDiskFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		super(fpSetConfig);
	}

	public void setIndex(long[] anIndex) {
		this.index = anIndex;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/output/source/MethodInvocationCounter.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import java.util.LinkedHashMap;
import java.util.Map;

//import org.aspectj.lang.JoinPoint;

public class MethodInvocationCounter {
	public static final String TBTOIP_addIncrement = "TagBasedTLCOutputIncrementalParser.addIncrement(..)";
	public static final String TOPCL_documentPartitioningChanged = "TLCOutputPartitionChangeListener.documentPartitioningChanged(..)";

	private static Map<String, Long> invocations = new LinkedHashMap<String, Long>();

//	static void enter(JoinPoint joinPoint) {
//		String key = joinPoint.getSignature().toShortString();
//		Long l = invocations.get(key);
//		if(l == null) {
//			l = 0L;
//		}
//		invocations.put(key, ++l);
//	}

	/**
	 * @return the invocations
	 */
	public static Map<String, Long> getInvocations() {
		return invocations;
	}
	
	public static void clear() {
		invocations.clear();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAPartitionScanner.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IPartitionTokenScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
import org.lamport.tla.toolbox.editor.basic.util.BufferedDocumentScanner;

/**
 * Partition token scanner
 * Modified 17 Aug 2012 by LL for PlusCal algorithm coloring
 *  
 * @author <NAME>
 * @version $Id$
 */
public class TLAPartitionScanner implements IPartitionTokenScanner
{

    public static final String TLA_PARTITIONING = "__tla_partitioning"; //$NON-NLS-1$

    public final static String TLA_MULTI_LINE_COMMENT = "__tla_multiline_comment"; //$NON-NLS-1$
    public final static String TLA_SINGLE_LINE_COMMENT = "__tla_singleline_comment"; //$NON-NLS-1$
    public final static String TLA_PCAL = "__tla_pcal"; //$NON-NLS-1$
    public final static String TLA_STRING = "__tla_string"; //$NON-NLS-1$
    public final static String TLA_START_PCAL_COMMENT = "__tla_start_pcal_comment"; //$NON-NLS-1$ // Added for PlusCal
    public final static String TLA_END_PCAL_COMMENT = "__tla_end_pcal_comment"; //$NON-NLS-1$     //  "

    /**
     * supported partition types
     */
    public static final String[] TLA_PARTITION_TYPES = new String[] { TLA_MULTI_LINE_COMMENT, TLA_SINGLE_LINE_COMMENT,
            TLA_STRING,
            TLA_START_PCAL_COMMENT, TLA_END_PCAL_COMMENT};  // Added for PlusCal

    // states
    private static final int TLA = 0;
    private static final int SINGLE_LINE_COMMENT = 1;
    private static final int MULTI_LINE_COMMENT = 2;
    private static final int PCAL = 3;
    private static final int STRING = 4;
    private static final int START_PCAL_COMMENT = 5 ;  // Added for PlusCal
    private static final int END_PCAL_COMMENT = 6 ;    //  "
    
    private final IToken[] fTokens = new IToken[] { new Token(null), new Token(TLA_SINGLE_LINE_COMMENT),
            new Token(TLA_MULTI_LINE_COMMENT), new Token(TLA_PCAL), new Token(TLA_STRING),
            new Token(TLA_START_PCAL_COMMENT), new Token (TLA_END_PCAL_COMMENT)};  // Added for PlusCal

    // pre-fixes and post-fixes
    private static final int NONE = 0;
    private static final int BACKSLASH = 1;
    private static final int O_BRACKET = 2;
    private static final int C_BRACKET = 3;
    private static final int STAR = 4;
    private static final int CARRIAGE_RETURN = 5;
    private static final int C_BRACKET_STAR = 6;
    private static final int O_BRACKET_STAR = 7;
    private static final int MINUS = 8;
    private static final int MINUS_MINUS = 9;
    
    private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(1000); // faster implementation

    // The offset and length of the token currently under construction.
    private int fTokenOffset;
    private int fTokenLength;

    private int fPrefixLength;
    private int fLast;
    private int fState;

    // fEmulate is always false, which implies in turn that
    // fTLAOffset and fTLALength are never used.  This stuff
    // was probably used by Simon for testing.
    private boolean fEmulate = false;
    private int fTLAOffset;
    private int fTLALength;

    private int fCommentDepth;
    
    /*
     * The following added for PlusCal.
     */
    private IDocument fDocument ;  // This may not be used.
    /**
     * Holds the pcalMode argument with which setPartialRegion is called.
     */
    private int fpcalMode ;
    
    /**
     * After nextToken reads the "*)" that ends a PlusCal algorithm, it must return
     * the preceding PCAL token and the END_PCAL_COMMENT token before reading
     * any further characters.  To implement this, the outputEndPcalComment
     * flag is set to true when the PCAL token is returned; on the next call,
     * the END_PCAL_COMMENT token is returned immediately.
     */
    private boolean outputEndPcalComment = false ;
    
    /**
     * Constructor
     */
    public TLAPartitionScanner()
    {
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
     */
    public IToken nextToken()
    {
        
        // emulate TLAPartitionScanner
        if (fEmulate) {
            if (fTLAOffset != -1 && fTokenOffset + fTokenLength != fTLAOffset + fTLALength) {
                fTokenOffset += fTokenLength;
                return fTokens[TLA];
            } else {
                fTLAOffset= -1;
                fTLALength= 0;
            }
        }

        fTokenOffset += fTokenLength;
        fTokenLength = fPrefixLength;

        // Added for PlusCal to put out the END_PCAL_COMMENT token.
        // I have a hunch that it should decrement fTokenLength before calling
        // postFix, but the timing of the incrementing of fTokenLength in the
        // original code written by <NAME> is incomprehensible to me.
        if (outputEndPcalComment) {
            outputEndPcalComment = false ;
            fPrefixLength = 0;
            return fTokens[END_PCAL_COMMENT];
        }

        while (true)
        {
            final int ch = fScanner.read();

            // characters
            switch (ch) {
            case ICharacterScanner.EOF:
                if (fTokenLength > 0)
                {
                    fLast = NONE; // ignore last
                    return preFix(fState, TLA, NONE, 0);
                } else
                {
                    fLast = NONE;
                    fPrefixLength = 0;
                    return Token.EOF;
                }
            case '\r':
             // emulate TLAPartitionScanner
                if (!fEmulate && fLast != CARRIAGE_RETURN)
                {
                    fLast = CARRIAGE_RETURN;
                    fTokenLength++;
                    continue;
                } else
                {
                    switch (fState) {
                    case SINGLE_LINE_COMMENT:
                    case STRING:
                        if (fTokenLength > 0)
                        {
                            IToken token = fTokens[fState];

                            // emulate TLAPartitionScanner
                            if (fEmulate) {
                                fTokenLength++;
                                fLast= NONE;
                                fPrefixLength= 0;
                            } else {
                                fLast= CARRIAGE_RETURN;
                                fPrefixLength= 1;
                            }
                            
                            fState = TLA;
                            return token;

                        } else
                        {
                            consume();
                            continue;
                        }

                    default:
                        consume();
                        continue;
                    }
                }

            case '\n':
                switch (fState) {
                case SINGLE_LINE_COMMENT:
                case STRING:
                    return postFix(fState);

                default:
                    consume();
                    continue;
                }

            default:
                if (!fEmulate && fLast == CARRIAGE_RETURN)
                {
                    switch (fState) {
                    case SINGLE_LINE_COMMENT:
                    case STRING:

                        int last;
                        int newState;
                        switch (ch) {

                        case '(':
                            last = O_BRACKET;
                            newState = TLA;
                            break;

                        case ')':
                            last = C_BRACKET;
                            newState = TLA;
                            break;

                        case '*':
                            last = STAR;
                            newState = TLA;
                            break;

                        case '"':
                            last = NONE;
                            newState = STRING;
                            break;

                        case '\r':
                            last = CARRIAGE_RETURN;
                            newState = TLA;
                            break;

                        case '\\':
                            last = BACKSLASH;
                            newState = TLA;
                            break;

                        default:
                            last = NONE;
                            newState = TLA;
                            break;
                        }

                        fLast = NONE; // ignore fLast
                        return preFix(fState, newState, last, 1);

                    default:
                        break;
                    }
                }
            }

            // states
            switch (fState) {

            case TLA:
                switch (ch) {

                case '\\':
                    fLast = BACKSLASH;
                    fTokenLength++;
                    break;

                case '(':
                    fLast = O_BRACKET;
                    fTokenLength++;
                    break;

                case '*':
                    if (fLast == BACKSLASH)
                    {
                        if (fTokenLength - getLastLength() > 0)
                        {
                            // return single line comment
                            return preFix(TLA, SINGLE_LINE_COMMENT, NONE, 2);
                        } else
                        {
                            preFix(TLA, SINGLE_LINE_COMMENT, NONE, 2);
                            fTokenOffset += fTokenLength;
                            fTokenLength = fPrefixLength;
                            break;
                        }
                    } else if (fLast == O_BRACKET)
                    {
                        fCommentDepth++;
                        if (fTokenLength - getLastLength() > 0) {
                            return preFix(TLA, MULTI_LINE_COMMENT, O_BRACKET_STAR, 2);
                        }
                        else
                        {
                            preFix(TLA, MULTI_LINE_COMMENT, O_BRACKET_STAR, 2);
                            fTokenOffset += fTokenLength;
                            fTokenLength = fPrefixLength;
                            break;
                        }

                    } else
                    {
                        fTokenLength++;
                        fLast = STAR;
                        break;
                    }

                case '"':
                    fLast = NONE; // ignore fLast
                    if (fTokenLength > 0)
                        return preFix(TLA, STRING, NONE, 1);
                    else
                    {
                        preFix(TLA, STRING, NONE, 1);
                        fTokenOffset += fTokenLength;
                        fTokenLength = fPrefixLength;
                        break;
                    }

                // The following case added for PlusCal
                case ')' :
                    if ((fpcalMode == TLAFastPartitioner.IN_PCAL) && (fLast == STAR)) {
                        fpcalMode = TLAFastPartitioner.AFTER_PCAL ;
                        if (fTokenLength - getLastLength() > 0) {
                            outputEndPcalComment = true ;  
                            return preFix(TLA, TLA, NONE, 2) ;
                               // the next state and last value are what they should be
                               // after the next call of getNext returns the END_PCAL_COMMENT
                               // token.
                        }
                        else {
                            return postFix(END_PCAL_COMMENT) ;
                        }
                    }
                default:
                    consume();
                    break;
                }
                break;

            case SINGLE_LINE_COMMENT:
                consume();
                break;

            case MULTI_LINE_COMMENT:
                switch (ch) {
                case '*':
                    if (fLast == O_BRACKET) 
                    {
                        fCommentDepth++;
                        consume();
                        break;
                    } else {
                        fTokenLength++;
                        fLast = STAR;
                        break;
                    }

                case ')':
                    if (fLast == STAR)
                    {
                        fCommentDepth--;
                        if (fCommentDepth == 0) 
                        {
                            // return multi-line comment
                            return postFix(MULTI_LINE_COMMENT);
                        } else {
                            consume();
                            break;
                        }
                    } else
                    {
                        consume();
                        break;
                    }
                case '(':
                    fLast = O_BRACKET;
                    fTokenLength++;
                    break;
                    
                // The following case added for PlusCal testing
                case '-':
                    if (    (fCommentDepth == 1)
                         && (fpcalMode == TLAFastPartitioner.BEFORE_PCAL) 
                         && (fLast == MINUS)) {
                        int nxtPos = fTokenLength + fTokenOffset + 1;
                        try {
                            if (   (   (fDocument.getLength() >= nxtPos + 4)
                                    && (fDocument.get(nxtPos, 4).equals("fair")))
                                || (   (fDocument.getLength() >= nxtPos + 9)
                                    && (fDocument.get(nxtPos, 9).equals("algorithm")))) {
                              fCommentDepth = 0 ;
                              fpcalMode = TLAFastPartitioner.IN_PCAL ;
                              return preFix(START_PCAL_COMMENT, TLA, MINUS_MINUS, 2) ;
                            }
                        } catch (BadLocationException e) {
                            // This shouldn't happen
                        }
                    }
                    fLast = MINUS ;
                    fTokenLength++;
                    break;
                default:
                    consume();
                    break;
                }
                break;

            case STRING:
                switch (ch) {
                case '\"':
                    if (fLast != BACKSLASH)
                    {
                        // return String
                        return postFix(STRING);

                    } else
                    {
                        consume();
                        break;
                    }

                default:
                    consume();
                    break;
                }
                break;
            }
        }
    }

    /* (non-Javadoc)
     * The setRange method is called when initializing the tokenizing for a document that has just been 
     * loaded into an editor.  It is called with document a zero-length document and offset and length both 0.
     * After this call, TLAFastPartitioner (originally FastPartitioner) then calls nextToken on the zero-length
     * document, reading from fScanner yields only an EOF token (value = -1).  It then calls setPartialRange
     * with the actual document followed by calls to nextToken--presumably calling nextToken until nextToken
     * returns the EOF token.  Since the Eclipse infrastructure seems to enjoy doing the same thing multiple
     * times, this sequence of calling setRange followed by setPartialRange can be performed more than once. 
     * 
     * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(org.eclipse.jface.text.IDocument, int, int)
     */
    public void setRange(IDocument document, int offset, int length)
    {
        fScanner.setRange(document, offset, length);
        fTokenOffset = offset;
        fTokenLength = 0;
        fPrefixLength = 0;
        fCommentDepth = 0;
        fLast = NONE;
        fState = TLA;

        fDocument = document ;                         // added for PlusCal, probably unnecessary
        fpcalMode = TLAFastPartitioner.BEFORE_PCAL ;   //  "
        outputEndPcalComment = false ;                 //  "
        
        // emulate TLAPartitionScanner
        if (fEmulate)
        {
            fTLAOffset = -1;
            fTLALength = 0;
        }

    }

    /* (non-Javadoc)
     * This method is needed to implement the IPartitionTokenScanner interface, but it should
     * never be called.  TLAFastPartitioner uses the following method instead.
     * 
     * @see org.eclipse.jface.text.rules.IPartitionTokenScanner#setPartialRange(org.eclipse.jface.text.IDocument, int, int, java.lang.String, int)
     */
    public void setPartialRange(IDocument document, int offset, int length, 
            String contentType, int partitionOffset) {
        
    }
    
    /* (non-Javadoc)
     * @see org.eclipse.jface.text.rules.IPartitionTokenScanner#setPartialRange(org.eclipse.jface.text.IDocument, int, int, java.lang.String, int)
     */
    public void setPartialRange(IDocument document, int offset, int length, 
                                String contentType, int partitionOffset, int pcalMode)
    {
        fScanner.setRange(document, offset, length);
        fTokenOffset = partitionOffset;
        fTokenLength = 0;
        fPrefixLength = offset - partitionOffset;
        
        fLast = NONE;
        
        fDocument = document ;
        fpcalMode = pcalMode ;
        if (   (pcalMode != TLAFastPartitioner.IN_PCAL)
            && (contentType != null)
            && contentType.equals(TLA_PCAL)) {
            // ERROR
            System.out.println(
               "TLAPartitionScanner.setPartialRange called with contentType/pcalMode mismatch.") ;
        }
        outputEndPcalComment = false ;
        
        if (offset == partitionOffset)
        {
            // restart at beginning of partition
            fState = TLA;
        } else
        {
            fState = getState(contentType);
        }
        
        if (fState == MULTI_LINE_COMMENT) 
        {
            fCommentDepth = getCommentDepth(document, partitionOffset, fPrefixLength);
        } else {
            fCommentDepth = 0;    
        }

        // emulate TLAPartitionScanner
        if (fEmulate)
        {
            fTLAOffset = -1;
            fTLALength = 0;
        }
    }

    /**
     * If the scanner starts inside of the multi-line partition, the depth of comment nesting need to be determined. This is performed by this method.
     * @param document the document
     * @param offset start of the partition
     * @param length number of characters between the start of partition and the offset from which the scanner will continue
     * @return comment depth
     */
    private int getCommentDepth(IDocument document, int offset, int length)
    {
        try
        {
            String partitionText = document.get(offset, length);
            // regex for (* and *) needs escaping
            return partitionText.split("\\(\\*").length - partitionText.split("\\*\\)").length;
            
        } catch (BadLocationException e)
        {
            e.printStackTrace();
            return 1;
        }
    }

    /*
     * @see ITokenScanner#getTokenLength()
     */
    public int getTokenLength()
    {
        return fTokenLength;
    }

    /*
     * @see ITokenScanner#getTokenOffset()
     */
    public int getTokenOffset()
    {
        return fTokenOffset;
    }

    /**
     * Map content types to internal states.  
     * This is called only to interpret a contentType sent by TLAFastPartitioner
     * in a call of setPartialRange.  Thus, it only contains states of "real"
     * partition types, not START_PCAL_COMMENT or END_PCAL_COMMENT.  
     * @param contentType
     * @return
     */
    private static int getState(String contentType)
    {
        if (contentType == null)
            return TLA;
        else if (contentType.equals(TLA_MULTI_LINE_COMMENT))
            return MULTI_LINE_COMMENT;
        else if (contentType.equals(TLA_SINGLE_LINE_COMMENT))
            return SINGLE_LINE_COMMENT;
        else if (contentType.equals(TLA_PCAL))
            // Methods of this class don't distinguish between TLA
            // and PCAL tokens.  When setPartialRange is called
            // with this contentType, its pcalMode argument should
            // equal true.
            return TLA;                             
        else if (contentType.equals(TLA_STRING))
            return STRING;
        else
            return TLA;
    }

    /**
     * Consume a character from the scanner
     */
    private final void consume()
    {
        fTokenLength++;
        fLast = NONE;
    }

    /**
     * 
     * @param state
     * @return
     */
    private final IToken postFix(int state)
    {
        fTokenLength++;
        fLast = NONE;
        fState = TLA;
        fPrefixLength = 0;
        return fTokens[state];
    }

    /**
     * 
     * @param state
     * @param newState
     * @param last
     * @param prefixLength
     * @return
     */
    private final IToken preFix(int state, int newState, int last, int prefixLength)
    {
        if (fEmulate && state == TLA && (fTokenLength - getLastLength() > 0))
        {
            fTokenLength -= getLastLength();
            fLast = last;
            fTLAOffset= fTokenOffset;
            fTLALength= fTokenLength;
            fPrefixLength = prefixLength;
            fTokenLength = 1;
            fState = newState;
            return fTokens[state];

        } else
        {
            fTokenLength -= getLastLength();
            fLast = last;
            fPrefixLength = prefixLength;
            IToken token = fTokens[state];
            fState = newState;
            return token;
        }
    }

    /**
     * Return the length of the last significant characters read 
     * @return
     */
    private int getLastLength()
    {
        switch (fLast) {
        default:
            return -1;
        case NONE:
            return 0;
        case CARRIAGE_RETURN:
        case BACKSLASH:
        case STAR:
        case C_BRACKET:
        case O_BRACKET:
        case MINUS:
            return 1;
        case C_BRACKET_STAR:
        case O_BRACKET_STAR:
        case MINUS_MINUS:      // Added for PlusCal
            return 2;
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/view/ObligationSourceViewerConfiguration.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.view;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;

/**
 * The configuration for source viewers displaying pretty-printed forms of obligations.
 * Uses the syntax highlighting of the tla editor.
 * 
 * @author <NAME>
 *
 */
public class ObligationSourceViewerConfiguration extends SourceViewerConfiguration
{

    /**
     * This registers one damager repairer for all content in the source viewer.
     * The damager-repairer scans the content for TLA keywords and sets them to the
     * same color used in the tla editor.
     */
    public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer)
    {
        PresentationReconciler reconciler = new PresentationReconciler();

        DefaultDamagerRepairer dr = new DefaultDamagerRepairer(TLAEditorActivator.getDefault().getTLACodeScanner());
        reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
        reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);

        return reconciler;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/ParseError.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.st;


public interface ParseError  {

  public String reportedError();
  public String defaultError() ;
}



<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ShowUsesParseResultListener.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.parser.IParseResultListener;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.ui.preference.EditorPreferencePage;
import org.lamport.tla.toolbox.util.ResourceHelper;

/**
 * This class implements a listener that, when the module is reparsed, checks the LEAR_DECLARATION_USE_MARKERS_ON_PARSE
 * Editor preference and, if selected, should delete any Use markers.  The spec objects' getModuleToShow() value indicates
 * the module on which those markers should be, and they are retrieved from that name. 
 * 
 * @author lamport
 *
 */
public class ShowUsesParseResultListener extends SpecLifecycleParticipant implements IParseResultListener
{
    /** 
     * This method is called when the spec is parsed, as well as on other occasions
     * that don't interest us.  It deletes the Show Use markers if the user's preference
     * is to do so and if we can find any to delete.
     */
    public boolean eventOccured(SpecEvent event)
    {

        if (event.getType() != SpecEvent.TYPE_PARSE)
        {
            return true;
        }

        // Check if user preference is to remove use markers on parse.
        if (!Activator.getDefault().getPreferenceStore().getBoolean(
                EditorPreferencePage.CLEAR_DECLARATION_USE_MARKERS_ON_PARSE)) {
            return true;
        }
        
        // User wants to remove markers.  Remove them if there are any.
        Spec spec = event.getSpec();
        String moduleName = spec.getModuleToShow();
        if (moduleName == null)
        {
            return true;
        }
        IResource resource = ResourceHelper.getResourceByModuleName(moduleName);
        if (resource == null)
        {
            return true;
        }
        try
        {
            resource.deleteMarkers(ShowUsesHandler.SHOW_USE_MARKER_TYPE, false, 99);
        } catch (CoreException e)
        {
            // I don't know why this should ever fail, but there's nothing to be done 
            // if marker deletion fails except to hope that it's because there 
            // weren't any.
        }
        
        return true;

    }
    /**
     * I have no idea when this method is supposed to be called, but I have not
     * seen it ever called.
     */
    public void newParseResult(ParseResult parseResult)
    {
    	TLAEditorActivator.getDefault().logDebug("newParseResult called with status: " + parseResult.getStatus());
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/TLCWorkerSmartProxyTest.java<|end_filename|>
package tlc2.tool.distributed;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.rmi.RemoteException;

import org.junit.Test;

import tlc2.tool.TLCState;
import tlc2.tool.WorkerException;
import tlc2.tool.distributed.selector.DummyTLCWorker;
import tlc2.tool.queue.DummyTLCState;

public class TLCWorkerSmartProxyTest {

	private static final int ZERO = 0;
	private static final int ONE = 1;
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE * (1/10);
	
	@Test
	public void testGetNetworkOverheadMaxStateOne() throws RemoteException, WorkerException {
		long calculationDuration = Long.MAX_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ONE]) > 0);
	}
	
	@Test
	public void testGetNetworkOverheadMinStateOne() throws RemoteException, WorkerException {
		long calculationDuration = Long.MIN_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ONE]) > 0);
	}
	
	@Test
	public void testGetNetworkOverheadZeroStateOne() throws RemoteException, WorkerException {
		long calculationDuration = ZERO;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ONE]) > 0);
	}

	@Test
	public void testGetNetworkOverheadMaxStateZero() throws RemoteException, WorkerException {
		long calculationDuration = Long.MAX_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ZERO]) > 0);
	}

	@Test
	public void testGetNetworkOverheadMinStateZero() throws RemoteException, WorkerException {
		long calculationDuration = Long.MIN_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ZERO]) > 0);
	}

	@Test
	public void testGetNetworkOverheadZeroStateZero() throws RemoteException, WorkerException {
		long calculationDuration = ZERO;
		assertTrue(doTest(calculationDuration, new DummyTLCState[ZERO]) > 0);
	}

	@Test
	public void testGetNetworkOverheadMinStateMax() throws RemoteException, WorkerException {
		long calculationDuration = Long.MIN_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[MAX_ARRAY_SIZE]) > 0);
	}

	@Test
	public void testGetNetworkOverheadMaxStateMa() throws RemoteException, WorkerException {
		long calculationDuration = Long.MAX_VALUE;
		assertTrue(doTest(calculationDuration, new DummyTLCState[MAX_ARRAY_SIZE]) > 0);
	}

	@Test
	public void testGetNetworkOverheadZeroStateMax() throws RemoteException, WorkerException {
		long calculationDuration = ZERO;
		assertTrue(doTest(calculationDuration, new DummyTLCState[MAX_ARRAY_SIZE]) > 0);
	}
	
	private double doTest(final long calculationDuration, final TLCState[] states) throws RemoteException, WorkerException {
		DummyTLCWorker aWorker = new DummyTLCWorker(calculationDuration);
		TLCWorkerSmartProxy proxy = new TLCWorkerSmartProxy(aWorker);

		// let proxy calculate current network overhead
		NextStateResult nsr = proxy.getNextStates(states);
		assertNotNull(nsr);

		double networkOverhead = proxy.getNetworkOverhead();
		return networkOverhead;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/compare/MarkerComparator.java<|end_filename|>
package org.lamport.tla.toolbox.util.compare;

import java.util.Comparator;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.lamport.tla.toolbox.util.TLAMarkerHelper;

/**
 * Compares IMarkers
 * 
 * @author <NAME>
 * @version $Id$
 */
public class MarkerComparator implements Comparator<IMarker> {

	/* (non-Javadoc)
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 */
	public int compare(IMarker m1, IMarker m2) {
		int m1severity = m1.getAttribute(IMarker.SEVERITY,
				IMarker.SEVERITY_INFO);
		int m2severity = m2.getAttribute(IMarker.SEVERITY,
				IMarker.SEVERITY_INFO);

		if (m1severity == m2severity) {
			// same severity, look on the resource
			IResource r1 = m1.getResource();
			IResource r2 = m2.getResource();

			if (r2.equals(r1)) {
				// same resource, look on the line numbers
				int line1 = m1.getAttribute(TLAMarkerHelper.LOCATION_BEGINLINE,
						-1);
				int line2 = m2.getAttribute(TLAMarkerHelper.LOCATION_BEGINLINE,
						-1);

				return new Integer(line2).compareTo(new Integer(line1));

			} else {
				return r2.getName().compareTo(r1.getName());
			}

		} else {
			return new Integer(m2severity).compareTo(new Integer(m1severity));
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/ModelCoverage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.model;

/**
 * TLC's coverage implementation (see tlc2.tool.coverage.CostModelCreator) only
 * supports two modes: Off and On. However, we consider On too much information
 * for novice users who are (likely) only interested in identifying spec errors
 * that leave a subset of actions permanently disabled. The Toolbox therefore
 * adds a third mode "Action" which filters TLC's output for All. This obviously
 * means that the overhead of collecting coverage in Action and On mode is
 * identical. This shouldn't matter however as novice users don't create large
 * specs anyway and the Toolbox warns users when a large spec has been
 * configured with coverage. (see
 * org.lamport.tla.toolbox.tool.tlc.output.data.CoverageUINotification)
 * Alternatively, tlc2.tool.coverage.ActionWrapper.report() could be changed to
 * omit the report of its children (line 126) to effectively create the Action
 * mode at the TLC layer. I decided against it though, because I didn't want to
 * extend the -coverage TLC parameter.
 */
public enum ModelCoverage {
	/**
	 * This was an inner-enum to the {@link Model} class, but the Eclipse IDE's
	 * syntax colorer was breaking on code that refers to inner-enums (and
	 * inner-inner-enums that were refactored out of Model's state change listener
	 * related code.)
	 */
	
	OFF,
	ACTION,
	ON;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/management/TLCServerMXWrapper.java<|end_filename|>
// Copyright (c) Jan 4, 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.distributed.management;

import java.io.IOException;
import java.rmi.RemoteException;

import javax.management.NotCompliantMBeanException;

import tlc2.TLCGlobals;
import tlc2.tool.TLCState;
import tlc2.tool.distributed.TLCServer;
import tlc2.tool.distributed.fp.IFPSetManager;
import tlc2.tool.management.TLCStandardMBean;

/**
 * @author <NAME>
 */
public class TLCServerMXWrapper extends TLCStandardMBean implements TLCStatisticsMXBean {

	private final TLCServer tlcServer;
	
	public TLCServerMXWrapper(final TLCServer aTLCServer)
			throws NotCompliantMBeanException {
		super(TLCStatisticsMXBean.class);
		tlcServer = aTLCServer;
		
		// register all TLCStatisticsMXBeans under the same name
		registerMBean("tlc2.tool:type=ModelChecker");
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStatesGenerated()
	 */
	public long getStatesGenerated() {
		if (tlcServer.isRunning()) {
			return tlcServer.getStatesGenerated();
		}
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getDistinctStatesGenerated()
	 */
	public long getDistinctStatesGenerated() {
		if (tlcServer.isRunning()) {
			final IFPSetManager fpSetManager = tlcServer.getFPSetManager();
			if (fpSetManager != null) {
				return fpSetManager.size();
			}
		}
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStateQueueSize()
	 */
	public long getStateQueueSize() {
		return tlcServer.getNewStates();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStatesGeneratedPerMinute()
	 */
	public long getStatesGeneratedPerMinute() {
		return tlcServer.getStatesGeneratedPerMinute();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getDistinctStatesGeneratedPerMinute()
	 */
	public long getDistinctStatesGeneratedPerMinute() {
		return tlcServer.getDistinctStatesGeneratedPerMinute();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getProgress()
	 */
	public int getProgress() {
		if (tlcServer.isRunning()) {
			try {
					return tlcServer.trace.getLevelForReporting();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return -1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getWorkerCount()
	 */
	public int getWorkerCount() {
		return tlcServer.getWorkerCount();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#checkpoint()
	 */
	public void checkpoint() {
		TLCGlobals.forceChkpt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getAverageBlockCnt()
	 */
	public long getAverageBlockCnt() {
		return tlcServer.getAverageBlockCnt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getRuntimeRatio()
	 */
	public double getRuntimeRatio() {
		// Distributed TLC does not support liveness checking
		return 0d;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#liveCheck()
	 */
	public void liveCheck() {
		// Distributed TLC does not support liveness checking
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getCurrentState()
	 */
	public String getCurrentState() {
		final TLCState state = tlcServer.stateQueue.sPeek();
		if (state != null) {
			return state.toString();
		}
		return "N/A";
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getSpecName()
	 */
	public String getSpecName() {
		if (tlcServer.isRunning()) {
			try {
				return tlcServer.getSpecFileName();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		return "N/A";
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getModelName()
	 */
	public String getModelName() {
		if (tlcServer.isRunning()) {
			try {
				return tlcServer.getConfigFileName();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		return "N/A";
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#stop()
	 */
	public void stop() {
		synchronized (tlcServer) {
			tlcServer.setDone();
			tlcServer.stateQueue.finishAll();
			tlcServer.notifyAll();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#suspend()
	 */
	@Override
	public void suspend() {
		synchronized (tlcServer) {
			tlcServer.stateQueue.suspendAll();
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#resume()
	 */
	@Override
	public void resume() {
		synchronized (tlcServer) {
			tlcServer.stateQueue.resumeAll();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/UnrecoverablePositionedException.java<|end_filename|>
package pcal.exception;

import pcal.AST;

/**
 * @author <NAME>
 * @version $Id$
 */
public class UnrecoverablePositionedException extends UnrecoverableException
{
    private AST position;
    
    public UnrecoverablePositionedException(String message)
    {
        super(message);
    }

    /**
     * @param message
     * @param position
     */
    public UnrecoverablePositionedException(String message, AST position)
    {
        super(message);
        this.position = position;
    }
    
    /**
     * @return the elementAt
     */
    public AST getPosition()
    {
        return position;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/manager/WorkspaceSpecManager.java<|end_filename|>
package org.lamport.tla.toolbox.spec.manager;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Iterator;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.nature.TLANature;
import org.lamport.tla.toolbox.tool.SpecEvent;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.tool.SpecRenameEvent;
import org.lamport.tla.toolbox.ui.property.GenericSelectionProvider;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.SpecLifecycleManager;
import org.lamport.tla.toolbox.util.compare.SpecComparator;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

/**
 * Specification manager based on the Workspace
 * @version $Id$
 * @author <NAME>
 */
public class WorkspaceSpecManager extends GenericSelectionProvider implements ISpecManager, IResourceChangeListener,
        IAdaptable, IAdapterFactory
{
    private Hashtable<String, Spec> specStorage = new Hashtable<String, Spec>(47);
    private Spec loadedSpec = null;
    private SpecLifecycleManager lifecycleManager = null;

    /**
     * Constructor
     */
    public WorkspaceSpecManager(final IProgressMonitor monitor)
    {
        // initialize the spec life cycle manager
        lifecycleManager = new SpecLifecycleManager();

        final IWorkspace ws = ResourcesPlugin.getWorkspace();

        final String specLoadedName = PreferenceStoreHelper.getInstancePreferenceStore().getString(
                IPreferenceConstants.I_SPEC_LOADED);

        final IProject[] projects = ws.getRoot().getProjects();
        try
        {

            for (int i = 0; i < projects.length; i++)
            {
                // changed from projects[i].isAccessible()
                final IProject project = projects[i];
				if (project.isOpen())
                {
                    if (project.hasNature(TLANature.ID))
                    {
						// Refresh the project in case the actual on-disk
						// representation and the cached Eclipse representation
						// have diverged. This can happen when e.g. another
						// Toolbox opens the project or the files get manually
						// edited. Without calling refresh, code down below 
                    	// might throw exceptions due to out-of-sync problems.  
                    	project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
                        
                    	final Spec spec = new Spec(project);
                        // Added by LL on 12 Apr 2011
                        // If spec.rootFile = null, then this is a bad spec. So
                        // we should report it and not perform addSpec(spec).  It
                        // would be nice if we could report it to the user, but
                        // it seems to be impossible to popup a window at this point
                        // in the code.
                        if (spec.getRootFile() == null)
                        {
                            Activator.getDefault().logError("The bad spec is: `" + project.getName() + "'", null);
                        } else
                        {
                            // This to threw a null pointer exception for Tom, probably causing the abortion
                            // of the Toolbox start. But it started on the next attempt.  Should we catch the
                            // and perhaps report the bad spec?
                            addSpec(spec);
                        }
                        
                        // load the spec if found
                        if (spec.getName().equals(specLoadedName))
                        {
                            this.setSpecLoaded(spec);
                        }
                    }
                } else
                {
                    // DELETE closed projects
                    project.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, monitor);
                }
            }

            if (specLoadedName != null && !specLoadedName.equals("") && this.loadedSpec == null)
            {
                // there was a spec loaded but it was not found
                // explicit un-set it
                setSpecLoaded(null);
            }

        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error initializing specification workspace", e);
        }

        ws.addResourceChangeListener(this);
        
        Platform.getAdapterManager().registerAdapters(this, IProject.class);
    }

    /**
     * Destructor
     */
    public void terminate()
    {
        IWorkspace ws = ResourcesPlugin.getWorkspace();
        ws.removeResourceChangeListener(this);
        if (this.loadedSpec != null
                && PreferenceStoreHelper.getInstancePreferenceStore().getBoolean(
                        IPreferenceConstants.I_RESTORE_LAST_SPEC))
        {
            PreferenceStoreHelper.getInstancePreferenceStore().setValue(IPreferenceConstants.I_SPEC_LOADED,
                    this.loadedSpec.getName());
        } else
        {
            PreferenceStoreHelper.getInstancePreferenceStore().setValue(IPreferenceConstants.I_SPEC_LOADED, "");
        }

    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#addSpec(toolbox.spec.Spec)
     */
    public void addSpec(Spec spec)
    {
        specStorage.put(spec.getName(), spec);
        lifecycleManager.sendEvent(new SpecEvent(spec, SpecEvent.TYPE_CREATE));
    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#getLoadedSpec()
     */
    public Spec getSpecLoaded()
    {
        return this.loadedSpec;
    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#getRecentlyOpened()
     */
    public Spec[] getRecentlyOpened()
    {
        Collection<Spec> specs = specStorage.values();
        return specs.toArray(new Spec[specs.size()]);
    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#getSpecByName(java.lang.String)
     */
    public Spec getSpecByName(String specName)
    {
        return (Spec) specStorage.get(specName);
    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#getSpecByRootModule(java.lang.String)
     */
    public Spec getSpecByRootModule(String rootModulePath)
    {
        if (rootModulePath != null)
        {
            Iterator<Spec> specI = specStorage.values().iterator();
            while (specI.hasNext())
            {
                Spec spec = specI.next();
                // try/catch added by LL on 12 April 2011 because
                // corrupted database can cause the call of getRootFileName() to
                // throw a null pointer exception.
                try
                {
                    if (spec.getRootFilename().equals(rootModulePath))
                    {
                        return spec;
                    }
                } catch (Exception e)
                {
                	e.printStackTrace();
                    // Just ignore the exception and pray.
                }
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * @see org.lamport.tla.toolbox.spec.manager.ISpecManager#setSpecLoaded(toolbox.spec.Spec)
     */
    public void setSpecLoaded(Spec spec)
    {
        if (spec == null)
        {
            // close a spec
            // modified by LL on 30 May 2010 to add the follow test that
            // there is a loaded spec to close.
            if (this.loadedSpec != null)
            {
                this.lifecycleManager.sendEvent(new SpecEvent(this.loadedSpec, SpecEvent.TYPE_CLOSE));
            }
        } else
        {
            // open a spec
            this.lifecycleManager.sendEvent(new SpecEvent(spec, SpecEvent.TYPE_OPEN));
        }

        this.loadedSpec = spec;
        if (this.loadedSpec != null)
        {
            // touch the spec, but why? This is essentially going to cause a spec rebuild
            this.loadedSpec.setLastModified();
        }
    }

    /*
     * (non-Javadoc)
     * @see
     * org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent
     * )
     */
    public void resourceChanged(IResourceChangeEvent event)
    {
        /*
         * remove elements from the storage if the projects are deleted
         */
        IResource resource = event.getResource();
        if (resource != null && IResource.PROJECT == resource.getType()
                && IResourceChangeEvent.PRE_DELETE == event.getType())
        {
            specStorage.remove(resource.getName());
        }

    }

    /**
     * Renames the given spec to the given name 
     * @param spec
     * @param newName
     */
    public void renameSpec(final Spec oldSpec, final String newName, final IProgressMonitor aMonitor)
    {
        // remove from storage
        specStorage.remove(oldSpec.getName());

        // rename the underlying resource
        final IProject project = ResourceHelper.projectRename(oldSpec.getProject(), newName, aMonitor);
        
        // create new project with updated name
        final Spec newSpec = new Spec(project);
        newSpec.setLastModified();

        // add it to storage
        addSpec(newSpec);
        
        this.lifecycleManager.sendEvent(new SpecRenameEvent(oldSpec, newSpec));
        
        try {
			// Renaming a spec constitutes various updates/changes in dependent
			// bundles such as the TLC Model. A Model indirectly references the
        	// old IProject through its ILaunchConfiguration. Thus, defer the
        	// deletion of the old IProject _after_ dependent bundles had a 
        	// chance to react to the renaming event.
			oldSpec.getProject().delete(IResource.NONE, aMonitor);
		} catch (CoreException shouldNotHappen) {
			shouldNotHappen.printStackTrace();
		}
    }
    
    /**
	 * Removes the specification always deleting project content (files).
	 * 
	 * @see #removeSpec(Spec, IProgressMonitor, boolean)
	 * @param spec
	 *            specification to remove
	 * @param aMonitor
	 *            a monitor to track progress
	 */
    public void removeSpec(final Spec spec, final IProgressMonitor aMonitor)
    {
    	removeSpec(spec, aMonitor, true);
    }

    /**
     * Removes the specification.  
     * Modified 3 August 2011 by LL to add the boolean argument to say if this
     * is a Forget command, which doesn't delete the spec's .toolbox directory,
     * or a Delete command, which does.
     * 
     * @param spec specification to remove
     * @param aMonitor a monitor to track progress
     * @param isForget do not delete .toolbox directory
     */
    public void removeSpec(final Spec spec, final IProgressMonitor aMonitor, boolean isForget)
    {
        this.lifecycleManager.sendEvent(new SpecEvent(spec, SpecEvent.TYPE_DELETE));
        ResourceHelper.deleteProject(spec.getProject(), aMonitor, isForget);
        specStorage.remove(spec.getName());
        if (loadedSpec == spec) {
			// If the spec being deleted is the current open one, unset the
			// loadedSpec. Otherwise getMostRecentlyOpenedSpec will return the
			// deleted one later if no other spec is opened in between.
        	loadedSpec = null;
        }
    }

    /**
     * Is triggered when a spec has been parsed
     * not intended to be called by clients
     */
    public void specParsed(Spec spec)
    {
        // inform the participants
        this.lifecycleManager.sendEvent(new SpecEvent(spec, SpecEvent.TYPE_PARSE));
    }

    /**
     * Constructs a specification name from the proposition string
     * @param proposition a string with spec name 
     * @param firstRun a flag for the first run
     * @return the name of a spec that is not already used.
     */
    public String constructSpecName(String proposition, boolean firstRun)
    {
        Spec existingSpec = getSpecByName(proposition);
        if (existingSpec != null)
        {
            if (firstRun)
            {
                return constructSpecName(proposition.concat("_1"), false);
            } else
            {
                String oldNumber = proposition.substring(proposition.lastIndexOf("_"));
                int number = Integer.parseInt(oldNumber) + 1;
                proposition = proposition.substring(0, proposition.lastIndexOf("_"));
                return constructSpecName(proposition + number, false);
            }
        }

        return proposition;
    }

    /**
     * Retrieves loaded spec encapsulated in to a selection object  
     */
    public ISelection getSelection()
    {
        if (this.loadedSpec != null)
        {
            return new StructuredSelection(this.loadedSpec);
        } else
        {
            return null;
        }
    }

    /**
     * Sets the spec loaded 
     */
    public void setSelection(ISelection selection)
    {
        if (selection == null)
        {
            setSpecLoaded(null);
            return;
        }
        if (selection instanceof IStructuredSelection)
        {
            IStructuredSelection sSelection = (IStructuredSelection) selection;
            if (sSelection.toArray() instanceof Spec[])
            {
                Spec[] specs = (Spec[]) sSelection.toArray();
                if (specs.length == 0)
                {
                    setSpecLoaded(null);
                } else if (specs.length == 1)
                {
                    setSpecLoaded(specs[0]);
                } else
                {
                    throw new IllegalArgumentException("Only one specification can be selected");
                }
            } else
            {
                throw new IllegalArgumentException(
                        "Workspace specification manager only accepts specification objects to be selected");
            }
        } else
        {
            throw new IllegalArgumentException(
                    "Workspace specification manager only accepts specification object in a StructuredSelection");
        }
    }

    /**
     * Only support the interface, no real adaptivity
     */
    public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter)
    {
        return null;
    }

	public Collection<Spec> getSpecs() {
		return Collections.unmodifiableCollection(specStorage.values());
	}

    /**
     * @return The {@link Spec} most recently opened or null if no specs are known
     */
    public Spec getMostRecentlyOpenedSpec()
    {
        if (loadedSpec != null)
        {
            return loadedSpec;
        }

        final Comparator<Spec> comparator = new SpecComparator();
        
        // no spec currently open
        // search for the last spec to be closed
        Spec[] specs = getRecentlyOpened();
        Spec mostRecentlyOpened = null;
        for (int i = 0; i < specs.length; i++)
        {
        	int compare = comparator.compare(mostRecentlyOpened, specs[i]);
        	if(compare > 0) {
        		mostRecentlyOpened = specs[i];
        	}
        }

        return mostRecentlyOpened;
    }

	/**
	 * @return Whether the given spec is the currently loaded spec
	 */
	public boolean isSpecLoaded(final Spec aSpec) {
		return getSpecLoaded() == aSpec;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class)
	 */
	public Object getAdapter(final Object adaptableObject,
			@SuppressWarnings("rawtypes") final Class adapterType) {
		if (adaptableObject instanceof IProject) {
			final IProject project = (IProject) adaptableObject;
			final String key = project.getName();
			return specStorage.get(key);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
	 */
	@SuppressWarnings("rawtypes")
	public Class[] getAdapterList() {
		return new Class[] { Spec.class };
	}

	public void addSpecLifecycleParticipant(SpecLifecycleParticipant specLifecycleParticipant) {
		this.lifecycleManager.addSpecLifecycleParticipant(specLifecycleParticipant);
	}

	public void removeSpecLifecycleParticipant(SpecLifecycleParticipant specLifecycleParticipant) {
		this.lifecycleManager.removeSpecLifecycleParticipant(specLifecycleParticipant);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/dfid/FPIntSet.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:12:32 PST by lamport
//      modified on Tue May 15 11:44:57 PDT 2001 by yuanyu

package tlc2.tool.fp.dfid;

import java.io.IOException;
import java.rmi.RemoteException;

/**
 * <b>Note:</b> All concrete subclasses of this class are required to
 * guarantee that their methods are thread-safe.
 * @version $Id$
 */
public abstract class FPIntSet
// SZ Jul 13, 2009: there is no reason to extend the RMI interfaces, since they are not used
// extends UnicastRemoteObject implements FPIntSetRMI 
{

  public static int Port = 10998;   // port # for fpset server

  protected FPIntSet() throws RemoteException { /*SKIP*/ }
  
  /**
   * Performs any initialization necessary to handle "numThreads"
   * worker threads and one main thread. Subclasses will need to
   * override this method as necessary. This method must be called
   * after the constructor but before any of the other methods below.
   */
  public abstract void init(int numThreads, String metadir, String filename)
  throws IOException;
    
  /* Returns the number of fingerprints in this set. */
  public abstract long size();
    
  /**
   * We use two bits to record the status of a fp: one DONE bit and
   * one Leveled bit.  The remaining 30 bits are used for level.
   */
  public static final int SBits = 2;
  public static final int LBits = 30;

  public static final int SBitsMask = 0x3;
  public static final int DoneMask = 0x1;
  public static final int LeveledMask = 0x2;

  public static final int NEW = 0;
  public static final int DONE = 1;
  
  
  /* 
   * SZ Mar 9, 2009: These variables seem to be used in the following way.
   * 
   * An instance of FPIntSet is hold by every worker. In addition, a "global" FPIntSet is used in the ModelChecker.
   * The static fields are used to compare the "global" value with the instance values of the worker instances.
   * This is a very fishy, and should be changed to the following: static modifiers should be removed and replaced by explicit
   * comparison with the instance variable controlled by the model checker 
   */
  protected static int Level = 1;
  protected static int Leveled = 0;

  public static void incLevel() {
    Level++;
    Leveled = 2 - Leveled;
  }

  public static boolean isCompleted(int status) {
    return (((status & LeveledMask) == Leveled) ||
	    ((status & DoneMask) == DONE));
  }

  public static boolean isDone(int status) {
    return (status & DoneMask) == DONE;
  }
  
  public static int getLevel(int status) {
    return status >>> SBits;
  }

  public static boolean isLeaf(int status) {
    return status == NEW || (status >>> SBits) == Level;
  }
  
  /**
   * Set fp to be leveled, which means that there is no need to
   * explore fp again at this level.
   */
  public abstract void setLeveled(long fp);
  
  /**
   * Set the status of fp to status. It does nothing if the status of
   * fp in this is already higher than status.  This method will not
   * change the Leveled bit.
   *
   * The return value is an integer:
   *   - if fp was not in the set, returns NEW.
   *   - if fp was in the set, returns the old 3-bit status.
   *
   * NOTE: The methods setStatus and getStatus can be used together.
   * They can not be used with the methods put and contains.
   */
  public abstract int setStatus(long fp, int status);

  /**
   * Returns the current 3-bit status of fp.  If fp is not in the set,
   * returns NEW.
   */
  public abstract int getStatus(long fp);  
  
  public abstract boolean allLeveled();

  public void close() { /*SKIP*/ }

  public void addThread() throws IOException { /*SKIP*/ }
  
  public abstract void exit(boolean cleanup) throws IOException;

  public abstract long checkFPs() throws IOException;

  public abstract void beginChkpt() throws IOException;
  public abstract void commitChkpt() throws IOException;
  public abstract void recover() throws IOException;

  /* The set of checkpoint methods for remote checkpointing. */  
  public abstract void beginChkpt(String filename) throws IOException;
  public abstract void commitChkpt(String filename) throws IOException;
  public abstract void recover(String filename) throws IOException;
  
// SZ Jul 10, 2009: main method that could have been used during the RMI tests
// removed since it is dead code now
//  public static void main(String args[]) {
//    ToolIO.out.println("TLC FP Server " + TLCGlobals.versionOfTLC);
//
//    String metadir = null;
//    String fromChkpt = null;
//    int index = 0;
//    while (index < args.length) {
//      if (args[index].charAt(0) == '-') {
//	printErrorMsg("Error: unrecognized option: " + args[index]);
//	System.exit(0);
//      }
//      if (metadir != null) {
//	printErrorMsg("Error: more than one directory for metadata: " + metadir +
//		      " and " + args[index]);
//	System.exit(0);
//      }
//      metadir = args[index++] + FileUtil.separator;
//    }
//
//    String hostname = "Unknown";
//    try {
//      hostname = InetAddress.getLocalHost().getHostName();
//      metadir = (metadir == null) ? hostname : (metadir + hostname);
//      File filedir = new File(metadir);
//      if (!filedir.exists()) {
//	boolean created = filedir.mkdirs();
//	if (!created) {
//	  System.err.println("Error: fingerprint server could not make a directory" +
//			     " for the disk files it needs to write.\n");
//	  System.exit(0);
//	}
//      }
//      // Start memory-based fingerprint set server.
//      // Note: It would be wrong to use the disk-based implementation.
//      FPIntSet fpSet = new MemFPIntSet();
//      fpSet.init(1, metadir, "fpset");
//      if (fromChkpt != null) {
//	fpSet.recover();    // recover when instructed
//      }
//      Registry rg = LocateRegistry.createRegistry(Port);
//      rg.rebind("FPSetServer", fpSet);
//      System.out.println("Fingerprint set server at " + hostname + " is ready.");
//
//      synchronized(fpSet) {
//	while (true) {
//	    System.out.println("Progress: The number of fingerprints stored at " +
//			     hostname + " is " + fpSet.size() + ".");
//	  fpSet.wait(300000);	  
//	}
//      }
//    }
//    catch (Exception e) {
//        System.err.println(hostname + ": Error: " + e.getMessage());
//    }
//  }

//  private static void printErrorMsg(String msg) {
//      System.err.println(msg);
//      System.err.println("Usage: java tlc2.tool.FPSet [-option] metadir");
//  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/TLAtoPCalMarker.java<|end_filename|>
// Copyright (c) Jan 30, 2012 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.util;

import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.IAction;

import pcal.TLAtoPCalMapping;
import tla2sany.st.Location;

/**
 * A {@link TLAtoPCalMarker} wraps the given {@link IMarker} and provides
 * functionality to map from the TLA+ location the {@link IMarker} points to, to
 * its logical equivalent PCal code.
 * <p>
 * Additionally it is used by the UI (e.g. an {@link IAction}) to indicate to
 * lower layers that they should not link to TLA+, but to PCal.
 * 
 * @author <NAME>
 */
public class TLAtoPCalMarker implements IMarker {

	private final IMarker delegate;
	private final TLAtoPCalMapping mapping;

	public TLAtoPCalMarker(final IMarker delegate, TLAtoPCalMapping mapping) {
		Assert.isLegal(delegate.getResource() instanceof IFile);
		this.delegate = delegate;
		Assert.isNotNull(mapping);
		this.mapping = mapping;
	}

	/**
	 * @return The {@link pcal.Region} corresponding to this
	 *         {@link TLAtoPCalMarker}. Returns <code>null</code>, if no
	 *         corresponding PCal code can be found.
	 */
	public pcal.Region getRegion() {
		pcal.Region region;
		try {
			Location location = (Location) delegate.getAttribute(TLAMarkerHelper.LOCATION);
			region = location.toRegion();
		} catch (CoreException e) {
			// may not happen! (return null in this case which client code has
			// to handle anyway)
			e.printStackTrace();
			return null;
		}
		final int offset = AdapterFactory.GetLineOfPCalAlgorithm((IFile) delegate.getResource());
		return mapping.mapTLAtoPCalRegion(region, offset);
	}
	
	/**
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
		return delegate.getAdapter(adapter);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#delete()
	 */
	public void delete() throws CoreException {
		delegate.delete();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#equals(java.lang.Object)
	 */
	public boolean equals(Object object) {
		return delegate.equals(object);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#exists()
	 */
	public boolean exists() {
		return delegate.exists();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttribute(java.lang.String)
	 */
	public Object getAttribute(String attributeName) throws CoreException {
		return delegate.getAttribute(attributeName);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttribute(java.lang.String, int)
	 */
	public int getAttribute(String attributeName, int defaultValue) {
		return delegate.getAttribute(attributeName, defaultValue);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttribute(java.lang.String, java.lang.String)
	 */
	public String getAttribute(String attributeName, String defaultValue) {
		return delegate.getAttribute(attributeName, defaultValue);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttribute(java.lang.String, boolean)
	 */
	public boolean getAttribute(String attributeName, boolean defaultValue) {
		return delegate.getAttribute(attributeName, defaultValue);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttributes()
	 */
	public Map<String, Object> getAttributes() throws CoreException {
		return delegate.getAttributes();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getAttributes(java.lang.String[])
	 */
	public Object[] getAttributes(String[] attributeNames) throws CoreException {
		return delegate.getAttributes(attributeNames);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getCreationTime()
	 */
	public long getCreationTime() throws CoreException {
		return delegate.getCreationTime();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getId()
	 */
	public long getId() {
		return delegate.getId();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getResource()
	 */
	public IResource getResource() {
		return delegate.getResource();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#getType()
	 */
	public String getType() throws CoreException {
		return delegate.getType();
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#isSubtypeOf(java.lang.String)
	 */
	public boolean isSubtypeOf(String superType) throws CoreException {
		return delegate.isSubtypeOf(superType);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#setAttribute(java.lang.String, int)
	 */
	public void setAttribute(String attributeName, int value)
			throws CoreException {
		delegate.setAttribute(attributeName, value);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#setAttribute(java.lang.String, java.lang.Object)
	 */
	public void setAttribute(String attributeName, Object value)
			throws CoreException {
		delegate.setAttribute(attributeName, value);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#setAttribute(java.lang.String, boolean)
	 */
	public void setAttribute(String attributeName, boolean value)
			throws CoreException {
		delegate.setAttribute(attributeName, value);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#setAttributes(java.lang.String[], java.lang.Object[])
	 */
	public void setAttributes(String[] attributeNames, Object[] values)
			throws CoreException {
		delegate.setAttributes(attributeNames, values);
	}

	/**
	 * @see org.eclipse.core.resources.IMarker#setAttributes(java.util.Map)
	 */
	public void setAttributes(@SuppressWarnings("rawtypes") Map attributes)
			throws CoreException {
		delegate.setAttributes(attributes);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jnlp/src/org/lamport/tla/toolbox/distributed/CombinedJNLPGeneratorServlet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package org.lamport.tla.toolbox.distributed;

/**
 * Serves the JNLP file for the fingerprint server & TLC worker combination.
 * 
 * Beginning with 1.7.0 we ceased supporting JNLP, due to our move to Java 11. Until a contributor arrives to take over
 * this functionality, including providing a nice way to bundle IcedTea or similar with the Toolbox, i am marking this
 * class as deprecated.
 * 
 * @deprecated
 */
@SuppressWarnings("serial")
public class CombinedJNLPGeneratorServlet extends JNLPGeneratorServlet {

	public static final String JNLP = "combined.jnlp";
	public static final String MAINCLASS = "tlc2.tool.distributed.fp.TLCWorkerAndFPSet";
	public static final String DESCRIPTION = "A combined fingerprint server (FPSet) and a TLCWorker";
	public static final String INDEX_DESC = "Start a combined fingerprint server (FPSet) and a TLCWorker";

	public CombinedJNLPGeneratorServlet() {
		super(MAINCLASS, DESCRIPTION, JNLP);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/pprint/Node.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:20:57 PST by lamport
//      modified on Fri Jun 11 17:51:46 PDT 1999 by yuanyu
//      modified on Thu Jun 10 14:52:19 EDT 1999 by tuttle

package tlc2.pprint;

public class Node {

  public static final int CONSTANT = 1;
  public static final int SET = 2;
  public static final int SEQUENCE = 3;
  public static final int RECORD = 4;
  public static final int RECORDPAIR = 5;
  public static final int FUNCTION = 6;
  public static final int FUNCTIONPAIR = 7;
  public static final int SUBSET = 8;  

  private int type;
  private int first;
  private int last;
  private Node children;
  private Node next;
  private String string;
  private String formatted;

/***************************************************************************/

  Node(String str, int s, int t) {
    string = str;
    type = t;
    first = s;
    last = 0;
    children = null;
    next = null;
    formatted =null;
  }

  Node(String str, int s, int e, int t) {
    string = str;
    type = t;
    first = s;
    last = e;
    children = null;
    next = null;
    formatted =null;
  }    

/***************************************************************************/

  public int type() {
    return type;
  }
  public int first() {
    return first;
  }
  public int last() {
    return last;
  }
  public Node children() {
    return children;
  }
  public Node next() {
    return next;
  }
  public String string() {
    return string;
  }
  public String formatted() {
    return formatted;
  }

/***************************************************************************/

  public void type(int t) {
    type = t;
    return;
  }
  public void first(int s) {
    first = s;
    return;
  }
  public void last(int e) {
    last = e;
    return;
  }
  public void children(Node c) {
    children = c;
    return;
  }
  public void next(Node n) {
    next = n;
    return;
  }
  public void string(String s) {
    string = s;
    return;
  }
  public void formatted(String s) {
    formatted = s;
    return;
  }

/***************************************************************************/

  public String value() {
    return string.substring(first,last+1);
  }
  public int length() {
    return last-first+1;
  }

  public void appendChild(Node n) {
    Node ch = this.children();
    
    if (ch == null) {
      this.children(n);
      return;
    }

    while (ch.next() != null) {
      ch = ch.next();
    }
    ch.next(n);
    return;
  }

  public String toString() {
    String s = "";

    for (Node ch = children(); ch != null; ch = ch.next()) {
      s = s + ch;
    }
    return s + first() + " " + last() + " " + value() + "\n";
  }
  
/***************************************************************************/

}


<|start_filename|>tlatools/org.lamport.tlatools/test/util/IsolatedTestCaseRunner.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package util;

import java.lang.reflect.InvocationTargetException;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.JUnit4;
import org.junit.runners.model.InitializationError;

public class IsolatedTestCaseRunner extends Runner {

	private final JUnit4 delegate;

	public IsolatedTestCaseRunner(final Class<?> testFileClass)
			throws InitializationError, ClassNotFoundException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
	
		// Since IsolatedTestCaseRunner runs several isolated tests in a single VM, it
		// is good practice to clean resources before each new test.
		System.gc();
		
		ClassLoader classLoader = IsolatedTestCaseRunner.class.getClassLoader();
		if (classLoader instanceof URLClassLoader) {
			// When run within e.g. Eclipse, the classloader might not be of instance
			// URLClassLoader. In this case, just use the provided class loader which won't
			// isolate tests. A set of tests can thus only be run in a single VM from ant
			// or maven which pass a URLClassLoader.
			classLoader = new IsolatedTestCaseClassLoader((URLClassLoader) classLoader);
		}
		delegate = new JUnit4(classLoader.loadClass(testFileClass.getName()));
	}

	@Override
	public Description getDescription() {
		return delegate.getDescription();
	}

	@Override
	public void run(RunNotifier notifier) {
		delegate.run(notifier);
	}
	
	private class IsolatedTestCaseClassLoader extends URLClassLoader {

		private final Map<String, Class<?>> cache = new HashMap<>();
		private final Set<String> packages = new HashSet<>();
		
		public IsolatedTestCaseClassLoader(URLClassLoader classLoader) {
			super(classLoader.getURLs());
			
			// All of TLC's java packages. 
			packages.add("tla2sany");
			packages.add("pcal");
			packages.add("util");
			packages.add("tla2tex");
			packages.add("tlc2");
		}

		@Override
		public Class<?> loadClass(String name) throws ClassNotFoundException {
			if (cache.containsKey(name)) {
				// Cache to not load classes twice for a single test case which results in a
				// LinkageError.
				return cache.get(name);
			}
			for (final String pkg : packages) {
				if (name.startsWith(pkg)) {
					final Class<?> findClass = findClass(name);
					cache.put(name, findClass);
					return findClass;
				}
			}
			return super.loadClass(name);
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/preference/TLCChainedPreferenceStore.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Microsoft Corp. - Adaption for TLC Toolbox
 *******************************************************************************/
package org.lamport.tla.toolbox.tool.prover.ui.preference;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;


/**
 * Preference store that composes multiple preference stores in a
 * chain and serves a preference value from the first preference store in the
 * chain that contains the preference.
 * <p>
 * This preference store is read-writable.</p>
 *
 * @since 3.0
 */
public class TLCChainedPreferenceStore implements IPreferenceStore {

	/** Child preference stores. */
	private IPreferenceStore[] fPreferenceStores;

	/** Listeners on this chained preference store. */
	private ListenerList<IPropertyChangeListener> fClientListeners= new ListenerList<IPropertyChangeListener>(ListenerList.IDENTITY);

	/** Listeners on the child preference stores. */
	private List<PropertyChangeListener> fChildListeners= new ArrayList<PropertyChangeListener>();

	/**
	 * Listener on the chained preference stores. Forwards only the events
	 * that are visible to clients.
	 */
	private class PropertyChangeListener implements IPropertyChangeListener {

		/** Preference store to listen too. */
		private IPreferenceStore fPreferenceStore;

		/**
		 * Initialize with the given preference store.
		 *
		 * @param preferenceStore the preference store
		 */
		public PropertyChangeListener(IPreferenceStore preferenceStore) {
			setPreferenceStore(preferenceStore);
		}

		/*
		 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
		 */
		public void propertyChange(PropertyChangeEvent event) {
			IPreferenceStore childPreferenceStore= getPreferenceStore();
			handlePropertyChangeEvent(childPreferenceStore, event);
		}

		/**
		 * Registers this listener on the preference store.
		 */
		public void register() {
			getPreferenceStore().addPropertyChangeListener(this);
		}

		/**
		 * Unregisters this listener from the preference store.
		 */
		public void unregister() {
			getPreferenceStore().removePropertyChangeListener(this);
		}

		/**
		 * Returns the preference store.
		 *
		 * @return the preference store
		 */
		public IPreferenceStore getPreferenceStore() {
			return fPreferenceStore;
		}

		/**
		 * Sets the preference store.
		 *
		 * @param preferenceStore the preference store to set
		 */
		public void setPreferenceStore(IPreferenceStore preferenceStore) {
			fPreferenceStore= preferenceStore;
		}

	}

	/**
	 * Sets the chained preference stores.
	 *
	 * @param preferenceStores the chained preference stores to set
	 */
	public TLCChainedPreferenceStore(IPreferenceStore[] preferenceStores) {
		Assert.isTrue(preferenceStores != null && preferenceStores.length > 0);
		fPreferenceStores= new IPreferenceStore[preferenceStores.length];
		System.arraycopy(preferenceStores, 0, fPreferenceStores, 0, preferenceStores.length);
		// Create listeners
		for (int i= 0, length= fPreferenceStores.length; i < length; i++) {
			PropertyChangeListener listener= new PropertyChangeListener(fPreferenceStores[i]);
			fChildListeners.add(listener);
		}
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
	 */
	public void addPropertyChangeListener(IPropertyChangeListener listener) {
		if (fClientListeners.size() == 0) {
			registerChildListeners();
		}
		fClientListeners.add(listener);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#removePropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
	 */
	public void removePropertyChangeListener(IPropertyChangeListener listener) {
		fClientListeners.remove(listener);
		if (fClientListeners.size() == 0) {
			unregisterChildListeners();
		}
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#contains(java.lang.String)
	 */
	public boolean contains(String name) {
		return getVisibleStore(name) != null;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#firePropertyChangeEvent(java.lang.String, java.lang.Object, java.lang.Object)
	 */
	public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
		firePropertyChangeEvent(new PropertyChangeEvent(this, name, oldValue, newValue));
	}

	/**
	 * Fire the given property change event.
	 *
	 * @param event the property change event
	 */
	private void firePropertyChangeEvent(PropertyChangeEvent event) {
		Object[] listeners= fClientListeners.getListeners();
		for (int i= 0; i < listeners.length; i++)
			 ((IPropertyChangeListener) listeners[i]).propertyChange(event);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getBoolean(java.lang.String)
	 */
	public boolean getBoolean(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getBoolean(name);
		return BOOLEAN_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultBoolean(java.lang.String)
	 */
	public boolean getDefaultBoolean(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultBoolean(name);
		return BOOLEAN_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultDouble(java.lang.String)
	 */
	public double getDefaultDouble(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultDouble(name);
		return DOUBLE_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultFloat(java.lang.String)
	 */
	public float getDefaultFloat(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultFloat(name);
		return FLOAT_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultInt(java.lang.String)
	 */
	public int getDefaultInt(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultInt(name);
		return INT_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultLong(java.lang.String)
	 */
	public long getDefaultLong(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultLong(name);
		return LONG_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDefaultString(java.lang.String)
	 */
	public String getDefaultString(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDefaultString(name);
		return STRING_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getDouble(java.lang.String)
	 */
	public double getDouble(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getDouble(name);
		return DOUBLE_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getFloat(java.lang.String)
	 */
	public float getFloat(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getFloat(name);
		return FLOAT_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getInt(java.lang.String)
	 */
	public int getInt(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getInt(name);
		return INT_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getLong(java.lang.String)
	 */
	public long getLong(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getLong(name);
		return LONG_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#getString(java.lang.String)
	 */
	public String getString(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.getString(name);
		return STRING_DEFAULT_DEFAULT;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#isDefault(java.lang.String)
	 */
	public boolean isDefault(String name) {
		IPreferenceStore visibleStore= getVisibleStore(name);
		if (visibleStore != null)
			return visibleStore.isDefault(name);
		return false;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#needsSaving()
	 */
	public boolean needsSaving() {
		for (IPreferenceStore store : fPreferenceStores) {
			if (store.needsSaving()) {
				return true;
			}
		}
		return false;
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#putValue(java.lang.String, java.lang.String)
	 */
	public void putValue(String name, String value) {
		getVisibleStore(name).putValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, double)
	 */
	public void setDefault(String name, double value) {
		getVisibleStore(name).setDefault(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, float)
	 */
	public void setDefault(String name, float value) {
		getVisibleStore(name).setDefault(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, int)
	 */
	public void setDefault(String name, int value) {
		getVisibleStore(name).setDefault(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, long)
	 */
	public void setDefault(String name, long value) {
		getVisibleStore(name).setDefault(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, java.lang.String)
	 */
	public void setDefault(String name, String defaultObject) {
		getVisibleStore(name).setDefault(name, defaultObject);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setDefault(java.lang.String, boolean)
	 */
	public void setDefault(String name, boolean value) {
		getVisibleStore(name).setDefault(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setToDefault(java.lang.String)
	 */
	public void setToDefault(String name) {
		getVisibleStore(name).setToDefault(name);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, double)
	 */
	public void setValue(String name, double value) {
		getVisibleStore(name).setValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, float)
	 */
	public void setValue(String name, float value) {
		getVisibleStore(name).setValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, int)
	 */
	public void setValue(String name, int value) {
		getVisibleStore(name).setValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, long)
	 */
	public void setValue(String name, long value) {
		getVisibleStore(name).setValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, java.lang.String)
	 */
	public void setValue(String name, String value) {
		getVisibleStore(name).setValue(name, value);
	}

	/*
	 * @see org.eclipse.jface.preference.IPreferenceStore#setValue(java.lang.String, boolean)
	 */
	public void setValue(String name, boolean value) {
		getVisibleStore(name).setValue(name, value);
	}

	/**
	 * Handle property change event from the child listener with the given child preference store.
	 *
	 * @param childPreferenceStore the child preference store
	 * @param event the event
	 */
	private void handlePropertyChangeEvent(IPreferenceStore childPreferenceStore, PropertyChangeEvent event) {
		String property= event.getProperty();
		Object oldValue= event.getOldValue();
		Object newValue= event.getNewValue();

		IPreferenceStore visibleStore= getVisibleStore(property);

		/*
		 * Assume that the property is there but has no default value (its owner relies on the default-default value)
		 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52827
		 */
		if (visibleStore == null && newValue != null)
			visibleStore= childPreferenceStore;

		if (visibleStore == null) {
			// no visible store
			if (oldValue != null)
				// removal in child, last in chain -> removal in this chained preference store
				firePropertyChangeEvent(event);
		} else if (visibleStore == childPreferenceStore) {
			// event from visible store
			if (oldValue != null) {
				// change in child, visible store -> change in this chained preference store
				firePropertyChangeEvent(event);
			} else {
				// insertion in child
				IPreferenceStore oldVisibleStore= null;
				int i= 0;
				int length= fPreferenceStores.length;
				while (i < length && fPreferenceStores[i++] != visibleStore) {
					// do nothing
				}
				while (oldVisibleStore == null && i < length) {
					if (fPreferenceStores[i].contains(property))
						oldVisibleStore= fPreferenceStores[i];
					i++;
				}

				if (oldVisibleStore == null) {
					// insertion in child, first in chain -> insertion in this chained preference store
					firePropertyChangeEvent(event);
				} else {
					// insertion in child, not first in chain
					oldValue= getOtherValue(property, oldVisibleStore, newValue);
					if (!oldValue.equals(newValue))
						// insertion in child, different old value -> change in this chained preference store
						firePropertyChangeEvent(property, oldValue, newValue);
					// else: insertion in child, same old value -> no change in this chained preference store
				}
			}
		} else {
			// event from other than the visible store
			boolean eventBeforeVisibleStore= false;
			for (int i= 0, length= fPreferenceStores.length; i < length; i++) {
				IPreferenceStore store= fPreferenceStores[i];
				if (store == visibleStore)
					break;
				if (store == childPreferenceStore) {
					eventBeforeVisibleStore= true;
					break;
				}
			}

			if (eventBeforeVisibleStore) {
				// removal in child, before visible store

				/*
				 * The original event's new value can be non-null (removed assertion).
				 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69419
				 */

				newValue= getOtherValue(property, visibleStore, oldValue);
				if (!newValue.equals(oldValue))
					// removal in child, before visible store, different old value -> change in this chained preference store
					firePropertyChangeEvent(property, oldValue, newValue);
				// else: removal in child, before visible store, same old value -> no change in this chained preference store
			}
			// else: event behind visible store -> no change in this chained preference store
		}
	}

	/**
	 * Returns an object of the same dynamic type as <code>thisValue</code>, the returned object
	 * encapsulates the value of the <code>property</code> from the preference <code>store</code>.
	 *
	 * @param property the name of the considered property
	 * @param store the preference store
	 * @param thisValue the given value
	 * @return the other value
	 */
	private Object getOtherValue(String property, IPreferenceStore store, Object thisValue) {

		if (thisValue instanceof Boolean)
			return store.getBoolean(property) ? Boolean.TRUE : Boolean.FALSE;
		else if (thisValue instanceof Double)
			return Double.valueOf(store.getDouble(property));
		else if (thisValue instanceof Float)
			return Float.valueOf(store.getFloat(property));
		else if (thisValue instanceof Integer)
			return Integer.valueOf(store.getInt(property));
		else if (thisValue instanceof Long)
			return Long.valueOf(store.getLong(property));
		else if (thisValue instanceof String)
			return store.getString(property);

		return store.getString(property);
	}

	/**
	 * Returns the preference store from which the given property's value
	 * is visible.
	 *
	 * @param property the name of the property
	 * @return the preference store from which the property's value is visible,
	 * 	<code>null</code> if the property is unknown
	 */
	private IPreferenceStore getVisibleStore(String property) {
		// Redirect to the corresponding preference store based on key
		// while assuming the texteditor pref is at array pos 0
		if ((property.toLowerCase().contains("color") && !property
				.endsWith(ColorPredicatePreferencePage.PREDICATE))
				|| property.contains(ColorPredicatePreferencePage.APPLIES_TO_LEAF_ONLY)
				|| property.contains(ColorPredicatePreferencePage.STEP_STATUS_OVERVIEW)) {
			return fPreferenceStores[0];
		} else {
			return fPreferenceStores[1];
		}
	}

	/**
	 * Register the child listeners on the child preference stores.
	 */
	private void registerChildListeners() {
		Iterator<PropertyChangeListener> iter= fChildListeners.iterator();
		while (iter.hasNext()) {
			PropertyChangeListener listener= iter.next();
			listener.register();
		}
	}

	/**
	 * Unregister the child listeners from the child preference stores.
	 */
	private void unregisterChildListeners() {
		Iterator<PropertyChangeListener> iter= fChildListeners.iterator();
		while (iter.hasNext()) {
			PropertyChangeListener listener= iter.next();
			listener.unregister();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/configuration/ConfigConstants.java<|end_filename|>
/***************************************************************************
* This file seems to contain constants that are used to initialize the     *
* semantic analysis.  This includes information about built-in operators.  *
* A parser defined by config.jj apparently parses the string               *
* defaultConfig to extract this information.                               *
***************************************************************************/
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

// Last modified on Mon 16 February 2009 at 10:03:01 PST by lamport

package tla2sany.configuration;

interface ConfigConstants {
  int nada = 0;
  int infixOP = 1;
  int prefixOP = 2;
  int postfixOP = 3;
  int preINfixOP = 4;

  int leftAssoc = 10;
  int rightAssoc = 11;
  int noAssoc = 12;

  int EOF = 0;
  int SINGLE_LINE = 4;
  int CONSTANT = 7;
  int OPERATOR = 8;
  int INFIX = 9;
  int POSTFIX = 10;
  int PREFIX = 11;
  int NFIX = 12;
  int NOTOP = 13;
  int SYNONYM = 14;
  int LEFTASSOC = 15;
  int RIGHTASSOC = 16;
  int NOASSOC = 17;
  int BUILTIN = 18;
  int OPCHAR = 19;
  int LETTER = 20;
  int OPID = 21;
  int NUMBER = 22;
  int RESTRICTED = 23;

  int DEFAULT = 0;
  int IN_COMMENT = 1;

  String[] tokenImage = {
    "<EOF>",
    "\" \"",
    "\"\\t\"",
    "\"\\n\"",
    "\"(*\"",
    "\"*)\"",
    "<token of kind 6>",
    "<CONSTANT>",
    "<OPERATOR>",
    "<INFIX>",
    "<POSTFIX>",
    "<PREFIX>",
    "<NFIX>",
    "<NOTOP>",
    "<SYNONYM>",
    "<LEFTASSOC>",
    "<RIGHTASSOC>",
    "<NOASSOC>",
    "<BUILTIN>",
    "<OPCHAR>",
    "<LETTER>",
    "<OPID>",
    "<NUMBER>",
    "<RESTRICTED>",
  };

  String defaultConfig =
    /***********************************************************************
    * This is used in config/Configuration.java to create Operator         *
    * objects for each operator, which are put in the hashtable            *
    * Operators.BuiltinTable.                                              *
    ***********************************************************************/
    "operator [ 160 160 Left postfix \n" +
    "operator . 170 170 Left infix \n" +
    "operator ' 150 150 None postfix\n" +
    "operator ^ 140 140 None infix\n" +  // None, verified.
    "operator / 130 130 None infix\n" +
    "operator * 130 130 Left infix\n" +
    "operator - 110 110 Left infix\n" +
    "operator -. 120 120 None prefix\n" +
    "operator + 100 100 Left infix\n" +
    "operator = 50 50 None infix\n" +
    "operator \\lnot 40 40 Left prefix \n" +
    "synonym  ~ \\lnot\n" +
    "synonym \\neg \\lnot\n" +
    "operator \\land 30 30 Left infix\n" +
    "synonym  /\\ \\land\n" +
    "operator \\lor 30 30 Left infix\n" +
    "synonym  \\/ \\lor\n" +
    "operator ~> 20 20 None infix\n" +
    "operator => 10 10  None infix\n" +
    //\n" +
    "operator [] 40 150 None prefix \n" +
    "operator <> 40 150 None prefix \n" +
    "operator ENABLED 40 150 None prefix \n" +
    "operator UNCHANGED 40 150 None prefix \n" +
    "operator SUBSET 100 130 None prefix \n" +
    "operator UNION 100 130 None prefix \n" +
    "operator DOMAIN 100 130 None prefix \n" +
    //\n" +
    "operator ^+ 150 150 None postfix\n" +
    "operator ^* 150 150 None postfix\n" +
    "operator ^# 150 150 None postfix\n" +
    //\n" +
    "operator \\cdot 50 140  Left infix\n" +
    //\n" +
    "operator \\equiv 20 20  None infix\n" +
    "synonym <=> \\equiv\n" +
    //\n" +
    "operator -+-> 20 20 None infix\n" +
    "operator /= 50 50 None infix\n" +
    "synonym # /=\n" +
    "operator \\subseteq 50 50 None infix\n" +
    "operator \\in 50 50 None infix\n" +
    "operator \\notin 50 50 None infix\n" +
    "operator < 50 50 None infix\n" +
    "operator \\leq 50 50 None infix\n" +
    "synonym <= \\leq\n" +
    "synonym =< \\leq\n" +
    "operator > 50 50 None infix\n" +
    "operator \\geq 50 50 None infix\n" +
    "synonym >= \\geq\n" +
    //\n" +
    "operator \\times 100 130 Left nfix\n" +
    "synonym  \\X \\times\n" +
    "operator \\ 80 80 None infix\n" +
    "operator \\intersect 80 80 Left infix\n" +
    "synonym \\cap \\intersect \n" +
    "operator \\union 80 80 Left infix\n" +
    "synonym \\cup \\union\n" +
    //\n" +
    "operator ... 90 90 None infix\n" +
    "operator .. 90 90 None infix\n" +
    "operator | 100 110 Left infix\n" +
    "operator || 100 110 Left infix\n" +
    "operator && 130 130 Left infix\n" +
    "operator & 130 130 Left infix\n" +
    "operator $$ 90 130 Left infix\n" +
    "operator $ 90 130 Left infix\n" +  
    "operator ?? 90 130 Left infix\n" +
    //"operator ? 90 130 Left infix\n" +  // Removed requested by Leslie (16 Feb. 01)
    "operator %% 100 110 Left infix\n" +
    "operator % 100 110 None infix\n" +
    "synonym \\mod %\n" +
    "operator ## 90 130 Left infix\n" +
    "operator ++ 100 100 Left infix\n" +
    "operator -- 110 110 Left infix\n" +
    "operator ** 130 130 Left infix\n" +
    "operator // 130 130 None infix\n" +
    "operator ^^ 140 140 None infix\n" +
    "operator @@ 60 60 Left infix\n" +
    "operator !! 90 130 None infix\n" +
    "operator |- 50 50 None infix\n" +
    "operator |= 50 50 None infix\n" +
    "operator -| 50 50 None infix\n" +
    "operator =| 50 50 None infix\n" +
    "operator <: 70 70 None infix\n" +
    "operator :> 70 70 None infix\n" +
    "operator := 50 50 None infix\n" +
    "operator ::= 50 50 None infix\n" +
// \n" +
    "operator \\oplus 100 100 Left infix\n" +
    "synonym (+) \\oplus\n" +
    "operator \\ominus 110 110 Left infix\n" +
    "synonym (-) \\ominus\n" +
    "operator \\odot 130 130 Left infix\n" +
    "synonym (.) \\odot\n" +
    "operator \\oslash 130 130 None infix\n" +
    "synonym (/) \\oslash\n" +
    "operator \\otimes 130 130 Left infix\n" +
    "synonym (\\X) \\otimes\n" +
// \n" +
    "operator \\uplus 90 130 Left infix\n" +
    "operator \\sqcap 90 130 Left infix\n" +
    "operator \\sqcup 90 130 Left infix\n" +
    "operator \\div 130 130 None infix\n" +
    "operator \\wr 90 140 None infix\n" +
    "operator \\star 130 130 Left infix\n" +
    "operator \\o 130 130 Left infix\n" +
    "synonym  \\circ \\o \n" +
    "operator \\bigcirc 130 130 Left infix\n" +
    "operator \\bullet 130 130 Left infix\n" +
    "operator \\prec 50 50 None infix\n" +
    "operator \\succ 50 50 None infix\n" +
    "operator \\preceq 50 50 None infix\n" +
    "operator \\succeq 50 50 None infix\n" +
    "operator \\sim 50 50 None infix\n" +
    "operator \\simeq 50 50 None infix\n" +
    "operator \\ll 50 50 None infix\n" +
    "operator \\gg 50 50 None infix\n" +
    "operator \\asymp 50 50 None infix\n" +
    "operator \\subset 50 50 None infix\n" + // subseteq is builtin
    "operator \\supset 50 50 None infix\n" +
    "operator \\supseteq 50 50 None infix\n" +
    "operator \\approx 50 50 None infix\n" +
    "operator \\cong 50 50 None infix\n" +
    "operator \\sqsubset 50 50 None infix\n" +
    "operator \\sqsubseteq 50 50 None infix\n" +
    "operator \\sqsupset 50 50 None infix\n" +
    "operator \\sqsupseteq 50 50 None infix\n" +
    "operator \\doteq 50 50 None infix\n" +
    "operator \\propto 50 50 None infix\n" +
    //\n" +
    "builtin STRING    $$_string     constant\n" +
    "builtin FALSE     $$_false      constant\n" +
    "builtin TRUE      $$_true       constant\n" +
    "builtin BOOLEAN   $$_boolean    constant\n" +
    //\n" +
    "builtin =         $$_equal        infix\n" +
    "builtin /=        $$_notEqual     infix\n" +
    //\n" +
    "builtin .         $$_dot          infix\n" +
    "builtin '         $$_prime        postfix\n" +
    "builtin \\lnot     $$_not          prefix\n" +
    "builtin \\neg      $$_neg          prefix\n" +
    "builtin \\land     $$_and          infix\n" +
    "builtin \\lor      $$_or           infix\n" +
    "builtin \\equiv    $$_equivalent   infix\n" +
    "builtin =>        $$_implies      infix\n" +
    //\n" +
    "builtin SUBSET     $$_subset      prefix\n" +
    "builtin UNION      $$_union       prefix\n" +
    "builtin DOMAIN     $$_domain      prefix\n" +
    "builtin \\subseteq  $$_subseteq    infix \n" +
    "builtin \\in        $$_in          infix \n" +
    "builtin \\notin     $$_notin       infix \n" +
    "builtin \\          $$_setdiff     infix \n" +
    "builtin \\intersect $$_setinter    infix \n" +
    "builtin \\union     $$_setunion    infix \n" +
    "builtin \\times     $$_times       infix \n" +
    //\n" +
    "builtin ~>         $$_leadsTo     infix \n" +
    "builtin []         $$_box         prefix\n" +
    "builtin <>         $$_diamond     prefix\n" +
    "builtin ENABLED    $$_enabled     prefix\n" +
    "builtin UNCHANGED  $$_unchanged   prefix\n" +
    "builtin \\cdot     $$_cdot        infix \n" +
    "builtin -+->       $$_arrow       infix \n" +
//
    "builtin $AngleAct                $$_null   2\n" +
    "builtin $BoundedChoose           $$_null  -1\n" +
    "builtin $BoundedExists           $$_null  -1\n" +
    "builtin $BoundedForall           $$_null  -1\n" +
    "builtin $CartesianProd           $$_null  -1\n" +
    "builtin $Case                    $$_null  -1\n" +
    "builtin $ConjList                $$_null  -1\n" +
    "builtin $DisjList                $$_null  -1\n" +
    "builtin $Except                  $$_null  -1\n" + // arity corrected from 1 to -1 DRJ 20 Nov '00
    "builtin $FcnApply                $$_null   2\n" +
    "builtin $FcnConstructor          $$_null  -1\n" +
    "builtin $IfThenElse              $$_null   3\n" +
    "builtin $NonRecursiveFcnSpec     $$_null   1\n" +
    "builtin $Pair                    $$_null   2\n" +
    "builtin $RcdConstructor          $$_null  -1\n" +
    "builtin $RcdSelect               $$_null   2\n" +
    "builtin $RecursiveFcnSpec        $$_null   1\n" +
    "builtin $Seq                     $$_null  -1\n" +
    "builtin $SetEnumerate            $$_null  -1\n" +
    "builtin $SetOfAll                $$_null  -1\n" +
    "builtin $SetOfFcns               $$_null  -1\n" +
    "builtin $SetOfRcds               $$_null  -1\n" + // Added by DRJ 1 Oct '00 
    "builtin $SF                      $$_null   2\n" +
    "builtin $SquareAct               $$_null   2\n" +
    "builtin $SubsetOf                $$_null   1\n" +
    "builtin $TemporalExists          $$_null   1\n" +
    "builtin $TemporalForall          $$_null   1\n" +
    "builtin $TemporalWhile           $$_null   2\n" +
    "builtin $Tuple                   $$_null  -1\n" +
    "builtin $UnboundedChoose         $$_null   1\n" +
    "builtin $UnboundedExists         $$_null   1\n" +
    "builtin $UnboundedForall         $$_null   1\n" +
    "builtin $WF                      $$_null   2\n"   +
    "builtin $Nop                     $$_null   1\n"   +
    "builtin $Qed                     $$_null   0\n"   +
    "builtin $Pfcase                  $$_null   1\n"   +
    "builtin $Have                    $$_null   1\n"   +
    "builtin $Take                    $$_null   1\n"   +
    "builtin $Pick                    $$_null   1\n"   +
    "builtin $Witness                 $$_null   -1\n"  +

    /***********************************************************************
    * $Suffices added by LL 16 Feb 2009.                                   *
    ***********************************************************************/
    "builtin $Suffices                $$_null   1\n"   

  ;
}



<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/provider/ToolboxLabelProvider.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.provider;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.IDescriptionProvider;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Module;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.provider.SpecContentProvider.Group;

/**
 * Label provider for all toolbox internal elements
 */
public class ToolboxLabelProvider extends LabelProvider implements ILabelProvider, IDescriptionProvider {
	
	public String getText(final Object element) {
		if (element == null) {
			return null;
		}
		if (element instanceof Spec) {
			final Spec spec = (Spec) element;
			final IFile root = spec.getRootFile();
			if (root == null) {
				return null;
			}
			if (root.getName().replaceAll(".tla$", "").equals(spec.getName())) {
				// Don't append name of root module if identical to spec name (which is usually
				// the default).
				return spec.getName();
			}
			return spec.getName() + " [ " + root.getName() + " ]";
		} else if (element instanceof Module) {
			return ((Module) element).getModuleName();
		} else if (element instanceof Group) {
			return element.toString();
		}
		return null;
	}

	// This is at least shown in the Toolbox's status line at the bottom.
	public String getDescription(final Object element) {
		if (element instanceof Spec) {
			final Spec spec = (Spec) element;
			final IFile root = spec.getRootFile();
			if (root == null) {
				return super.getText(element);
			}
			return spec.getName() + " [ " + root.getLocation().toFile() + " ]";
		} else if (element instanceof Module) {
			final Module module = (Module) element;
			return module.getModuleName() + " [ " + module.getResource().getLocation().toFile() + " ]";
		}
		return super.getText(element);
	}

	public Image getImage(final Object element) {
		if (element == null) {
			return null;
		}
		if (element instanceof Spec) {
			if (Activator.getSpecManager().isSpecLoaded((Spec) element)) {
				return Activator.getDefault().getImageRegistry().get(Activator.IMG_SPEC_OPEN);
			}
			return Activator.getDefault().getImageRegistry().get(Activator.IMG_SPEC_CLOSED);
		} else if (element instanceof Module) {
			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE);
		} else if (element instanceof Group) {
			return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_COPY);
		}
		return null;
	}
}

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/TLARegistry.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:18:28 PST by lamport
//      modified on Fri Sep 15 11:06:03 PDT 2000 by yuanyu

package tlc2.tool.impl;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Provides a mapping between the TLA+ names and Java names.
 * <br><b>Note:</b>
 * 
 * @author <NAME>
 */
public class TLARegistry {

  private static final Hashtable<String, String> javaToTLA = new Hashtable<String, String>();

  public static String get(String name) {
    return javaToTLA.get(name);
  }

  /**
   * puts a value into the registry.
   * @param tname the TLA+ name 
   * @param jname the corresponding Java name
   * @return the previous value, if one
   */
  public static String put(String tname, String jname) {
    return javaToTLA.put(tname, jname);
  }

  public static String mapName(String name) {
    String tname = TLARegistry.get(name);
    return ((tname == null) ? name : tname);
  }

  /* Used only for debugging. */
  public static String allNames() {
    StringBuffer sb = new StringBuffer("{");
    Enumeration<String> eNames = javaToTLA.keys();
    if (eNames.hasMoreElements()) {
      sb.append(eNames.nextElement());
    }
    while (eNames.hasMoreElements()) {
      sb.append(", ");
      sb.append(eNames.nextElement());
    }
    sb.append("}");
    return sb.toString();
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/model/AbstractModelStateChangeListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.model;

/**
 * An instance of this is notified when the running state of the model changes. There is no guarantee as to which thread
 * is being used to send the notification.
 * 
 * @see Model#add(AbstractModelStateChangeListener)
 * @see Model#remove(AbstractModelStateChangeListener)
 */
public abstract class AbstractModelStateChangeListener {
	public enum State {
		RUNNING, NOT_RUNNING, DELETED, REMOTE_RUNNING, REMOTE_NOT_RUNNING;
		
		public boolean in(final State ... states) {
			for (final State state : states) {
				if (state == this) {
					return true;
				}
			}
			return false;
		}
	}

	
	public static class ChangeEvent {
		private final State state;
		private final Model model;

		public ChangeEvent(final Model model, final State state) {
			this.model = model;
			this.state = state;
		}

		public State getState() {
			return state;
		}

		public Model getModel() {
			return model;
		}
	}

	
	/**
	 * @return true iff the listener should be unsubscribed from receiving future events after it handled the event.
	 */
	public abstract boolean handleChange(final ChangeEvent event);
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/TokenizerException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class TokenizerException extends UnrecoverableException
{

    /**
     * @param message
     */
    public TokenizerException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/TLCTest.java<|end_filename|>
package tlc2;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import org.junit.Test;

import tlc2.tool.fp.FPSetConfiguration;
import tlc2.tool.fp.FPSetFactory;
import util.TLAConstants;
import util.TLCRuntime;

public class TLCTest {

	@Test
	public void testHandleParametersAbsoluteInvalid() {
		final TLC tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] {"-fpmem", "-1", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
	}
	
	@Test
	public void testHandleParametersAbsoluteValid() {
		final TLC tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-fpmem", "101", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
	}
	
	@Test
	public void testHandleParametersFractionInvalid() {
		final TLC tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] {"-fpmem", "-0.5", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
	}
	
	/**
	 * Allocating to little should result in min default
	 */
	@Test
	public void testHandleParametersAllocateLowerBound() {
		final TLC tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-fpmem", "0", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
		final FPSetConfiguration fpSetConfiguration = tlc.getFPSetConfiguration();
		assumeTrue(FPSetFactory.allocatesOnHeap(fpSetConfiguration.getImplementation()));
		assertEquals("Allocating to little should result in min default",
				TLCRuntime.MinFpMemSize, fpSetConfiguration
						.getMemoryInBytes());
	}
	
	/**
	 * Overallocating should result in max default
	 */
	@Test
	public void testHandleParametersAllocateUpperBound() {
		final TLC tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-fpmem", Long.toString(Long.MAX_VALUE),
				TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
        final long maxMemory = (long) (Runtime.getRuntime().maxMemory() * 0.75d);
        final FPSetConfiguration fpSetConfiguration = tlc.getFPSetConfiguration();
		assumeTrue(FPSetFactory.allocatesOnHeap(fpSetConfiguration.getImplementation()));
		assertEquals("Overallocating should result in max default (75%)",
				maxMemory, fpSetConfiguration.getMemoryInBytes());
	}
	
	/**
	 * .5 is valid
	 */
	@Test
	public void testHandleParametersAllocateHalf() {
		final TLC tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-fpmem", ".5", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
        final long maxMemory = (long) (Runtime.getRuntime().maxMemory() * 0.50d);
        final FPSetConfiguration fpSetConfiguration = tlc.getFPSetConfiguration();
		assumeTrue(FPSetFactory.allocatesOnHeap(fpSetConfiguration.getImplementation()));
		assertEquals("Overallocating should result in max default (50%)",
				maxMemory, fpSetConfiguration.getMemoryInBytes());
	}
	
	/**
	 * .99 is valid
	 */
	@Test
	public void testHandleParametersAllocate90() {
		final TLC tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-fpmem", ".99", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
        final long maxMemory = (long) (Runtime.getRuntime().maxMemory() * 0.99d);
		final FPSetConfiguration fpSetConfiguration = tlc.getFPSetConfiguration();
		assumeTrue(FPSetFactory.allocatesOnHeap(fpSetConfiguration.getImplementation()));
		assertEquals("Overallocating should result in max default (99%)",
				maxMemory, fpSetConfiguration.getMemoryInBytes());
	}
	
	/**
	 *  is valid
	 */
	@Test
	public void testHandleParametersMaxSetSize() {
		final int progDefault = TLCGlobals.setBound;
		
		TLC tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] {"-maxSetSize", "NaN", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
		
		tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] {"-maxSetSize", "0", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
		tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] {"-maxSetSize", "-1", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
		tlc = new TLC();
		assertFalse(tlc.handleParameters(new String[] { "-maxSetSize", Integer.toString(Integer.MIN_VALUE),
				TLAConstants.Files.MODEL_CHECK_FILE_BASENAME }));
		
		tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] {"-maxSetSize", "1", TLAConstants.Files.MODEL_CHECK_FILE_BASENAME}));
		assertTrue(TLCGlobals.setBound == 1);
		

		tlc = new TLC();
		assertTrue(tlc.handleParameters(
				new String[] { "-maxSetSize", Integer.toString(progDefault), TLAConstants.Files.MODEL_CHECK_FILE_BASENAME }));
		assertTrue(TLCGlobals.setBound == progDefault);
		
		tlc = new TLC();
		assertTrue(tlc.handleParameters(new String[] { "-maxSetSize", Integer.toString(Integer.MAX_VALUE),
				TLAConstants.Files.MODEL_CHECK_FILE_BASENAME }));
		assertTrue(TLCGlobals.setBound == Integer.MAX_VALUE);
	}
	
	@Test
	public void testRuntimeConversion() {
		assertEquals("59s", TLC.convertRuntimeToHumanReadable(59000L));
		assertEquals("59min 59s", TLC.convertRuntimeToHumanReadable(3599000L));
		assertEquals("23h 59min", TLC.convertRuntimeToHumanReadable(86340000L));
		assertEquals("1d 23h", TLC.convertRuntimeToHumanReadable(169200000L));
		assertEquals("2d 23h", TLC.convertRuntimeToHumanReadable(255600000L));
		assertEquals("99d 23h", TLC.convertRuntimeToHumanReadable(8636400000L));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/queue/DiskByteArrayQueue.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:25:48 PST by lamport  
//      modified on Thu Feb  8 23:32:12 PST 2001 by yuanyu   

package tlc2.tool.queue;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.util.Arrays;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.value.IValue;
import tlc2.value.IValueInputStream;
import tlc2.value.IValueOutputStream;
import tlc2.value.ValueConstants;
import tlc2.value.impl.BoolValue;
import tlc2.value.impl.FcnRcdValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.ModelValue;
import tlc2.value.impl.RecordValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.StringValue;
import tlc2.value.impl.TupleValue;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;
import util.IDataInputStream;
import util.IDataOutputStream;
import util.UniqueString;
import util.WrongInvocationException;

/**
 * A {@link DiskByteArrayQueue} uses the local hard disc as a backing store for
 * states. An in-memory buffer of size {@link DiskByteArrayQueue}{@link #BufSize}
 */
public class DiskByteArrayQueue extends ByteArrayQueue {
	// TODO dynamic bufsize based on current VM parameters?
	private final static int BufSize = Integer.getInteger(DiskStateQueue.class.getName() + ".BufSize", 8192);

	/*
	 * Invariants: I1. Entries in deqBuf are in the indices: [deqIndex,
	 * deqBuffer.length ) I2. Entries in enqBuf are in the indices: [ 0,
	 * enqIndex ) I3. 0 <= deqIndex <= deqBuf.length, where deqIndex == 0 =>
	 * buffer full deqIndex == deqBuf.length => buffer empty I4. 0 <= enqIndex
	 * <= enqBuf.length, where enqIndex == 0 => buffer empty enqIndex ==
	 * enqBuf.length => buffer full
	 */

	/* Fields */
	private final String filePrefix;
	protected byte[][] deqBuf, enqBuf;
	protected int deqIndex, enqIndex;
	protected ByteArrayPoolReader reader;
	protected ByteArrayPoolWriter writer;
	
	/**
	 * The SPC takes care of deleting swap files on the lower end of the range
	 * (loPool, hiPool). It terminates, when the first checkpoint is written at
	 * which point checkpointing itself takes care of removing obsolete swap
	 * files.
	 */
	protected final StatePoolCleaner cleaner;
	private int loPool, hiPool, lastLoPool, newLastLoPool;
	private File loFile;
	
	// TESTING ONLY!
	DiskByteArrayQueue() throws IOException {
		this(Files.createTempDirectory("DiskByteArrayQueue").toFile().toString());
	}

	/* Constructors */
	public DiskByteArrayQueue(String diskdir) {
		this.deqBuf = new byte[BufSize][];
		this.enqBuf = new byte[BufSize][];
		this.deqIndex = BufSize;
		this.enqIndex = 0;
		this.loPool = 1;
		this.hiPool = 0;
		this.lastLoPool = 0;
		this.filePrefix = diskdir + FileUtil.separator;
		File rFile = new File(this.filePrefix + Integer.toString(0));
		this.reader = new ByteArrayPoolReader(BufSize, rFile);
		this.reader.setDaemon(true);
		this.loFile = new File(this.filePrefix + Integer.toString(this.loPool));
		this.reader.start();
		this.writer = new ByteArrayPoolWriter(BufSize, this.reader);
		this.writer.setDaemon(true);
		this.writer.start();
		this.cleaner = new StatePoolCleaner();
		this.cleaner.setDaemon(true);
		this.cleaner.start();
	}

	final void enqueueInner(byte[] state) {
		if (this.enqIndex == this.enqBuf.length) {
			// enqBuf is full; flush it to disk
			try {
				String pstr = Integer.toString(this.hiPool);
				File file = new File(this.filePrefix + pstr);
				this.enqBuf = this.writer.doWork(this.enqBuf, file);
				this.hiPool++;
				this.enqIndex = 0;
			} catch (Exception e) {
				Assert.fail(EC.SYSTEM_ERROR_WRITING_STATES,
						new String[] { "queue", (e.getMessage() == null) ? e.toString() : e.getMessage() });
			}
		}
		this.enqBuf[this.enqIndex++] = state;
	}

	final byte[] dequeueInner() {
		if (this.deqIndex == this.deqBuf.length) {
			this.fillDeqBuffer();
		}
		return this.deqBuf[this.deqIndex++];
	}
	
	byte[] peekInner() {
		if (this.deqIndex == this.deqBuf.length) {
			this.fillDeqBuffer();
		}
		return this.deqBuf[this.deqIndex];
	}

	private final void fillDeqBuffer() {
		try {
			if (this.loPool + 1 <= this.hiPool) {
				// We are sure there are disk files.
				if (this.loPool + 1 >= this.hiPool) {
					// potential read-write conflict on a file
					this.writer.ensureWritten();
				}
				this.deqBuf = this.reader.doWork(this.deqBuf, this.loFile);
				this.deqIndex = 0;
				this.loPool++;
				String pstr = Integer.toString(this.loPool);
				this.loFile = new File(this.filePrefix + pstr);
			} else {
				// We still need to check if a file is buffered.
				this.writer.ensureWritten();
				byte[][] buf = this.reader.getCache(this.deqBuf, this.loFile);
				if (buf != null) {
					this.deqBuf = buf;
					this.deqIndex = 0;
					this.loPool++;
					String pstr = Integer.toString(this.loPool);
					this.loFile = new File(this.filePrefix + pstr);
				} else {
					// copy entries from enqBuf to deqBuf.
					this.deqIndex = this.deqBuf.length - this.enqIndex;
					System.arraycopy(this.enqBuf, 0, this.deqBuf, this.deqIndex, this.enqIndex);
					this.enqIndex = 0;
				}
			}
			// Notify the cleaner to do its job unless its waits for more work
			// to pile up.
			if ((loPool - lastLoPool) > 100) { //TODO Take BufSize into account. It defines the disc file size.
				synchronized (this.cleaner) {
					this.cleaner.deleteUpTo = loPool - 1;
					this.cleaner.notifyAll();
				}
			}
		} catch (Exception e) {
			Assert.fail(EC.SYSTEM_ERROR_READING_STATES, new String[] { "queue",
					(e.getMessage() == null) ? e.toString() : e.getMessage() });
		}
	}

	/* Checkpoint. */
	public final void beginChkpt() throws IOException {
		synchronized (this.cleaner) {
			// Checkpointing takes precedence over periodic cleaning
			// (cleaner would otherwise delete checkpoint files as it know
			// nothing of checkpoints).
			this.cleaner.finished = true;
			this.cleaner.notifyAll();
		}
		
		String filename = this.filePrefix + "queue.tmp";
	  	final BufferedDataOutputStream vos = new BufferedDataOutputStream(filename);
		vos.writeLong(this.len);
		vos.writeInt(this.loPool);
		vos.writeInt(this.hiPool);
		vos.writeInt(this.enqIndex);
		vos.writeInt(this.deqIndex);
		for (int i = 0; i < this.enqIndex; i++) {
	  		vos.writeInt(this.enqBuf[i].length);
	  		vos.write(this.enqBuf[i]);
		}
		for (int i = this.deqIndex; i < this.deqBuf.length; i++) {
	  		vos.writeInt(this.deqBuf[i].length);
	  		vos.write(this.deqBuf[i]);
		}
		vos.close();
		this.newLastLoPool = this.loPool - 1;
	}

	public final void commitChkpt() throws IOException {
		for (int i = this.lastLoPool; i < this.newLastLoPool; i++) {
			String pstr = Integer.toString(i);
			File oldPool = new File(this.filePrefix + pstr);
			if (!oldPool.delete()) {
				String msg = "DiskStateQueue.commitChkpt: cannot delete " + oldPool;
				throw new IOException(msg);
			}
		}
		this.lastLoPool = this.newLastLoPool;
		File oldChkpt = new File(this.filePrefix + "queue.chkpt");
		File newChkpt = new File(this.filePrefix + "queue.tmp");
		if ((oldChkpt.exists() && !oldChkpt.delete()) || !newChkpt.renameTo(oldChkpt)) {
			String msg = "DiskStateQueue.commitChkpt: cannot delete " + oldChkpt;
			throw new IOException(msg);
		}
	}

	public final void recover() throws IOException {
		String filename = this.filePrefix + "queue.chkpt";
	  	final BufferedDataInputStream vis = new BufferedDataInputStream(filename);
		this.len = vis.readLong();
		this.loPool = vis.readInt();
		this.hiPool = vis.readInt();
		this.enqIndex = vis.readInt();
		this.deqIndex = vis.readInt();
		this.lastLoPool = this.loPool - 1;

		for (int i = 0; i < this.enqIndex; i++) {
			this.enqBuf[i] = new byte[vis.readInt()];
			vis.read(this.enqBuf[i]);
		}
		for (int i = this.deqIndex; i < this.deqBuf.length; i++) {
			this.deqBuf[i] = new byte[vis.readInt()];
			vis.read(this.deqBuf[i]);
		}
		vis.close();
		File file = new File(this.filePrefix + Integer.toString(this.lastLoPool));
		boolean canRead = (this.lastLoPool < this.hiPool);
		this.reader.restart(file, canRead);
		String pstr = Integer.toString(this.loPool);
		this.loFile = new File(this.filePrefix + pstr);
	}

	public void finishAll() {
		super.finishAll();
		synchronized (this.writer) {
			this.writer.notifyAll();
		}
		synchronized (this.reader) {
			this.reader.setFinished();
			this.reader.notifyAll();
		}
		synchronized (this.cleaner) {
			this.cleaner.finished = true;
			this.cleaner.notifyAll();
		}
	}

	private class StatePoolCleaner extends Thread {

		private volatile boolean finished = false;
		public int deleteUpTo;
		
		private StatePoolCleaner() {
			super("RawTLCStatePoolCleaner");
		}

		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		public void run() {
			try {
				synchronized (this) {
					while (!this.finished) {
						this.wait();
						if (this.finished) {
							return;
						}
						
						for (int i = lastLoPool; i < deleteUpTo; i++) {
							final File oldPoolFile = new File(filePrefix + Integer.toString(i));
							if (!oldPoolFile.delete()) {
								// No reason to terminate/kill TLC when the cleanup fails.
								// Contrary to StatePoolReader/Write, cleanup is optional
								// functionality whose purpose is to prevent the disc from
								// filling up. If the cleaner fails, the user can still
								// manually delete the files.
								MP.printWarning(EC.SYSTEM_ERROR_CLEANING_POOL, oldPoolFile.getCanonicalPath());
							}
						}
						lastLoPool = deleteUpTo;
					}
				}
			} catch (Exception e) {
				// Assert.printStack(e);
				MP.printError(EC.SYSTEM_ERROR_CLEANING_POOL, e.getMessage(), e);
				System.exit(1);
			}
		}
	}
	
	private static final class ByteArrayPoolWriter extends Thread {

	    private byte[][] buf;     
	    private File poolFile;           // the file to be written
	    private final ByteArrayPoolReader reader;  // the consumer if not null
	    
	  public ByteArrayPoolWriter(int bufSize, ByteArrayPoolReader reader) {
		  super("RawTLCStatePoolWriter");
	    this.buf = new byte[bufSize][];
	    this.poolFile = null;
	    this.reader = reader;
	  }
	  
	  /*
	   * This method first completes the preceding write if not started.
	   * It then notifies this writer to flush enqBuf to file. In practice,
	   * we expect the preceding write to have been completed. 
	   */
	  public final synchronized byte[][] doWork(byte[][] enqBuf, File file)
	  throws IOException {
	    if (this.poolFile != null) {
	  	  final BufferedDataOutputStream vos = new BufferedDataOutputStream(this.poolFile);
	  	  for (int i = 0; i < this.buf.length; i++) {
	  		  vos.writeInt(this.buf[i].length);
	  		  vos.write(this.buf[i]);
	  	  }
	      vos.close();
	    }
	    byte[][] res = this.buf;
	    this.buf = enqBuf;
	    this.poolFile = file;
	    this.notify();
	    return res;
	  }

	  /* Spin waiting for the write to complete.  */
	  public final void ensureWritten() throws InterruptedException {
	    synchronized(this) {
	      while (this.poolFile != null) {
		this.wait();
	      }
	    }
	  }

	  public final synchronized void beginChkpt(ObjectOutputStream oos)
	  throws IOException {
	    boolean hasFile = (this.poolFile == null) ? false : true;
	    oos.writeBoolean(hasFile);
	    if (hasFile) {
	      oos.writeObject(this.poolFile);
	      for (int i = 0; i < this.buf.length; i++) {
		oos.writeObject(this.buf[i]);
	      }
	    }
	  }

	  /* Note this method is not synchronized.  */
	  public final void recover(ObjectInputStream ois) throws IOException {    
	    boolean hasFile = ois.readBoolean();
	    if (hasFile) {
	      try {
		this.poolFile = (File)ois.readObject();
		for (int i = 0; i < this.buf.length; i++) {
		  this.buf[i] = (byte[])ois.readObject();
		}
	      }
	      catch (ClassNotFoundException e) 
	      {
	          Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e);
	      }
	    }
	    else {
	      this.poolFile = null;
	    }
	  }

	  /**
	   * Write "buf" to "poolFile". The objects in the queue are written
	   * using Java's object serialization facilities.
	   */
	  public void run() {
	    try {
	      synchronized(this) {
		while (true) {
		  while (this.poolFile == null) {
		    this.wait();
		    // we are done without ever receiving a pool file
		    if(this.poolFile == null) {
		    	return;
		    }
		  }
		  final BufferedDataOutputStream vos = new BufferedDataOutputStream(this.poolFile);
		  for (int i = 0; i < this.buf.length; i++) {
			  vos.writeInt(this.buf[i].length);
			  vos.write(this.buf[i]);
		  }
		  vos.close();
		  this.poolFile = null;
		  this.notify();
		  if (this.reader != null) this.reader.wakeup();
		}
	      }
	    }
	    catch (Exception e) {
	      // Assert.printStack(e);
	        MP.printError(EC.SYSTEM_ERROR_WRITING_POOL, e.getMessage(), e);
	      System.exit(1);
	    }
	  }
	}
	
	private static final class ByteArrayPoolReader extends Thread {

		  public ByteArrayPoolReader(int bufSize, File file) {
			  super("RawTLCStatePoolReader");
		    this.buf = new byte[bufSize][];
		    this.poolFile = file;
		    this.isFull = false;
		    this.canRead = false;
		  }
		  
		  private byte[][] buf;
		  private File poolFile;      // the file to be read
		  private boolean isFull;     // true iff the buf is filled
		  private boolean canRead;    // true iff the file can be read
		  private boolean finished = false;

		  public final synchronized void wakeup() {
		    this.canRead = true;
		    this.notify();
		  }

		  public final synchronized void restart(File file, boolean canRead) {
		    this.poolFile = file;
		    this.isFull = false;
		    this.canRead = canRead;
		    this.notify();
		  }
		  
		  /*
		   * In the most common case, this method expects to see the buffer is
		   * full, it returns its buffer and notifies this reader to read the
		   * content of the file.
		   */
		  public final synchronized byte[][] doWork(byte[][] deqBuf, File file)
		  throws IOException, ClassNotFoundException {
		    if (this.isFull) {
		      assert this.poolFile == null : EC.SYSTEM_FILE_NULL;
		      byte[][] res = this.buf;
		      this.buf = deqBuf;
		      this.poolFile = file;
		      this.isFull = false;      // <file, false>
		      this.canRead = true;
		      this.notify();
		      return res;
		    }
		    else if (this.poolFile != null) {
		  	  final BufferedDataInputStream vis = new BufferedDataInputStream(this.poolFile);
		  	  for (int i = 0; i < deqBuf.length; i++) {
		      	  deqBuf[i] = new byte[vis.readInt()];
		      	  vis.read(deqBuf[i]);
		  	  }
		      vis.close();
		      this.poolFile = file;     // <file, false>
		      this.canRead = true;
		      this.notify();
		      return deqBuf;
		    }
		    else {
		  	  final BufferedDataInputStream vis = new BufferedDataInputStream(this.poolFile);
		  	  for (int i = 0; i < deqBuf.length; i++) {
		  		  deqBuf[i] = new byte[vis.readInt()];
		      	  vis.read(deqBuf[i]);
		  	  }
		      vis.close();              // <null, false>
		      return deqBuf;
		    }
		  }

		  /*
		   * Returns the cached buffer if filled. Otherwise, returns null.
		   */
		  public final synchronized byte[][] getCache(byte[][] deqBuf, File file)
		  throws IOException, ClassNotFoundException {
		    if (this.isFull) {
		      assert this.poolFile == null : EC.SYSTEM_FILE_NULL;
		      byte[][] res = this.buf;
		      this.buf = deqBuf;
		      this.poolFile = file;
		      this.isFull = false;      // <file, false>
		      this.canRead = false;
		      return res;
		    }
		    else if (this.poolFile != null && this.canRead) {
		      // this should seldom occur.
		  	  final BufferedDataInputStream vis = new BufferedDataInputStream(this.poolFile);
		  	  for (int i = 0; i < deqBuf.length; i++) {
		  		  deqBuf[i] = new byte[vis.readInt()];
		      	  vis.read(deqBuf[i]);
		      }
		      vis.close();
		      // this.poolFile.delete();
		      this.poolFile = file;    // <file, false>
		      this.canRead = false;
		      return deqBuf;
		    }
		    return null;
		  }

		  public final synchronized void beginChkpt(ObjectOutputStream oos)
		  throws IOException {
		    boolean hasFile = this.poolFile != null;
		    oos.writeBoolean(hasFile);
		    oos.writeBoolean(this.canRead);
		    oos.writeBoolean(this.isFull);
		    if (hasFile) {
		      oos.writeObject(this.poolFile);
		    }
		    if (this.isFull) {
		      for (int i = 0; i < this.buf.length; i++) {
			oos.writeObject(this.buf[i]);
		      }
		    }
		  }

		  /* Note that this method is not synchronized. */
		  public final void recover(ObjectInputStream ois) throws IOException {
		    boolean hasFile = ois.readBoolean();
		    this.canRead = ois.readBoolean();
		    this.isFull = ois.readBoolean();
		    try {
		      if (hasFile) {
			this.poolFile = (File)ois.readObject();
		      }
		      if (this.isFull) {
			for (int i = 0; i < this.buf.length; i++) {
			  this.buf[i] = (byte[])ois.readObject();
			}
		      }
		    }
		    catch (ClassNotFoundException e) 
		    {
		      Assert.fail(EC.SYSTEM_CHECKPOINT_RECOVERY_CORRUPT, e);
		    }
		  }
		  
		  /**
		   * Read the contents of "poolFile" into "buf". The objects in the
		   * file are read using Java's object serialization facilities.
		   */
		  public void run() {
		    try {
		      synchronized(this) {
			while (true) {
			  while (this.poolFile == null || this.isFull || !this.canRead) {
			    this.wait();
			    if(this.finished ) {
			    	return;
			    }
			  }
			  final BufferedDataInputStream vis = new BufferedDataInputStream(this.poolFile);
			  for (int i = 0; i < this.buf.length; i++) {
		    	  this.buf[i] = new byte[vis.readInt()];
		    	  vis.read(this.buf[i]);
			  }
			  vis.close();
			  this.poolFile = null;
			  this.isFull = true;       // <null, true>
			}
		      }
		    }
		    catch (Exception e) 
		    {
		      // Assert.printStack(e);
		      MP.printError(EC.SYSTEM_ERROR_READING_POOL, e.getMessage(), e);
		      System.exit(1);
		    }
		  }
		  
		  public void setFinished() {
			  finished = true;
		  }
	}
	
	static final class ByteValueOutputStream implements IValueOutputStream, IDataOutputStream {

		private byte[] bytes;
		
		private int idx;
		
		public ByteValueOutputStream() {
			this.bytes = new byte[16]; // TLCState "header" already has 6 bytes.
			this.idx = 0;
		}
		
	    private void ensureCapacity(int minCap) {
	        if (minCap - bytes.length > 0) {
	            int oldCap = bytes.length;
	            int newCap = oldCap << 1; // double size
	            if (newCap - minCap < 0) {
	            	newCap = minCap;
	            }
	            bytes = Arrays.copyOf(bytes, newCap);
	        }
	    }

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeShort(short)
		 */
		@Override
		public final void writeShort(short s) throws IOException {
			ensureCapacity(idx + 2);
	        this.bytes[idx++] = (byte) ((s >>> 8) & 0xff);
	        this.bytes[idx++] = (byte) (s & 0xff);
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeInt(int)
		 */
		@Override
		public final void writeInt(int i) throws IOException {
			ensureCapacity(idx + 4);
	        this.bytes[idx++] = (byte) ((i >>> 24) & 0xff);
	        this.bytes[idx++] = (byte) ((i >>> 16) & 0xff);
	        this.bytes[idx++] = (byte) ((i >>> 8) & 0xff);
	        this.bytes[idx++] = (byte) (i & 0xff);
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeLong(long)
		 */
		@Override
		public final void writeLong(long l) throws IOException {
			ensureCapacity(idx + 8);
	        this.bytes[idx++] = (byte) ((l >>> 56) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 48) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 40) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 32) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 24) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 16) & 0xff);
	        this.bytes[idx++] = (byte) ((l >>> 8) & 0xff);
	        this.bytes[idx++] = (byte) (l & 0xff);
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#close()
		 */
		@Override
		public final void close() throws IOException {
			// No-op
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeShortNat(short)
		 */
		@Override
		public final void writeShortNat(short x) throws IOException {
			if (x > 0x7f) {
				this.writeShort((short) -x);
			} else {
				this.writeByte((byte) x);
			}
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeNat(int)
		 */
		@Override
		public final void writeNat(int x) throws IOException {
			if (x > 0x7fff) {
				this.writeInt(-x);
			} else {
				this.writeShort((short) x);
			}
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeLongNat(long)
		 */
		@Override
		public final void writeLongNat(long x) throws IOException {
			if (x <= 0x7fffffff) {
				this.writeInt((int) x);
			} else {
				this.writeLong(-x);
			}
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeByte(byte)
		 */
		@Override
		public final void writeByte(byte b) throws IOException {
			ensureCapacity(idx + 1);
			this.bytes[idx++] = b;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#writeBoolean(boolean)
		 */
		@Override
		public final void writeBoolean(boolean bool) throws IOException {
	        byte b = (bool ? (byte)1 : (byte)0);
	        this.writeByte(b);
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#getOutputStream()
		 */
		@Override
		public final IDataOutputStream getOutputStream() {
			return this;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueOutputStream#put(java.lang.Object)
		 */
		@Override
		public final int put(Object obj) {
			return -1;
		}

		public final byte[] toByteArray() {
			final byte[] copyOf = Arrays.copyOf(bytes, idx);
			idx = 0;
			return copyOf;
		}

		/* (non-Javadoc)
		 * @see util.IDataOutputStream#writeString(java.lang.String)
		 */
		@Override
		public final void writeString(String str) throws IOException {
			final int length = str.length();
			ensureCapacity(idx + length);
			
			final char[] c = new char[length];
			str.getChars(0, length, c, 0);
			
			for (int i = 0; i < c.length; i++) {
				this.bytes[idx++] = (byte) c[i];
			}
		}
	}
	
	static final class ByteValueInputStream implements ValueConstants, IValueInputStream, IDataInputStream {

		private final byte[] bytes;
		
		private int idx = 0;

		public ByteValueInputStream(byte[] bytes) {
			this.bytes = bytes;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#read()
		 */
		@Override
		public final IValue read() throws IOException {
			final byte kind = this.readByte();

			switch (kind) {
			case BOOLVALUE: {
				return (this.readBoolean()) ? BoolValue.ValTrue : BoolValue.ValFalse;
			}
			case INTVALUE: {
				return IntValue.gen(this.readInt());
			}
			case STRINGVALUE: {
				return StringValue.createFrom(this);
			}
			case MODELVALUE: {
				return ModelValue.mvs[this.readShort()];
			}
			case INTERVALVALUE: {
				return new IntervalValue(this.readInt(), this.readInt());
			}
			case RECORDVALUE: {
				return RecordValue.createFrom(this);
			}
			case FCNRCDVALUE: {
				return FcnRcdValue.createFrom(this);
			}
			case SETENUMVALUE: {
				return SetEnumValue.createFrom(this);
			}
			case TUPLEVALUE: {
				return TupleValue.createFrom(this);
			}
			default: {
				throw new WrongInvocationException("ValueInputStream: Can not unpickle a value of kind " + kind);
			}
			}
		}

		private final boolean readBoolean() throws EOFException, IOException {
	        return (bytes[idx++] != 0);
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readShort()
		 */
		@Override
		public final int readShort() throws IOException {
	        return (short) ((bytes[idx++] << 8) | (bytes[idx++] & 0xff));
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readInt()
		 */
		@Override
		public final int readInt() throws IOException {
	        int res = bytes[idx++];
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        return res;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readLong()
		 */
		@Override
		public final long readLong() throws IOException {
	        long res = bytes[idx++];
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        res <<= 8; res |= (bytes[idx++] & 0xff);
	        return res;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#close()
		 */
		@Override
		public final void close() throws IOException {
			// No-op
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readNat()
		 */
		@Override
		public final int readNat() throws IOException {
		    int res = this.readShort();
		    if (res >= 0) return res;
		    res = (res << 16) | (this.readShort() & 0xFFFF);
		    return -res;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readShortNat()
		 */
		@Override
		public final short readShortNat() throws IOException {
			short res = this.readByte();
			if (res >= 0) return res;
			return (short) -((res << 8) | (this.readByte() & 0xFF));
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readLongNat()
		 */
		@Override
		public final long readLongNat() throws IOException {
		    long res = this.readInt();
		    if (res >= 0) return res;
		    res = (res << 32) | ((long)this.readInt() & 0xFFFFFFFFL);
		    return -res;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#readByte()
		 */
		@Override
		public final byte readByte() throws EOFException, IOException {
			return bytes[idx++];
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#assign(java.lang.Object, int)
		 */
		@Override
		public final void assign(Object obj, int idx) {
			// No-op
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#getIndex()
		 */
		@Override
		public final int getIndex() {
			return -1;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#getInputStream()
		 */
		@Override
		public final IDataInputStream getInputStream() {
			return this;
		}

		/* (non-Javadoc)
		 * @see tlc2.value.IValueInputStream#getValue(int)
		 */
		@Override
		public final UniqueString getValue(int idx) {
			throw new WrongInvocationException("Not supported");
		}

		/* (non-Javadoc)
		 * @see util.IDataInputStream#readString(int)
		 */
		@Override
		public final String readString(int length) throws IOException {
			final char[] s = new char[length];
			for (int i = 0; i < s.length; i++) {
				s[i] = (char) this.bytes[idx++];
			}
			return new String(s);
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.queue.IStateQueue#delete()
	 */
	@Override
	public void delete() {
		finishAll();
		new File(this.filePrefix).delete();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/iterator/TLCIterator2Test.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.fp.iterator;

public class TLCIterator2Test extends TLCIteratorTest {

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.iterator.TLCIteratorTest#getBuffer()
	 */
	@Override
	protected long[][] getBuffer() {
		final long[][] buff = new long[8][];
		buff[0] = getArray(8, 1, 8);
		buff[1] = getArray(8, 9, 6);
		buff[2] = null;
		buff[3] = null;
		
		buff[4] = getArray(8, 15, 7); // Bucket with last element
		buff[5] = null;
		
		// Simulate that this bucket is filled with fingerprints who have all
		// been flushed to disk.
		buff[6] = new long[4];
		buff[6][0] = 22L | 0x8000000000000000L;
		buff[6][1] = 0L;
		buff[6][2] = 0L;
		buff[6][3] = 0L;
		
		buff[7] = null;
		return buff;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/preference/AdditionalPreferencesPage.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.tool.prover.ui.preference;

import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;

/**
 * @author lamport
 */
public class AdditionalPreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
    /*
     * The names of the preferences for the user-defined predicates.
     */
    public static final String[] USER_DEFINED_PREDICATE = { "UserDefinedPredicateA", "UserDefinedPredicateB",
            "UserDefinedPredicateC", "UserDefinedPredicateD", "UserDefinedPredicateE", "UserDefinedPredicateF"};
    public static final String[] UPPER_CASE_LETTERS = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L" };

	public AdditionalPreferencesPage() {
        super(GRID);
        setPreferenceStore(ProverUIActivator.getDefault().getPreferenceStore());
        setDescription("User-Defined Color Predicates");
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors()
     */
	protected void createFieldEditors() {
        // To change the number of user-defined predicates, look up all uses of
        // USER_DEFINED_PREDICATE and USER_DEFINED.
        for (int i = 0; i < USER_DEFINED_PREDICATE.length; i++)
        {
            addField(new ColorPredicateFieldEditor(USER_DEFINED_PREDICATE[i],
                    "     Predicate " + UPPER_CASE_LETTERS[i], getFieldEditorParent()));
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
	public void init(IWorkbench workbench) { }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/TLAPMConsoleFactory.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui;

import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleFactory;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.MessageConsole;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Used in the extension point org.eclipse.ui.console.ConsoleFactories
 * for creating a console for the TLAPM.
 * 
 * The method {@link TLAPMConsoleFactory#openConsole()} is specified
 * by the interface and is used to create/open the console.
 * 
 * The method {@link TLAPMConsoleFactory#getTLAPMConsole()} can be used
 * by other class to get the console for the TLAPM.
 * 
 * @author <NAME>
 *
 */
public class TLAPMConsoleFactory implements IConsoleFactory
{

    /**
     * The name used to register the console so that it can
     * later be found using {@link TLAPMConsoleFactory#getTLAPMConsole()}
     */
    private static final String TLAPM_CONSOLE_ID = "TLAPM-Console";

    /**
     * Opens a generic console view using {@link TLAPMConsoleFactory#TLAPM_CONSOLE_ID} as the
     * console name so that it can be found later.
     */
    public void openConsole()
    {
        IWorkbenchPage activePage = UIHelper.getActivePage();
        if (activePage != null)
        {
            try
            {
                activePage.showView(IConsoleConstants.ID_CONSOLE_VIEW, TLAPM_CONSOLE_ID, IWorkbenchPage.VIEW_ACTIVATE);
            } catch (PartInitException e)
            {
                ConsolePlugin.log(e);
            }
        }
    }

    /**
     * Returns a handle on the console for
     * the TLAPM.
     * @return
     */
    public static MessageConsole getTLAPMConsole()
    {
        MessageConsole console = findConsole(TLAPM_CONSOLE_ID);

        return console;
    }

    /**
     * Finds the console with a given name.
     * 
     * @param name, name of the console
     * @return
     */
    private static MessageConsole findConsole(String name)
    {
        if (name == null)
        {
            throw new IllegalArgumentException("Console name must be not null");
        }
        IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager();

        IConsole[] existing = consoleManager.getConsoles();
        // try to find existing
        for (int i = 0; i < existing.length; i++)
        {
            if (name.equals(existing[i].getName()))
            {
                return (MessageConsole) existing[i];
            }
        }

        // no console found, create a new one
        MessageConsole myConsole = new MessageConsole(name, null);
        consoleManager.addConsoles(new IConsole[] { myConsole });
        return myConsole;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/explorer/ExplorerQuitException.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.explorer;

public class ExplorerQuitException extends Exception {
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/GobbleOutput.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS GobbleOutput                                                       *
*                                                                          *
* When you execute a system command with the exec method of the Runtime    *
* class, the output produced by the command is put into a buffer.  If      *
* that buffer fills up, the command hangs waiting for the output to be     *
* read from that buffer.  A GobbleOutput object is used to read that       *
* output from the buffer and throw it away.                                *
*                                                                          *
* A GobbleOutput object is a thread.  The code                             *
*                                                                          *
*    GobbleOutput threadObj = new GobbleOutput(bool, proc, str);           *
*    threadObj.start() ;                                                   *
*                                                                          *
* launches a thread that reads and throws away the output produced         *
* by Process proc on either stdout (if bool = true) or stderr (if          *
* bool = false).  If you're not sure where proc sends its output,          *
* you can launch two threads to read both output streams.                  *
*                                                                          *
* The String str is the name of the command, and is used only for an       *
* error message.                                                           *
***************************************************************************/
package tla2tex ;
import java.io.InputStream;

public class GobbleOutput extends Thread 
 { boolean stdOrError ;  
     /**********************************************************************
     * True  if gobbling stdout                                            *
     * False if gobbling stderr                                            *
     **********************************************************************/
   Process proc ;
   String  cmd ;
   GobbleOutput(boolean stdOrError ,
                Process proc,
                String  cmd)
     {this.stdOrError = stdOrError ;
      this.proc = proc;
      this.cmd  = cmd;
     }
   public void run()
    { InputStream outStream = null;
      if (stdOrError)
        { outStream = proc.getInputStream(); }
       else
        { outStream = proc.getErrorStream(); }
      byte[] readBytes   = new byte[100000] ;
      int outBytes = 1;
      try { while ( outBytes != -1 )
             { outBytes = outStream.read(readBytes); }
          }
      catch (Exception e)
       { Debug.ReportError(
              "Trying to read output for command\n " + cmd +
               "\n produced the following error\n    " + e.getMessage());
       } ;
    }
 }

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/DefStepNode.java<|end_filename|>
// Portions Copyright (c) 2007 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Strings;
import tla2sany.xml.SymbolContext;
import util.UniqueString;

/***************************************************************************
* This class represents definition step of a proof, which consists of a    *
* sequence of operator-, function-, or module-definition steps.  (A        *
* module definition is something like "Id == INSTANCE...".)                *
***************************************************************************/

public class DefStepNode extends LevelNode {

  /*************************************************************************
  * The fields.                                                            *
  *************************************************************************/
  private UniqueString stepNumber ;
    /***********************************************************************
    * The step number of the step if it has one, otherwise null if it's    *
    * not a numbered step.                                                 *
    ***********************************************************************/

  private OpDefNode[] defs ;
    /***********************************************************************
    * The sequence of definitions.                                         *
    ***********************************************************************/

  /*************************************************************************
  * The constructor.                                                       *
  *************************************************************************/
  public DefStepNode(TreeNode stn, UniqueString stepNum, OpDefNode[] theDefs){
    super(DefStepKind, stn);
    this.stepNumber = stepNum;
    this.defs = theDefs;
   }

  /*************************************************************************
  * The methods just return the field values.                              *
  *************************************************************************/
  public UniqueString getStepNumber() {return stepNumber ;}
  public OpDefNode[] getDefs() {return defs;}

  @Override
  public boolean levelCheck(int iter) {
    /***********************************************************************
    * Level check the steps and the instantiated modules coming from       *
    * module definitions.                                                  *
    ***********************************************************************/
    return this.levelCheckSubnodes(iter, defs) ;
   }

  @Override
  public void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;
    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    for (int  i = 0; i < defs.length; i++) {
      defs[i].walkGraph(semNodesTable, visitor);
      } ;
      visitor.postVisit(this);
   }

  @Override
  public SemanticNode[] getChildren() {
      SemanticNode[] res = new SemanticNode[defs.length];
      for (int i = 0; i < defs.length; i++) {
          res[i] = defs[i];
      }
      return res;
   }
  
  @Override
  public String toString(int depth) {
    if (depth <= 0) return "";
    String ret = "\n*DefStepNode:\n"
                  + super.toString(depth)
                  + Strings.indent(2, "\ndefs:") ;
    for (int i = 0 ; i < this.defs.length; i++) {
        ret += Strings.indent(4, this.defs[i].toString(depth-1)) ;
      } ;
    return ret;
   }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
      Element e = doc.createElement("DefStepNode");
      for (int i=0; i<defs.length;i++) {
        e.appendChild(defs[i].export(doc,context));
      }
      return e;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/impl/KSubsetValueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import java.util.stream.IntStream;

import org.junit.Test;

import tlc2.util.Combinatorics;
import tlc2.util.FP64;

public class KSubsetValueTest {
	
	@Test
	public void testEnumerateN32() {
		final IntervalValue iv = new IntervalValue(1, 32);
		assertEquals(32, iv.size());

		final KSubsetValue kSubset = new KSubsetValue(2, iv);
		final SetEnumValue set = (SetEnumValue) kSubset.toSetEnum();
		assertEquals(496, set.size());
		Value[] array = set.elems.toArray();
		for (int i = 0; i < array.length; i++) {
			assertNotNull(array[i]);
			assertEquals(2, array[i].size());
		}
	}
	
	@Test
	public void testEnumerateN33() {
		final IntervalValue iv = new IntervalValue(1, 33);
		assertEquals(33, iv.size()); // Larger than Int/32 bits!

		final KSubsetValue kSubset = new KSubsetValue(2, iv);
		final SetEnumValue set = (SetEnumValue) kSubset.toSetEnum();
		assertEquals(528, set.size());
		Value[] array = set.elems.toArray();
		for (int i = 0; i < array.length; i++) {
			assertNotNull(array[i]);
			assertEquals(2, array[i].size());
		}
	}
	
	@Test
	public void testEnumerateN63() {
		final IntervalValue iv = new IntervalValue(1, 63);
		assertEquals(63, iv.size());

		final KSubsetValue kSubset = new KSubsetValue(2, iv);
		final SetEnumValue set = (SetEnumValue) kSubset.toSetEnum();
		assertEquals(1953, set.size());
		Value[] array = set.elems.toArray();
		for (int i = 0; i < array.length; i++) {
			assertNotNull(array[i]);
			assertEquals(2, array[i].size());
		}
	}
	
	@Test
	public void testEnumerateN64() {
		final IntervalValue iv = new IntervalValue(1, 64);
		assertEquals(64, iv.size());
		try {
			new KSubsetValue(42, iv).toSetEnum();
		} catch (IllegalArgumentException e) {
			return;
		}
		fail();
	}
	
	@Test
	public void testNormalization() {
		final ValueVec vals = new ValueVec();
		vals.addElement(IntValue.gen(1));
		vals.addElement(IntValue.gen(7));
		vals.addElement(IntValue.gen(42));
		vals.addElement(IntValue.gen(42));
		vals.addElement(IntValue.gen(23));
		final Value set = new SetEnumValue(vals, false);
		
		final KSubsetValue kSubset = new KSubsetValue(2, set);
		assertEquals(6, kSubset.size());
		
		final ValueEnumeration elements = kSubset.elements();
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(1), IntValue.gen(7) }, false), elements.nextElement());
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(1), IntValue.gen(23) }, false), elements.nextElement());
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(7), IntValue.gen(23) }, false), elements.nextElement());
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(1), IntValue.gen(42) }, false), elements.nextElement());
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(7), IntValue.gen(42) }, false), elements.nextElement());
		assertEquals(new SetEnumValue(new Value[] { IntValue.gen(23), IntValue.gen(42) }, false), elements.nextElement());
		assertNull(elements.nextElement());
	}

	private void doTest(final IntStream ints, final IntervalValue iv) {
		ints.forEach(i -> {
			final long expectedSize = Combinatorics.choose(iv.size(), i);

			final KSubsetValue kSubset = new KSubsetValue(i, iv);
			
			// Assert expected size before fingerprint and normalization.
			assertEquals(expectedSize, kSubset.size());
			
			// Check that fingerprint doesn't throw an exception.
			kSubset.fingerPrint(FP64.Zero);
			
			// Assert expected size after fingerprinting and normalization.
			assertEquals(expectedSize, kSubset.size());
			
			// Check if explicit enumeration of elements generates all elements.
			assertEquals(expectedSize, kSubset.toSetEnum().size());
		});
	}

	@Test
	public void testKSubsetFingerprintingS009() {
		doTest(IntStream.of(1, 9), new IntervalValue(1, 9));
	}

	@Test
	public void testKSubsetFingerprintingS032() {
		// In-between ks take too long, cause OOM or overflow exceptions.
		doTest(IntStream.of(1, 2, 3, 4, 5, 28, 29, 30, 31, 32), new IntervalValue(1, 32));
	}


	@Test
	public void testKSubsetFingerprintingS033() {
		// In-between ks take too long, cause OOM or overflow exceptions.
		doTest(IntStream.of(1, 2, 3, 4, 5, 29, 30, 31, 32, 33), new IntervalValue(1, 33));
	}

	@Test
	public void testKSubsetFingerprintingS063() {
		// In-between ks take too long, cause OOM or overflow exceptions.
		doTest(IntStream.of(1, 2, 3, 4, 60, 61, 62, 63), new IntervalValue(1, 63));
	}
}
/*

Assuming the definition of kSubset would be part of TLC, not the
CommunityModules, we would write a test for the following spec.

---- MODULE Github611 ----
EXTENDS FiniteSetsExt, FiniteSets, Naturals, TLC

ASSUME 50..150 \in kSubset(6, 1..200)

GenerateKSets ==
	kSubset(2, 1..63)

GenerateFilteredKSets ==
	{s \in GenerateKSets : Cardinality(s) = 2}

ASSUME GenerateKSets = GenerateFilteredKSets
 
S ==
	kSubset(2, 1..63)

VARIABLES a,b,c,d,e,f
vars == <<a,b,c,d,e,f>>

Init ==
	/\ a = kSubset(2, 1..63)
	/\ b = kSubset(4, 1..63)
	/\ c = kSubset(59, 1..63)
	/\ d = kSubset(61, 1..63)
	/\ e = S
	/\ f = GenerateFilteredKSets
	/\ PrintT(Cardinality(e))
	/\ PrintT(Cardinality(f))
	
Next ==
	UNCHANGED vars

Inv ==
	/\ Cardinality(a) = 1953 
	/\ Cardinality(b) = 595665 
	/\ Cardinality(c) = 595665 
	/\ Cardinality(d) = 1953 
	/\ Cardinality(e) = 1953
	/\ Cardinality(f) = 1953 

====

---- CONFIG Github611 ----
INIT Init
NEXT Next
INVARIANT Inv
====
*/

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/wizard/FormulaWizardPage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.wizard;

import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.editor.basic.TLAFastPartitioner;
import org.lamport.tla.toolbox.editor.basic.TLAPartitionScanner;
import org.lamport.tla.toolbox.editor.basic.TLASourceViewerConfiguration;
import org.lamport.tla.toolbox.tool.tlc.ui.util.FormHelper;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * A page with a simple field for formula editing
 * @author <NAME>
 */
public class FormulaWizardPage extends WizardPage
{
    private SourceViewer sourceViewer;
    private Document document;
	private final String extendedDescription;
	private final String helpId;

    public FormulaWizardPage(String action, String description)
    {
        this(action, description, null, null);
    }
    
    public FormulaWizardPage(String action, String description, String extendedDescription, String helpId)
    {
        super("FormulaWizardPage");
        setTitle(action);
        setDescription(description);
        this.extendedDescription = extendedDescription;
        this.helpId = helpId;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent)
    {
    	
        Composite container = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout(1, false);
        container.setLayout(layout);
        
        if (helpId != null) {
        	UIHelper.setHelp(container, helpId);
        }
        
		sourceViewer = FormHelper.createSourceViewer(container, SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL,
				new TLASourceViewerConfiguration());
		sourceViewer.getTextWidget().addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (isUndoKeyPress(e)) {
					sourceViewer.doOperation(ITextOperationTarget.UNDO);
				} else if (isRedoKeyPress(e)) {
					sourceViewer.doOperation(ITextOperationTarget.REDO);
				}
			}

			private boolean isRedoKeyPress(KeyEvent e) {
				return ((e.stateMask & SWT.CONTROL) > 0) && ((e.keyCode == 'y') || (e.keyCode == 'Y'));
			}

			private boolean isUndoKeyPress(KeyEvent e) {
				return ((e.stateMask & SWT.CONTROL) > 0) && ((e.keyCode == 'z') || (e.keyCode =='Z'));
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}
		});

        // SWT.FILL causes the text field to expand and contract
        // with changes in size of the dialog window.
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        gd.heightHint = 200;
        gd.widthHint = 400;
        gd.grabExcessHorizontalSpace = true;
        gd.grabExcessVerticalSpace = true;

        StyledText control = sourceViewer.getTextWidget();
        control.addModifyListener(new ModifyListener() {

            public void modifyText(ModifyEvent e)
            {
                getContainer().updateButtons();
            }

        });
        control.setEditable(true);
        control.setLayoutData(gd);

    

        if (this.document == null)
        {
            this.document = new Document();
        }
		final IDocumentPartitioner partitioner = new TLAFastPartitioner(
				TLAEditorActivator.getDefault().getTLAPartitionScanner(), TLAPartitionScanner.TLA_PARTITION_TYPES);
		document.setDocumentPartitioner(TLAPartitionScanner.TLA_PARTITIONING, partitioner);
		partitioner.connect(document);
        sourceViewer.setDocument(this.getDocument());

        
        // Add extended description below source viewer if given.
        if (extendedDescription != null) {
        	final Label extendedLbl = new Label(container, SWT.WRAP);
        	extendedLbl.setText(extendedDescription);
			gd = new GridData(GridData.FILL_HORIZONTAL);
			gd.widthHint = 400; // same width as source viewer
			extendedLbl.setLayoutData(gd);
        }

        setControl(container);
    }

    public Document getDocument()
    {
        return this.document;
    }

    public void setDocument(Document document)
    {
        this.document = document;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/DebugPrinter.java<|end_filename|>
package util;

import tlc2.TLCGlobals;

/**
 * Debugging helper
 * @author <NAME>
 * @version $Id$
 */
public class DebugPrinter
{
    /**
     * Prints out a message if the program has been called with -debug option 
     * @param message
     */
    public static void print(String message)
    {
        if (TLCGlobals.debug) 
        {
            System.out.println(Thread.currentThread().getId() + "\t" + message);
        }
    }

    /**
     * Exception stacktrace printer
     * @param e
     */
    public static void print(Throwable e)
    {
        if (TLCGlobals.debug) 
        {
            System.err.println(Thread.currentThread().getId() + "thrown an exception");
            e.printStackTrace(System.err);
        }
    }

    
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/TraceExpressionSpecTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2;

import java.util.Date;

import org.junit.Test;

import tlc2.tool.impl.FastTool;
import tlc2.tool.impl.Tool;
import tlc2.tool.liveness.ModelCheckerTestCase;
import util.FilenameToStream;
import util.SimpleFilenameToStream;

public abstract class TraceExpressionSpecTest extends ModelCheckerTestCase {

	private static final String OUTPUT_PATH = "states"; // Rest of tests dump stuff here.

	public TraceExpressionSpecTest(final String specName, final String configName, String mode, int exitStatus) {
		this(specName, "TESpecTest", configName, mode, exitStatus);
	}

	public TraceExpressionSpecTest(final String specName, final String path, final String configName, String mode, int exitStatus) {
		super(specName, path,
				new String[] { "-generateSpecTE", "-config", configName, "-teSpecOutDir", OUTPUT_PATH, mode },
				exitStatus);
	}

	protected FilenameToStream getResolver() {
		return new SimpleFilenameToStream(OUTPUT_PATH);
	}

	@Override
	protected boolean doCoverage() {
		return false;
	}

	@Override
	protected boolean doDump() {
		return false;
	}

	@Override
	protected boolean noGenerateSpec() {
		return false;
	}

	@Test
	public void testSpec() throws Exception {
		final Date timestamp = new Date(tlc.getStartTime());
		final String traceSpecName = TraceExplorationSpec.deriveTESpecModuleName(spec, timestamp);
		doTest(new FastTool(traceSpecName, traceSpecName + ".tla", tlc.getResolver()), TraceExplorationSpec.teModuleId(timestamp));
	}

	protected abstract void doTest(Tool tool, final String id) throws Exception;
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/TLAMarkerHelper.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import java.util.Vector;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.ui.handler.OpenSpecHandler;

import pcal.TLAtoPCalMapping;
import tla2sany.st.Location;

/**
 * Marker helpers
 * @author <NAME>
 * @version $Id$
 */
public class TLAMarkerHelper
{
    /**
     * End column of the error as reported by SANY
     */
    public static final String LOCATION_ENDCOLUMN = "toolbox.location.endcolumn";
    /**
     * End line of the error as reported by SANY
     */
    public static final String LOCATION_ENDLINE = "toolbox.location.endline";
    /**
     * Begin column of the error as reported by SANY
     */
    public static final String LOCATION_BEGINCOLUMN = "toolbox.location.begincolumn";
    /**
     * Begin line of the error as reported by SANY
     */
    public static final String LOCATION_BEGINLINE = "toolbox.location.beginline";
    /**
     * Module name (different from the generally use filename)
     */
    public static final String LOCATION_MODULENAME = "toolbox.location.modulename";
    /**
     * {@link Location} the {@link IMarker} is a marker for 
     */
    public static final String LOCATION = "toolbox.region";

    /**
     * Supertype for all problem markers
     */
    public static final String TOOLBOX_MARKERS_ALL_MARKER_ID = "toolbox.markers.ToolboxProblemMarker";
    /**
     * The marker ID for displaying TLA+ Parser Errors
     */
    public static final String TOOLBOX_MARKERS_TLAPARSER_MARKER_ID = "toolbox.markers.TLAParserProblemMarker";
    /**
     * The marker ID for displaying PCal Translation Errors
     */
    public static final String TOOLBOX_MARKERS_TRANSLATOR_MARKER_ID = "toolbox.markers.PCalTranslatorProblemMarker";

    /**
     * Installs a SANY problem marker on a given resource
     * REFACTOR: remove runable....
     * @param resource resource handle to put the marker on
     * @param moduleName name of the module (usually the resource, but if module not found, the resource will be the project)
     * @param severityError one of the marker severity constants
     * @param coordinates 4 integer numbers (beginline, begincolumn, endline, endcolumn) 
     * @param message message of the marker
     * @param monitor monitor for progress 
     * @param type marker type: {@link TLAMarkerHelper#TOOLBOX_MARKERS_TLAPARSER_MARKER_ID} or {@link TLAMarkerHelper#TOOLBOX_MARKERS_TRANSLATOR_MARKER_ID} 
     */
    public static void installProblemMarker(final IResource resource, final String moduleName, final int severityError,
            final int[] coordinates, final String message, IProgressMonitor monitor, final String type)
    {
        Assert.isNotNull(resource);
        Assert.isNotNull(moduleName);
        Assert.isNotNull(coordinates);

        IWorkspaceRunnable runnable = new IWorkspaceRunnable() {

            public void run(IProgressMonitor monitor) throws CoreException
            {
                IMarker marker = null;
                if (!resource.exists())
                {
                    // the resource will not exist if the problem is in a standard module
                    // in this case putting the marker on the project is an acceptable
                    // solution
                    // this will raise the error view, but clicking on the error will
                    // do nothing, which is the desired behavior
                    if (Activator.isSpecManagerInstantiated() && Activator.getSpecManager().getSpecLoaded() != null
                            && Activator.getSpecManager().getSpecLoaded().getProject() != null)
                    {
                        IProject project = Activator.getSpecManager().getSpecLoaded().getProject();
                        marker = project.createMarker(type);
                        /* The marker is being installed on the project
                         * so the location of the error does not make sense
                         * This is indicated by setting all of the
                         * coordinates to -1.
                         */
                        for (int i = 0; i < coordinates.length; i++)
                        {
                            coordinates[i] = -1;
                        }
                    } else
                    {
                        return;
                    }
                } else
                {
                    marker = resource.createMarker(type);
                }
                // Once we have a marker object, we can set its attributes
                marker.setAttribute(IMarker.SEVERITY, severityError);
                marker.setAttribute(IMarker.MESSAGE, message);
                marker.setAttribute(IMarker.LOCATION, AdapterFactory.getFormattedLocation(coordinates, moduleName));

                marker.setAttribute(LOCATION_MODULENAME, moduleName);
                marker.setAttribute(LOCATION_BEGINLINE, coordinates[0]);
                marker.setAttribute(LOCATION_BEGINCOLUMN, coordinates[1]);
                marker.setAttribute(LOCATION_ENDLINE, coordinates[2]);
                marker.setAttribute(LOCATION_ENDCOLUMN, coordinates[3]);
                
                // Create a SANY location from the given location attributes
				marker.setAttribute(LOCATION, new Location(coordinates));
                
                final IMarker fMarker = marker;

                // important! either use line numbers (for creation of a single line marker)
                // or char_start/char_end (to create exact markers, even multi-line)
                UIHelper.runUISync(new Runnable() {
					/* (non-Javadoc)
					 * @see java.lang.Runnable#run()
					 */
					public void run() {
						try {
							
							if (coordinates[0] == coordinates[3] || coordinates[3] == -1)
							{
								fMarker.setAttribute(IMarker.LINE_NUMBER, coordinates[0]);
							} else
							{
								// retrieve the resource
								IDocument document = null;
								
								// since we know that the editor uses file based editor representation
								FileEditorInput fileEditorInput = new FileEditorInput((IFile) resource);
								FileDocumentProvider fileDocumentProvider = new LegacyFileDocumentProvider();
								try
								{
									fileDocumentProvider.connect(fileEditorInput);
									document = fileDocumentProvider.getDocument(fileEditorInput);
								} finally
								{
									/*
									 * Once the document has been retrieved, the document provider is
									 * not needed. Always disconnect it to avoid a memory leak.
									 * 
									 * Keeping it connected only seems to provide synchronization of
									 * the document with file changes. That is not necessary in this context.
									 */
									fileDocumentProvider.disconnect(fileEditorInput);
								}
								if (document != null)
								{
									try
									{
										// find the line in the document
										IRegion lineRegion = document.getLineInformation(coordinates[0] - 1);
										
										// get the text representation of the line
										String textLine = document.get(lineRegion.getOffset(), lineRegion.getLength());
										
										fMarker.setAttribute(IMarker.CHAR_START, lineRegion.getOffset()
												+ getRealOffset(textLine, coordinates[1] - 1));
										fMarker.setAttribute(IMarker.CHAR_END, lineRegion.getOffset()
												+ getRealOffset(textLine, coordinates[3]));
										
									} catch (BadLocationException e)
									{
										Activator.getDefault().logError("Error accessing the specified error location", e);
									}
								}
						}
		                } catch (CoreException e) {
							Activator.getDefault().logError("Error accessing the specified error location", e);
		                }
					}
                });
            }
        };
        try
        {
            resource.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, monitor);
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error installing the problem markers", e);
        }

    }

    /**
     * Delete all markers from this resource and all child resources
     * @param resource resource containing markers
     * @param monitor
     * @param type, marker to delete 
     */
    public static void removeProblemMarkers(final IResource resource, final IProgressMonitor monitor, final String type)
    {
        IWorkspaceRunnable runnable = new IWorkspaceRunnable() {

            public void run(IProgressMonitor monitor) throws CoreException
            {
                IMarker[] problems = null;
                int depth = IResource.DEPTH_INFINITE;
                problems = resource.findMarkers(type, true, depth);
                for (int i = 0; i < problems.length; i++)
                {
                    problems[i].delete();
                }
            }
        };

        try
        {
            resource.getWorkspace().run(runnable, monitor);
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error removing the problem markers", e);
        }
    }

    /**
     * Convenience method to delete all types of markers
     */
    public static void removeProblemMarkers(final IResource resource, final IProgressMonitor monitor)
    {
        removeProblemMarkers(resource, monitor, TLAMarkerHelper.TOOLBOX_MARKERS_TLAPARSER_MARKER_ID);
    }

    /**
     * Retrieves problem markers associated with given resource
     * @param resource
     * @param monitor
     * @return
     */
    public static IMarker[] getProblemMarkers(final IResource resource, final IProgressMonitor monitor)
    {
        IMarker[] problems = null;
        try
        {
            problems = resource.findMarkers(TLAMarkerHelper.TOOLBOX_MARKERS_ALL_MARKER_ID, true,
                    IResource.DEPTH_INFINITE);
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error retrieving the problem markers", e);
            problems = new IMarker[0];
        }
        return problems;
    }

    /**
     * Calculates the offset in a particular line
     * @param line
     * @param offset
     * @return
     */
    public static int getRealOffset(String line, int offset)
    {
        if (line.indexOf("\t") != -1)
        {
            /*
             TODO this is ugly.. the users should not use tabs
             
              
             
            // TODO handle this different, read from the editor settings
            int TAB_WIDTH = 8;
            int realOffset = offset;
            int modificator = 0;
            // tab is inside the line
            for (int i = 0; i != -1; i = line.indexOf("\t", i + 1))
            {
                if (i < offset)
                {

                    int tabLength = ((i + modificator) / TAB_WIDTH + 1) * TAB_WIDTH - (i + modificator);
                    modificator += (tabLength - 1);
                    realOffset = realOffset - (tabLength - 1);
                }
            }
            return realOffset;
            */
        }

        return Math.min(offset, line.length());

    }

    /**
     * @see TLAMarkerHelper#gotoMarker(IMarker, boolean)
     */
    public static void gotoMarker(IMarker problem)
    {
    	gotoMarker(problem, false);
    }
    
    /**
     * Opens the TLA+ Editor and goes to the marker
     * @param problem
     * @param jumpToPcal 
     */
    public static void gotoMarker(IMarker problem, boolean jumpToPcal)
    {
        if (problem.getResource() instanceof IFile)
        {
            IFile module = (IFile) problem.getResource();
            IEditorPart part = UIHelper.openEditor(OpenSpecHandler.TLA_EDITOR, new FileEditorInput(module));
            IGotoMarker gotoMarker = null;
            if (part instanceof IGotoMarker)
            {
                gotoMarker = (IGotoMarker) part;
            } else
            {
                gotoMarker = (IGotoMarker) part.getAdapter(IGotoMarker.class);
            }
            if (gotoMarker != null)
            {
            	if (jumpToPcal) {
            		final String moduleName = module.getName();
            		final TLAtoPCalMapping mapping = ToolboxHandle.getCurrentSpec().getTpMapping(moduleName);
            		if (mapping != null) {
            			problem = new TLAtoPCalMarker(problem, mapping);
            		} else {
            			UIHelper.setStatusLineMessage("No valid TLA to PCal mapping found for current selection");
            			return;
            		}
            	}
                gotoMarker.gotoMarker(problem);
            }
        } else
        {
            // nothing to open
        }
    }

    /**
     * Convenience method that determines if the current spec has problems
     * @return true, if current spec project contain problem markers
     */
    public static boolean currentSpecHasProblems()
    {
        Spec spec = Activator.getSpecManager().getSpecLoaded();
        if (spec == null)
        {
            return false;
        }
        return (TLAMarkerHelper.getProblemMarkers(spec.getProject(), null).length > 0);
    }

    /**
     * @param problem
     * @return
     */
    public static String getType(IMarker problem)
    {
        try
        {
            return problem.getType();
        } catch (CoreException e)
        {
            Activator.getDefault().logError("Error retriving marker type", e);
        }
        return null;
    }

    /**
     * Installs the error markers from the vector of MarkerInformationHolders
     * @param detectedErrors
     */
    public static void installProblemMarkers(Vector<TLAMarkerInformationHolder> detectedErrors, IProgressMonitor monitor)
    {
        if (detectedErrors == null || detectedErrors.isEmpty())
        {
            return;
        }

        for (int i = 0; i < detectedErrors.size(); i++)
        {
            TLAMarkerInformationHolder holder = (TLAMarkerInformationHolder) detectedErrors.get(i);
            installProblemMarker(holder.resource, holder.moduleName, holder.severityError, holder.coordinates,
                    holder.message, monitor, holder.type);
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test-concurrent/tlc2/tool/fp/ConcurrentWriteTest.java<|end_filename|>
// Copyright (c) 2016 <NAME>. All rights reserved.
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.Test;

import tlc2.util.BufferedRandomAccessFile;

public class ConcurrentWriteTest {
	@Test
	public void test() throws IOException {
		final File tempFile = File.createTempFile("ConcurrentWriteTest_test", ".bin");
		
		RandomAccessFile tmpRAF0 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF0.setLength(4000L * Long.BYTES);
		for(long i = 0L; i < 1000; i++) {
			tmpRAF0.writeLong(i);
		}
		
		for(long i = 1000L; i < 2000; i++) {
			tmpRAF0.writeLong(i);
		}
		
		for(long i = 2000L; i < 3000; i++) {
			tmpRAF0.writeLong(i);
		}
		
		for(long i = 3000L; i < 4000; i++) {
			tmpRAF0.writeLong(i);
		}
		
		tmpRAF0.close();
		
		final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "r");
		for(long i = 0L; i < 4000; i++) {
			assertEquals(i, tmpRAF.readLong());
		}
		tmpRAF.close();
	}

	@Test
	public void test1() throws IOException {
		final File tempFile = File.createTempFile("ConcurrentWriteTest_test1", ".bin");
		final long limit = 4000000L;
		final long partition = limit / 4L;
		
		final RandomAccessFile tmpRAF0 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF0.setLength(limit * Long.BYTES);
		for(long i = 0L; i < partition; i++) {
			tmpRAF0.writeLong(i);
		}
		
		final RandomAccessFile tmpRAF1 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF1.setLength(limit * Long.BYTES);
		tmpRAF1.seek(partition * Long.BYTES);
		for (long i = partition; i < (2L * partition); i++) {
			tmpRAF1.writeLong(i);
		}

		final RandomAccessFile tmpRAF2 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF2.setLength(limit * Long.BYTES);
		tmpRAF2.seek((2L * partition) * Long.BYTES);
		for (long i = (2L * partition); i < (3L * partition); i++) {
			tmpRAF2.writeLong(i);
		}

		final RandomAccessFile tmpRAF3 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF3.setLength(limit * Long.BYTES);
		tmpRAF3.seek((3L * partition) * Long.BYTES);
		for (long i = (3L * partition); i < (4L * partition); i++) {
			tmpRAF3.writeLong(i);
		}
		
		tmpRAF0.close();
		tmpRAF1.close();
		tmpRAF2.close();
		tmpRAF3.close();
		
		final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "r");
		for(long i = 0L; i < limit; i++) {
			assertEquals(i, tmpRAF.readLong());
		}
		tmpRAF.close();
	}
	
	@Test
	public void test2() throws IOException {
		final File tempFile = File.createTempFile("ConcurrentWriteTest_test2", ".bin");
		final long limit = 4000000L;
		final long partition = limit / 4L;
		
		final RandomAccessFile tmpRAF0 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF0.setLength(limit * Long.BYTES);

		final RandomAccessFile tmpRAF1 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF1.setLength(limit * Long.BYTES);
		tmpRAF1.seek(partition * Long.BYTES);

		final RandomAccessFile tmpRAF2 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF2.setLength(limit * Long.BYTES);
		tmpRAF2.seek((2L * partition) * Long.BYTES);

		final RandomAccessFile tmpRAF3 = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF3.setLength(limit * Long.BYTES);
		tmpRAF3.seek((3L * partition) * Long.BYTES);

		for(long i = 0L; i < (1L * partition); i++) {
			tmpRAF0.writeLong(i);
		}
		
		for(long i = (1L * partition); i < (2L * partition); i++) {
			tmpRAF1.writeLong(i);
		}
		
		for(long i = (2L * partition); i < (3L * partition); i++) {
			tmpRAF2.writeLong(i);
		}
		
		for(long i = (3L * partition); i < (4L * partition); i++) {
			tmpRAF3.writeLong(i);
		}
		
		tmpRAF0.close();
		tmpRAF1.close();
		tmpRAF2.close();
		tmpRAF3.close();
		
		final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "r");
		for(long i = 0L; i < limit; i++) {
			assertEquals(i, tmpRAF.readLong());
		}
		tmpRAF.close();
	}
	
	@Test
	public void test3() throws IOException, InterruptedException {
		final File tempFile = File.createTempFile("ConcurrentWriteTest_test3", ".bin");
		final long limit = 400000000L;
		final long writers = 8L;
		final long partition = limit / writers;

		final Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>>((int) writers);
		for (long i = 0L; i < writers; i++) {
			final long id = i;
			tasks.add(new Callable<Void>() {
				public Void call() throws Exception {
					final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "rw");
					tmpRAF.setLength(limit * Long.BYTES);
					tmpRAF.seek(id * partition * Long.BYTES);

					for (long j = (id * partition); j < ((id + 1) * partition); j++) {
						tmpRAF.writeLong(j);
					}

					tmpRAF.close();
					return null;
				}
			});
		}
		
		final ExecutorService executorService = Executors.newFixedThreadPool((int) writers);
		executorService.invokeAll(tasks);
		executorService.shutdown();

		final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "r");
		for(long i = 0L; i < limit; i++) {
			assertEquals(i, tmpRAF.readLong());
		}
		tmpRAF.close();
	}

	@Test
	public void test4() throws IOException, InterruptedException {
		final File tempFile = File.createTempFile("ConcurrentWriteTest_test4", ".bin");
		final long limit = 400000000L;
		final long writers = 8L;
		final long partition = limit / writers;
		final RandomAccessFile tmpRAF = new BufferedRandomAccessFile(tempFile, "rw");
		tmpRAF.setLength(limit * Long.BYTES);
		final FileChannel channel = tmpRAF.getChannel();

		final Collection<Callable<Void>> tasks = new ArrayList<Callable<Void>>((int) writers);
		for (long i = 0L; i < writers; i++) {
			final long id = i;
			tasks.add(new Callable<Void>() {
				public Void call() throws Exception {
					long position = id * partition * Long.BYTES;
					final ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES/* * 1024*/);
					for (long j = (id * partition); j < ((id + 1) * partition); j++/*j+=1024L*/) {
//						for (int i = 0; i < buffer.capacity(); i++) {
							buffer.putLong(j/* + i*/);
							buffer.flip();
//						}
						channel.write(buffer, position + (j * Long.BYTES));
						buffer.clear();
					}
					channel.force(false);
					return null;
				}
			});
		};
		
		final ExecutorService executorService = Executors.newFixedThreadPool((int) writers);
		executorService.invokeAll(tasks);
		executorService.shutdown();
		
		tmpRAF.close();	

		final BufferedRandomAccessFile checkRaf = new BufferedRandomAccessFile(tempFile, "r");
		for(long i = 0L; i < limit; i++) {
			assertEquals(i, checkRaf.readLong());
		}
		checkRaf.close();
	}
}


<|start_filename|>general/tests/testlist.cmd<|end_filename|>
@set CLASSPATH=../../tlatools/class
@set TLC=java -Xmx100m tlc2.TLC -cleanup 
@set SANY=java tla2sany.SANY
 
%TLC% test1
%TLC% test2
%TLC% test3
%TLC% test4
%TLC% test5
%TLC% test6
%TLC% test7
%TLC% test8
%TLC% test9
%TLC% test10
%TLC% test11
%TLC% test12
%TLC% test13
%TLC% test14
%TLC% test15
%TLC% test16
%TLC% test17
%TLC% test18
%TLC% test19
%TLC% test20
%TLC% test21
%TLC% test22
%TLC% test23
%TLC% test24
%TLC% test25
%TLC% test26
%TLC% test27
%TLC% test28
%TLC% test29
%TLC% test30
%TLC% test31
%TLC% test32
%TLC% test33
%TLC% test34
%TLC% test35
%TLC% test36
%TLC% test37
%TLC% test38
%TLC% test39
%TLC% test40
%TLC% test41
%TLC% test42
%TLC% test43
%TLC% test44
%TLC% test45
%TLC% test46
%TLC% test47
%TLC% test48
%TLC% test49
%TLC% test50
%TLC% test51
%TLC% test52
%TLC% test53
%TLC% test54
%TLC% test55
%TLC% test56
%TLC% test57
%TLC% test58
%TLC% test59
%TLC% test60
%TLC% test61
%TLC% test62
%TLC% test201
%TLC% test202
%TLC% test203
%TLC% test204
%TLC% test205
%TLC% test206
%TLC% test207
%TLC% test208
%TLC% test209
%SANY% test210
%SANY% test211

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/NumeralNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.math.BigInteger;
import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import tla2sany.explorer.ExploreNode;
import tla2sany.explorer.ExplorerVisitor;
import tla2sany.st.TreeNode;
import tla2sany.xml.SymbolContext;

/**
 * Describes a numeral like 4095.  This number is represented by the
 * values
 *
 *   int val()          = 4095
 *   BigInteger bigVal() = null
 *
 * However, if the number is too big to be represented as an
 * integer, then its value is bigVal() and the value of val() is
 * meaningless.
 */
public class NumeralNode extends ExprNode {

  private int value;
  private BigInteger bigValue = null;
  private String image;

  /**
   * The following method was modified by LL on 20 Jul 2011 to handle
   * \b, \o, and \h numbers.
   *
   * @param s
   * @param stn
   * @throws AbortException
   */
  public NumeralNode( String s, TreeNode stn ) throws AbortException {
    super(NumeralKind, stn);
    this.image = s;
    String num = s.toLowerCase();
    int radix = 10;
    if (num.charAt(0)=='\\') {
     if (num.charAt(1)=='b') {
    	 radix = 2;
     } else if (num.charAt(1)=='o') {
    	 radix = 8;
     } else if (num.charAt(1)=='h') {
    	 radix = 16;
     } else {
    	 throw new AbortException();  // This shouldn't happen.
     }
     num = num.substring(2);
    }
    try {

      this.value = Integer.parseInt( num, radix );
    } catch ( NumberFormatException e ) {
      this.bigValue = new BigInteger( s, radix );
    }
  }

  public final int val() { return this.value; }

  public final BigInteger bigVal() { return this.bigValue; }
  
  	/**
	 * @return true if the numerical value of this instance should be referenced via
	 *         {@link #val()}, false if it should be referenced via
	 *         {@link #bigVal()}
	 */
  public final boolean useVal() {
	  return (bigValue == null);
  }

  /**
   * Returns the value as a string--for example, "4095".  This string
   * reflects how the value appeared in the input, so it should be
   * "\O7777" if that's what appears in the source.
   */
  @Override
  public final String toString() { return this.image; }

  /* Level Checking */
  @Override
  public final boolean levelCheck(int iter) {
    levelChecked = iter;
      /*********************************************************************
      * Set it just to show that levelCHeck was called.                    *
      *********************************************************************/
    return true;
  }

//  public final int getLevel() { return ConstantLevel; }
//
//  public final HashSet getLevelParams() { return EmptySet; }
//
//  public final SetOfLevelConstraints getLevelConstraints() {
//    return EmptyLC;
//  }
//
//  public final SetOfArgLevelConstraints getArgLevelConstraints() {
//    return EmptyALC;
//  }
//
//  public final HashSet getArgLevelParams() { return EmptySet; }

  /**
   * toString, levelDataToString, and walkGraph methods to implement
   * ExploreNode interface
   */
//  public final String levelDataToString() {
//    return "Level: "               + this.getLevel()               + "\n" +
//           "LevelParameters: "     + this.getLevelParams()         + "\n" +
//           "LevelConstraints: "    + this.getLevelConstraints()    + "\n" +
//           "ArgLevelConstraints: " + this.getArgLevelConstraints() + "\n" +
//           "ArgLevelParams: "      + this.getArgLevelParams()      + "\n" ;
//  }

  @Override
  public final void walkGraph(Hashtable<Integer, ExploreNode> semNodesTable, ExplorerVisitor visitor) {
    Integer uid = Integer.valueOf(myUID);
    if (semNodesTable.get(uid) != null) return;

    semNodesTable.put(uid, this);
    visitor.preVisit(this);
    visitor.postVisit(this);
  }

  @Override
  public final String toString(int depth) {
    if (depth <= 0) return "";

    return("\n*NumeralNode: " + super.toString(depth) + " Value: " + value +
	   (bigValue != null ? ("; big value: " + bigValue.toString()) : "") +
	   "; image: " + image);
  }

  @Override
  protected Element getLevelElement(Document doc, SymbolContext context) {
      String v = (bigValue != null) ? bigValue.toString() : (Integer.toString(value));
      Element e = doc.createElement("IntValue");
      Node n = doc.createTextNode(v);
      e.appendChild(n);
      return appendElement(doc, "NumeralNode", e);
    //return appendText(doc,"NumeralNode",(bigValue != null) ? bigValue.toString() : (Integer.toString(value)));
  }
}



<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/NonDistributedFPSetManager.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package tlc2.tool.distributed.fp;

import java.io.IOException;
import java.util.concurrent.ExecutorService;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCTrace;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

@SuppressWarnings("serial")
public class NonDistributedFPSetManager implements IFPSetManager {

	private final FPSetRMI fpSet;
	private final String hostname;
	private final transient TLCTrace trace; // Do not serialize trace and send it over the wire. Recovery executes on the master, not on the workers.

	public NonDistributedFPSetManager(final FPSetRMI fpSet,
			final String hostname, TLCTrace trace) throws IOException {
		this.fpSet = fpSet;
		this.hostname = hostname;
		this.trace = trace;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#register(tlc2.tool.distributed.fp.FPSetRMI, java.lang.String)
	 */
	public void register(FPSetRMI fpSet, String hostname)
			throws FPSetManagerException {
		throw new UnsupportedOperationException("Not applicable for non-distributed FPSetManager");
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#numOfServers()
	 */
	public int numOfServers() {
		return 1;
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#numOfAliveServers()
	 */
	public int numOfAliveServers() {
		return numOfServers();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#getHostName()
	 */
	public String getHostName() {
		return hostname;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#put(long)
	 */
	public boolean put(long fp) {
		try {
			return this.fpSet.put(fp);
		} catch (IOException e) {
			// not expected to happen
			MP.printError(EC.GENERAL, e);
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#contains(long)
	 */
	public boolean contains(long fp) {
		try {
			return this.fpSet.contains(fp);
		} catch (IOException e) {
			// not expected to happen
			MP.printError(EC.GENERAL, e);
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#getFPSetIndex(long)
	 */
	public int getFPSetIndex(long fp) {
		return 0;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#putBlock(tlc2.util.LongVec[])
	 */
	public BitVector[] putBlock(LongVec[] fps) {
		final BitVector[] res = new BitVector[fps.length];
		for (int i = 0; i < fps.length; i++) {
			LongVec longVec = fps[i];
			try {
				res[i] = this.fpSet.putBlock(longVec);
			} catch (IOException e) {
				// not expected to happen
				MP.printError(EC.GENERAL, e);
				res[i] = new BitVector(0);
			}
		}
		return res;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#putBlock(tlc2.util.LongVec[], java.util.concurrent.ExecutorService)
	 */
	public BitVector[] putBlock(LongVec[] fps, ExecutorService executorService) {
		return putBlock(fps);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#containsBlock(tlc2.util.LongVec[])
	 */
	public BitVector[] containsBlock(LongVec[] fps) {
		final BitVector[] res = new BitVector[fps.length];
		for (int i = 0; i < fps.length; i++) {
			LongVec longVec = fps[i];
			try {
				res[i] = this.fpSet.containsBlock(longVec);
			} catch (IOException e) {
				// not expected to happen
				MP.printError(EC.GENERAL, e);
				res[i] = new BitVector(0);
			}
		}
		return res;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#containsBlock(tlc2.util.LongVec[], java.util.concurrent.ExecutorService)
	 */
	public BitVector[] containsBlock(LongVec[] fps,
			ExecutorService executorService) {
		return containsBlock(fps);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#checkFPs()
	 */
	public long checkFPs() {
		try {
			return this.fpSet.checkFPs();
		} catch (IOException e) {
			// not expected to happen
			MP.printError(EC.GENERAL, e);
			return -1;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#checkInvariant()
	 */
	public boolean checkInvariant() {
		try {
			return this.fpSet.checkInvariant();
		} catch (IOException e) {
			// not expected to happen
			MP.printError(EC.GENERAL, e);
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#size()
	 */
	public long size() {
		try {
			return this.fpSet.size();
		} catch (IOException e) {
			// not supposed to happen
			MP.printError(EC.GENERAL, e);
			return -1;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#getStatesSeen()
	 */
	public long getStatesSeen() {
		try {
			return this.fpSet.size();
		} catch (IOException e) {
			// not supposed to happen
			MP.printError(EC.GENERAL, e);
			return -1;
		}
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#getMask()
	 */
	public long getMask() {
		return Long.MAX_VALUE;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#checkpoint(java.lang.String)
	 */
	public void checkpoint(String fname) throws InterruptedException, IOException {
		this.fpSet.beginChkpt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.IFPSetManager#commitChkpt()
	 */
	public void commitChkpt() throws IOException {
		this.fpSet.commitChkpt();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#recover(java.lang.String)
	 */
	public void recover(String fname) throws InterruptedException, IOException {
		this.fpSet.recover(trace);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.fp.FPSetManager#close(boolean)
	 */
	public void close(boolean cleanup) throws IOException {
		this.fpSet.close();
		// Correspond with the existing impl in FPSetManager#exit(boolean) and
		// exit the FPSet
		this.fpSet.exit(cleanup);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/compare/SpecComparator.java<|end_filename|>
package org.lamport.tla.toolbox.util.compare;

import java.util.Comparator;

import org.eclipse.core.runtime.CoreException;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.handler.CloseSpecHandler;

/**
 *
 * @author zambrovski
 */
public class SpecComparator implements Comparator<Spec>
{

    /**
     * Specifications are compared by comparison of when they were last
     * closed, with compare(spec1, spec2) returning +1 iff spec1 was
     * last closed before spec2 was.  As far as I know, this is used
     * only for ordering the specs in the Open Spec menu.  
     *     Changed by LL and <NAME> on 12 October 2009
     * 
     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
     */
    public int compare(Spec s1, Spec s2)
    {
        if (s1 == null)
        {
            return 1;
        } else if (s2 == null)
        {
            return -1;
        } else
        {
            long s1Time = getLastClosedTime(s1);
            long s2Time = getLastClosedTime(s2);
            if (s1Time == s2Time)
            {
                return 0;
            } else if (s1Time > s2Time)
            {
                return -1;
            } else
            {
                return 1;
            }
        }
        // if (s1.getLastModified() == null && s2.getLastModified()!= null)
        // {
        // return 1;
        // } else if (s2.getLastModified() == null && s1.getLastModified() != null)
        // {
        // return -1;
        // } else if (s2.getLastModified() == null && s1.getLastModified() == null)
        // {
        // return 0;
        // } else
        // {
        // return s1.getLastModified().compareTo(s2.getLastModified());
        // }
    }

    /**
     * Returns the time spec Spec was last closed.
     * @param spec
     * @return
     */
    private long getLastClosedTime(Spec spec)
    {
        try
        {
            String timeAsString = spec.getProject().getPersistentProperty(CloseSpecHandler.LAST_CLOSED_DATE);
            if (timeAsString == null)
            { 
                // This value may be null if the user has just created
                // the spec and not yet closed it when he clicks on the Open
                // Spec menu.  (I'm not sure.)  LL
                // Activator.getDefault().logDebug("Null read as LAST_CLOSED_DATE.");
                return 0;
            }
            return Long.parseLong(timeAsString);

        } catch (CoreException e)
        {
            Activator.getDefault().logDebug("Exception thrown when reading project LAST_CLOSED time.");
            return 0;
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/style.css<|end_filename|>
body { background : #ffffe4;
       font-family : verdana;
       font-size : 17px; }
h1 {color : #0000c0; font-size:175% }
h2 {color : #0000c0; }
h3 {color : #0000c0; }
hr {color:#0000c0;}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/ForgetSpecHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import java.util.Iterator;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.spec.manager.WorkspaceSpecManager;
import org.lamport.tla.toolbox.ui.navigator.ToolboxExplorer;
import org.lamport.tla.toolbox.util.ToolboxJob;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Forget specification.
 * 
 * This class is a clone of the DeleteSpecHandler method, except that the
 * ToolboxJob calls Activator.getSpecManager().removeSpec with the different
 * third argument that causes the .toolbox directory not to be deleted.
 * Strings were also appropriately changed.  I was unable to figure out how
 * to use a single handler for both the Forget and the Delete commands.
 *
 * It would be nice if the confirmation dialog that the command popped up
 * contained a checkbox that allows the user to suppress the confirmation
 * dialog on future executions.  To allow the user to change his mind
 * and require confirmation, this requires that whether or not a confirmation
 * is raised be a user-settable preference.  (The main TLA+ preference pages is
 * currently the only preference page where it makes sense to put this preference.)
 * This can all be implemented as follows:
 * 
 *   - Add to the IPreferenceConstants class a definition like
 *   
 *        public static final String NO_CONFIRM_ON_FORGET = "doNotConfirmOnForget";
 *   
 *   - Add the appropriate command to set the preference's default value
 *     in the initializeDefaultPreferences method of the PreferenceInitializer
 *     class.
 * 
 *   - Add the preference selector to the TLA+ Preferences page by adding the 
 *     appropriate checkbox with the createFieldEditors method of the 
 *     GeneralPreferencePage class.  (Use the "Continue Previous Session on Restart"
 *     checkbox as a model.)
 *     
 *   - Create a ConfirmForgetDialog class that creates the dialog.  That class's
 *     okPressed method should set the preference if necessary.  See
 *     LaunchProverDialog for a model.
 *     
 *   - Modify the ForgetSpecHandler class's execution method so it first tests the 
 *     preference to see if it should launch the dialog.  I believe it does this with
 *     
 *         IPreferenceStore store = PreferenceStoreHelper.getInstancePreferenceStore();
 *         boolean shouldIgnore = store.getBoolean(IPreferenceConstants.NO_CONFIRM_ON_FORGET)
 *     
 *     If it should, the execution method then launches the dialog  and waits until the 
 *     user closes it.  See GeneralLaunchProverHandler class's execute method to see how 
 *     that's done.
 *     
 * I didn't add this feature because the TLA+ Preference page has so little on it
 * that it seems a shame to complicate it for such a trivial feature.  This decision
 * should be re-examined if additional features are added to that page.
 * 
  * @author <NAME>
 */
public class ForgetSpecHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
         /*
         * No parameter try to get it from active navigator if any
         */
        IWorkbenchPage activePage = UIHelper.getActivePage();
        if (activePage != null)
        {
            ISelection selection = activePage.getSelection(ToolboxExplorer.VIEW_ID);
            if (selection != null && selection instanceof IStructuredSelection
                    && !((IStructuredSelection) selection).isEmpty())
            {
                
                Iterator<Object> selectionIterator = ((IStructuredSelection) selection).iterator();
                while (selectionIterator.hasNext()) 
                {
                	Object next = selectionIterator.next();
                	if (!(next instanceof Spec)) {
                		// The selection can contain models and groups too.
                		continue;
                	}
                    final Spec spec = (Spec) next;
                    boolean answer = MessageDialog.openQuestion(UIHelper.getShellProvider().getShell(), "Forget specification?",
                            "Do you really want to remove specification " + spec.getName() + " from the Toolbox's list of specs?");
                    if (answer)
                    {
                    	// close the spec handler (in the ui thread)
                    	final WorkspaceSpecManager specManager = Activator.getSpecManager();
                        if (specManager.isSpecLoaded(spec)) {
                        	new CloseSpecHandler().execute(event);
                        }
                    	
    					// use confirmed rename -> rename
    					final Job j = new ToolboxJob("Deleting spec...") {
    						protected IStatus run(final IProgressMonitor monitor) {
    							Activator.getSpecManager().removeSpec(spec, monitor, true);
    							return Status.OK_STATUS;
    						}
    					};
    					j.schedule();
                    }
                }
            }
        }

        
        return null;
    }


	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (UIHelper.getActivePage() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/Test.java<|end_filename|>
// With a little luck, the assignment statement pc := "foo"  should be
// MakeAssign(pc, MakeExpr(Singleton2(StringToken("foo"))))

package pcal ;
import java.io.File;
import java.util.Vector;

import util.ToolIO;

class Test
  { public static Vector Singleton(Object obj) 
      /*********************************************************************
      * If we think of a vector as a sequence, then this returns <<obj>>.  *
      *********************************************************************/
      { Vector result = new Vector() ;
        result.addElement(obj) ;
        return result; 
      }
 
    public static Vector Singleton2(Object obj)
      /*********************************************************************
      * If we think of a vector as a sequence, then this returns           *
      * << <<obj>> >>.                                                     *
      *********************************************************************/
      { return Singleton(Singleton(obj));
      } 

    public static TLAToken StringToken(String str)
      /*********************************************************************
      * Returns a new STRING token with string str.                        *
      *********************************************************************/
      { TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.STRING ;;
        return result ;
      }

    public static TLAToken BuiltinToken(String str)
      /*********************************************************************
      * Returns a new BUILTIN token with string str.  (A token like "="    *
      * has type BUILTIN, though in the translation phase, there will      *
      * probably be no difference in how BUILTIN and IDENT tokens are      *
      * handled.)                                                          *
      *********************************************************************/
      { TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.BUILTIN ;;
        return result ;
      }

    public static TLAToken IdentToken(String str)
      /*********************************************************************
      * Returns a new IDENT token for identifier str.                      *
      *********************************************************************/
      { TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.IDENT ;
        return result ;
      }

    public static TLAExpr MakeExpr(Vector vec)
      /*********************************************************************
      * Makes a normalized expression exp with exp.tokens = vec.           *
      *********************************************************************/
      { TLAExpr result = new TLAExpr(vec) ;
        result.normalize() ;
        return result ;
      }

    public static TLAExpr TokVectorToExpr(Vector vec, int spaces)
      /*********************************************************************
      * If vec is a vector of TLAToken objects, then this method returns   *
      * a TLAExpr describing a one-line expression composed of clones of   *
      * the tokens in vec separated by `spaces' spaces.                    *
      *********************************************************************/
      { Vector firstLine = new Vector() ;
        int nextCol = 0 ;
        int i = 0 ;
        while (i < vec.size())
          { TLAToken tok = ((TLAToken) vec.elementAt(i)).Clone() ;
            tok.column = nextCol ;
            firstLine.addElement(tok) ;
            nextCol = nextCol + tok.getWidth() + spaces ;
            i = i + 1 ;
          } ;
        
        return MakeExpr(Singleton(firstLine)) ;
      } ;

    public static AST.Assign MakeAssign(String id, TLAExpr exp)
      /*********************************************************************
      * Makes the assignment statement id := exp.                          *
      *********************************************************************/
      { AST.SingleAssign sAss = new AST.SingleAssign() ;
        sAss.lhs.var = id ;
        sAss.lhs.sub = MakeExpr(new Vector()) ;
        sAss.rhs = exp ;
        AST.Assign result = new AST.Assign() ;
        result.ass = Singleton(sAss) ;
        return result ;
      }


/***************************************************************************
* The AST node for `when pc = "foo"'  should be produced by something like *
* Vector toks = new Vector() ;                                             *
*                                                                          *
*     toks.addElement(IdentToken("pc")) ;                                  *
*     toks.addElement(BuiltInToken("=")) ;                                 *
*     toks.addElement(StringToken("foo")) ;                                *
*     AST.When node = new AST.when() ;                                     *
*     node.exp = TokVectorToExpr(toks) ;                                   *
*                                                                          *
***************************************************************************/
   public static void main(String[] args) 
     { File f = new File("no-file.cfg") ;
       ToolIO.out.println("no-file.canRead() = " + f.canRead()) ;
       ToolIO.out.println("no-file.canWrite() = " + f.canWrite()) ;
       ToolIO.out.println("no-file.exists() = " + f.exists()) ;
       f = new File("read-only.cfg") ;
       ToolIO.out.println("read-only.canRead() = " + f.canRead()) ;
       ToolIO.out.println("read-only.canWrite() = " + f.canWrite()) ;
       ToolIO.out.println("read-only.exists() = " + f.exists()) ;
       f = new File("Bakery.cfg") ;
       ToolIO.out.println("Bakery.canRead() = " + f.canRead()) ;
       ToolIO.out.println("Bakery.canWrite() = " + f.canWrite()) ;
       ToolIO.out.println("Bakery.exists() = " + f.exists()) ;
       
     }


  }


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/debug/TLCSuccessorsStackFrame.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.debug;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.lsp4j.debug.Scope;
import org.eclipse.lsp4j.debug.Variable;

import tla2sany.semantic.OpDefNode;
import tla2sany.st.Location;
import tla2sany.st.TreeNode;
import tlc2.tool.Action;
import tlc2.tool.INextStateFunctor;
import tlc2.tool.TLCState;
import tlc2.tool.impl.Tool;
import tlc2.util.Context;
import tlc2.value.impl.RecordValue;

public class TLCSuccessorsStackFrame extends TLCStateStackFrame {

	private transient final INextStateFunctor fun;
	private transient final Action a;

	public TLCSuccessorsStackFrame(TLCStackFrame parent, OpDefNode node, Context ctxt, Tool tool, TLCState s, Action a,
			INextStateFunctor fun) {
		super(parent, node, ctxt, tool, s);
		this.a = a;
		this.fun = fun;
		//TODO Append action name, too? => node.getName().toString()
		// Overwrite setName from parent that uses HumanReadableImage, which -for an
		// OpDefNode- is not the location.
		setName(node.toString());
	}
	
	public int getSuccessorId() {
		// +4 because TLCStateStackFrame and TLCStackFrame already use up ctxtId+1,
		// ctxtId+2, and ctxtId+3.
		return this.ctxtId + 4;
	}
	
	@Override
	public Variable[] getVariables(int vr) {
		if (vr == getSuccessorId()) {
			return tool.eval(() -> {
				// A) Filter those states from fun#getStates that are a-steps where a is the Action
				// corresponding to this frame.
				final Set<TLCState> aSteps = fun.getStates().getSubSet(a);
				
				// B) Convert a-steps into the DAP representation.
				final Variable[] vars = new Variable[aSteps.size()];
				Iterator<TLCState> itr = aSteps.iterator();
				for (int i = 0; i < vars.length; i++) {
					RecordValue r = new RecordValue(itr.next());
					vars[i] = getStateAsVariable(r, a.getName().toString() + (i+1));
				}
				return vars;
			});
		}
		return super.getVariables(vr);
	}
	
	@Override
	public Scope[] getScopes() {
		final List<Scope> scopes = new ArrayList<>();
		scopes.addAll(Arrays.asList(super.getScopes()));
		
		final Scope scope = new Scope();
		scope.setName("Successors");
		scope.setVariablesReference(getSuccessorId());
		// Move "Successors" above "Trace".  This is brittle!
		scopes.add(scopes.size() - 1, scope);
		
		return scopes.toArray(new Scope[scopes.size()]);
	}
	
	@Override
	public boolean matches(final TLCSourceBreakpoint bp) {
		final OpDefNode odn = (OpDefNode) node;
		// TreeNode.one()[0] is the LHS of the definition => A user activates is by
		// setting an "in-line" breakpoint into the LHS of the def.
		if (odn.getTreeNode() != null && odn.getTreeNode().one().length > 0) {
			final TreeNode[] one = odn.getTreeNode().one();
			final Location location = one[0].getLocation();
			final int hits = bp.getHits();
			return bp.getLine() == location.beginLine() && location.beginColumn() <= bp.getColumnAsInt()
					&& bp.getColumnAsInt() <= location.endColumn() && fun.getStates().getSubSet(a).size() >= hits;
		}
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/tool/queue/DiskQueueBenachmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.queue;

import java.io.IOException;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Group;
import org.openjdk.jmh.annotations.GroupThreads;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import tlc2.tool.TLCState;
import tlc2.tool.TLCStates;
import tlc2.util.FlightRecorderProfiler;

@State(Scope.Group)
@BenchmarkMode(Mode.Throughput)
public class DiskQueueBenachmark {
	
	@Param({"1", "2", "4", "8", "16", "32", "64"})
	public int vars;

	@Param({"DiskByteArrayQueue", "DiskStateQueue"})
	public String impl;
	
	private IStateQueue dsq;

	private TLCState state;
	
    @Setup
    public void up() throws IOException {
		if (impl.equals("DiskByteArrayQueue")) {
			this.dsq = new DiskByteArrayQueue();
		} else {
			this.dsq = new DiskStateQueue();
		}

		this.state = TLCStates.createDummyState(vars);
    }
    
    @TearDown
    public void down() throws IOException {
    	this.dsq.delete();
    }
    
    @Benchmark
    @Group("g02")
    @GroupThreads(1)
    public TLCState consumer1() {
        return this.dsq.sDequeue();
    }

    @Benchmark
    @Group("g02")
    @GroupThreads(1)
    public void producer1() {
    	this.dsq.sEnqueue(this.state);
    }
    
    
    @Benchmark
    @Group("g04")
    @GroupThreads(2)
    public TLCState consumer2() {
        return this.dsq.sDequeue();
    }

    @Benchmark
    @Group("g04")
    @GroupThreads(2)
    public void producer2() {
    	this.dsq.sEnqueue(this.state);
    }

    
    @Benchmark
    @Group("g08")
    @GroupThreads(4)
    public TLCState consumer4() {
        return this.dsq.sDequeue();
    }

    @Benchmark
    @Group("g08")
    @GroupThreads(4)
    public void producer4() {
    	this.dsq.sEnqueue(this.state);
    }

    
    @Benchmark
    @Group("g16")
    @GroupThreads(8)
    public TLCState consumer8() {
        return this.dsq.sDequeue();
    }

    @Benchmark
    @Group("g16")
    @GroupThreads(8)
    public void producer8() {
    	this.dsq.sEnqueue(this.state);
    }
    
    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(DiskQueueBenachmark.class.getSimpleName())
                .addProfiler(FlightRecorderProfiler.class)
                .build();

        new Runner(opt).run();
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/model/spec-options-page.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/model/spec-options-page.html  -->


<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>Spec Options Page</title>
</head>
<!-- a comment here -->

<body>
<h1>Spec Options Page</h1>

 
<pre>
Contents
  <a href="#additional">Additional Definitions</a>
  <a href="#state">State Constraint</a>
  <a href="#model">Model Values</a>
  <a href="#override">Definition Override</a>
  <a href="#action">Action Constraint</a>
</pre>

<P> 
This model editor page allows you to add less-often
used parts of a model that describe the spec
that the Toolbox calls TLC to check.&nbsp;  It's a good idea to browse
this page just to see what options it provides, since
some of the features are not ones you would expect.&nbsp;
The page is raised  from a link on the <a href="overview-page.html">Model Overview Page</a>.
 </P>

<h2><a name="additional">Additional Definitions</a></h2>

<p>
It is sometimes convenient to define operators just
for use in the expressions that specify a model.&nbsp;  For
example, you might want to define an operator that
you use can use in more than one invariant.&nbsp;  If you
don't want those definitions to be part of the spec,
you can put them in this section of the page.&nbsp;  These
definitions can use any operator or parameters that
can be used in the the root module, as well as any
<a href="model-values.html">model value</a> that is
declared in the model.
</p>

<p>
In addition to definitions, in this section you can also 
put assumptions (<code>ASSUME</code>&nbsp; statements)
for TLC to check.&nbsp;  Putting other
things in this section, such as declarations,
will result in mysterious TLC errors.

</p>
<h2><a name="state">State Constraint</a></h2>

<p>
Many behavior specifications have an infinite set of reachable 
states.&nbsp;  For example, message queues could get arbitrarily large.&nbsp;  
TLC will run forever (or until your computer runs out
of disk space) on such a behavior spec.&nbsp;  You could just let it
run and keep looking for violations of safety properties such as invariance.&nbsp;
However, it's a better idea to limit the set of states by entering
a state constraint here.
</p>

<p>
A state constraint is a state predicate, which is a
Boolean-valued expression that contains unprimed variables.&nbsp;
When computing the set of reachable states, TLC will not
explore successor states of any state it finds that does
<em>not</em> satisfy the state constraint.&nbsp;  For example,
specifying&nbsp; <code>len < 3</code>&nbsp; essentially
limits the set of reachable states that TLC finds to ones
that can be reached by a sequence of states in which 
the value of the variable&nbsp; <code>len</code>&nbsp; 
is less than 3.&nbsp;  See Section 14.3 (page 240) of 
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em> for an explanation of how TLC
computes reachable states.&nbsp;  Note that there is no need
for multiple state constraints because they can simply be
conjoined to form a single constraint.
</p>

<!-- 
<p>A state constraint has an effect only in model checking mode.  (See
<a href="#launching">TLC Options</a>.)
</p>
 -->

<h2><a name="model">Model Values</a></h2>

You can enter here a set of model values, which you can then
use in expressions that define the model--for example, in
the value substituted for a declared constant.&nbsp;  See the
<A href="model-values.html"><em>Model Values and Symmetry</em></A> help
page for an explanation of what model values are and how they
are used.

<h2><a name="override">Definition Override</a></h2>
<p>
We want our specifications to be as simple and easy to understand as
possible.&nbsp;  Sometimes this leads to a definition that TLC cannot evaluate,
or that it can evaluate only very inefficiently.&nbsp;  In that case, we
must <em>override</em> the definition by telling TLC to replace it with
a new definition.&nbsp;   To do this, click on the section's&nbsp; <samp>Add</samp>&nbsp;
button, select the operator whose definition you want to override, and 
click&nbsp; <samp>OK</samp>&nbsp;.&nbsp;  (You can also double-click on the
operator name.)&nbsp;  This will raise a dialog in which you can specify
the overriding.
</p>

<p>
If the operator whose definition you are overriding has arguments,
you will be presented with a form for writing the new definition in
the obvious way.&nbsp;  If it has no arguments, you have two
options.&nbsp;  With the <em>Ordinary assignment</em> option, you just
write the new definition.&nbsp;  The <em>Model value</em> option
defines the operator to equal a model value of the same name.&nbsp;
See the
<A href="model-values.html"><em>Model Values and Symmetry</em></A> help
page for an explanation of model values and the most common
reason why you would want to override the definition in this way.
</p>

<p>
You can override definitions made in modules other than the root module.&nbsp;
If a definition is in a module imported with an&nbsp; <samp>INSTANCE</samp>&nbsp;
statement, then the name of the module containing the definition is indicated.
</p>

<p>
You can edit or remove an overriding specification in the obvious way: by selecting it and
using the&nbsp; <samp>Edit</samp>&nbsp; or&nbsp; <samp>Remove</samp>&nbsp; button.&nbsp;
(Editing is also selected by double-clicking on the item.)
</p>

<p fontsize=80%>
<b>Some Fine Print</b>&nbsp;
<font size=-1>
When overriding a definition, 
the new definition can use any operator or parameters that
can be used in the the root module, as well as any
<a href="model-values.html">model value</a> that is
declared in the model.&nbsp;  This means that you can override
a definition with an expression that
contains operators that are undefined at the point where the
original definition occurred.&nbsp;
TLC evaluates overridden definitions in the
obvious way, and bizarre overriding can
lead to strange results.&nbsp;  For example, if&nbsp; <samp>Fact</samp>&nbsp; is defined by
<pre>
   Fact(n)  ==  IF n = 0 THEN 1 ELSE n * Bar(n-1)
</pre>
and the definition of&nbsp; <samp>Bar</samp>&nbsp; is overridden with
<pre>
   Bar(n) <- Fact(n)
</pre>
then TLC will evaluate&nbsp; <samp>Fact(n)</samp>&nbsp; to 
equal&nbsp; <samp>n!</samp>&nbsp; for any natural 
number&nbsp; <samp>n</samp>&nbsp;.&nbsp;
There is no good reason to use such bizarre overriding.</font> 
</p>


<h2><a name="action">Action Constraint</a></h2>

An action constraint is much like a <a href="#state">state constraint</a>, except 
that the constraint formula may also include primed variables.&nbsp;
See Section 14.3 (page 240) of 
<em><a href=
"http://research.microsoft.com/en-us/um/people/lamport/tla/book.html" target="_blank">
Specifying Systems</a></em> for an explanation of how TLC uses an
action constraint.


<hr> 
<!-- uncomment to add links to any subtopics that are added 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
 --> 
<!-- delete rest of line to comment out -->  

<a href = "creating-model.html">&uarr; Creating a Model</a>
 
</hr>

</body>
</html>


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/handler/OperatingSystemPDFRunnable.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex.handler;

import org.eclipse.core.resources.IResource;
import org.eclipse.ui.IWorkbenchPartSite;
import org.lamport.tla.toolbox.tool.tla2tex.TLA2TeXActivator;

public class OperatingSystemPDFRunnable extends AbstractPDFViewerRunnable {
	/** We have no need for any of these parameters but our superclass is coded to assert their non-null-ness. **/
	public OperatingSystemPDFRunnable(final ProducePDFHandler handler, final IWorkbenchPartSite site, final IResource aSpecFile) {
		super(handler, site, aSpecFile);
	}

	public void run() {
        monitor.subTask("Opening PDF File");
        
		final String openCommand = "open " + outputFileName;
		try {
			Runtime.getRuntime().exec(openCommand);
		} catch (final Exception e) {
			TLA2TeXActivator.getDefault().logError("Unable to execute 'open' command on PDF.", e);
		}

        monitor.worked(1);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/IFPSetManager.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp;

import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.ExecutorService;

import tlc2.tool.distributed.fp.FPSetManager.FPSets;
import tlc2.tool.fp.FPSet;
import tlc2.tool.fp.FPSetConfiguration;
import tlc2.tool.fp.MSBDiskFPSet;
import tlc2.util.BitVector;
import tlc2.util.LongVec;

/**
 *
 */
public interface IFPSetManager extends Serializable {

	/**
	 * @see FPSetRMI#checkFPs()
	 */
	long checkFPs();

	/**
	 * @see FPSetRMI#checkInvariant()
	 */
	boolean checkInvariant();
	
	/**
	 */
	void checkpoint(String fname) throws InterruptedException, IOException;

	/**
	 * @see FPSetRMI#close()
	 */
	void close(boolean cleanup) throws IOException;

	/**
	 * @see FPSetRMI#commitChkpt()
	 */
	void commitChkpt() throws IOException;

	/**
	 * @see FPSetRMI#contains(long)
	 */
	boolean contains(long fp);

	/**
	 * The given {@link LongVec} has to have the same size as
	 * {@link IFPSetManager#numOfServers()}.
	 * <p>
	 * As a second pre-condition, the fingerprints in the {@link LongVec} have
	 * to be ordered corresponding with the fingerprint space partitioning used
	 * by this {@link IFPSetManager}. It is the callers responsibility to set up
	 * the {@link LongVec} in this way (for efficiency reasons).
	 * 
	 * @see IFPSetManager#numOfServers()
	 * @see IFPSetManager#getFPSetIndex(long)
	 * @see FPSetRMI#containsBlock(LongVec)
	 */
	BitVector[] containsBlock(LongVec[] fps);

	/**
	 * The given {@link LongVec} has to have the same size as
	 * {@link IFPSetManager#numOfServers()}.
	 * 
	 * @see FPSetRMI#containsBlock(LongVec);
	 */
	BitVector[] containsBlock(LongVec[] fps, ExecutorService executorService);

	/**
	 * The index of the {@link FPSetRMI} corresponding with the given
	 * fingerprint in this {@link IFPSetManager}. It is used by worker nodes to
	 * pre-sort the fingerprints in {@link LongVec} according to the index of
	 * the {@link FPSetRMI} responsible for the subset of the fingerprint space.
	 * 
	 * @param fp
	 *            The fingerprint for which the index should be calculated.
	 * @return The index of the {@link FPSet} that is assigned this subset of
	 *         the fingerprint space.
	 *         <p>
	 *         Assignment is based on the least significant bits. This selection
	 *         of fingerprint bits is important. Selecting the most significant
	 *         bits of a fingerprint to assign an {@link FPSet} would violate
	 *         the invariant of MSB-based {@link FPSet}s such as
	 *         {@link MSBDiskFPSet}. They assume that the
	 *         {@link FPSetConfiguration#getFpBits()} are fixed. FPSetManager
	 *         may dynamically reassign additional subsets of the fingerprint
	 *         space to an existing {@link FPSet}, when the previously assigned
	 *         {@link FPSet} is lost due to a network or hardware failure.
	 */
	int getFPSetIndex(final long fp);

	/**
	 * @see FPSetRMI#getStatesSeen()
	 */
	long getStatesSeen();

	/**
	 * @return The number of {@link FPSetRMI} instances backing this
	 *         {@link IFPSetManager}.
	 *         <p>
	 *         The {@link IFPSetManager} distributes the fingerprint space
	 *         across the number of instances at its own discretion.
	 */
	int numOfServers();

	/**
	 * @return The number of alive {@link FPSetRMI} instances backing this
	 *         {@link IFPSetManager}. It results a value in the range [0,
	 *         {@link IFPSetManager#numOfServers()}]<p>
	 *         It does <b>not</b> re-count reassigned {@link FPSets}. 
	 * 
	 * @see IFPSetManager#numOfServers()
	 */
	int numOfAliveServers();

	/**
	 * @see FPSetRMI#put(long)
	 */
	boolean put(long fp);

	/**
	 * The given {@link LongVec} has to have the same size as
	 * {@link IFPSetManager#numOfServers()}.
	 * 
	 * @see FPSetRMI#putBlock(LongVec)
	 */
	BitVector[] putBlock(LongVec[] fps);

	/**
	 * The given {@link LongVec} has to have the same size as
	 * {@link IFPSetManager#numOfServers()}.
	 * 
	 * @see FPSetRMI#putBlock(LongVec)
	 */
	BitVector[] putBlock(LongVec[] fps, ExecutorService executorService);

	/**
	 * @see FPSetRMI#recover(String)
	 */
	void recover(String fname) throws InterruptedException, IOException;

	/**
	 * Registers the given {@link FPSetRMI} as a usable instance of this
	 * {@link IFPSetManager}. This means that the given {@link FPSetRMI} will be
	 * used to store and lookup fingerprints during model checking. It is up to
	 * the {@link IFPSetManager} to partition the fingerprint space, meaning the
	 * {@link FPSetRMI} will not see all fingerprints of all distinct states.
	 */
	void register(FPSetRMI fpSet, String hostname) throws FPSetManagerException;

	/**
	 * @see FPSetRMI#size()
	 */
	long size();
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/ShowUsesHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.jface.text.IRegion;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.editor.basic.tla.TokenSpec;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.st.Location;
import tla2sany.st.SyntaxTreeConstants;

/**
 * 
 */

/**
 * This is the handler for the Show Uses command, which allows the user
 * to mark and visit all uses of a symbol.  However, unlike the Show
 * Declaration command, for an instantiated symbol like Foo!bar, it 
 * shows only uses of Foo!bar, not other uses of the original symbol
 * bar.
 * 
 * If the chosen symbol is used in more than one module (possible only
 * by EXTENDing a module with its declaration or by INSTANCEing it
 * with no renaming or parameter substitution), then a pop-up dialog
 * allows the user to choose which module to display.
 * 
 * Note: Implementing SyntaxTreeConstants simply imports the definitions
 *       of the constants defined in that interface.
 *       
 * Note: See roadmap.txt for how to get the markers to show on the right-hand
 *       vertical bar.
 * 
 * @author lamport
 *
 */
public class ShowUsesHandler extends AbstractHandler implements IHandler, SyntaxTreeConstants
{
    /**    This is the handler for the Goto Next Use command.
     * 
     * @author lamport
     *
     */

    public static String titleText(String prefix)
    {
        if (prefix == "")
        {
            return "Definitions and Declarations";
        } else
        {
            return prefix;
        }

    }

    /**
     * This class defines the pop-up dialog that allows the user
     * to choose which module's uses to show.
     * 
     * The code was copied from the ShowDeclarationsPopupDialog
     * subclass of ShowDeclarationsHandler.
     * 
     * @author lamport
     *
     */
    public static class ShowUsesPopupDialog extends PopupDialog
    {
        Shell parent; // The dialog's parent shell

        /**
         * moduleList is the list of all modules from which the user chooses.
         * 
         * showUses[i] is an array of all uses in module moduleList[i].
         */
        String[] moduleList;
        SemanticNode[][] showUses;

        List list; // The org.eclipse.swt.widgets.List (not ordinary Java List) being displayed.
        boolean showAll = true; // True iff displaying definitions imported by instantiation.
        String filterPrefix = ""; // For filtering displayed declarations as user types prefix.

        /*
         * The TLA editor with focus and the module it's open on.  They are saved because the editor
         * no longer has focus when the popup dialog is raised.
         */
        TLAEditor editor;
        ModuleNode module;

        public ShowUsesPopupDialog(Shell parent, String[] moduleList, SemanticNode[][] usesArray)
        {
            super(parent, SWT.NO_TRIM, true, // takeFocusOnOpen
                    false, // persistSize
                    true, // persistLocation
                    true, // showDialogMenu
                    true, // showPersistActions
                    "Choose Module", // titleText
                    "Click or choose by typing prefix or arrow keys and enter."); // infoText
            this.parent = parent;
            this.moduleList = moduleList;
            this.showUses = usesArray;
            this.editor = EditorUtil.getTLAEditorWithFocus();
            if (this.editor != null)
            {
                module = ResourceHelper.getModuleNode(editor.getModuleName());
            }
        }

        /**
         * This is the method that puts the content into the popup's
         * dialog area.  It puts an org.eclipse.swt.widgets.List
         * (note that this isn't an ordinary Java List) there.
         * 
         * This is identical to the corresponding method in 
         * ShowDeclarationsHandler except for the obvious name changes
         * and the different setList method.  See that method
         * for the comments.
         * 
         */
        protected Control createDialogArea(Composite composite)
        {
            list = new List(composite, SWT.SINGLE | SWT.V_SCROLL | SWT.RESIZE);
            setList();
            list.addSelectionListener(new ShowUsesSelectionListener(this.showUses, this.moduleList)); // EditorUtil.getTLAEditorWithFocus()));
            list.addKeyListener(new ShowUsesKeyListener(this)); // Testing
            list.setSelection(0);
            return list;
        }

        /**
         * This is just to make setTitleText a public method so the handlers
         * can call it.
         */
        public void setTitleText(String str)
        {
            super.setTitleText(str);
        }

        protected void setList()
        {
            list.removeAll();
            for (int i = 0; i < moduleList.length; i++)
            {
                if (moduleList[i].startsWith(filterPrefix))
                {
                    list.add(moduleList[i]);
                }
            }
        }
    }

    /**
     * A listener for the List put into the dialog by the createDialogArea
     * method of ShowDefinitionsPopupDialog.
     * 
     * @author lamport
     *
     */
    public static class ShowUsesSelectionListener implements SelectionListener
    {
        // Copies of the arrays from ShowUsesHandler
        SemanticNode[][] showUses;
        String[] moduleNames;

        public ShowUsesSelectionListener(SemanticNode[][] showUses2, String[] moduleNames) // TLAEditor editor)
        {
            super();
            this.showUses = showUses2;
            this.moduleNames = moduleNames;
        }

        /**
         * This method seems to be called on the second click
         * when double-clicking on the selection.  Or maybe not.
         */
        public void widgetDefaultSelected(SelectionEvent e)
        {
        }

        /**
         * Called when the user selects an item in the List.
         */
        public void widgetSelected(SelectionEvent e)
        {
            List list = ((List) e.widget);
            Spec spec = ToolboxHandle.getCurrentSpec();
            if (spec != null)
            {
                spec.setModuleToShow(list.getSelection()[0]);

                String moduleName = list.getSelection()[0];
                spec.setModuleToShow(list.getSelection()[0]);
                int idx = selectString(moduleNames, moduleName);
                if (idx != -1)
                {
                    setUseMarkers(showUses[idx], moduleName, spec);
                }

            }
        }
    }

    /**
     * The Key Listener for keyboard input to the popup dialog.  The following
     * kinds of keyboard input are handled:
     * <ul>
     * <li> Return, which is equivalent to clicking on the selected item.
     * <li> Space, which toggles between showing and hiding instantiated declarations.
     * <li> Arrow keys, which move the selection.
     * <li> Letters, numbers, "_", and "!", which are added to the prefix used for
     *      filtering what is shown.
     * <li> Delete/backspace, which deletes one character from the filtering prefix.
     * </ul>
     * Other typed input is ignored.
     * @author lamport
     *
     */
    public static class ShowUsesKeyListener implements KeyListener
    { // Shell parent;
        ShowUsesPopupDialog popup;

        // boolean showAll; // a local copy of the current specs' showAllDeclarations field.

        public ShowUsesKeyListener(ShowUsesPopupDialog popup)
        { // this.parent = parent;
            this.popup = popup;
        }

        public void keyPressed(KeyEvent e)
        {
            char keyPressed = e.character;
            int keyCode = e.keyCode;
            List list = popup.list;
            int selection = list.getSelectionIndex();

            // This prevents the KeyEvent from changing the selection and triggering
            // execution of the SelectionListener.
            e.doit = false;

            // Check which key was pressed and handle it appropriately.
            if (keyCode == SWT.ARROW_DOWN || keyCode == SWT.ARROW_RIGHT)
            {
                if (list.getItemCount() == 0 || selection == -1)
                {
                    return;
                }
                list.select(Math.min(list.getItemCount(), selection + 1));
            } else if (keyCode == SWT.ARROW_UP || keyCode == SWT.ARROW_LEFT)
            {
                if (list.getItemCount() == 0 || selection == -1)
                {
                    return;
                }
                list.select(Math.max(0, selection - 1));
            } else if (keyCode == SWT.CR || keyCode == SWT.KEYPAD_CR)
            {
                Spec spec = ToolboxHandle.getCurrentSpec();
                if (spec != null)
                {
                    String moduleName = list.getSelection()[0];
                    spec.setModuleToShow(list.getSelection()[0]);
                    int idx = selectString(popup.moduleList, moduleName);
                    if (idx != -1)
                    {
                        setUseMarkers(popup.showUses[idx], moduleName, spec);
                    }
                }
                ;
                popup.close();
            } else if (Character.isLetterOrDigit(keyPressed) || (keyPressed == '_') || (keyPressed == '!'))
            {
                popup.filterPrefix = popup.filterPrefix + keyPressed;
                popup.setList();
                popup.setTitleText(ShowUsesHandler.titleText(popup.filterPrefix));
                // popup.setInfoText(ShowUsesHandler.infoText(popup.showAll));
                if (list.getItemCount() > 0)
                {
                    list.select(0);
                }

            } else if ((keyCode == SWT.DEL || keyCode == SWT.BS) && !popup.filterPrefix.equals(""))
            {
                popup.filterPrefix = popup.filterPrefix.substring(0, popup.filterPrefix.length() - 1);
                popup.setList();
                popup.setTitleText(ShowUsesHandler.titleText(popup.filterPrefix));
                // popup.setInfoText(ShowUsesHandler.infoText(popup.showAll));
                if (list.getItemCount() > 0)
                {
                    list.select(0);
                }
            }
        }

        public void keyReleased(KeyEvent e)
        {
            // TODO Auto-generated method stub

        }

    }

    public static final String SHOW_USE_MARKER_TYPE = "org.lamport.tla.toolbox.editor.basic.showUse";

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        // We need the current spec for accessing the fields
        // that the Show Uses command and the Goto Next/Previous Use commands need.
        // If there is no spec, there's nothing we can do.
        Spec spec = ToolboxHandle.getCurrentSpec();
        if (spec == null)
        {
            return null;
        }

        // Delete any existing markers.
        // Get the resource on which markers are to go, and set the markers.
        String oldModuleName = spec.getModuleToShow();
        if (oldModuleName != null)
        {
            IResource resource = ResourceHelper.getResourceByModuleName(oldModuleName);
            if (resource != null)
            {
                try
                {
                    resource.deleteMarkers(SHOW_USE_MARKER_TYPE, false, 99);
                } catch (CoreException e)
                {
                    // This should not happen;
                    e.printStackTrace();
                }
                spec.setMarkersToShow(null);
            }
        }

        // We will need the module name, which we get from the editor.
        TLAEditor tlaEditor = EditorUtil.getTLAEditorWithFocus();
        if (tlaEditor == null)
        {
            return null;
        }
        String moduleName = tlaEditor.getModuleName();
        ModuleNode moduleNode = ResourceHelper.getModuleNode(moduleName);
        if (moduleNode == null)
        {
            return null;
        }

        // We now get the SymbolNode that is the definition or declaration
        // of the symbol at which the TLA Editor's cursor is.
        TokenSpec currentTokenSpec = TokenSpec.findCurrentTokenSpec();
        if (currentTokenSpec == null || currentTokenSpec.resolvedSymbol == null)
        {
            return null;
        }
        SymbolNode resolvedSymbol = currentTokenSpec.resolvedSymbol;

        // TLAEditorActivator.getDefault().logDebug("We found symbol node named " + resolvedSymbol.getName());

        // Set tempModuleNames to the sorted array of all user module names.
        String[] tempModuleNames = ResourceHelper.getModuleNames();

        // Set tempUsesArray[i] to the array of SemanticNode[] nodes that are uses of
        // resolvedSymbol in module moduleNames[i], and sets numberOfModulesUsedIn
        // to the number of values of i for which usesArray[i] is neither null
        // nor a zero-length array.
        int numberOfModulesUsedIn = 0;
        SemanticNode[][] tempUsesArray = new SemanticNode[tempModuleNames.length][];
        for (int i = 0; i < tempModuleNames.length; i++)
        {
            tempUsesArray[i] = ResourceHelper.getUsesOfSymbol(resolvedSymbol, ResourceHelper
                    .getModuleNode(tempModuleNames[i]));
            if ((tempUsesArray[i] != null) && (tempUsesArray[i].length > 0))
            {
                numberOfModulesUsedIn++;
            }
        }

        // Raise an error menu if there are no instances.
        if (numberOfModulesUsedIn == 0)
        {
            MessageDialog.openWarning(UIHelper.getShellProvider().getShell(), "Cannot find uses",
                    "There are no uses of the symbol " + resolvedSymbol.getName());
            return null;
        }

        // Set usesArray and moduleNames to the subarrays of of tempUsesArray and
        // tempModuleNames for which there are instances of the symbols, with the
        // currently selected module's name put first if it is one of them.
        SemanticNode[][] usesArray = new SemanticNode[numberOfModulesUsedIn][];
        String[] moduleNames = new String[numberOfModulesUsedIn];
        int j = 0;
        for (int i = 0; i < tempModuleNames.length; i++)
        {
            if ((tempUsesArray[i] != null) && (tempUsesArray[i].length > 0))
            {
                usesArray[j] = tempUsesArray[i];
                moduleNames[j] = tempModuleNames[i];
                j++;
            }
        }
        j = -1;
        for (int i = 0; i < moduleNames.length; i++)
        {
            if (moduleName.equals(moduleNames[i]))
            {
                j = i;
                break;
            }
        }
        if (j > 0)
        {
            SemanticNode[] savedUses = usesArray[j];
            for (int i = j - 1; i > -1; i--)
            {
                usesArray[i + 1] = usesArray[i];
                moduleNames[i + 1] = moduleNames[i];
            }
            usesArray[0] = savedUses;
            moduleNames[0] = moduleName;
        }

        // If there are uses in more than one module, have the user choose
        // which one
        String moduleToShow = null;
        if (moduleNames.length > 1)
        {
            Shell parent = UIHelper.getShellProvider().getShell();
            ShowUsesPopupDialog popup = new ShowUsesPopupDialog(parent, moduleNames, usesArray);
            popup.open();
        } else
        {
            // The original code was bogus, since it's looping through all the
            // modules in moduleNames, which has length 1 in this else branch.
            // In particular, if there are no uses of the symbol in the module
            // containing its definition, then it reported an an error.
            // To fix the bug with minimal changes, LL added the following statement
            // on 11 Feb 2012.
            moduleName = moduleNames[0];
            
            moduleToShow = moduleName;

            spec.setModuleToShow(moduleToShow);

            int moduleIndex = -1;
            for (int i = 0; i < moduleNames.length; i++)
            {
                if (moduleNames[i].equals(moduleToShow))
                {
                    moduleIndex = i;
                    break;
                }
            }
            if (moduleIndex < 0)
            {
                Activator.getDefault().logDebug("Could not find module name in array in which it should be.  " + "This is a bug.");
                return null;
            }

            // Set locations to the array of Locations of the uses. To do this, we
            // look at the OpApplNode's syntax node tree and check for the following cases:
            // Foo(...) : the node is an N_OpApplication node, it's
            // first child is an N_GeneralID whose location is good.
            // ... %% ... : the node is an N_InfixExpr node, whose 2nd child is
            // an N_GenInfixOp whose location is good.
            // x : the node is an N_GeneralID node whose location is good
            // ...^+ : the node is an N_PostfixExpr node whose second heir
            // is an N_GeneralPostfixOp whose location is good
            SemanticNode[] uses = usesArray[moduleIndex];
            setUseMarkers(uses, moduleName, spec);
        }
        // Location[] locations = new Location[uses.length];
        // for (int i = 0; i < locations.length; i++)
        // {
        // // Set stn to the syntax tree node whose location should
        // // be used.
        // SyntaxTreeNode stn = (SyntaxTreeNode) uses[i].stn;
        // switch (stn.getKind()) {
        // case N_OpApplication:
        // stn = (SyntaxTreeNode) stn.heirs()[0];
        // break;
        // case N_InfixExpr:
        // case N_PostfixExpr:
        // stn = (SyntaxTreeNode) stn.heirs()[1];
        // break;
        // default:
        // TLAEditorActivator.getDefault().logDebug("Found unexpected kind " + stn.getKind() + " for stn node of symbol use.");
        // }
        // locations[i] = stn.getLocation();
        // }
        // Arrays.sort(locations, new LocationComparator());
        //
        // // Jump to the first location. This ensures that the module is
        // // now displayed by the current editor. (At least, I hope this
        // // happens synchronously.)
        // UIHelper.jumpToLocation(locations[0]);
        // spec.setCurrentSelection(0);
        //
        // // Get the resource on which markers are to go, and set the markers.
        // IResource resource = ResourceHelper.getResourceByModuleName(spec.getModuleToShow());
        // if (resource == null)
        // {
        // TLAEditorActivator.getDefault().logDebug("Why the hell is the resource null?");
        // return null;
        // }
        //
        // try
        // {
        // // Remove all markers showing uses.
        // resource.deleteMarkers(SHOW_USE_MARKER_TYPE, false, 99);
        // spec.setMarkersToShow(null);
        //
        // IMarker[] markersToShow = new IMarker[locations.length];
        //
        // // create the markers and put them in this.markersToShow
        // for (int i = 0; i < markersToShow.length; i++)
        // {
        // // The following is inefficient, because it's doing the same
        // // computation each time to find the document from the
        // // location.
        // IRegion iregion = AdapterFactory.locationToRegion(locations[i]);
        // IMarker marker;
        // marker = resource.createMarker(SHOW_USE_MARKER_TYPE);
        // Map markerAttributes = new HashMap(2);
        // markerAttributes.put(IMarker.CHAR_START, new Integer(iregion.getOffset()));
        // markerAttributes.put(IMarker.CHAR_END, new Integer(iregion.getOffset() + iregion.getLength()));
        // marker.setAttributes(markerAttributes);
        // markersToShow[i] = marker;
        // }
        // spec.setMarkersToShow(markersToShow);
        // } catch (CoreException e)
        // {
        // // TODO Auto-generated catch block
        // e.printStackTrace();
        // }

        return null;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (EditorUtil.getTLAEditorWithFocus() == null) {
			return false;
		}
		return super.isEnabled();
	}
	
    /**
     * TODO: This method has the following minor bug.  When Foo is defined in module
     * M, which is instantiated by  I == INSTANCE M, then when one of the OpApplNodes
     * in uses represents a subexpression name like I!Foo!2, then just the "I" rather
     * than the "I!Foo" is marked.  This is pretty harmless and is probably not worth
     * fixing.
     * 
     * @param uses
     * @param moduleName
     * @param spec
     */
    private static void setUseMarkers(SemanticNode[] uses, String moduleName, Spec spec)
    {
        Location[] locations = new Location[uses.length];
        for (int i = 0; i < locations.length; i++)
        {
            // Set stn to the syntax tree node whose location should
            // be used.
            SyntaxTreeNode stn = (SyntaxTreeNode) uses[i].stn;
            switch (stn.getKind()) {
            case N_OpApplication:
                stn = (SyntaxTreeNode) stn.heirs()[0];
                break;
            case N_InfixExpr:
            case N_PostfixExpr:
                stn = (SyntaxTreeNode) stn.heirs()[1];
                break;
            case N_GeneralId:
                // Following code added by LL on 14 Sep 2010 as part of fix
                // for handling uses of a defined symbol in a subexpression name.
                // For a use of Foo in a subexpression name like Foo!..., the
                // OpApplNode uses[i] will have as its subExpressionOf field
                // non-null and a SyntaxTreeNode representing a tree whose
                // left-most leaf SyntaxTreeNode is a syntactic element
                // representing "Foo". We recognize this SyntaxTreeNode because
                // if has a kind representing a syntactic element, which means
                // a kind less than NULL_ID.
                // Following code modified by LL on 17 Sep 2010 by adding second
                // conjunct of `if' test. It appears that, if an OpApplNode represents
                // the application of a defined operator, and not a subexpression name,
                // then its subExpression field equals (==) its operator field, rather
                // than being null.
                if (uses[i] instanceof OpApplNode)
                {
                    OpApplNode oan = (OpApplNode) uses[i];
                    if (oan.subExpressionOf != null && oan.subExpressionOf != oan.getOperator())
                    {
                        while (stn.getKind() > NULL_ID && stn.heirs() != null && stn.heirs().length > 0)
                        {
                            stn = (SyntaxTreeNode) stn.heirs()[0];
                        }
                    }
                }
                break;
            default:
            	TLAEditorActivator.getDefault().logWarning("Found unexpected kind " + stn.getKind() + " for stn node of symbol use.");
            }
            locations[i] = stn.getLocation();
        }
        Arrays.sort(locations, new LocationComparator());

        // Jump to the first location. This ensures that the module is
        // now displayed by the current editor. (At least, I hope this
        // happens synchronously.)
        UIHelper.jumpToLocation(locations[0]);
        spec.setCurrentSelection(0);

        // Get the resource on which markers are to go, and set the markers.
        IResource resource = ResourceHelper.getResourceByModuleName(spec.getModuleToShow());
        if (resource == null)
        {
        	TLAEditorActivator.getDefault().logWarning("Why is the resource null?");
            return;
        }

        try
        {
            // Remove all markers showing uses.
            resource.deleteMarkers(SHOW_USE_MARKER_TYPE, false, 99);
            spec.setMarkersToShow(null);

            IMarker[] markersToShow = new IMarker[locations.length];

            // create the markers and put them in this.markersToShow
            for (int i = 0; i < markersToShow.length; i++)
            {
                // The following is inefficient, because it's doing the same
                // computation each time to find the document from the
                // location.
                IRegion iregion = AdapterFactory.locationToRegion(locations[i]);
                IMarker marker;
                marker = resource.createMarker(SHOW_USE_MARKER_TYPE);
                Map<String, Integer> markerAttributes = new HashMap<String, Integer>(2);
                markerAttributes.put(IMarker.CHAR_START, new Integer(iregion.getOffset()));
                markerAttributes.put(IMarker.CHAR_END, new Integer(iregion.getOffset() + iregion.getLength()));
                marker.setAttributes(markerAttributes);
                markersToShow[i] = marker;
            }
            spec.setMarkersToShow(markersToShow);
        } catch (CoreException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * If strArray[i] equals str, then return i (for the smallest
     * such i); otherwise return -1;
     * 
     * @param strArray
     * @param str
     * @return
     */
    private static int selectString(String[] strArray, String str)
    {
        for (int i = 0; i < strArray.length; i++)
        {
            if (strArray[i].equals(str))
            {
                return i;
            }
        }
        return -1;
    }

    /**
     * A comparator to compare two locations.  It must only be used
     * to compare Location objects.
     * @author lamport
     *
     */
    private static class LocationComparator implements Comparator<Location>
    {
        public int compare(Location loc1, Location loc2)
        {
            // Most of this code is a clone from SemanticNode.compareTo
            if (loc1.beginLine() < loc2.beginLine())
            {
                return -1;
            }
            if (loc1.beginLine() > loc2.beginLine())
            {
                return 1;
            }
            if (loc1.beginColumn() == loc2.beginColumn())
            {
                return 0;
            }
            return (loc1.beginColumn() < loc2.beginColumn()) ? -1 : 1;
        }

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/dfid/MemFPIntSet.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp.dfid;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.RemoteException;

import tlc2.output.EC;
import tlc2.output.MP;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;
import util.WrongInvocationException;

/**
 * A <code>MemFPIntSet</code> is a subclass of <code>FPIntSet</code>
 * and a memory-based fingerprint set implementations.  As required by
 * <code>FPIntSet</code>, this class must guarantee that its methods
 * are thread-safe.
 */

public class MemFPIntSet extends FPIntSet {
  private String metadir;
  private String filename;

  /**
   * The load factor and initial capacity for the hashtable.
   */
  private static final int MaxLoad = 20;
  private static final int LogInitialCapacity = 16;

  /**
   * The hash table used to represent the set.
   */
  private int[][] table;

  /**
   * The total number of entries in the set.
   */
  private long count;

  /**
   * Rehashes the table when count exceeds this threshold.
   */
  private long threshold;
    
  /**
   * The bit-mask used in hashing fingerprints.  Relies on two assumptions:
   *  (1) table.length is a power of 2.
   *  (2) fingerprints are so random that extracting parts of their bits
   *      makes a good hash function.
   */
  private int mask;

  /* Constructs a new, empty FPSet.  */
  public MemFPIntSet() throws RemoteException {
    this(LogInitialCapacity, MaxLoad);
  }

  /* The following constructor is provided for test programs only. */
  public MemFPIntSet(int logInitialCapacity, int maxLoad) throws RemoteException {
    int initialCapacity = 1 << logInitialCapacity;
    this.count = 0;
    this.threshold = (initialCapacity * maxLoad);
    this.table = new int[initialCapacity][];
    this.mask = initialCapacity - 1;
  }

  public final void init(int numThreads, String metadir, String filename) {
    this.metadir = metadir;
    this.filename = filename;
  }
    
  /**
   * Returns the number of fingerprints in this set.
   * @return  the number of fingerprints in this set.
   */
  public final synchronized long size() { return this.count; }

  public final synchronized long sizeof() {
    long size = 28; // 8 (ptr table) + 8 (long count) + 8 (long threshold) + 4 (int mask)
    size += 16 + (this.table.length * 8); // for this.table
    for (int i = 0; i < this.table.length; i++) {
      if (this.table[i] != null) {
	size += 16 + (this.table[i].length * 4);
      }
    }
    return size;
  }

  public synchronized final void setLeveled(long fp) {
    int index = (int)(fp & this.mask);
    int[] list = this.table[index];

    // Test if the fingerprint is already in the hashtable.
    if (list != null) {
      int listlen = list.length;
      for (int i = 0; i < listlen; i += 3) {
	long fp1 = ((long)list[i] << 32) | ((long)list[i+1] & 0xFFFFFFFFL);
	if (fp1 == fp) {
	  list[i+2] = (list[i+2] & ~LeveledMask) | Leveled;
	  return;
	}
      }
    }

    throw new WrongInvocationException("MemFPIntSet.setLeveled: The fp must have been in the set.");
  }
  
  public synchronized final int setStatus(long fp, int status) {
    int index = (int)(fp & this.mask);
    int[] list = this.table[index];

    // Test if the fingerprint is already in the hashtable.
    if (list != null) {
      int listlen = list.length;
      for (int i = 0; i < listlen; i += 3) {
	long fp1 = ((long)list[i] << 32) | ((long)list[i+1] & 0xFFFFFFFFL);
	if (fp == fp1) {
	  int status1 = list[i+2];
	  list[i+2] = status1 | status;
	  // System.err.println("setStatus: " + fp + "  " + status1 + " -> " + this.getStatus(fp));
	  return status1;
	}
      }
    }

    if (count >= threshold) {
      // If the threshold is exceeded, rehash the table and recompute 
      // the index.
      this.rehash();
      index = (int)(fp & this.mask);
      list = this.table[index];
    } 

    // Creates the new entry.
    int len = (list == null ? 0 : list.length);
    int[] newList = new int[len+3];
    if (list != null) System.arraycopy(list, 0, newList, 0, len);
    newList[len] = (int)(fp >>> 32);
    newList[len+1] = (int)fp;
    newList[len+2] = (Level << 2) | Leveled | status;
    this.table[index] = newList;
    this.count++;
    // System.err.println("setStatus: " + fp + "  NEW -> " + this.getStatus(fp));
    return NEW;
  }

  public synchronized final int getStatus(long fp) {
    int index = (int)(fp & this.mask);
    int[] list = this.table[index];

    // Test if the fingerprint is already in the hashtable.
    if (list != null) {
      int listlen = list.length;
      for (int i = 0; i < listlen; i += 3) {
	long fp1 = ((long)list[i] << 32) | ((long)list[i+1] & 0xFFFFFFFFL);
	if (fp1 == fp) {
	  return list[i+2];
	}
      }
    }
    return NEW;
  }

  public final boolean allLeveled() {
    for (int i = 0; i < this.table.length; i++) {
      int[] bucket = this.table[i];
      if (bucket != null) {
	for (int j = 0; j < bucket.length; j += 3) {
	  if ((bucket[j+2] & LeveledMask) != Leveled) {
	    return false;
	  }
	}
      }
    }
    return true;
  }
  
  /**
   * Rehashes the contents of the hashtable into a hashtable with a 
   * larger capacity. This method is called automatically when the 
   * number of items in the hashtable exceeds this hashtable's capacity 
   * and load factor. 
   */
  private final void rehash() {
    long min = this.count, max = 0;
    int[][] oldTable = this.table;
    int oldCapacity = oldTable.length;
    int[][] newTable = new int[oldCapacity * 2][];
    final int onebitmask = oldCapacity;

    for (int i = 0; i < oldCapacity; i++) {
      int[] list = oldTable[i];
      if (list != null) {
	// The entries in list will be distributed over two arrays in
	// the new hash table.
	// count how big each list will be
	int cnt0 = 0;
	int cnt1 = 0;
	int listlen = list.length;
	if (listlen < min) min = listlen;
	if (listlen > max) max = listlen;
	for (int j = 0; j < listlen; j += 3) {
	  if ((list[j+1] & onebitmask) == 0)
	    cnt0 += 3;
	  else
	    cnt1 += 3;
	}
        	    
	// handle special cases if either list is empty
	if (cnt0 == 0) {
	  newTable[i+oldCapacity] = list;
	}
	else if (cnt1 == 0) {
	  newTable[i] = list;
	}
	else {
	  // allocate two new arrays
	  int[] list0 = new int[cnt0]; 
	  int[] list1 = new int[cnt1]; 
            	  
	  // copy the entries from the old list into the two new ones
	  for (int j = 0; j < listlen; j += 3) {
	    if ((list[j+1] & onebitmask) == 0) {
	      list0[cnt0-3] = list[j];
	      list0[cnt0-2] = list[j+1];
	      list0[cnt0-1] = list[j+2];
	      cnt0 -= 3;
	    }
	    else {
	      list1[cnt1-3] = list[j];
	      list1[cnt1-2] = list[j+1];
	      list1[cnt1-1] = list[j+2];
	      cnt1 -= 3;
	    }
	  }
            	    
	  // install new arrays in new table
	  newTable[i] = list0;
	  newTable[i+oldCapacity] = list1;
	}
      }
    }
    this.threshold *= 2;
    this.table = newTable;
    this.mask = newTable.length - 1;
  }

  public final void exit(boolean cleanup) throws IOException {
    if (cleanup) {
      // Delete the metadata directory:
      File file = new File(this.metadir);
      FileUtil.deleteDir(file, true);
    }
    String hostname = InetAddress.getLocalHost().getHostName();    
    MP.printMessage(EC.TLC_FP_COMPLETED, hostname);
    System.exit(0);    
  }

  public final long checkFPs() {
    long dis = Long.MAX_VALUE;
    for (int i = 0; i < this.table.length; i++) {
      int[] bucket = this.table[i];
      if (bucket != null) {
	for (int j = 0; j < bucket.length; j += 3) {
	  for (int k = j+3; k < bucket.length; k += 3) {
	    long x = ((long)bucket[j]) << 32 | bucket[j+1];
	    long y = ((long)bucket[k]) << 32 | bucket[k+1];
	    dis = Math.min(dis, Math.abs(x-y));
	  }
	  for (int k = i+1; k < this.table.length; k++) {
	    int[] bucket1 = this.table[k];
	    if (bucket1 != null) {
	      for (int m = 0; m < bucket1.length; m += 3) {
		long x = ((long)bucket[j]) << 32 | bucket[j+1];
		long y = ((long)bucket1[m]) << 32 | bucket1[m+1];
		long dis1 = (x > y) ? x-y : y-x;
		if (dis1 >= 0) {
		  dis = Math.min(dis, dis1);
		}
	      }
	    }
	  }
	}
      }
    }
    return dis;
  }

  // Checkpoint.
  public final void beginChkpt(String fname) throws IOException {
    BufferedDataOutputStream dos =
      new BufferedDataOutputStream(this.chkptName(fname, "tmp"));
    for (int i = 0; i < this.table.length; i++) {
      int[] bucket = this.table[i];
      if (bucket != null) {
	for (int j = 0; j < bucket.length; j++) {
	  dos.writeInt(bucket[j]);
	}
      }
    }
    dos.close();
  }
      
  final public void beginChkpt() throws IOException {
    this.beginChkpt(this.filename);
  }

  final public void commitChkpt(String fname) throws IOException {
    File oldChkpt = new File(this.chkptName(fname, "chkpt"));
    File newChkpt = new File(this.chkptName(fname, "tmp"));
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) {
      throw new IOException("MemFPIntSet.commitChkpt: cannot delete " + oldChkpt);
    }
  }
  
  final public void commitChkpt() throws IOException {
    this.commitChkpt(this.filename);
  }
    
  public final void recover(String fname) throws IOException {
    BufferedDataInputStream dis = 
      new BufferedDataInputStream(this.chkptName(fname, "chkpt"));
    try {
      while (!dis.atEOF()) {
	int fhi = dis.readInt();
	int flo = dis.readInt();
	int level = dis.readInt();

	if (count >= threshold) this.rehash();

	int index = (int)(flo & this.mask);
	int[] list = this.table[index];
	int len = (list == null ? 0 : list.length);
	int[] newList = new int[len+3];
	if (list != null) System.arraycopy(list, 0, newList, 0, len);
	newList[len] = fhi;
	newList[len+1] = flo;
	newList[len+2] = level;
	this.table[index] = newList;
	this.count++;
      }
    }
    catch (EOFException e) 
    {
      Assert.fail(EC.SYSTEM_DISK_IO_ERROR_FOR_FILE, "checkpoints");
    }
    dis.close();
  }
  
  final public void recover() throws IOException {
    this.recover(this.filename);
  }
    
  final private String chkptName(String fname, String ext) {
    return this.metadir + FileUtil.separator + fname + ".fp." + ext;
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/preference/IModelEditorPreferenceConstants.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.preference;

public interface IModelEditorPreferenceConstants {
	/**
	 * If set, the Evaluate Constant Expressions section of the Results page will be shown in its own model editor tab.
	 */
	public static final String I_MODEL_EDITOR_SHOW_ECE_AS_TAB = "showECEAsTab";

	/**
	 * The preference defining how the user would prefer to see overridden definitions displayed.
	 */
	public static final String I_OVERRIDDEN_DEFINITION_STYLE = "definitionOverrideStyle";
	/**
	 * The style of "Definition [Module Name]"
	 */
	public static final String I_OVERRIDDEN_DEFINITION_STYLE_MODULE_NAME = "byModuleName";
	/**
	 * The style of "InstanceVariableName!Definition" where there is a declaration in the code like:
	 * 		InstanceVariableName == INSTANCE ModuleName WITH ...
	 */
	public static final String I_OVERRIDDEN_DEFINITION_STYLE_INSTANCE_NAME = "byInstanceName";
}


<|start_filename|>tlatools/org.lamport.tlatools.consumer.distributed/src/org/lamport/tla/distributed/consumer/faulty/FaultyConsumer.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.distributed.consumer.faulty;

import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public abstract class FaultyConsumer {

	/**
	 * The upper bound for the sleep period between TLCServer connects and
	 * disconnects in seconds.
	 */
	private final int sleepUpperBound = Integer.getInteger(
			FaultyConsumer.class.getName() + ".sleep", 180);
	
	protected final Random rnd = new Random();
	
	protected final Executor executor = Executors.newSingleThreadExecutor();
	
	/**
	 * @param upperBound The upper bound for the thread to sleep
	 * @return The actual sleep time in seconds
	 */
	protected long sleep() {
		long seconds = rnd.nextInt(sleepUpperBound);
		try {
			// add least 1 second
			Thread.sleep((seconds + 1) * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return seconds;
	}

	/**
	 * @return true iff kill should be executed
	 */
	protected boolean shouldKill() {
		// draw from a uniform distribution
		return rnd.nextBoolean();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/HideAllProofsHandler.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.jface.text.ITextSelection;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.proof.IProofFoldCommandIds;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;

/**
 * Handler for command that hides all proofs in a module.
 * 
 * @author <NAME>
 *
 */
public class HideAllProofsHandler extends ProofFoldCommandHandler
{

    /**
     * This method is used to update the enablement state. This has the
     * effect of graying out any menu items for the
     * command if the handler is disabled. Through experimentation, this method seems to be
     * called just before such menu items are rendered in the UI and
     * just before the handler is executed.
     */
    public void setEnabled(Object context)
    {
        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();

        if (editor != null)
        {
            if (editor.getProofStructureProvider() != null)
            {
                setBaseEnabled(editor.getProofStructureProvider().canRunFoldOperation(
                        IProofFoldCommandIds.FOLD_ALL_PROOFS,
                        (ITextSelection) editor.getSelectionProvider().getSelection()));
            }
        }
    }
	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (EditorUtil.getTLAEditorWithFocus() == null) {
			return false;
		}
		return super.isEnabled();
	}

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/launch/IModelConfigurationDefaults.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.launch;

/**
 * Defaults for the model configuration
 * @author <NAME>
 * @version $Id$
 */
public interface IModelConfigurationDefaults extends IConfigurationDefaults
{
    /**
     * constant for no spec
     */
    public static final int MODEL_BEHAVIOR_TYPE_NO_SPEC = 0;
    /**
     * constant for spec as a single formula
     */
    public static final int MODEL_BEHAVIOR_TYPE_SPEC_CLOSED = 1;
    /**
     * constant for spec as init, next fairness
     */
    public static final int MODEL_BEHAVIOR_TYPE_SPEC_INIT_NEXT = 2;

    
    /**
     * Default if the closed specification is used
     */
    public static final int MODEL_BEHAVIOR_TYPE_DEFAULT = MODEL_BEHAVIOR_TYPE_SPEC_INIT_NEXT ; 
    
    
    
    /**
     * Default for checking the deadlock
     */
    public static final boolean MODEL_CORRECTNESS_CHECK_DEADLOCK_DEFAULT = true;
    
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/data/ErrorMessage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output.data;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.lamport.tla.toolbox.tool.prover.ui.ProverUIActivator;

/**
 * Class representing an error message sent by tlapm. Such messages
 * are sent if there is buggy behavior in tlapm. The message typically
 * contains some information to be reported to tlapm developers.
 * 
 * @author <NAME>
 *
 */
public class ErrorMessage extends TLAPMMessage
{

    /**
     * The field name whose value is the warning message. 
     */
    public static final String MSG_FIELD = "msg";
    /**
     * The field name whose value is a url. This url
     * can be used to submit bug reports.
     */
    public static final String URL_FIELD = "url";

    /**
     * The error message.
     */
    private String message;
    /**
     * The url contained in the message.
     */
    private String url;

    /**
     * Creates a new {@link ErrorMessage} from the {@link Set}
     * of {@link Entry} where the key of each {@link Entry} is the field
     * name and the value is the field value string as output by the TLAPM.
     * 
     * This method expects a field {@link #MSG_FIELD} and a field {@link #URL_FIELD}.
     * 
     * @param fieldPairs
     * @param moduleName
     * @return
     */
    public static ErrorMessage getErrorMessage(Set fieldPairs, String moduleName)
    {

        ErrorMessage message = new ErrorMessage();

        for (Iterator it = fieldPairs.iterator(); it.hasNext();)
        {
            Map.Entry nextEntry = (Map.Entry) it.next();
            String fieldName = (String) nextEntry.getKey();
            String fieldValue = (String) nextEntry.getValue();
            if (fieldName != null && fieldValue != null)
            {
                if (fieldName.equals(MSG_FIELD))
                {
                    message.message = fieldValue;
                } else if (fieldName.equals(URL_FIELD))
                {
                    message.url = fieldValue;
                } else
                {
                    ProverUIActivator.getDefault().logDebug("Unknown field name for warning message : " + fieldName + ".");
                }
            }
        }

        return message;

    }

    /**
     * Returns the error message from the tlapm.
     * 
     * @return
     */
    public String getMessage()
    {
        return message;
    }

    /**
     * Returns the String url from the tlapm.
     * 
     * @return
     */
    public String getURL()
    {
        return url;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/Changed.java<|end_filename|>
/****************************************************************************
 * CLASS Changed                                                            * 
 * last modified on Wed 31 Aug 2005 at 13:18:17 UT by keith                 *
 ****************************************************************************/

package pcal;

import java.util.Vector;

public class Changed {
	/*
	 * A Changed object is used when generating the actions to keep track
	 * of how many times a variable has been set in the conjuncts produced
	 * so far.  It's an error if the variable has been set more than once.
	 * If it has been set once, then uses of it in expressions must be
	 * replaced by their primed versions.
	 * 
	 * The object has two fields: 
	 *   vars: a vector of variable names.  It is set to the vector
	 *         of all variables.
	 *   count: an array whose i-th element is the number of times the
	 *          i-th variable in vars has been changed.
	 */
    public int[] count; /* number times variable set */
    public Vector vars; /* list of variables */

    public Changed (Vector vars) {
	count = new int[vars.size()];
	this.vars = vars;
	for (int i = 0; i < count.length; i++)
	    count[i] = 0;
    }

    public Changed (Changed c) {
	vars = c.vars;
	count = new int[vars.size()];
	for (int i = 0; i < count.length; i++)
	    count[i] = c.count[i];
    }

    public String toString () {
	String s = "[";
	for (int i = 0; i < count.length; i++)
	    s = s
		+ ((i == 0) ? "" : ", ")
		+ ((String) vars.elementAt(i))
		+ " "
		+ count[i];
	s = s + "]";
	return s;
    }

    public int Size() {
	return count.length;
    }

    public boolean IsChanged(String s) {
	for (int i = 0; i < count.length; i++)
	    if (s.equals((String) vars.elementAt(i)))
		return (count[i] > 0);
	return false;
    }

    public void Merge (Changed  c) {
	PcalDebug.Assert(count.length == c.count.length);
	for (int i = 0; i < count.length; i++)
	    count[i] = (count[i] > c.count[i]) ? count[i] : c.count[i];
    }

    public int Set (String v) {
	for (int i = 0; i < count.length; i++)
	    if (v.equals((String) vars.elementAt(i)))
		return ++count[i];
	return 0;
    }

    /* String of vars whose change count is 0 */
    public String Unchanged () {
	String s = "";
	for (int i = 0; i < count.length; i++)
	    if (count[i] == 0)
		s = s
		    + ((s.length() == 0) ? "" : ", ")
		    + (String) vars.elementAt(i);
	return s;
    }

    /* String of vars that were changed in c but not in this */
    public String Unchanged (Changed c) {
	String s = "";
	for (int i = 0; i < count.length; i++)
	    if ((count[i] == 0) && c.count[i] > 0)
		s = s
		    + ((s.length() == 0) ? "" : ", ")
		    + (String) vars.elementAt(i);
	return s;
    }
  
    /* Vector of strings of vars whose change count is 0 */
    /* Each string is no longer than ch characters       */
    /* (except for vars whose length is over ch-1)       */
    /* This method is called only once, from             */
    /* GenLabeledStmt.                                   */
    public Vector Unchanged (int ch) {
	Vector sv = new Vector();
	String s = "";
	boolean haveOne = false;
	for (int i = 0; i < count.length; i++)
	    if (count[i] == 0) {
		String one = (String) vars.elementAt(i);
		if (haveOne) s = s + ", ";
		else haveOne = true;
		if (s.length() + one.length() > ch) {
		    if (s.length() > 0) sv.addElement(s);
		    s = one;
		}
		else s = s + one;
	    }
	if  (s.length() > 0) sv.addElement(s);
	return sv;
    }

    /* String of vars that were changed in c but not in this */
    /* Each string is no longer than ch characters           */
    /* (except for vars whose length is over ch-1)           */
    public Vector Unchanged (Changed c, int ch) {
	Vector sv = new Vector();
	String s = "";
	boolean haveOne = false;
	for (int i = 0; i < count.length; i++)
	    if ((count[i] == 0) && c.count[i] > 0) {
		String one = (String) vars.elementAt(i);
		if (haveOne) s = s + ", ";
		else haveOne = true;
		if (s.length() + one.length() > ch) {
		    if (s.length() > 0) sv.addElement(s);
		    s = one;
		}
		else s = s + one;
	    }
	if  (s.length() > 0) sv.addElement(s);
	return sv;
    }
  
    /* Number of vars whose change count is 0 */
    public int NumUnchanged () {
	int ct = 0;
	for (int i = 0; i < count.length; i++)
	    if (count[i] == 0) ct = ct + 1;
	return ct;
    }

    /* Number of vars that were changed in c but not in this */
    public int NumUnchanged (Changed c) {
	int ct = 0;

	for (int i = 0; i < count.length; i++)
	    if ((count[i] == 0) && c.count[i] > 0)
		ct = ct + 1;
	return ct;
    }
  
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/MemFPSet2.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.tool.fp;

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.RemoteException;

import tlc2.output.EC;
import tlc2.output.MP;
import tlc2.tool.TLCTrace;
import util.Assert;
import util.BufferedDataInputStream;
import util.BufferedDataOutputStream;
import util.FileUtil;

/**
 * <code>MemFPSet2</code> is a subclass of {@link MemFPSet} that
 * implements a fingerprint set as a hashtable with a central spine
 * and collision buckets.
 * <P>
 * This class recognizes the following attribute in its
 * <code>alist</code> argument:
 * <PRE>
 * Name          Type     Default  Legal range  Meaning
 * ------------  -------  -------  -----------  ---------------------------------
 * LogSpineSize  Integer  24       [24 .. 30]   Log of size of hash table's spine
 * </PRE>
 * <P>
 * Collision buckets are implemented as arrays that are grown on
 * demand, one entry at a time.  The last 3 bytes of each fingerprint
 * is encoded in the bucket index, leaving 5 bytes to be stored in the
 * buckets.  Under the Compaq JVM with the <I>-fast64</I> flag,
 * pointers are 8 bytes long, and the overhead per array is 16 bytes
 * (8 bytes object overhead, 4 bytes padding, and 4 bytes for the
 * length field).  Assuming a spine size of 2<SUP>24</SUP>, the cost
 * of storing 2<SUP>30</SUP> fingerprints is 5.375 GB.
 */

public final class MemFPSet2 extends FPSet {
    private String metadir;
    private String filename;
  
    /* The hash table used to represent the set. */
    private byte[][] table;
    //@ invariant table.length > 0
    /*@ invariant (forall int i; 0 <= i & i < table.length ==>
            table[i] == null | (table[i].length / 5) * 5 ==  table[i].length) */
    
    /* The total number of entries in the set. */
    private long count;

    /* The bit-mask used in hashing fingerprints. Relies on two assumptions:
       <OL>
       <LI> <code>table.length</code> is a power of 2
       <LI> fingerprints are so random that extracting parts of their bits
            makes a good hash function.
       </OL>
     */
    private int mask;
    //@ invariant mask == table.length - 1

    private int LogSpineSize = 24;
  
  /* Constructs a new, empty FPSet. */
  public MemFPSet2(final FPSetConfiguration fpSetConfig) throws RemoteException {
	super(fpSetConfig);
    int spineSize = 1 << LogSpineSize;
    this.count = 0;
    this.table = new byte[spineSize][];
    this.mask = spineSize - 1;
  }
  
  public FPSet init(int numThreads, String metadir, String fname) {
    this.metadir = metadir;
    this.filename = metadir + FileUtil.separator + fname;
	return this;
  }

  public synchronized final long size() { return this.count; }
    
  public synchronized final boolean put(long fp) {
        int index = (int)(fp & this.mask);
        byte[] bucket = this.table[index];
        byte b1 = (byte)((fp >>> 24) & 0xffL);
        byte b2 = (byte)((fp >>> 32) & 0xffL);
        byte b3 = (byte)((fp >>> 40) & 0xffL);
        byte b4 = (byte)((fp >>> 48) & 0xffL);
        byte b5 = (byte)((fp >>> 56) & 0xffL);
        // Test if the fingerprint is already in the hashtable.
        int len = bucket == null ? 0 : bucket.length;
        for (int i = 0; i < len; i += 5) {
            if (bucket[i  ] == b1 && 
                bucket[i+1] == b2 && 
                bucket[i+2] == b3 && 
                bucket[i+3] == b4 && 
                bucket[i+4] == b5) return true;
        }
        // bucket is full 
        byte[] newBucket = new byte[len + 5];
        if (bucket != null) System.arraycopy(bucket, 0, newBucket, 0, len);
        this.table[index] = newBucket;
        newBucket[len  ] = b1;
        newBucket[len+1] = b2;
        newBucket[len+2] = b3;
        newBucket[len+3] = b4;
        newBucket[len+4] = b5;
        this.count++;
        return false;
  }

  public synchronized final boolean contains(long fp) {
    int index = (int)(fp & this.mask);
    byte[] bucket = this.table[index];
    byte b1 = (byte)((fp >>> 24) & 0xffL);
    byte b2 = (byte)((fp >>> 32) & 0xffL);
    byte b3 = (byte)((fp >>> 40) & 0xffL);
    byte b4 = (byte)((fp >>> 48) & 0xffL);
    byte b5 = (byte)((fp >>> 56) & 0xffL);
    // Test if the fingerprint is already in the hashtable.
    int len = bucket == null ? 0 : bucket.length;
    for (int i = 0; i < len; i += 5) {
      if (bucket[i  ] == b1 && 
	  bucket[i+1] == b2 && 
	  bucket[i+2] == b3 && 
	  bucket[i+3] == b4 && 
	  bucket[i+4] == b5) return true;
    }
    return false;
  }

  public final void exit(boolean cleanup) throws IOException {
	super.exit(cleanup);
    if (cleanup) {
      // Delete the metadata directory:
      FileUtil.deleteDir(this.metadir, true);
    }
    String hostname = InetAddress.getLocalHost().getHostName();    
    MP.printMessage(EC.TLC_FP_COMPLETED, hostname);
    System.exit(0);    
  }

  public final long checkFPs() {
    long dis = Long.MAX_VALUE;
    for (int i = 0; i < this.table.length; i++) {
      long low = i & 0xffffffL;	
      byte[] bucket = this.table[i];
      if (bucket != null) {
	int j = 0;
	while (j < bucket.length) {
	  long b1 = (bucket[j++] & 0xffL) << 24;
	  long b2 = (bucket[j++] & 0xffL) << 32;
	  long b3 = (bucket[j++] & 0xffL) << 40;
	  long b4 = (bucket[j++] & 0xffL) << 48;
	  long b5 = (bucket[j++] & 0xffL) << 56;
	  long fp = b5 | b4 | b3 | b2 | b1 | low;
	  int k = j;
	  while (k < bucket.length) {
	    b1 = (bucket[k++] & 0xffL) << 24;
	    b2 = (bucket[k++] & 0xffL) << 32;
	    b3 = (bucket[k++] & 0xffL) << 40;
	    b4 = (bucket[k++] & 0xffL) << 48;
	    b5 = (bucket[k++] & 0xffL) << 56;
	    long fp1 = b5 | b4 | b3 | b2 | b1 | low;
	    long dis1 = (fp > fp1) ? fp-fp1 : fp1-fp;
	    if (dis1 >= 0) {
	      dis = Math.min(dis, dis1);
	    }
	  }
	  for (k = i+1; k < this.table.length; k++) {
	    byte[] bucket1 = this.table[k];
	    if (bucket1 != null) {
	      long low1 = k & 0xffffffL;
	      int k1 = 0;
	      while (k1 < bucket.length) {
		b1 = (bucket[k1++] & 0xffL) << 24;
		b2 = (bucket[k1++] & 0xffL) << 32;
		b3 = (bucket[k1++] & 0xffL) << 40;
		b4 = (bucket[k1++] & 0xffL) << 48;
		b5 = (bucket[k1++] & 0xffL) << 56;
		long fp1 = b5 | b4 | b3 | b2 | b1 | low1;
		long dis1 = (fp > fp1) ? fp-fp1 : fp1-fp;
		if (dis1 >= 0) {
		  dis = Math.min(dis, dis1);
		}
	      }
	    }
	  }
	}
      }
    }
    return dis;
  }

  public final void beginChkpt(String fname) throws IOException {
    BufferedDataOutputStream dos =
      new BufferedDataOutputStream(this.chkptName(fname, "tmp"));
    for (int i = 0; i < this.table.length; i++) {
      long low = i & 0xffffffL;
      byte[] bucket = this.table[i];
      if (bucket != null) {
	int j = 0;
	while (j < bucket.length) {
	  long b1 = (bucket[j++] & 0xffL) << 24;
	  long b2 = (bucket[j++] & 0xffL) << 32;
	  long b3 = (bucket[j++] & 0xffL) << 40;
	  long b4 = (bucket[j++] & 0xffL) << 48;
	  long b5 = (bucket[j++] & 0xffL) << 56;
	  long fp = b5 | b4 | b3 | b2 | b1 | low;
	  dos.writeLong(fp);
	}
      }
    }
    dos.close();
  }

  final public void commitChkpt(String fname) throws IOException {
    File oldChkpt = new File(this.chkptName(fname, "chkpt"));
    File newChkpt = new File(this.chkptName(fname, "tmp"));
    if ((oldChkpt.exists() && !oldChkpt.delete()) ||
	!newChkpt.renameTo(oldChkpt)) 
    {
      throw new IOException("MemFPSet2.commitChkpt: cannot delete " + oldChkpt);
    }
  }
    
  public final void recover(String fname) throws IOException {
    BufferedDataInputStream dis = 
      new BufferedDataInputStream(this.chkptName(fname, "chkpt"));
    try {
      while (!dis.atEOF()) {
	Assert.check(!this.put(dis.readLong()), EC.TLC_FP_NOT_IN_SET);
      }
    }
    catch (EOFException e) 
    {
        throw new IOException("MemFPSet2.recover: failed.");
    }
    dis.close();
  }

  public final void beginChkpt() throws IOException {
    this.beginChkpt(this.filename);
  }

  public final void commitChkpt() throws IOException {
    this.commitChkpt(this.filename);
  }

  public final void recover(TLCTrace trace) throws IOException {
    this.recover(this.filename);
  }

  public final void recoverFP(long fp) throws IOException {
    Assert.check(!this.put(fp), EC.TLC_FP_NOT_IN_SET);
  }
  
  final private String chkptName(String fname, String ext) {
    return this.metadir + FileUtil.separator + fname + ".fp." + ext;
  }
    
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/MemIntStack.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:33 PST by lamport
//      modified on Thu Jan 10 18:33:42 PST 2002 by yuanyu

package tlc2.util;

public final class MemIntStack extends MemBasedSet implements IntStack {
	private static final int MIN_CAPACITY = 1024;

	public MemIntStack(String diskdir, String name) {
		super(MIN_CAPACITY);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#pushInt(int)
	 */
	public final synchronized void pushInt(int x) {
		if (this.size == this.elems.length) {
			final int[] newElems = ensureCapacity(MIN_CAPACITY);
			System.arraycopy(elems, 0, newElems, 0, this.size);
			this.elems = newElems;
		}
		this.elems[this.size] = x;
		this.size++;
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#pushLong(long)
	 */
	public final synchronized void pushLong(long x) {
		this.pushInt((int) (x & 0xFFFFFFFFL));
		this.pushInt((int) (x >>> 32));
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#popInt()
	 */
	public final synchronized int popInt() {
		return this.elems[--this.size];
	}

	public final synchronized int peakInt() {
		return peakInt(size - 1);
	}

	public final synchronized int peakInt(int pos) {
		return this.elems[pos];
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#popLong()
	 */
	public final synchronized long popLong() {
		long high = this.popInt();
		long low = this.popInt();
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	public final synchronized long peakLong() {
		long high = this.peakInt();
		long low = this.peakInt();
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	public final synchronized long peakLong(int pos) {
		long high = this.peakInt(pos + 1);
		long low = this.peakInt(pos);
		return (high << 32) | (low & 0xFFFFFFFFL);
	}

	/* (non-Javadoc)
	 * @see tlc2.util.IntStack#reset()
	 */
	public final void reset() {
		this.size = 0;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/debug/TLCStateStackFrame.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.debug;

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.lsp4j.debug.Scope;
import org.eclipse.lsp4j.debug.Variable;

import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolNode;
import tlc2.TLCGlobals;
import tlc2.tool.Action;
import tlc2.tool.EvalException;
import tlc2.tool.TLCState;
import tlc2.tool.TLCStateInfo;
import tlc2.tool.TLCStateMutExt;
import tlc2.tool.impl.DebugTool;
import tlc2.tool.impl.Tool;
import tlc2.util.Context;
import tlc2.value.IValue;
import tlc2.value.impl.LazyValue;
import tlc2.value.impl.RecordValue;
import tlc2.value.impl.StringValue;
import util.Assert.TLCRuntimeException;
import util.UniqueString;

public class TLCStateStackFrame extends TLCStackFrame {
	
	@SuppressWarnings("serial")
	public static class DebuggerValue extends StringValue {
		// A placeholder for the value of a variable that has not yet been evaluated.
		static final String NOT_EVALUATED = "?";

		private DebuggerValue() {
			super(UniqueString.of(DebuggerValue.NOT_EVALUATED));
		}

		@Override
		public StringBuffer toString(StringBuffer sb, int offset, boolean swallow) {
			return sb.append("?");
		}
		
		@Override
		public String getKindString() {
			// Let's not NPE if somebody ever calls getKindString.
			return getTypeString();
		}

		@Override
		public String getTypeString() {
			// Don't show the meaningless string "DebuggerValue" but "Evaluation pending" if
			// a user hovers over this value in the variables view.
			return "Evaluation pending... (value has not be determined yet)";
		}
	}
	
	public static final DebuggerValue NOT_EVAL = new DebuggerValue();
	
	public static final String SCOPE = "State";

	public static final String TRACE = "Trace";

	protected transient final TLCState state;
	protected transient final int stateId;

	public TLCStateStackFrame(TLCStackFrame parent, SemanticNode node, Context ctxt, Tool tool, TLCState state) {
		this(parent, node, ctxt, tool, state, null);
	}

	public TLCStateStackFrame(TLCStackFrame parent, SemanticNode node, Context ctxt, Tool tool, TLCState state,
			RuntimeException e) {
		super(parent, node, ctxt, tool, e);
		this.state = state.deepCopy();
		assert this.state instanceof TLCStateMutExt;
		
		// Tempting to use state.fingerprint/hashCode, but would normalize all values as(
		// a side effect.
		this.stateId = rnd.nextInt(Integer.MAX_VALUE - 1) + 1;
	}
	
	protected TLCState getS() {
		return getT();
	}
	
	protected TLCState getT() {
		return state;
	}

	Variable[] getTrace() {
		return getVariables(stateId + 1);
	}

	@Override
	public Variable[] getVariables(int vr) {
		if (vr == stateId) {
			return tool.eval(() -> {
				return new Variable[] { toVariable() };
			});
		}
		if (vr == stateId + 1) {
			return ((DebugTool) tool).eval(() -> {
				try {
					// A) Last state of the trace s_f.
					final TLCState t = getT();
					
					if (t.getPredecessor() == null) {
						assert t.isInitial();
						// No need to re-construct a trace if this.state is an initial state. Note that
						// getTrace(s)/getTraceInfo(s) below would return a trace, but a check at the
						// beginning seems easier.
						return new Variable[] { getStateAsVariable(new RecordValue(t, NOT_EVAL), "1: "
								+ (t.hasAction() ? t.getAction().getLocation() : TLCStateInfo.INITIAL_PREDICATE)) };
					}
					
					final Deque<Variable> trace = new ArrayDeque<>();
					trace.add(
							getStateAsVariable(new RecordValue(t, NOT_EVAL), t.getLevel() + ": " + t.getAction().getLocation()));

					final TLCStateInfo[] prefix;
					if (TLCGlobals.simulator != null) {
						prefix = TLCGlobals.simulator.getTraceInfo(t.getLevel() - 1);
					} else {
						// B) Suffix from s_f to either an initial state or a state whose predecessor
						// has to be looked up from disk (s_d).
						TLCState last = t;
						TLCState s = t;
						while ((s = s.getPredecessor()) != null) {
							if (s.isInitial()) {
								trace.add(getStateAsVariable(new RecordValue(s, NOT_EVAL),
										"1: " + (s.hasAction() ? s.getAction().getLocation()
												: TLCStateInfo.INITIAL_PREDICATE)));
								return trace.toArray(new Variable[trace.size()]);
							}
							trace.add(getStateAsVariable(new RecordValue(s, NOT_EVAL),
									s.getLevel() + ": " + s.getAction().getLocation()));
							last = s;
						}
						
						// C) The prefix from an initial state s_i to the predecessor of s_d. We can
						// assert that s_d is no initial state, it will *not* be part of prefix.
						final List<TLCStateInfo> arrayList = new ArrayList<>(
								Arrays.asList(TLCGlobals.mainChecker.getTraceInfo(last)));
						prefix = arrayList.toArray(TLCStateInfo[]::new);
					}

					// Combine and convert the trace into debugger Variables. It's in
					// reverse order because the variable view shows the current state in the
					// "State" node (SCOPE) above Trace; if a user ignores the "State" and "Trace"
					// nodes, it almost reads like a regular trace.
					for (int i = prefix.length - 1; i >= 0; i--) {
						final TLCStateInfo ti = prefix[i];
						trace.add(getStateAsVariable(new RecordValue(ti.state),
								// The name of the variable has to be unique for all states to show up in the
								// variable view. Otherwise, the variable view will silently discard all but on
								// of the variable with the same name. Thus, we prepend the state number, which
								// also make it easier for users to understand how states are ordered.
								ti.state.getLevel() + ": " + ti.info.toString()));
					}
					
					return trace.toArray(new Variable[trace.size()]);
				} catch (IOException e) {
					//TODO: Handle exception case.
					return new Variable[0];
				}
			});
		}
		return super.getVariables(vr);
	}

	protected Variable toVariable() {
		return getStateAsVariable(toRecordValue(), getActionName(getT()));
	}

	private String getActionName(final TLCState state) {
		if (state.getAction() == null) {
			return "<Initial predicate>";
		}
		final Action a = state.getAction();
		return a.getName() == null ? "Action" : a.getName().toString();
	}
	
	protected RecordValue toRecordValue() {
		return new RecordValue(getT(), NOT_EVAL);
	}

	Variable[] getStateVariables() {
		return getVariables(stateId);
	}

	@Override
	protected Variable getVariable(final LinkedList<SemanticNode> path) {
		assert !path.isEmpty();
		
		if (!isPrimeScope(path)) {
			SymbolNode var = tool.getVar(path.getFirst(), ctxt, false, tool.getId());
			if (var != null) {
				final IValue value = getS().lookup(var.getName());
				if (value != null) {
					return getVariable(value, var.getName());
				} else {
					Variable v = new Variable();
					v.setName(var.getName().toString());
					v.setValue(DebuggerValue.NOT_EVALUATED);
					return v;
				}
			}
		} else if (isPrimeScope(path)) {
			// TLCStateStackFrame implies that there is no successor state, probably because
			// the stack frame belongs to the evaluation of the initial predicate, an
			// invariant, a state-constraint...  In this scope, a primed variable has no value.
			final Variable variable = new Variable();
			variable.setName(path.getFirst().getHumanReadableImage());
			variable.setValue(path.getFirst().getLocation().toString());
			return variable;
		}
		return super.getVariable(path);
	}
	
	protected boolean isPrimeScope(LinkedList<SemanticNode> path) {
		for (SemanticNode semanticNode : path) {
			if (semanticNode instanceof OpApplNode) {
				OpApplNode oan = (OpApplNode) semanticNode;
				if (ASTConstants.OP_prime == oan.getOperator().getName()) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public Scope[] getScopes() {
		final List<Scope> scopes = new ArrayList<>();
		scopes.addAll(Arrays.asList(super.getScopes()));
		
		// TODO: Consider merging SCOPE and TRACE. The separation, however, makes sure
		// that we only pay the price for re-constructing the error-trace if a user
		// actually expands the Trace node in the variable view, which I assume to
		// happen less often than expanding the current state (SCOPE).
		// Alternatively, we could cache the re-constructed trace while a user steps
		// through an action, i.e. while the trace doesn't change.  Traversing
		// up the TLCStackFrame stack is already implemented by
		// tlc2.debug.TLCStackFrame.getStackVariables(List<Variable>). For simulation,
		// we get the trace for free though.  There would be no need to cache it.
		Scope scope = new Scope();
		scope.setName(getScope());
		scope.setVariablesReference(stateId);
		scopes.add(scope);
		
		scope = new Scope();
		scope.setName(TRACE);
		scope.setVariablesReference(stateId + 1);
		scopes.add(scope);
		
		return scopes.toArray(new Scope[scopes.size()]);
	}

	protected String getScope() {
		return SCOPE;
	}

	@Override
	protected Object unlazy(LazyValue lv) {
		return unlazy(lv, null);
	}
	
	@Override
	protected Object unlazy(final LazyValue lv, final Object fallback) {
		try {
			return tool.eval(() -> {
				return lv.eval(tool, getS());
			});
		} catch (TLCRuntimeException | EvalException e) {
			return fallback == null ? e : fallback;
		}
	}

	@Override
	public boolean matches(final TLCSourceBreakpoint bp) {
		if (super.matches(bp)) {
			if (bp.getHits() > 0) {
				// TODO: getLast here to have uniform hit count for actions an their
				// state-constraint.
				return getT().getLevel() >= bp.getHits(); 
			}
			return true;
		}
		return false;
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/ICoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class ICoverageTest extends AbstractCoverageTest {

    public ICoverageTest () {
        super("I");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "1"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "20", "5", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertCoverage("<Action line 11, col 9 to line 11, col 25 of module I>: 5:5\n" + 
				"  line 11, col 9 to line 11, col 25 of module I: 5\n" + 
				"  |line 11, col 15 to line 11, col 25 of module I: 1:6\n" + 
				"<Action line 11, col 52 to line 11, col 55 of module I>: 0:15\n" + 
				"  line 11, col 52 to line 11, col 52 of module I: 15\n" +
				"  |line 8, col 1 to line 9, col 22 of module I: 15\n" + 
				"  ||line 9, col 8 to line 9, col 22 of module I: 15\n" + 
				"  ||line 8, col 9 to line 8, col 15 of module I: 15\n" + 
				"  line 11, col 54 to line 11, col 54 of module I: 15\n" +
				"<Inv line 13, col 1 to line 13, col 3 of module I>\n" + 
				"  line 13, col 8 to line 13, col 34 of module I: 5\n" + 
				"  |line 13, col 27 to line 13, col 34 of module I: 15\n" + 
				"  |line 13, col 17 to line 13, col 24 of module I: 5");
		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/FPSetFactory.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.fp;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import tlc2.TLCGlobals;
import tlc2.output.EC;
import tlc2.output.MP;
import util.TLCRuntime;
import util.TLCRuntime.ARCH;

public abstract class FPSetFactory {

	/**
	 * System property with which a consumer defines the class name of the
	 * {@link FPSet} implementation to use.
	 */
	public static final String IMPL_PROPERTY = FPSet.class.getName() + ".impl";
	
	private static boolean allocatesOnHeap(final Class<? extends FPSet> clazz) {
		return !OffHeapDiskFPSet.class.isAssignableFrom(clazz);
	}

	public static boolean allocatesOnHeap(final String clazz) {
		try {
			final ClassLoader classLoader = FPSet.class.getClassLoader();
			@SuppressWarnings("unchecked")
			Class<? extends FPSet> cls = (Class<? extends FPSet>) classLoader
					.loadClass(clazz);
			return allocatesOnHeap(cls);
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	private static boolean supportsArchitecture(String clazz) {
		try {
			final ClassLoader classLoader = FPSet.class.getClassLoader();
			@SuppressWarnings("unchecked")
			Class<? extends FPSet> cls = (Class<? extends FPSet>) classLoader
					.loadClass(clazz);
			return supports32Bits(cls);
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	private static boolean supports32Bits(final Class<? extends FPSet> clazz) {
		if (TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86
				&& OffHeapDiskFPSet.class.isAssignableFrom(clazz)) {
			return false;
		}
		return true;
	}
	
	private static boolean isDiskFPSet(Class<? extends FPSet> cls) {
		return DiskFPSet.class.isAssignableFrom(cls);
	}

	static boolean isDiskFPSet(final String clazz) {
		try {
			final ClassLoader classLoader = FPSet.class.getClassLoader();
			@SuppressWarnings("unchecked")
			Class<? extends FPSet> cls = (Class<? extends FPSet>) classLoader
					.loadClass(clazz);
			return isDiskFPSet(cls);
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	/**
	 * @see getFPSet
	 * @return
	 * @throws RemoteException 
	 */
	public static FPSet getFPSet() throws RemoteException {
		return getFPSet(new FPSetConfiguration());
	}

	/**
	 * Creates a new {@link FPSet} depending on what the caller wants.
	 * @param fpBits if 0, a {@link DiskFPSet} will be returned, a {@link MultiFPSet} otherwise.
	 * @param fpMemSizeInBytes
	 * @return
	 * @throws RemoteException
	 */
	public static FPSet getFPSet(final FPSetConfiguration fpSetConfig) throws RemoteException {
		
		final String implClassname = fpSetConfig.getImplementation();
		
		// fpBits > 0 indicates that the consumer requires a MultiFPSet
		if (fpSetConfig.allowsNesting()) {
			// Pass physical memory instead of logical FP count to adhere to
			// the general FPSet ctor contract.
			// @see http://bugzilla.tlaplus.net/show_bug.cgi?id=290
			return new MultiFPSet(fpSetConfig);
		} else {
			if (implClassname != null) {
				if (supportsArchitecture(implClassname)) {
					return loadImplementation(implClassname, fpSetConfig);
				} else {
					final ARCH architecture = TLCRuntime.getInstance().getArchitecture();
					final String msg = String.format(
							"Selected fingerprint set (set of visited states) %s does not support current architecture %s. "
									+ "Reverting to default fingerprint set. "
									+ "Off-heap memory allocated via -XX:MaxDirectMemorySize flag cannot be used by default "
									+ "fingerprint set and is therefore wasted.",
							implClassname, architecture);
					MP.printWarning(EC.TLC_FEATURE_UNSUPPORTED, msg);
				}
			}
			return new MSBDiskFPSet(fpSetConfig);
		}
	}
	

	/**
	 * Create and *initialize* the set.
	 */
	public static Future<FPSet> getFPSetInitialized(final FPSetConfiguration fpSetConfiguration, final String metadir,
			final String mainFile) {
		final ExecutorService es = Executors.newSingleThreadExecutor();
		return es.submit(new Callable<FPSet>() {
			@Override
			public FPSet call() throws Exception {
				try {
					final FPSet fpSet = FPSetFactory.getFPSet(fpSetConfiguration);
					fpSet.init(TLCGlobals.getNumWorkers(), metadir, mainFile);
					return fpSet;
				} finally {
					es.shutdown();
				}
			}
		});
	}

	/**
	 * @return A list of classes implementing {@link FPSet}. Eventually this
	 *         list should be constructed dynamically during runtime.
	 */
	public static String[] getImplementations() {
		final List<String> l = new ArrayList<String>();
		
		l.add(MSBDiskFPSet.class.getName());
		l.add(LSBDiskFPSet.class.getName());
		l.add(OffHeapDiskFPSet.class.getName());

		return l.toArray(new String[l.size()]);
	}

	/**
	 * @return The default for {@link FPSet#getImplementations()}
	 */
	public static String getImplementationDefault() {
		return MSBDiskFPSet.class.getName();
	}

	/**
	 * @param clazz FPSet implementation to use
	 * @param memory Memory dedicated to the FPSet implementation in MiB
	 * @return
	 */
	public static String getVMArguments(final String clazz, final long memory) {
		if (allocatesOnHeap(clazz)) {
			return "-Xmx" + memory + "m";
		} else {
			return "-XX:MaxDirectMemorySize=" + memory + "m";
		}
	}

	/**
	 * This block of code tries to load the given class with the FPSet class
	 * loader. Thus, the class has to be available to it.
	 * 
	 * @param clazz
	 * @param fpMemSizeInBytes 
	 * @param fpBits 
	 * @return
	 */
	private static FPSet loadImplementation(final String clazz, final FPSetConfiguration fpSetConfig) {
		Exception exp = null;
		try {
			// poor mans version of modularity, booh!
			final ClassLoader classLoader = FPSet.class.getClassLoader();
			final Class<?> factoryClass = classLoader.loadClass(clazz);
			
//			// HACK class loading to pass _non heap_ memory into subclasses of
//			// OffHeapFPSet.
//			if (!allocatesOnHeap(clazz)) {
//				long l = TLCRuntime.getInstance().getNonHeapPhysicalMemory() / (long) LongSize;
//				// divide l among all FPSet instances
//				fpMemSizeInFPs = l >> fpBits; 
//			}

			final Constructor<?> constructor = factoryClass
					.getDeclaredConstructor(new Class[] { FPSetConfiguration.class });
			final Object instance = constructor.newInstance(
					fpSetConfig);
			// sanity check if given class from string implements FPSet
			if (instance instanceof FPSet) {
				return (FPSet) instance;
			}
		} catch (ClassNotFoundException e) {
			exp = e;
		} catch (InstantiationException e) {
			exp = e;
		} catch (IllegalAccessException e) {
			exp = e;
		} catch (SecurityException e) {
			exp = e;
		} catch (NoSuchMethodException e) {
			exp = e;
		} catch (IllegalArgumentException e) {
			exp = e;
		} catch (InvocationTargetException e) {
			exp = e;
		}
		// LL modified error message on 7 April 2012
		MP.printWarning(EC.GENERAL, "unsuccessfully trying to load custom FPSet class: " + clazz, exp);
		return null;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui.test/src/org/lamport/tla/toolbox/tool/tlc/ui/util/FormHelperTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import junit.framework.TestCase;

/**
 * @author <NAME>
 * @version $Id$
 */
public class FormHelperTest extends TestCase
{

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
    }

    public void testIsIdetifier()
    {

        assertFalse(FormHelper.isIdentifier(""));
        assertFalse(FormHelper.isIdentifier(null));
        assertTrue(FormHelper.isIdentifier("ksdhf"));
        assertTrue(FormHelper.isIdentifier("090a0909"));
        assertFalse(FormHelper.isIdentifier("ksd hf"));

        assertFalse(FormHelper.isIdentifier("ksd hf"));
        assertFalse(FormHelper.isIdentifier("0000"));
        assertFalse(FormHelper.isIdentifier("000_111"));
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/pcal/PCalWordDetector.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.pcal;

import org.eclipse.jface.text.rules.IWordDetector;
import org.lamport.tla.toolbox.editor.basic.tla.TLAWordDetector;

public class PCalWordDetector extends TLAWordDetector implements IWordDetector {

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.editor.basic.tla.TLAWordDetector#isWordPart(char)
	 */
	@Override
	public boolean isWordPart(final char character) {
		if (character == ':' || character == '=') {
			// Detect assignment ":=" as word.
			return true;
		} else if (character == '|') {
			// Detect multi-assignment "||" as word.
			return true;
		}
		return super.isWordPart(character);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/output/TagBasedTLAPMOutputIncrementalParser.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui.output;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.lamport.tla.toolbox.tool.prover.job.ProverJob;
import org.lamport.tla.toolbox.tool.prover.output.IProverProcessOutputSink;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ErrorMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ObligationNumberMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.ObligationStatusMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.StepStatusMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.TLAPMMessage;
import org.lamport.tla.toolbox.tool.prover.ui.output.data.WarningMessage;
import org.lamport.tla.toolbox.tool.prover.ui.util.ProverHelper;

/**
 * This class is used to parse raw output from
 * the TLAPM to produce instances of {@link TLAPMMessage}
 * to describe that output. It creates resource markers
 * representing the information from the messages.
 * 
 * The first implementation stored output in a source, but
 * we decided that caching this information is unnecessary.
 * Markers are used instead.
 * 
 * Output from the prover comes in the following generic
 * form:
 * 
 * @!!BEGIN
 * @!!<field-name>:<field-value>
 * @!!<field-name>:<field-value>
 * .
 * .
 * .
 * @!!END
 * 
 * TLAPM output streams into this class through calls of
 * {@link TagBasedTLAPMOutputIncrementalParser#addIncrement(String)},
 * 
 * See {@link TagBasedTLAPMOutputIncrementalParser#addIncrement(String)}
 * for the parsing algorithm.
 * 
 * @author <NAME>
 *
 */
public class TagBasedTLAPMOutputIncrementalParser implements IProverProcessOutputSink
{

    /**
     * The buffer that holds the current string of text out of which
     * messages can be parsed.
     */
    private StringBuilder currentSearchTextBuffer;
    /**
     * The module on which the prover was launched.
     */
    private IFile moduleFile;
    /**
     * The description of the prover launch.
     * Contains information about
     * the parameters used to launch the prover.
     */
    private ProverJob proverJob;
    /**
     * The monitor that can
     * be used to report information about progress.
     * In particular, it should be used to report
     * progress on obligation processing.
     */
    private IProgressMonitor monitor;
    /**
     * Flag indicating that this parser has encountered
     * a start tag but has not yet found its matching
     * end tag.
     */
    private boolean inMessage = false;

    public static final String DELIM = "@!!";
    public static final String START_TAG = DELIM + "BEGIN";
    public static final String END_TAG = DELIM + "END";

    /**
     * Called to stream text into this parser.
     * 
     * This method creates instances of {@link TLAPMMessage} and
     * process them according to their type.
     * 
     * See the comments within the method for the parsing algorithm.
     * 
     * @param text
     * @throws BadLocationException
     */
    public void appendText(String text)
    {
        /*
         * The following sends each string between a
         * begin and end tag to be parsed into
         * an instance of TLAPMMessage.
         * 
         * Every piece of text to this method is appended to the
         * current search text buffer. This method executes
         * the following algorithm while one of the following
         * conditions is true:
         * 
         * A.) This parser has encountered a start tag without an end
         * tag previously and there is at least one end tag in currentSearchTextBuffer.
         * 
         * B.) This parser has not encountered a start tag without an end
         * tag previously and there is at least one start tag in currentSearchTextBuffer.
         * 
         * The loop:
         * 
         * 1.) If this parser has encountered a start tag without an end
         * tag previously, then there is at least one end tag in the buffer because
         * we are in this loop. Everything from the beginning of currentSearchTextBuffer
         * to the beginning of the first end tag in currentSearchTextBuffer is
         * a message. Parse that into an instance of TLAPMMessage, then remove
         * everything from the beginning of currentSearchTextBuffer to the end
         * of the first end tag. Set the flag indicating that we have NOT encountered
         * a start tag without an end tag.
         * 
         * 2.) If this parser has not encountered a start tag without an end
         * tag previously, then there is at least on start tag in this buffer
         * because we are in this loop. Remove everything from the beginning
         * of currentSearchTextBuffer to the end of the first start tag. Set
         * the flag indicating that we have encountered a start
         * tag without an end tag.
         * 
         * 3.) After either step 1 or step 2 has been completed, search for the next
         * tag. If this parser has previously encountered a start tag without an end
         * tag, search for an end tag. Else search for a start tag.
         * 
         * Note: the boolean inMessage is true iff this parser has previously encountered a
         * start tag without a matching end tag.
         */
        currentSearchTextBuffer.append(text);
        /*
         * tagIndex is the index of the tag we are looking for.
         * If this parser has encountered a start tag without an end
         * tag previously, then we are looking for an end tag. Else, we are looking
         * for a start tag.
         */
        int tagIndex = -1;
        if (inMessage)
        {
            tagIndex = currentSearchTextBuffer.indexOf(END_TAG);
        } else
        {
            tagIndex = currentSearchTextBuffer.indexOf(START_TAG);
        }

        while (tagIndex != -1)
        {
            if (inMessage)
            {
                /* This parser has encountered a start tag without an end
                 * tag previously, then there is at least one end tag in the buffer because
                 * we are in this loop. Everything from the beginning of currentSearchTextBuffer
                 * to the beginning of the first end tag in currentSearchTextBuffer is
                 * a message. Parse that into an instance of TLAPMMessage, then remove
                 * everything from the beginning of currentSearchTextBuffer to the end
                 * of the first end tag. Set the flag indicating that we have NOT encountered
                 * a start tag without an end tag.
                 * 
                 * Process the parsed message as indicated below.
                 */

                TLAPMMessage data = TLAPMMessage.parseMessage(currentSearchTextBuffer.substring(0, tagIndex),
                        moduleFile.getLocation().removeFileExtension().lastSegment());

                currentSearchTextBuffer.replace(0, tagIndex + END_TAG.length(), "");

                inMessage = false;

                if (data != null)
                {

                    /*
                     * Create the appropriate marker for the
                     * message. If the message is step status inform ProverHelper
                     * using ProverHelper.newStepStatusMessage(). If this is a
                     * launch for status checking, then the toolbox does not compute
                     * step statuses itself, so the step status messages must be used
                     * to update status markers. This means that the flag addMarker
                     * in the method newStepStatusMessage should be set to true.
                     * 
                     * If the message is an obligation
                     * status, create an obligation status marker.
                     * 
                     * If the message gives the number of obligations
                     * to be checked, then update the progress monitor
                     * for this parser to indicate this. If the message is an
                     * ObligationStatusMessage that indicates that
                     * the TLAPM is done processing the obligation in any
                     * way, then the monitor will reflect this fact.
                     * 
                     * If the message is a warning message, call the appropriate
                     * method in prover helper that processes warning messages.
                     */

                    if (data instanceof ObligationStatusMessage)
                    {
                        ProverHelper.processObligationMessage((ObligationStatusMessage) data, proverJob);

                        if (ProverHelper.isObligationFinished((ObligationStatusMessage) data, proverJob))
                        {
                            /*
                             * Indicate to the progress monitor to move 1/totalNumObligations fraction
                             * to the right.
                             */
                            monitor.worked(1);
                        }
                    } else if (data instanceof ObligationNumberMessage)
                    {
                        ObligationNumberMessage numMessage = (ObligationNumberMessage) data;
                        /*
                         * The call to begin task sets the text that appears above the progress
                         * bar. It also sets the total number of units of work. In this case, one
                         * unit of work is 1 obligation "finished". Then, when this class later
                         * calls monitor.worked(1), the progress bar will move 1/totalNumObligations
                         * fraction to the right.
                         * 
                         * The call to subtask sets the text that appears below the progress bar.
                         */
                        monitor.beginTask(proverJob.getProverJobTaskName(), numMessage.getCount());
                        monitor.subTask("Processing Obligations : " + numMessage.getCount() + " total.");
                    } else if (data instanceof StepStatusMessage)
                    {
                        ProverHelper.newStepStatusMessage((StepStatusMessage) data, proverJob);
                    } else if (data instanceof WarningMessage)
                    {
                        ProverHelper.processWarningMessage((WarningMessage) data);
                    } else if (data instanceof ErrorMessage)
                    {
                        ProverHelper.processErrorMessage((ErrorMessage) data);
                    }
                }

            } else
            {
                /*
                 * This parser has not encountered a start tag without an end
                 * tag previously, so there is at least on start tag in this buffer
                 * because we are in this loop. Remove everything from the beginning
                 * of currentSearchTextBuffer to the end of the first start tag. Set
                 * the flag indicating that we have encountered a start
                 * tag without an end tag.
                 */
                currentSearchTextBuffer.replace(0, tagIndex + START_TAG.length(), "");
                inMessage = true;
            }

            /*
             * tagIndex is the index of the tag we are looking for.
             * If this parser has encountered a start tag without an end
             * tag previously, then we are looking for an end tag. Else, we are looking
             * for a start tag.
             */
            if (inMessage)
            {
                tagIndex = currentSearchTextBuffer.indexOf(END_TAG);
            } else
            {
                tagIndex = currentSearchTextBuffer.indexOf(START_TAG);
            }
        }
    }

    /**
     * Constructor taking the path to the module for which there is output, the monitor that can
     * be used to report information about progress, and the description of the prover launch.
     * This contains information about the parameters used to launch the prover.
     * 
     * @param moduleFile
     * @param monitor
     * @param proverJob the description of the prover launch. Contains information about
     * the parameters used to launch the prover.
     */
    public void initializeSink(IFile moduleFile, ProverJob proverJob, IProgressMonitor monitor)
    {
        currentSearchTextBuffer = new StringBuilder();

        this.moduleFile = moduleFile;
        this.monitor = monitor;
        this.proverJob = proverJob;
    }

    /**
     * Called when no more text is to be
     * sent to this parser.
     * 
     * This method compares the step statuses
     * computed by the toolbox to the step statuses reported
     * by the tlapm.
     */
    public void processFinished()
    {
        ProverHelper.compareStepStatusComputations(proverJob);
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/GotoPrevUseHandler.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.editor.basic.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IMarker;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;

/**
 * @author lamport
 *
 */
public class GotoPrevUseHandler extends AbstractHandler implements IHandler
{

    /* (non-Javadoc)
     * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
     */
    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        Spec spec = ToolboxHandle.getCurrentSpec();
        if (spec == null)
        {
            // This should not happen.
            return null;
        }
        IMarker[] markers = spec.getMarkersToShow();
        if (markers == null)
        {
            // This should not happen.
            return null;
        }
        int selection = spec.getCurrentSelection();
        if (selection == 0) {
            selection = markers.length - 1;
        } else {
            selection = selection - 1;
        }
        spec.setCurrentSelection(selection);
        GotoNextUseHandler.jumpToCurrentSelection(spec);

        return null;
    }
    
    public boolean isEnabled()
    {
        Spec spec = ToolboxHandle.getCurrentSpec();
        if (spec == null)
        {
            return false;
        }
        return spec.getMarkersToShow() != null;
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/proof/TLAProofFoldingStructureProvider.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic.proof;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.spec.parser.IParseResultListener;
import org.lamport.tla.toolbox.spec.parser.ParseResult;
import org.lamport.tla.toolbox.spec.parser.ParseResultBroadcaster;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.LevelNode;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.NonLeafProofNode;
import tla2sany.semantic.ProofNode;
import tla2sany.semantic.TheoremNode;
import util.UniqueString;

/**
 * This class provides the foldable regions for the proofs
 * in a module.
 * 
 * Implementation note: currently, this class gets foldable information
 * from SANY. It gives the computed foldable positions to the eclipse folding
 * infrastructure. These positions are maintained by eclipse as sticky pointers
 * in the tla file. They are updated with each new successful parse by SANY.
 * 
 * @author <NAME>
 *
 */
public class TLAProofFoldingStructureProvider implements IParseResultListener, IDocumentListener
{

    /**
     * Editor for which this class is providing proof folding
     * structure.
     */
    private TLAEditor editor;
    /**
     * The {@link IDocument} representing the
     * tla module.
     */
    private IDocument document;
    /**
     * List of all {@link TLAProofPosition} for the
     * current proofs in the editor most recently returned
     * by the parser.
     * 
     * Note that this does not include proofs whose
     * last line is the same of the last line
     * of the statement which they prove. These proofs
     * do not fold.
     */
    private Vector<TLAProofPosition> foldPositions;
    /**
     * Time stamp for last modification of the document
     * represented by the editor as returned by
     * {@link System#currentTimeMillis()}.
     */
    private long documentLastModified;
    /**
     * Flag indicating if folding commands
     * can be performed. This should be false
     * if the fold regions from a new parse result are being computed
     * and true if the fold regions are not being computed
     * and the fold regions in foldPositions are sorted
     * by offset.
     */
    private boolean canPerformFoldingCommands;

    /**
     * Initializes this folding structure provider for the given editor.
     * 
     * @param editor
     */
    public TLAProofFoldingStructureProvider(TLAEditor editor)
    {
        canPerformFoldingCommands = true;
        this.editor = editor;
        this.document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
        foldPositions = new Vector<TLAProofPosition>();

        // add this as listener to document to listen for changes
        document.addDocumentListener(this);

        // get a parse result if the parse result broadcaster has already stored one
        if (editor.getEditorInput() instanceof IFileEditorInput) {
        	IFileEditorInput editorInput = (IFileEditorInput) editor.getEditorInput();
        	IPath location = editorInput.getFile().getLocation();
        	ParseResult parseResult = ParseResultBroadcaster.getParseResultBroadcaster().getParseResult(location);
        	if (parseResult != null)
        	{
        		newParseResult(parseResult);
        	}
        }

        // now listen to any new parse results
        ParseResultBroadcaster.getParseResultBroadcaster().addParseResultListener(this);

    }

    /**
     * Computes the {@link TLAProofPosition} for the {@link TheoremNode} and for any subproofs. For each proof in tree represented
     * by theoremNode, this determines if a matching fold exists in previousFolds. If one does exist, it is
     * removed from previous folds. If one does not exist, a new {@link TLAProofPosition} is created for the proof
     * and is added to additions.
     * 
     * Any {@link TLAProofPosition} that is added to additions or removed from previousFolds is added
     * to foldsInCurrentTree.
     * 
     * 
     * 
     * @param theoremNode
     * 
     * @throws BadLocationException 
     */
    private void computeProofFoldPositions(TheoremNode theoremNode, Map<ProjectionAnnotation, TLAProofPosition> additions, List<TLAProofPosition> foldsInCurrentTree,
            List<TLAProofPosition> previousFolds) throws BadLocationException
    {

        if (theoremNode.getProof() == null)
        {
            return;
        }

        // the region describing the statement of the theorem
        IRegion theoremStatementRegion = AdapterFactory.locationToRegion(document, theoremNode.getTheorem()
                .getLocation());
        // the region describing the theoremNode
        IRegion theoremRegion = AdapterFactory.locationToRegion(document, theoremNode.getLocation());
        // the proof node
        ProofNode proofNode = theoremNode.getProof();
        // the region describing the proof
        IRegion proofNodeRegion = AdapterFactory.locationToRegion(document, proofNode.getLocation());

        // if last line of proof is on last line of step, nothing to fold, so just return
        if (document.getLineOfOffset(theoremStatementRegion.getOffset() + theoremStatementRegion.getLength()) == document
                .getLineOfOffset(proofNodeRegion.getOffset() + proofNodeRegion.getLength()))
        {
            return;
        }

        /* 
         * Iterate through previous folds to find if fold matches location of proof
         * 
         * If fold is found, remove from list of previous folds, and add to list of new folds for
         * proof tree.
         * 
         * If fold is not found, create new one, add to list of additions, and add to list of
         * new folds for proof tree.
         */
        TLAProofPosition matchingPosition = null;
        for (Iterator<TLAProofPosition> it = previousFolds.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();

            // positions are considered the same if the beginning and end line are the same
            if (proofPosition.isSamePosition(proofNodeRegion, document))
            {
                matchingPosition = proofPosition;
                foldsInCurrentTree.add(matchingPosition);
                // TLAEditorActivator.getDefault().logDebug("Existing fold found at " + matchingPosition);
                it.remove();
                break;
            }
        }

        if (matchingPosition == null)
        {
            /*
             * No position found.
             * 
             * Create a new positions whose statement part goes from the beginning of theoremNode
             * to the end of the statement of theoremNode.
             */
            matchingPosition = new TLAProofPosition(proofNodeRegion.getOffset(), proofNodeRegion.getLength(),
                    theoremRegion.getOffset(), theoremStatementRegion.getOffset() + theoremStatementRegion.getLength()
                            - theoremRegion.getOffset(), new ProjectionAnnotation(), document);
            additions.put(matchingPosition.getAnnotation(), matchingPosition);
            foldsInCurrentTree.add(matchingPosition);
        }

        if (proofNode instanceof NonLeafProofNode)
        {
            // recursively compute proof positions
            NonLeafProofNode nonLeafProofNode = (NonLeafProofNode) proofNode;
            LevelNode[] steps = nonLeafProofNode.getSteps();

            /*
             * From the documentation of NonLeafProofNode,
             * a step can be one of four types:
             * 
             * DefStepNode
             * UseOrHideNode
             * InstanceNode
             * TheoremNode
             * 
             * Only TheoremNode can have a proof. Recursively compute
             * the proof positions for those steps.
             */
            for (int i = 0; i < steps.length; i++)
            {
                if (steps[i] instanceof TheoremNode)
                {
                    computeProofFoldPositions((TheoremNode) steps[i], additions, foldsInCurrentTree, previousFolds);
                }
            }
        }

    }

    /**
     * Called when there is a new parse result broadcast by
     * {@link ParseResultBroadcaster}. Updates the folding structure of the proofs
     * in the editor if the parse result points to the {@link ModuleNode} representing
     * the file in the editor for this class.
     */
	public void newParseResult(ParseResult parseResult) {
		if (editor == null) {
			Activator.getDefault().logDebug("Null editor in proof structure provider.");
			return;
		} else if (editor.getEditorInput() == null) {
			Activator.getDefault().logDebug("Null editor input in proof structure provider.");
			return;
		}
		
    	if (!(editor.getEditorInput() instanceof IFileEditorInput)) {
			// input can be the file history which isn't an IFileEditorInput and
			// thus cannot be parsed. There is no point parsing every revision
    		// of the file history anyway.
    		return;
    	}
    	
        /*
         * If the parsed resource for parseResult is in a different
         * directory than the file open in the editor, then parseResult
         * does not contain the ModuleNode representing the file
         * in the editor. This is because SANY only handles modules
         * in the same directory.
         */
        if (!parseResult.getParsedResource().getLocation().removeLastSegments(1).equals(
        	((IFileEditorInput) editor.getEditorInput()).getFile().getLocation().removeLastSegments(1)))
        {
            return;
        }

        String moduleName = ResourceHelper.getModuleName(((IFileEditorInput) editor.getEditorInput()).getFile());


        // check if the editor is dirty or the editor document has been modified
        // or saved before SANY finished
        // if it is, SANYs output is useless
        if (editor.isDirty()
                || parseResult.getParserCalled() < documentLastModified
                || parseResult.getParserCalled() < ((FileEditorInput) editor.getEditorInput()).getFile()
                        .getLocalTimeStamp())
        {
            return;
        }

        SpecObj specObj = parseResult.getSpecObj();

        if (specObj == null || (parseResult.getParseErrors() != null && parseResult.getParseErrors().isFailure())
                || (parseResult.getSemanticErrors() != null && parseResult.getSemanticErrors().isFailure()))
        {
            /*
             * Module not successfully parsed.
             * The information from the spec obj cannot
             * reliably be used to update the folding structure, so
             * just return.
             */
            return;
        }

        /*
         * Retrieve the ModuleNode corresponding to the module in the
         * editor.
         */
        Assert.isNotNull(specObj.getExternalModuleTable());

        ModuleNode moduleNode = specObj.getExternalModuleTable().getModuleNode(UniqueString.uniqueStringOf(moduleName));
        if (moduleNode == null)
        {
            // nothing to do
            return;
        }

        canPerformFoldingCommands = false;

        Map<ProjectionAnnotation, TLAProofPosition> additions = new HashMap<ProjectionAnnotation, TLAProofPosition>();
        Vector<TLAProofPosition> foldsInCurrentTree = new Vector<TLAProofPosition>();

        TheoremNode[] theorems = moduleNode.getTheorems();

        for (int i = 0; i < theorems.length; i++)
        {
            TheoremNode theoremNode = theorems[i];

            try
            {
                if (theoremNode.getLocation().source().equals(moduleName))
                {
                    /*TLAProofPosition theoremProof = */computeProofFoldPositions(theoremNode, additions,
                            foldsInCurrentTree, foldPositions);
                    // if (theoremProof != null)
                    // {
                    // rootPositions.add(theoremProof);
                    // }
                }
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error converting theorem location to region in module " + moduleName, e);
            }
        }

        // compute array of annotations to be deleted
        Annotation[] deletions = new ProjectionAnnotation[foldPositions.size()];
        int i = 0;
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            proofPosition.remove(document);
            deletions[i] = proofPosition.getAnnotation();
        }

        // set previous folds to new folds
        foldPositions = foldsInCurrentTree;

        editor.modifyProjectionAnnotations(deletions, additions);

        // check if foldPositions is sorted by offset
        // it probably is sorted, but in case the order returned by SANY changes,
        // then it makes sense to sort
        int currentOffset = -1;
        boolean isSorted = true;
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            if (proofPosition.getOffset() >= currentOffset)
            {
                currentOffset = proofPosition.getOffset();
            } else
            {
                isSorted = false;
                break;
            }
        }

        if (!isSorted)
        {
			Collections.sort(foldPositions, new Comparator<TLAProofPosition>() {

				public int compare(TLAProofPosition arg0, TLAProofPosition arg1) {
					return arg0.getOffset() - arg1.getOffset();
				}
			});
        }

        canPerformFoldingCommands = true;

    }

    /**
     * Should be called when this instance is no longer needed.
     */
    public void dispose()
    {
        ParseResultBroadcaster.getParseResultBroadcaster().removeParseResultListener(this);
    }

    /**
     * This method used to assess whether the document has
     * changed between the time that the parser was called
     * and when it completes.
     */
    public void documentAboutToBeChanged(DocumentEvent event)
    {
        documentLastModified = System.currentTimeMillis();

    }

    public void documentChanged(DocumentEvent event)
    {

    }

    /**
     * Returns whether or not the selection is at a proof step or theorem statement.
     * The selection can be a range of text, so a selection
     * is considered to be at a proof step if the index in the document
     * described by {@link ITextSelection#getOffset()}+{@link ITextSelection#getLength()} is
     * in a step or theorem statement.
     * @param selection selection in the editor
     * @return
     */
    private boolean containedByStep(int caretOffset)
    {
        try
        {
            for (int i = 0; i < foldPositions.size(); i++)
            {
                TLAProofPosition proofPosition = foldPositions.get(i);
                if (proofPosition.containsBeforeProof(caretOffset, document))
                {
                    return true;
                }
            }
        } catch (BadLocationException e)
        {
            Activator.getDefault().logError("Error computing if selection is in proof step.", e);
        }
        return false;
    }

    /**
     * Returns whether or not the selection is in a proof.
     * The selection can be a range of text, so a selection
     * is considered to be at a proof step if the index in the document
     * described by {@link ITextSelection#getOffset()}+{@link ITextSelection#getLength()} is
     * in a step or theorem statement.
     * @param selection selection in the editor
     * @return
     */
//    private boolean containedByProof(int caretOffset)
//    {
//        try
//        {
//            for (int i = 0; i < foldPositions.size(); i++)
//            {
//                TLAProofPosition proofPosition = (TLAProofPosition) foldPositions.get(i);
//                if (proofPosition.containsInProof(caretOffset, document))
//                {
//                    return true;
//                }
//            }
//        } catch (BadLocationException e)
//        {
//            Activator.getDefault().logError("Error computing if selection is in proof step.", e);
//        }
//        return false;
//    }

    /**
     * Returns whether or not the selection is at a proof step, theorem statement, or leaf proof.
     * The selection can be a range of text, so a selection
     * is considered to be at a proof step if the index in the document
     * described by {@link ITextSelection#getOffset()}+{@link ITextSelection#getLength()} is
     * in a step or theorem statement.
     * @param selection selection in the editor
     * @return
     */
    private boolean containedByStepOrProof(int caretOffset)
    {
        try
        {
            for (int i = 0; i < foldPositions.size(); i++)
            {
                TLAProofPosition proofPosition = foldPositions.get(i);
                if (proofPosition.containsInProofOrStatement(caretOffset, document))
                {
                    return true;
                }
            }
        } catch (BadLocationException e)
        {
            Activator.getDefault().logError("Error computing if selection is in proof step.", e);
        }
        return false;
    }

    /**
     * Returns whether the fold operation can be run. If this
     * returns false, then calling {@link TLAProofFoldingStructureProvider#runFoldOperation(String, ITextSelection)}
     * with the same commandId and caret offset should have no effect.
     * 
     * @param commandId
     * @param caretOffset
     * @return
     */
    public boolean canRunFoldOperation(String commandId, ITextSelection selection)
    {
        if (!canPerformFoldingCommands || selection == null)
        {
            return false;
        }

        int caretOffset = selection.getOffset() + selection.getLength();

        if (commandId.equals(IProofFoldCommandIds.FOCUS_ON_STEP))
        {
            // This can be done if the caret is at a step,
            // between a step and a proof (if there are empty lines
            // or comments in between a step and a proof), or at
            // a leaf proof.
            return containedByStepOrProof(caretOffset);
        } else if (commandId.equals(IProofFoldCommandIds.FOLD_ALL_PROOFS))
        {
            // Always possible.
            return true;
        } else if (commandId.equals(IProofFoldCommandIds.EXPAND_ALL_PROOFS))
        {
            // Always possible.
            return true;
        } else if (commandId.equals(IProofFoldCommandIds.EXPAND_SUBTREE))
        {
            // This can be done if the caret is at a step,
            // between a step and a proof (if there are empty lines
            // or comments in between a step and a proof).
            // This command does not make sense at a leaf proof.
            return containedByStep(caretOffset);
        } else if (commandId.equals(IProofFoldCommandIds.COLLAPSE_SUBTREE))
        {
            // This can be done if the caret is at a step,
            // between a step and a proof (if there are empty lines
            // or comments in between a step and a proof).
            // This command does not make sense at a leaf proof.
            return containedByStep(caretOffset);
        } else if (commandId.equals(IProofFoldCommandIds.SHOW_IMMEDIATE))
        {
            // This can be done if the caret is at a step,
            // between a step and a proof (if there are empty lines
            // or comments in between a step and a proof).
            // This command does not make sense at a leaf proof.
            return containedByStep(caretOffset);
        }
        return true;
    }

    /**
     * Runs the fold operation represented by commandId. This
     * should be an id from {@link IProofFoldCommandIds}.
     * 
     * Does nothing if currently computing the folds
     * from a parse result.
     * 
     * @param commandId
     * @param the current selection in the editor
     */
    public void runFoldOperation(String commandId, ITextSelection selection)
    {
        if (canPerformFoldingCommands)
        {
            /*
             * Allow commands to run even if a range of text
             * is selected (highlighted). We treat end of the selection
             * (indexed by offset+length) as the location of the caret
             * for the command. This means that for commands that act
             * on specific steps, the step on which the command acts is determined
             * by the position of selection.getOffset()+selection.getLength().
             */
            if (selection != null)
            {
                int caretOffset = selection.getOffset() + selection.getLength();
                if (commandId.equals(IProofFoldCommandIds.FOCUS_ON_STEP))
                {
                    foldEverythingUnusable(caretOffset);
                } else if (commandId.equals(IProofFoldCommandIds.FOLD_ALL_PROOFS))
                {
                    foldAllProofs();
                } else if (commandId.equals(IProofFoldCommandIds.EXPAND_ALL_PROOFS))
                {
                    expandAllProofs();
                } else if (commandId.equals(IProofFoldCommandIds.EXPAND_SUBTREE))
                {
                    expandCurrentSubtree(caretOffset);
                } else if (commandId.equals(IProofFoldCommandIds.COLLAPSE_SUBTREE))
                {
                    hideCurrentSubtree(caretOffset);
                } else if (commandId.equals(IProofFoldCommandIds.SHOW_IMMEDIATE))
                {
                    showImmediateDescendants(caretOffset);
                }
            }
        }
    }

    /**
     * Folds all proofs not containing the cursor.
     * 
     * Note that this will fold every proof if the cursor
     * is not in a proof.
     * 
     * @param cursorOffset
     */
    private void foldEverythingUnusable(int cursorOffset)
    {
        Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            try
            {
                if (proofPosition.containsInProofOrStatement(cursorOffset, document))
                {
                    if (proofPosition.getAnnotation().isCollapsed())
                    {
                        proofPosition.getAnnotation().markExpanded();
                        modifiedAnnotations.add(proofPosition.getAnnotation());
                    }
                } else if (!proofPosition.getAnnotation().isCollapsed())
                {
                    proofPosition.getAnnotation().markCollapsed();
                    modifiedAnnotations.add(proofPosition.getAnnotation());
                }
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error changing expansion state of proofs.", e);
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

    /**
     * Collapses all proofs.
     * 
     * @param cursorOffset
     */
    private void foldAllProofs()
    {
        Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            if (!proofPosition.getAnnotation().isCollapsed())
            {
                // should fold every proof
                // so that only theorem statements are shown
                proofPosition.getAnnotation().markCollapsed();
                modifiedAnnotations.add(proofPosition.getAnnotation());
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

    private void expandAllProofs()
    {
        Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            if (proofPosition.getAnnotation().isCollapsed())
            {
                // should fold every proof
                // so that only theorem statements are shown
                proofPosition.getAnnotation().markExpanded();
                modifiedAnnotations.add(proofPosition.getAnnotation());
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

    /**
     * Expands the proof of a statement and all sub proofs. Assumes
     * all TLAProofPosition in foldPositions are sorted by ascending offset.
     */
    private void expandCurrentSubtree(int offset)
    {
        List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
        // find statement containing offset
        TLAProofPosition found = null;

        /*
         * Iterate though folds until finding the first
         * TLAProofPosition that contains the offset before
         * its proof (i.e. in the step/theorem or in a line
         * between the step/theorem and the proof). Expand the
         * proof of this TLAProofPosition and continue iterating, expanding
         * all proofs that are contained in the found TLAProofPosition.
         * 
         * This requires that the proof positions be sorted in ascending
         * order of offset.
         */
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            try
            {
                if (found == null && proofPosition.containsBeforeProof(offset, document))
                {
                    found = proofPosition;
                    if (found.getAnnotation().isCollapsed())
                    {
                        found.getAnnotation().markExpanded();
                        modifiedAnnotations.add(found.getAnnotation());
                    }
                    continue;
                }

                if (found != null && found.contains(proofPosition))
                {
                    if (proofPosition.getAnnotation().isCollapsed())
                    {
                        proofPosition.getAnnotation().markExpanded();
                        modifiedAnnotations.add(proofPosition.getAnnotation());
                    }
                }
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error changing expansion state of proofs.", e);
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

    /**
     * Hides the proof of a statement and all subproofs. Assumes
     * all TLAProofPosition in foldPositions are sorted by ascending offset.
     */
    private void hideCurrentSubtree(int offset)
    {
        List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
        // find statement containing offset
        TLAProofPosition found = null;

        /*
         * Iterate though folds until finding the first
         * TLAProofPosition that contains the offset before
         * its proof (i.e. in the step/theorem or in a line
         * between the step/theorem and the proof). Collapse the
         * proof of this TLAProofPosition and continue iterating, collapsing
         * all proofs that are contained in the found TLAProofPosition.
         * 
         * This requires that the proof positions be sorted in ascending
         * order of offset.
         */
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            try
            {
                if (found == null && proofPosition.containsBeforeProof(offset, document))
                {
                    found = proofPosition;
                    if (!found.getAnnotation().isCollapsed())
                    {
                        found.getAnnotation().markCollapsed();
                        modifiedAnnotations.add(found.getAnnotation());
                    }
                    continue;
                }

                if (found != null && found.contains(proofPosition))
                {
                    if (!proofPosition.getAnnotation().isCollapsed())
                    {
                        proofPosition.getAnnotation().markCollapsed();
                        modifiedAnnotations.add(proofPosition.getAnnotation());
                    }
                }
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error changing expansion state of proofs.", e);
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

    /**
     * Shows the immediate descendants in the proof of a
     * statement and hides the proofs of the immediate descendants.
     * Assumes all TLAProofPosition in foldPositions are sorted by ascending offset.
     */
    private void showImmediateDescendants(int offset)
    {
        List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
        // find statement containing offset
        TLAProofPosition found = null;

        /*
         * Iterate though folds until finding the first
         * TLAProofPosition that contains the offset before
         * its proof (i.e. in the step/theorem or in a line
         * between the step/theorem and the proof). Expand proof
         * of found statement and collapse the proofs of all
         * TLAProofPositions inside.
         * 
         * This requires that the proof positions be sorted in ascending
         * order of offset.
         */
        for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
        {
            TLAProofPosition proofPosition = it.next();
            try
            {
                if (found == null && proofPosition.containsBeforeProof(offset, document))
                {
                    found = proofPosition;
                    if (found.getAnnotation().isCollapsed())
                    {
                        found.getAnnotation().markExpanded();
                        modifiedAnnotations.add(found.getAnnotation());
                    }
                    continue;
                }

                if (found != null && found.contains(proofPosition))
                {
                    if (!proofPosition.getAnnotation().isCollapsed())
                    {
                        proofPosition.getAnnotation().markCollapsed();
                        modifiedAnnotations.add(proofPosition.getAnnotation());
                    }
                }
            } catch (BadLocationException e)
            {
                Activator.getDefault().logError("Error changing expansion state of proofs.", e);
            }
        }

        editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
                .toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/WrongInvocationException.java<|end_filename|>
package util;

/**
 * This exception is signaling that the caller (the developer) is using a wrong invocation.
 * Especially it is written in cases in which some non-implemented implementation is invoked or
 * implementation is used not as expected.
 * @author <NAME>
 * @version $Id$
 */
public class WrongInvocationException extends RuntimeException
{

    public WrongInvocationException(String message)
    {
        super(message);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/ExecuteCommand.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS ExecuteCommand                                                     *
*                                                                          *
* This class contains the one public method                                *
*                                                                          *
*    public static void ExecuteCommand(String cmd);                        *
*                                                                          *
* It calls the operating system to execute the command cmd, using two      *
* GobbleOutput threads to get rid of any output produced by the command.   *
***************************************************************************/
package tla2tex ;

public class ExecuteCommand
{ public static void executeCommand(String cmd)
   {  int errorCode = -99;
      try { Runtime rt = Runtime.getRuntime() ;
            Process proc = null ;
            if (Parameters.MetaDir.equals("")) {
                proc = rt.exec(cmd);
            } else {
                proc = rt.exec(cmd, null, Parameters.ParentDir);                
            }
            GobbleOutput outThread = new GobbleOutput(true, proc, cmd);
            outThread.start() ;
            GobbleOutput errThread = new GobbleOutput(false, proc, cmd);
            errThread.start() ;
            errorCode = proc.waitFor();
            outThread.join();
            errThread.join();
          }
      catch (Exception e)
       { Debug.ReportError(
              "Trying to run the command `" + cmd
            + "' produced the following error\n    " + e.getMessage());
       } ;
      if (errorCode < 0)
        { Debug.ReportError(
            "Running the command `" + cmd 
          + "' produced an error");
        }
   }
 }

<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/tool/simulation/SimulatorBenchmark.java<|end_filename|>
package tlc2.tool.simulation;

import java.io.File;
import java.io.IOException;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import tla2sany.modanalyzer.SpecObj;
import tlc2.tool.Simulator;
import tlc2.util.RandomGenerator;
import util.SimpleFilenameToStream;
import util.ToolIO;

/**
 * A benchmark to measure multi-threaded simulation performance.
 */
@State(Scope.Benchmark)
public class SimulatorBenchmark {
	
    @Param({ "1", "2", "3", "4", "5", "6"})
    public int nWorkers;
    
	Simulator simulator;
	SpecObj specObj;
	RandomGenerator rng = new RandomGenerator(0);
	long seed = 0;

    @Setup
    public void up() throws IOException {
		ToolIO.setUserDir("test-model" + File.separator + "simulation" + File.separator + "BenchmarkSpec");
    }  
    
    @Setup(Level.Iteration)
    public void reseedIter() {
    	// For each iteration of a benchmark, we set the seed to a known value, so that each 
    	// benchmark fork starts a particular iteration with the same seed. 
		seed += 1;
		rng.setSeed(seed);
    }
    
    @Setup(Level.Trial)
    public void reseed() {
    	// We reset the random number generator to a fixed seed before benchmarking a specific worker count.
    	// This should help to make these benchmarks more deterministic for a fixed set of benchmark parameters. The initial
    	// seed of this random number generator should effectively determine what traces are explored in what order by the simulation
    	// workers, so a particular seed should correspond to a fixed exploration order of the behavior space.
		rng.setSeed(0);
		seed = 0;
    }
    
    public void simulatorBenchmark(int nWorkers) {
		try {
			int maxTraceDepth = 20;
			Simulator simulator = new Simulator("BenchmarkSpec", "MCInv", null, false, maxTraceDepth, Long.MAX_VALUE, rng, 0,
					new SimpleFilenameToStream(), nWorkers);
			simulator.simulate();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}    
    }
	
	@Benchmark
	@BenchmarkMode(Mode.AverageTime)
	public void SimulatorWorkers() {
		simulatorBenchmark(nWorkers);  
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/wizard/TypingWizardPage.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.wizard;

import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.lamport.tla.toolbox.util.UIHelper;

import tlc2.model.Assignment;
import tlc2.model.TypedSet;

/**
 * A wizard page for typing sets of model values
 * @author <NAME>
 * @version $Id$
 */
public class TypingWizardPage extends WizardPage
{

    private Combo typeCombo;
    private Button optionUntyped;
    private Button optionTyped;
    private Label label;
    // The addition of a helpId field parallels its use in the AssignmentWizardPage
    // class. However, this really isn't necessary because this wizard page
    // class is used only once, for the second screen of the constant-assignment
    // wizard, so helpId is only set to a single value which we could therefore
    // build into the code. But some day, we may have some use for another
    // such page, so... Added 11 Oct 2009 by LL
    private final String helpId; // The id of the help context for this wizard page

    /**
     * Constructor of the page 
     */
    protected TypingWizardPage(String action, String description, String helpId)
    {
        super("TypingWizardPage");
        setTitle(action);
        setDescription(description);
        setMessage("The set of model values you chose are untyped."
                + "  Do you want to assign types to these values?\n"
                + "Hit the  ?  button for help (especially if you chose the `Symmetry set' option)");
        this.helpId = helpId;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent)
    {
        Composite container = new Composite(parent, SWT.NULL);
        container.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true));
        GridLayout layout = new GridLayout(2, false);
        container.setLayout(layout);
        GridData gd;

        // untyped option
        optionUntyped = new Button(container, SWT.RADIO);
        optionUntyped.setText("Leave untyped");
        gd = new GridData(SWT.LEFT, SWT.TOP, false, false);
        gd.horizontalSpan = 2;
        optionUntyped.setLayoutData(gd);

        // typed option
        optionTyped = new Button(container, SWT.RADIO);
        optionTyped.setText("Make typed:");
        optionTyped.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e)
            {
                typeCombo.setEnabled(optionTyped.getSelection());
                label.setEnabled(optionTyped.getSelection());
            }
        });
        gd = new GridData(SWT.LEFT, SWT.TOP, false, false);
        gd.horizontalSpan = 2;
        optionTyped.setLayoutData(gd);

        // label for type selection
        label = new Label(container, SWT.NONE);
        label.setText("Type:");
        gd = new GridData(SWT.LEFT, SWT.TOP, false, false);
        gd.horizontalIndent = 10;
        label.setLayoutData(gd);

        // type combo box
        typeCombo = new Combo(container, SWT.BORDER);

        // add letters (assumes A-Z...a-z)
        for (char i = 'A'; i < 'z'; i++)
        {
            if (Character.isLetter(i))
            {
                typeCombo.add("" + i);
            }
        }
        gd = new GridData(SWT.LEFT, SWT.TOP, false, false);
        typeCombo.setLayoutData(gd);

        // select the typed option
        // Changed by LL on 3 July 2010 to select
        // the untyped option
        optionUntyped.setSelection(true);
        typeCombo.setText("A");
        // setUntypedOption();
        UIHelper.setHelp(container, helpId);
        setControl(container);
    }

    public void dispose()
    {
        // evaluate the selected option and change the MVs
        // only if current page was selected
        // if the page is not selected, it is constructed but not shown
        if (isCurrentPage() && optionTyped.getSelection())
        {
            // retrieve the type letter
            String type = typeCombo.getText();
            // get the MV set
            Assignment assignment = ((AssignmentWizard) getWizard()).getFormula();
            // parse the set
            TypedSet set = TypedSet.parseSet(assignment.getRight());
            // set type
            set.setType(type);
            // set the content back
            assignment.setRight(set.toString());
        }
        super.dispose();
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/fp/TLCWorkerAndFPSet.java<|end_filename|>
// Copyright (c) 2012 <NAME>. All rights reserved.
package tlc2.tool.distributed.fp;

import tlc2.tool.distributed.TLCWorker;

public class TLCWorkerAndFPSet {

	public static void main(final String[] args) {
		// Start distributed FPSet first
		new Thread(new Runnable() {
			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				DistributedFPSet.main(args);
			}
		}, DistributedFPSet.class.getName()).start();

		// Start worker afterwards as it requires FPSets to be available
		new Thread(new Runnable() {
			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				TLCWorker.main(args);
			}
		}, TLCWorker.class.getName()).start();
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.test/src/org/lamport/tla/toolbox/ui/handler/NewSpecHandlerTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.ui.handler;

import java.io.IOException;
import java.nio.file.Files;
import java.util.concurrent.CountDownLatch;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.ui.handler.NewSpecHandler.NewSpecHandlerJob;

import junit.framework.TestCase;
import util.TLAConstants;

public class NewSpecHandlerTest extends TestCase {

	public void testNewSpecHandlerSuccess() throws InterruptedException, IOException {
		assertTrue(runJob("TestNewSpecHandlerSuccess").isOK());
		
		// Do some cleanup, leftovers seem to interfere with other tests.
		final Spec spec = Activator.getSpecManager().getSpecByName("TestNewSpecHandlerSuccess");
		Activator.getSpecManager().removeSpec(spec, new NullProgressMonitor(), true);
		assertNull(Activator.getSpecManager().getSpecByName("TestNewSpecHandlerSuccess"));
	}

	public void testNewSpecHandlerFail() throws InterruptedException, IOException, CoreException {
		// Create a project (not a specification) that is going to be in the way
		// of the NewSpecHandler and which will make it fail.
		final IWorkspace ws = ResourcesPlugin.getWorkspace();
		ws.getRoot().getProject("TestNewSpecHandlerFail").create(new NullProgressMonitor());
		assertTrue(ws.getRoot().getProject("TestNewSpecHandlerFail").exists());

		// Above only creates a project but not a spec. 
		assertNull(Activator.getSpecManager().getSpecByName("TestNewSpecHandlerFail"));

		// Try to create a spec the Toolbox way which is supposed to fail.
		final IStatus iStatus = runJob("TestNewSpecHandlerFail");
		assertEquals(Status.ERROR, iStatus.getSeverity());
		
		// As a result of the above failed attempt to create a spec
		// 'TestNewSpecHandlerFail', a spec should appear in the SpecManager
		// with a file named "Delete me".
		final Spec spec = Activator.getSpecManager().getSpecByName("TestNewSpecHandlerFail");
		assertEquals("Failed to find 'Delete me' spec in ToolboxExplorer", "Delete me", spec.getRootFile().getName());
		
		// Verify that this spec can be deleted and is gone afterwards
		// (including the dangling project this is all about).
		Activator.getSpecManager().removeSpec(spec, new NullProgressMonitor(), true);
		assertNull(Activator.getSpecManager().getSpecByName("TestNewSpecHandlerFail"));
		assertFalse(ws.getRoot().getProject("TestNewSpecHandlerFail").exists());
	}

	private IStatus runJob(String specName) throws IOException, InterruptedException {
		final NewSpecHandlerJob job = new NewSpecHandlerJob(specName,
				Files.createTempFile(specName, TLAConstants.Files.TLA_EXTENSION).toFile().getAbsolutePath(), false);
		MyJobChangeAdapter listener = new MyJobChangeAdapter();
		job.addJobChangeListener(listener);
		job.schedule();

		listener.await();

		assertNotNull(listener.getOuterEvent());
		return listener.getOuterEvent();
	}

	private static class MyJobChangeAdapter extends JobChangeAdapter {

		private IStatus outerEvent;

		private final CountDownLatch cdl;

		public MyJobChangeAdapter() {
			cdl = new CountDownLatch(1);
		}

		public void await() throws InterruptedException {
			cdl.await();
		}

		/**
		 * @return the outerEvent
		 */
		public IStatus getOuterEvent() {
			return outerEvent;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.
		 * runtime.jobs.IJobChangeEvent)
		 */
		@Override
		public void done(final IJobChangeEvent event) {
			super.done(event);
			outerEvent = event.getResult();
			cdl.countDown();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/SetOfLevelConstraints.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

class SetOfLevelConstraints extends HashMap<SymbolNode, Integer> implements LevelConstants {
  // Implements a map mapping parameters to levels. An entry <p,x> in
  // the set means that p must have a level <= x.
  /*************************************************************************
  * In other words, this is a HashMap of elements whose key is a           *
  * SymbolNode and whose value is an int.  An entry in this table means    *
  * that the key/parameter must have a level <= the value/int.             *
  *************************************************************************/
  
  /**
   * This method adds <param, level> into this map. It subsumes
   * any existing one. 
   */
  @Override
  public final Integer put(SymbolNode param, Integer level) {
    int newLevel = level.intValue();
    Integer old = this.get(param);

    int oldLevel = (old == null) ? MaxLevel : old.intValue();
    super.put(param, new Integer(Math.min(newLevel, oldLevel)));
    return old;
  }
  
  /**
   * This method adds all of the elements of its argument "s" to this
   * map, in each case "subsuming" it with any constraint already
   * present for the same parameter if one is there.
   */
  @Override
  public final void putAll(Map<? extends SymbolNode, ? extends Integer> s) {
    for (Iterator<? extends SymbolNode> iter = s.keySet().iterator(); iter.hasNext(); ) {
      SymbolNode key = iter.next();
      this.put(key, s.get(key));
    }
  }
  
  @Override
  public final String toString() {
    StringBuffer sb = new StringBuffer("{ ");
    for (Iterator<SymbolNode> iter = this.keySet().iterator(); iter.hasNext(); ) {
      SymbolNode param = iter.next();
      sb.append(param.getName() + " -> " + this.get(param));
      if (iter.hasNext()) sb.append(", ");
    }
    sb.append("}");
    return sb.toString();
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src-aj/tlc2/tool/WorkerMonitor.java<|end_filename|>
package tlc2.tool;

import java.util.HashSet;
import java.util.Set;

public class WorkerMonitor {

	private static final Set<ThreadListener> listeners = new HashSet<ThreadListener>();
	
	public static void addPerformanceResult(final Thread thread, final long runningTime) {
		for (ThreadListener threadListener : listeners) {
			threadListener.terminated(thread, runningTime);
		}
	}

	public static void addThreadListener(ThreadListener threadListener) {
		listeners.add(threadListener);
	}
	
	
	/**
	 * A ThreadListener is notified of when the Worker thread terminates. The
	 * notification includes the execution time of the thread.
	 */
	public static interface ThreadListener {

		void terminated(final Thread thread, final long runningTime);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/TableauDiskGraphTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;

import org.junit.Test;

import tlc2.util.BitVector;
import tlc2.util.LongVec;
import tlc2.util.statistics.FixedSizedBucketStatistics;
import tlc2.util.statistics.IBucketStatistics;

public class TableauDiskGraphTest extends DiskGraphTest {

	private static final IBucketStatistics GRAPH_STATS = new FixedSizedBucketStatistics("Test Dummy", 16);
	private static final int NUMBER_OF_SOLUTIONS = 1;
	private static final int NUMBER_OF_ACTIONS = 0;
	private static final BitVector NO_ACTIONS = null;
	
	
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.DiskGraphTest#getDiskGraph()
	 */
	protected AbstractDiskGraph getDiskGraph() throws IOException {
		return new TableauDiskGraph(createTempDirectory().getAbsolutePath(), NUMBER_OF_SOLUTIONS, GRAPH_STATS);
	}

	/* 
	 * Tests that the path is correctly reconstructed when a node's predecessors
	 * have an identical fingerprint but different tableau indices.
	 * 
	 *                  +------+                          
	 *	+-------+       |      |                          
	 *	|       |       |second+---------+                
	 *	| init  +-----> |0     |         |                
	 *	|       |       +------+         ^                
	 *	+-------+       +------+     +---+--+     +------+
	 *	                |(init)|     |      |     |      |
	 *	                |second+----->third +----->final |
	 *	+-------+       |1     |     |      |     |      |
	 *	|       |       +------+     +---+--+     +------+
	 *	| init  |       +------+         ^                
	 *	|       +-----> |      |         |                
	 *	+-------+       |second+---------+                
	 *	                |2     |                          
	 *	                +------+                           
	 *
	 */
	@Test
	public void testGetShortestPath() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		long initState = 1L;
		int initTableauIdx = 0;
		
		long secondState = 2L;
		// Its tableau indices range from 0 to 2. Tableau idx
		// 1 is an init state too.

		long thirdState = 3L;
		int thirdTableauIdx = 0;
				
		long finalState = 4L;
		int finalTableauIdx = 0;
		
		// init#1
		dg.addInitNode(initState, initTableauIdx);
		// second#1
		dg.addInitNode(secondState, 1);
		
		// Init#1
		GraphNode node = new GraphNode(initState, initTableauIdx);
		node.addTransition(secondState, 0, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		node.addTransition(secondState, 2, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// second#0
		node = new GraphNode(secondState, 0);
		node.addTransition(thirdState, thirdTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		// second#1
		node = new GraphNode(secondState, 1);
		node.addTransition(thirdState, thirdTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		// second#2
		node = new GraphNode(secondState, 2);
		node.addTransition(thirdState, thirdTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// third#0
		node = new GraphNode(thirdState, thirdTableauIdx);
		node.addTransition(finalState, finalTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// final#0
		node = new GraphNode(finalState, finalTableauIdx);
		dg.addNode(node);
		
		dg.createCache();
		final LongVec path = dg.getPath(finalState, finalTableauIdx);
		dg.destroyCache();
		
		// It is important that it finds the shortest path.
		assertEquals(3, path.size());
		assertEquals(finalState, path.elementAt(0));
		assertEquals(thirdState, path.elementAt(1));
		assertEquals(secondState, path.elementAt(2));
	}

	/*
	 *                       +---------+                        
	 *	                     |         |                        
	 *	     +--------------->  second +------------------+     
	 *	     |               |         |                  |     
	 *	     |               +---------+                  |     
	 *	     |                                            |     
	 *	+----+---+                                   +----v----+
	 *	|        |                                   |         |
	 *	| init   |                                   | final   |
	 *	|        |                                   |         |
	 *	+----+---+                                   +----+----+
	 *	     |                                            ^     
	 *	     |                +---------+                 |     
	 *	     |                |         |                 |     
	 *	     +---------------->  third  +-----------------+     
	 *	                      |         |                       
	 *	                      +---------+                        
 	 *
	 * (Drawn with http://asciiflow.com/)
	 */
	@Test
	public void testUnifyingNodeInPath() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		long initState = 1L;
		int initTableauIdx = 0;
		
		long secondState = 2L;
		int secondTableauIdx = 0;

		long thirdState = 3L;
		int thirdTableauIdx = 0;
				
		long finalState = 4L;
		int finalTableauIdx = 0;
		
		// Init
		dg.addInitNode(initState, initTableauIdx);
		
		// Init
		GraphNode node = new GraphNode(initState, initTableauIdx);
		
		/*
		 * The *order* in which the transitions are added to the init node define,
		 * which one of the two possible pathes is later found. Since we add
		 * the second state first, the path will be final -> second -> init
		 */
		node.addTransition(secondState, secondTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		node.addTransition(thirdState, thirdTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		
		dg.addNode(node);
		
		// second
		node = new GraphNode(secondState, secondTableauIdx);
		node.addTransition(finalState, finalTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// third
		node = new GraphNode(thirdState, thirdTableauIdx);
		node.addTransition(finalState, finalTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// final
		node = new GraphNode(finalState, finalTableauIdx);
		dg.addNode(node);
		
		dg.createCache();
		final LongVec path = dg.getPath(finalState, finalTableauIdx);
		dg.destroyCache();
		
		// There are now two path with identical length:
		// init -> second -> final & init -> third -> final
		// and both are correct path.
		assertEquals(3, path.size());
		assertEquals(finalState, path.elementAt(0));
		assertEquals(secondState, path.elementAt(1));
		assertEquals(initState, path.elementAt(2));
	}

	/*
	 * Similar to testUnifiyingNodeInPath except that the upper path has one
	 * extra node. This should mean that the search returns init -> third ->
	 * final because it is shorter regardless of second being added as a
	 * transition first.
	 *
	 *              +---------+       +---------+                        
	 *	            |         |       |         |                        
	 *	     +------>  frob   +------->  second +---------+     
	 *	     |      |         |       |         |         |     
	 *	     |      +---------+       +---------+         |     
	 *	     |                                            |     
	 *	+----+---+                                   +----v----+
	 *	|        |                                   |         |
	 *	| init   |                                   | final   |
	 *	|        |                                   |         |
	 *	+----+---+                                   +----+----+
	 *	     |                                            ^     
	 *	     |                +---------+                 |     
	 *	     |                |         |                 |     
	 *	     +---------------->  third  +-----------------+     
	 *	                      |         |                       
	 *	                      +---------+                        
	 */
	@Test
	public void testUnifyingNodeShortestPath() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		long initState = 1L;
		int initTableauIdx = 0;
		
		long frob = 5;
		int frobTableauIdx = 0;
		
		long secondState = 2L;
		int secondTableauIdx = 0;

		long thirdState = 3L;
		int thirdTableauIdx = 0;
				
		long finalState = 4L;
		int finalTableauIdx = 0;
		
		// Init
		dg.addInitNode(initState, initTableauIdx);
		
		// Init
		GraphNode node = new GraphNode(initState, initTableauIdx);
		
		/*
		 * The *order* in which the transitions are added to the init node define,
		 * which one of the two possible pathes is later found. Since we add
		 * the second state first, the path will be final -> second -> init
		 */
		node.addTransition(frob, frobTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		node.addTransition(thirdState, thirdTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		
		dg.addNode(node);
		
		// frob
		node = new GraphNode(frob, frobTableauIdx);
		node.addTransition(secondState, secondTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		
		// second
		node = new GraphNode(secondState, secondTableauIdx);
		node.addTransition(finalState, finalTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// third
		node = new GraphNode(thirdState, thirdTableauIdx);
		node.addTransition(finalState, finalTableauIdx, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 1);
		dg.addNode(node);
		
		// final
		node = new GraphNode(finalState, finalTableauIdx);
		dg.addNode(node);
		
		dg.createCache();
		final LongVec path = dg.getPath(finalState, finalTableauIdx);
		dg.destroyCache();
		
		// There are now two path with identical length:
		// init -> second -> final & init -> third -> final
		// and both are correct path.
		assertEquals(3, path.size());
		assertEquals(finalState, path.elementAt(0));
		assertEquals(thirdState, path.elementAt(1));
		assertEquals(initState, path.elementAt(2));
	}

	/*
	 * +----------+                   
	 * |          |                   
	 * | init     |                   
	 * |          |                   
	 * |          |                   
	 * +----------+                   
	 *                                
	 * +----------+       +----------+
	 * |          |       |          |
	 * | second   +------->  final   |
	 * | init     |       |          |
	 * |          |       |          |
	 * +----------+       +----------+
	 * 
	 * The specialty here is that there are *two* init nodes and one them has *no* successors.
	 * 
	 * @see Bug #293 in general/bugzilla/index.html
	 */
	@Test
	public void testPathWithTwoInitNodesWithTableau() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		long noSuccessorInitState = 1L;

		long regularInitState = 2L;
		
		long finalState = 3L;

		// Init
		dg.addInitNode(noSuccessorInitState, 0);
		
		/*
		 * Intentionally *NOT* adding the init via dg.addNode(init)
		 */
		
		// second init (this one gets added via addNode
		dg.addInitNode(regularInitState, 0);
		GraphNode node = new GraphNode(regularInitState, 0);
		node.addTransition(finalState, 0, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		
		// final
		node = new GraphNode(finalState, 0);
		dg.addNode(node);
		
		dg.createCache();
		LongVec path = dg.getPath(finalState, 0);
		dg.destroyCache();
		
		assertEquals(2, path.size());
		assertEquals(finalState, path.elementAt(0));
		assertEquals(regularInitState, path.elementAt(1));
		
		// Make sure it also returns a path if init is searched
		dg.createCache();
		path = dg.getPath(noSuccessorInitState, 0);
		dg.destroyCache();

		assertEquals(1, path.size());
		assertEquals(noSuccessorInitState, path.elementAt(0));
	}
	
	/*
	 * Test that getPath returns the correct init state if the graph contains
	 * multiple initial states with the same fingerprint but different tableau idxs.
	 */
	@Test
	public void testGetPathWithTwoInits() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();
		
		final long fingerprint = 1L;
		
		dg.addInitNode(fingerprint, 0);
		dg.addInitNode(fingerprint, 1);
		
		try {
			// Requesting path to node with tidx 2 is supposed to fail when no
			// such node is in the graph.
			dg.createCache();
			dg.getPath(fingerprint, 2);
			dg.destroyCache();
		} catch (RuntimeException e) {
			// Now that it has been added, it should be found.
			dg.addInitNode(fingerprint, 2);
			
			dg.createCache();
			LongVec path = dg.getPath(fingerprint, 2);
			dg.destroyCache();
			
			assertEquals(1, path.size());
			assertEquals(fingerprint, path.elementAt(0));
			return;
		}
		fail("Returned path to non-existing node");
	}
	
	/*
	 * Test how an initial node transitions through the done state
	 */
	@Test
	public void testNodeSetDone() throws IOException {
		final TableauDiskGraph dg = (TableauDiskGraph) getDiskGraph();
		final long fingerprint = 1L;

		// Adding as init leaves the node in the undone state
		dg.addInitNode(fingerprint, 0);
		assertFalse(dg.isDone(fingerprint));

		// Adding it with addNextState changes the done state to being done.
		GraphNode node = new GraphNode(fingerprint, 0);
		node.addTransition(fingerprint, 1, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);

		// It is done now
		assertTrue(dg.isDone(fingerprint));
	}
	
	/*
	 * Tests a path where both states have an identical fingerprint and only
	 * differ in the tableau idx.
	 */
	@Test
	public void testGetPathWithTwoNodesWithSameFingerprint() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		final long fingerprint = 1L;

		// first
		dg.addInitNode(fingerprint, 0);
		GraphNode node = new GraphNode(fingerprint, 0);
		node.addTransition(fingerprint, 1, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		
		// second
		node = new GraphNode(fingerprint, 1);
		dg.addNode(node);

		
		dg.createCache();
		final LongVec path = dg.getPath(fingerprint, 1);
		dg.destroyCache();

		assertEquals(2, path.size());
		assertEquals(fingerprint, path.elementAt(0));
		assertEquals(fingerprint, path.elementAt(1));
	}
	
	/*
	 * Test that it is possible to "update" a GraphNode's outgoing transitions.
	 */
	@Test
	public void testLookupExistingNodeWithTidx() throws IOException {
		final TableauDiskGraph dg = (TableauDiskGraph) getDiskGraph();
		
		GraphNode node = dg.getNode(1L, 1);
		assertEquals(0, node.succSize());
		dg.addNode(node);
		
		// Cause the DiskGraph to be read from disk
		dg.makeNodePtrTbl();
		
		node = dg.getNode(1L, 1);
		dg.addNode(node);
		assertEquals(0, node.succSize());
		
		node.addTransition(2, 2, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		assertEquals(1, node.succSize());
		assertTrue(node.transExists(2, 2));
		
		dg.makeNodePtrTbl();
		
		node = dg.getNode(1L, 1);
		assertEquals(1, node.succSize());

		node.addTransition(3, 3, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		assertEquals(2, node.succSize());
		assertTrue(node.transExists(2, 2));
		assertTrue(node.transExists(3, 3));
		
		// commit/chkpt
		dg.beginChkpt();
		dg.commitChkpt();
		dg.recover();
		
		node = dg.getNode(1L, 1);
		assertEquals(2, node.succSize());
		assertTrue(node.transExists(2, 2));
		assertTrue(node.transExists(3, 3));
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/NavigationLocationComposite.java<|end_filename|>
// Copyright (c) Dec 22, 2011 Microsoft Corporation.  All rights reserved.

package org.lamport.tla.toolbox.tool.tlc.ui.editor.page;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationLocation;

/**
 * @author <NAME>
 */
public class NavigationLocationComposite implements INavigationLocation {

	private final List<INavigationLocation> locations = new ArrayList<INavigationLocation>();

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#dispose()
	 */
	public void dispose() {
		for (INavigationLocation location : locations) {
			location.dispose();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#releaseState()
	 */
	public void releaseState() {
		for (INavigationLocation location : locations) {
			location.releaseState();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#saveState(org.eclipse.ui.IMemento)
	 */
	public void saveState(IMemento memento) {
		// unsupported right now
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreState(org.eclipse.ui.IMemento)
	 */
	public void restoreState(IMemento memento) {
		// unsupported right now
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#restoreLocation()
	 */
	public void restoreLocation() {
		for (INavigationLocation location : locations) {
			location.restoreLocation();
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#mergeInto(org.eclipse.ui.INavigationLocation)
	 */
	public boolean mergeInto(INavigationLocation currentLocation) {
		// not supported right now
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#getInput()
	 */
	public Object getInput() {
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#getText()
	 */
	public String getText() {
		// super class takes care of setting proper string
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#setInput(java.lang.Object)
	 */
	public void setInput(Object input) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.INavigationLocation#update()
	 */
	public void update() {
	}

	public void add(INavigationLocation aNavigationLocation) {
		locations.add(aNavigationLocation);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/OpDefEvaluator.java<|end_filename|>
package tlc2.tool.impl;

import tla2sany.semantic.SemanticNode;
import tlc2.tool.TLCState;
import tlc2.tool.coverage.CostModel;
import tlc2.util.Context;
import tlc2.value.IValue;

public interface OpDefEvaluator {
	IValue eval(SemanticNode body, Context empty, TLCState empty2, CostModel doNotRecord);
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/handler/OpenModuleHandler.java<|end_filename|>
package org.lamport.tla.toolbox.ui.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Handles the open-module command
 * @author <NAME>
 * @version $Id: OpenSpecHandler.java 155 2009-01-29 05:11:44Z simonzam $
 */
public class OpenModuleHandler extends AbstractHandler implements IHandler
{
    public static final String COMMAND_ID = "toolbox.command.module.open";
    public static final String PARAM_MODULE = "toolbox.command.module.open.param";

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        String moduleName = event.getParameter(PARAM_MODULE);
        openModule(moduleName);
        return null;
    }

    /**
     * This was the body of the <code>execute</code>, but was pulled out so it could be
     * used in other places to open a module.
     * 
     * @param moduleName
     */
    public static void openModule(String moduleName) {
        if (moduleName == null)
        {
            throw new RuntimeException("Module was null" );
        }
        Spec spec = Activator.getSpecManager().getSpecLoaded();
        final IFile module = ResourceHelper.getLinkedFile(spec.getProject(), ResourceHelper.getModuleFileName(moduleName));
        if (module == null)
        {
            throw new RuntimeException("Module " + moduleName + " could not be found" );
        }

        // open the editor
        IEditorPart part = UIHelper.openEditor(OpenSpecHandler.TLA_EDITOR, new FileEditorInput(module));
        part.addPropertyListener(new IPropertyListener() {

            public void propertyChanged(Object source, int propId)
            {
                if (IWorkbenchPartConstants.PROP_DIRTY == propId)
                {
                    // here the listeners to editor changes go into
                    
                } 
            }
        });

    }

	/* (non-Javadoc)
	 * @see org.eclipse.core.commands.AbstractHandler#isEnabled()
	 */
	@Override
	public boolean isEnabled() {
		if (Activator.getSpecManager().getSpecLoaded() == null) {
			return false;
		}
		return super.isEnabled();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/List.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:30 PST by lamport
//      modified on Mon Sep 25 13:25:21 PDT 2000 by yuanyu

package tlc2.util;


public class List {
  public class ConsCell {
    protected Object value;
    protected ConsCell next;

    ConsCell(Object value, ConsCell next) {
      this.value = value;
      this.next = next;
    }
  }
  
  public static List Empty = new List();
  protected ConsCell first;
  protected ConsCell last;

  /* Constructors.  */
  public List() { this.first = null; this.last = null; }

  public List(Object value) {
    this.first = new ConsCell(value, null);
    this.last = this.first;
  }

  public List(List lst) {
    this.first = lst.first;
    this.last = lst.last;
  }

  /* This method returns true iff the list is empty. */
  public final boolean isEmpty() { return (this.first == null); }

  /* This method returns the length of the list.  */
  public final int length() {
    int len = 0;
    ConsCell work = this.first;
    while (work != null) {
      len++;
      work = work.next;
    }
    return len;
  }

  /**
   * This method adds (destructively) a new element in the front 
   * of the list.
   */
  public final void push(Object value) {
    ConsCell cell = new ConsCell(value, this.first);
    this.first = cell;
    if (this.last == null) this.last = cell;
  }

  /**
   * This method removes (destructively) one element from the
   * front of the list.  It returns the removed element.
   */
  public final Object pop() {
    // Assert.check(this.first != null);
    Object result = this.first.value;
    this.first = this.first.next;
    if (this.first == null) this.last = null;
    return result;
  }

  /**
   * This method is the cons equivalent. It returns a new list
   * of adding a new element in the front.
   */
  public final List cons(Object value) {
    ConsCell cell = new ConsCell(value, this.first);
    List newList = new List();
    newList.first = cell;
    newList.last = (this.last == null) ? cell : this.last;
    return newList;
  }

  /**
   * This method is the car equivalent. It returns the first
   * element of the list.
   */
  public final Object car() {
    // Assert.check(this.first != null);
    return this.first.value;
  }

  /**
   * This method is the cdr equivalent. It returns a new list
   * of removing the first front element.
   */
  public final List cdr() {
    // Assert.check(this.first != null);
    List newList = new List();
    newList.first = this.first.next;
    newList.last = (newList.first == null) ? null : this.last;
    return newList;
  }

  /**
   * This method returns true iff the argument is a member of
   * the list. The equality check is on reference.
   */
  public final boolean member(Object value) {
    ConsCell cell = this.first;
    boolean isMember = false;
    while (cell != null) {
      if (cell.value == value) {
	isMember = true;
	break;
      }
      cell = cell.next;
    }
    return isMember;
  }

  /**
   * This method returns a new list that appends one element
   * at the end of this list.
   */
  public final List append1(Object value) {
    ConsCell cell = this.first;
    if (cell == null) return new List(value);

    List newList = new List(cell.value);
    cell = cell.next;
    while (cell != null) {
      ConsCell newCell = new ConsCell(cell.value, null);
      newList.last.next = newCell;
      newList.last = newCell;
      cell = cell.next;
    }
    ConsCell newCell = new ConsCell(value, null);
    newList.last.next = newCell;
    newList.last = newCell;
    return newList;
  }

  /* This method returns a new list that appends two lists. */
  public final List append(List lst) {
    ConsCell cell = this.first;
    if (cell == null) return new List(lst);

    List newList = new List(cell.value);
    cell = cell.next;
    while (cell != null) {
      ConsCell newCell = new ConsCell(cell.value, null);
      newList.last.next = newCell;
      newList.last = newCell;
      cell = cell.next;
    }
    cell = lst.first;
    while (cell != null) {
      ConsCell newCell = new ConsCell(cell.value, null);
      newList.last.next = newCell;
      newList.last = newCell;
      cell = cell.next;      
    }
    return newList;
  }

  /**
   * This method appends (destructively) an element to the end
   * of this list.
   */
  public final List append1D(Object value) {
    if (this.first == null) {
      this.first = new ConsCell(value, null);
      this.last = this.first;
    }
    else {
      this.last.next = new ConsCell(value, null);
      this.last = this.last.next;
    }
    return this;
  }

  /**
   * This method appends (destructively) a list to the end
   * of this list.
   */
  public final List appendD(List lst) {
    if (this.first == null) {
      this.first = lst.first;
    }
    else {
      this.last.next = lst.first;
    }
    if (lst.first != null) {
      this.last = lst.last;
    }
    return this;
  }

  /* The string representation. */
  public final String toString() {
    StringBuffer sb = new StringBuffer("[");
    ConsCell work = this.first;
    while (work != null) {
      sb.append(work.value.toString());
      work = work.next;
    }
    sb.append("]");
    return sb.toString();
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/output/IProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output;

import org.lamport.tla.toolbox.tool.tlc.model.Model;

/**
 * Basic interface for the sink
 * @author <NAME>
 */
public interface IProcessOutputSink
{
    /**
     * Debug stream
     */
    public final static int TYPE_DEBUG = -1;
    /**
     * Output stream
     */
    public final static int TYPE_OUT = 1;
    /**
     * Error stream 
     */
    public final static int TYPE_ERROR = 2;
    /**
     * Trace explorer output stream
     */
    public final static int TYPE_TRACE_EXPLORE = 3;
    /**
     * Extension point, the interface is used in
     */
    public static final String EXTENSION_ID = "org.lamport.tla.toolbox.tlc.processOutputSink";

    /**
     * Appends text to the sink
     * @param text 
     */
    public void appendText(String text);

    /**
     * Called prior the usage to initialize the sink
     * @param model name of the process
     * @param sinkType type, see constants {@link IProcessOutputSink#TYPE_DEBUG}, {@link IProcessOutputSink#TYPE_ERROR}, {@link IProcessOutputSink#TYPE_OUT}, {@link IProcessOutputSink#TYPE_TRACE_EXPLORE}
     */
    public void initializeSink(Model model, int sinkType);

    /**
     * Signal to the sink that the process has terminated and no data will be sent
     */
    public void processFinished();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/IgnoringListener.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

/**
 * Allows ignoring
 * 
 * @author <NAME>
 * @version $Id$ 
 */
public interface IgnoringListener
{
    public void setIgnoreInput(boolean ignoreInputChange);
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.prover/src/org/lamport/tla/toolbox/tool/prover/ui/ProverUIActivator.java<|end_filename|>
package org.lamport.tla.toolbox.tool.prover.ui;

import org.lamport.tla.toolbox.AbstractTLCActivator;
import org.osgi.framework.BundleContext;

/**
 * The activator class controls the plug-in life cycle
 */
public class ProverUIActivator extends AbstractTLCActivator
{

	// The plug-in ID
    public static final String PLUGIN_ID = "org.lamport.tla.toolbox.tool.prover.ui";

    // The shared instance
    private static ProverUIActivator plugin;

    public ProverUIActivator() {
		super(PLUGIN_ID);
	}
    
    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext context) throws Exception
    {
        super.start(context);
        plugin = this;

		// Moved the code below to ProverPreferenceInitializer. Calling
		// UIHElper.runUIAsync(..) from within the bundle activator can lead to
		// the unintended behavior or creating the SWT Display too early
		// *before* the regular Application has a chance to do so. If this
		// happens, the Display has no app name set causing the Toolbox to be
		// named "Swt" on Mac and Gnome (WM_CLASS)
//        UIHelper.runUIAsync(new Runnable() {
//			
//			public void run() {
//	            // Using somebody's else PreferenceStore is not a good idea!
//	        	// Use ProverUIActivator.getDefault().getPreferenceStore() instead.
//	            // @see Bug #261 in general/bugzilla/index.html
//		        IPreferenceStore store = getDefault().getPreferenceStore();
//
//		        /*
//		         * The following sets the default color predicates for the colors. First argument
//		         * is the key for each predicate for the logical color, and the second argument is
//		         * the predicate string (not the macro name).
//		         */
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(1), ColorPredicate.PREDICATE_NONE);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(2), ColorPredicate.PREDICATE_NONE);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(3), ColorPredicate.PREDICATE_BEING_PROVED);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(4), ColorPredicate.PREDICATE_STOPPED);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(5), ColorPredicate.PREDICATE_FAILED);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(6), ColorPredicate.PREDICATE_PROVED);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(7), ColorPredicate.PREDICATE_PROVED_OR_OMITTED);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(8), ColorPredicate.PREDICATE_PROVED_OR_OMITTED_OR_MISSING);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(9), ColorPredicate.PREDICATE_NONE);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(10), ColorPredicate.PREDICATE_NONE);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(11), ColorPredicate.PREDICATE_NONE);
//		        store.setDefault(ProverPreferencePage.getColorPredPrefName(12), ColorPredicate.PREDICATE_NONE);
//			}
//		});
         /*
         * DR commented out the following because default colors are now set in the plugin.xml file for this
         * plug-in.
         */
        //
        // /*
        // * The following sets the default colors values.
        // */
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(1), new RGB(255, 187, 187));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(2), new RGB(255, 255, 183));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(3), new RGB(217, 250, 174));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(4), new RGB(133, 133, 133));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(5), new RGB(174, 255, 174));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(6), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(7), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(8), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(9), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(10), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(11), new RGB(0, 0, 0));
        // PreferenceConverter.setDefault(store, ProverPreferencePage.getColorPrefName(12), new RGB(0, 0, 0));

        /*
         * The following was commented out by DR to make it easier to
         * understand how the obligations view is updated. Initially this
         * code got new obligation markers indirectly through a resource
         * change listener and passed them to the obligation view. Now
         * the obligations view is informed of new markers and of marker
         * deletions by the classes that call the marker creation and deletion,
         * namely, TagBasedTLAPMOutputIncrementalParser and ProverJob.
         * Add a resource change listener that reacts to new obligation
         * markers by updating the obligations view.
         */
        // IWorkspace workspace = ResourcesPlugin.getWorkspace();
        //
        // workspace.addResourceChangeListener(new IResourceChangeListener() {
        //
        // public void resourceChanged(IResourceChangeEvent event)
        // {
        // final IMarkerDelta[] deltas = event.findMarkerDeltas(ProverHelper.OBLIGATION_MARKER, false);
        // if (deltas.length == 0)
        // {
        // return;
        // }
        //
        // /*
        // * Update the obligation view with any obligation markers
        // * that have been added or modified.
        // *
        // * If any obligation markers have been deleted, this indicates that the prover
        // * has been relaunched. When the prover is relaunched, old obligation
        // * markers are deleted. We can clear the information of these old obligation
        // * markers from the obligation view by calling
        // * ObligationView.refreshObligationView().
        // */
        // boolean markersDeleted = false;
        // for (int i = 0; i < deltas.length; i++)
        // {
        // if (deltas[i].getType().equals(ProverHelper.OBLIGATION_MARKER))
        // {
        // if (deltas[i].getKind() == IResourceDelta.ADDED
        // || deltas[i].getKind() == IResourceDelta.CHANGED)
        // {
        // final IMarker marker = deltas[i].getMarker();
        // UIHelper.runUIAsync(new Runnable() {
        //
        // public void run()
        // {
        // ObligationsView.updateObligationView(marker);
        // }
        // });
        //
        // } else
        // {
        // markersDeleted = true;
        // }
        // }
        // }
        //
        // if (markersDeleted)
        // {
        // UIHelper.runUIAsync(new Runnable() {
        //
        // public void run()
        // {
        // ObligationsView.refreshObligationView();
        // }
        // });
        // }
        //
        // }
        // }, IResourceChangeEvent.POST_CHANGE);

    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext context) throws Exception
    {
        plugin = null;
        super.stop(context);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static ProverUIActivator getDefault()
    {
        return plugin;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/Strings.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.utilities;

public class Strings {

  public static final String []  blanks = {""," ","| ","   ","| | ",
                                   "     ","| | | ","       ","| | | | " };

  // Inserts blanks into a string right after newline characters to create
  // indentation when printed.
  public static String indent(int n /* numb blanks to insert*/ , String ss) {

    String s = "";
    if (n >= blanks.length) n = blanks.length-1;

    for (int i=0; i < ss.length(); i++) {
      s += ss.charAt(i);
      if (ss.charAt(i) == '\n' && i!=ss.length()-1) {  // no blanks after terminal \n
        s += blanks[n];
      }
    } // end for
    return s;
  }

  // Same as above, but uses StringBuffer operations internally
  // Should be much faster for very large strings
  public static String indentSB(int n, String ss) {

    StringBuffer sb = new StringBuffer(ss.length()*2);

    if (n>=blanks.length) n = blanks.length-1;

    for (int i = 0; i < ss.length(); i++) {
      sb.append(ss.charAt(i));
      if (ss.charAt(i) == '\n' && i!=ss.length()-1) {  // no blanks after terminal \n
        sb.append(blanks[n]);
      }
    } // end for
    return sb.toString();
  } // end method

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/impl/SymbolNodeValueLookupProvider.java<|end_filename|>
package tlc2.tool.impl;

import tla2sany.semantic.APSubstInNode;
import tla2sany.semantic.ASTConstants;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.ExprOrOpArgNode;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.LabelNode;
import tla2sany.semantic.LetInNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.OpArgNode;
import tla2sany.semantic.OpDefNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.Subst;
import tla2sany.semantic.SubstInNode;
import tla2sany.semantic.SymbolNode;
import tlc2.tool.BuiltInOPs;
import tlc2.tool.ToolGlobals;
import tlc2.tool.coverage.CostModel;
import tlc2.util.Context;
import tlc2.value.impl.EvaluatingValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.LazyValue;
import tlc2.value.impl.MethodValue;
import util.UniqueString;

public interface SymbolNodeValueLookupProvider {
    /* Return the variable if expr is a state variable. Otherwise, null. */
	default SymbolNode getVar(final SemanticNode expr, final Context c, final boolean cutoff, final int forToolId) {
		if (expr instanceof OpApplNode) {
			SymbolNode opNode = ((OpApplNode) expr).getOperator();

			if (opNode.getArity() == 0) {
				boolean isVarDecl = (opNode.getKind() == ASTConstants.VariableDeclKind);
				Object val = lookup(opNode, c, cutoff && isVarDecl, forToolId);

				if (val instanceof LazyValue) {
					LazyValue lval = (LazyValue) val;
					return getVar(lval.expr, lval.con, cutoff, forToolId);
				}
				if (val instanceof OpDefNode) {
					return getVar(((OpDefNode) val).getBody(), c, cutoff, forToolId);
				}
				if (isVarDecl) {
					return opNode;
				}
			}
		}
		return null;
	}

	default Object lookup(final SymbolNode opNode, final Context c, final boolean cutoff, final int forToolId) {
		final boolean isVarDecl = (opNode.getKind() == ASTConstants.VariableDeclKind);
		Object result = c.lookup(opNode, cutoff && isVarDecl);
		if (result != null) {
			return result;
		}

		result = opNode.getToolObject(forToolId);
		if (result != null) {
			return WorkerValue.mux(result);
		}

		if (opNode.getKind() == ASTConstants.UserDefinedOpKind) {
			// Changed by LL on 10 Apr 2011 from
			//
			// result = ((OpDefNode) opNode).getBody().getToolObject(toolId);
			//
			// to the following
			ExprNode body = ((OpDefNode) opNode).getBody();
			result = body.getToolObject(forToolId);
			while ((result == null) && (body.getKind() == ASTConstants.SubstInKind)) {
				body = ((SubstInNode) body).getBody();
				result = body.getToolObject(forToolId);
			}
			// end change

			if (result != null) {
				return result;
			}
		}
		return opNode;
	}

	default Object getVal(final ExprOrOpArgNode expr, final Context c, final boolean cachable, final int forToolId) {
		return getVal(expr, c, cachable, CostModel.DO_NOT_RECORD, forToolId);
	}

	default Object getVal(final ExprOrOpArgNode expr, final Context c, final boolean cachable, final CostModel cm, final int forToolId) {
		if (expr instanceof ExprNode) {
			return new LazyValue(expr, c, cachable, cm);
		}
		final SymbolNode opNode = ((OpArgNode) expr).getOp();
		return lookup(opNode, c, false, forToolId);
	}

	default Context getOpContext(final OpDefNode opDef, final ExprOrOpArgNode[] args, final Context c, final boolean cachable, final int forToolId) {
		return getOpContext(opDef, args, c, cachable, CostModel.DO_NOT_RECORD, forToolId);
	}

	default Context getOpContext(final OpDefNode opDef, final ExprOrOpArgNode[] args, final Context c,
			final boolean cachable, final CostModel cm, int forToolId) {
		final FormalParamNode[] formals = opDef.getParams();
		final int alen = args.length;
		Context c1 = c;
		for (int i = 0; i < alen; i++) {
			Object aval = getVal(args[i], c, cachable, cm, forToolId);
			c1 = c1.cons(formals[i], aval);
		}
		return c1;
	}

    /**
     * This method only returns an approximation of the level of the
     * expression.  The "real" level is at most the return value. Adding
     * <name, ValOne> to the context means that there is no need to
     * compute level for name.
     *
     * Note that this method does not work if called on a part of an
     * EXCEPT expression.
     */
	default int getLevelBound(final SemanticNode expr, final Context c, final int forToolId) {
		switch (expr.getKind()) {
			case ASTConstants.OpApplKind: {
				final OpApplNode expr1 = (OpApplNode) expr;
				return getLevelBoundAppl(expr1, c, forToolId);
			}
			case ASTConstants.LetInKind: {
				final LetInNode expr1 = (LetInNode) expr;
				final OpDefNode[] letDefs = expr1.getLets();
				final int letLen = letDefs.length;
				Context c1 = c;
				int level = 0;
				for (int i = 0; i < letLen; i++) {
					OpDefNode opDef = letDefs[i];
					level = Math.max(level, getLevelBound(opDef.getBody(), c1, forToolId));
					c1 = c1.cons(opDef, IntValue.ValOne);
				}
				return Math.max(level, getLevelBound(expr1.getBody(), c1, forToolId));
			}
			case ASTConstants.SubstInKind: {
				final SubstInNode expr1 = (SubstInNode) expr;
				final Subst[] subs = expr1.getSubsts();
				final int slen = subs.length;
				Context c1 = c;
				for (int i = 0; i < slen; i++) {
					final Subst sub = subs[i];
					c1 = c1.cons(sub.getOp(), getVal(sub.getExpr(), c, true, forToolId));
				}
				return getLevelBound(expr1.getBody(), c1, forToolId);
			}

			// Added by LL on 13 Nov 2009 to handle theorem and assumption names.
			case ASTConstants.APSubstInKind: {
				final APSubstInNode expr1 = (APSubstInNode) expr;
				final Subst[] subs = expr1.getSubsts();
				final int slen = subs.length;
				Context c1 = c;
				for (int i = 0; i < slen; i++) {
					final Subst sub = subs[i];
					c1 = c1.cons(sub.getOp(), getVal(sub.getExpr(), c, true, forToolId));
				}
				return getLevelBound(expr1.getBody(), c1, forToolId);
			}

			/***********************************************************************
			 * LabelKind case added by LL on 13 Jun 2007. *
			 ***********************************************************************/
			case ASTConstants.LabelKind: {
				final LabelNode expr1 = (LabelNode) expr;
				return getLevelBound(expr1.getBody(), c, forToolId);
			}
			default: {
				return 0;
			}
		}
	}

	/**
	 * Users will likely want to call only {@link #getLevelBound(SemanticNode, Context, int)} - this
	 * 	method is called from that method in certain cases.
	 */
	default int getLevelBoundAppl(final OpApplNode expr, Context c, final int forToolId) {
		final SymbolNode opNode = expr.getOperator();
		final UniqueString opName = opNode.getName();
		final int opcode = BuiltInOPs.getOpCode(opName);

		if (BuiltInOPs.isTemporal(opcode)) {
			return 3; // Conservative estimate
		}

		if (BuiltInOPs.isAction(opcode)) {
			return 2; // Conservative estimate
		}

		if (opcode == ToolGlobals.OPCODE_enabled) {
			return 1; // Conservative estimate
		}

		int level = 0;
		final ExprNode[] bnds = expr.getBdedQuantBounds();
		for (int i = 0; i < bnds.length; i++) {
			level = Math.max(level, getLevelBound(bnds[i], c, forToolId));
		}

		if (opcode == ToolGlobals.OPCODE_rfs) {
			// For recursive function, don't compute level of the function body
			// again in the recursive call.
			SymbolNode fname = expr.getUnbdedQuantSymbols()[0];
			c = c.cons(fname, IntValue.ValOne);
		}

		final ExprOrOpArgNode[] args = expr.getArgs();
		final int alen = args.length;
		for (int i = 0; i < alen; i++) {
			if (args[i] != null) {
				level = Math.max(level, getLevelBound(args[i], c, forToolId));
			}
		}

		if (opcode == 0) {
			// This operator is a user-defined operator.
			if (opName.getVarLoc() >= 0)
				return 1;

			final Object val = lookup(opNode, c, false, forToolId);
			if (val instanceof OpDefNode) {
				final OpDefNode opDef = (OpDefNode) val;
				c = c.cons(opNode, IntValue.ValOne);
				level = Math.max(level, getLevelBound(opDef.getBody(), c, forToolId));
			} else if (val instanceof LazyValue) {
				final LazyValue lv = (LazyValue) val;
				level = Math.max(level, getLevelBound(lv.expr, lv.con, forToolId));
            } else if (val instanceof EvaluatingValue) {
            	final EvaluatingValue ev = (EvaluatingValue) val;
            	level = Math.max(level, ev.getMinLevel());
            } else if (val instanceof MethodValue) {
            	final MethodValue mv = (MethodValue) val;
            	level = Math.max(level, mv.getMinLevel());
			}
		}
		return level;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/ISectionConstants.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor;


/**
 * Section definition constants
 * <br>
 * This interface contains identifiers given to sections of the three
 * Model Editor pages. An identifier is used in order to uniquely identify
 * the section. The {@link DataBindingManager} facility, provided by the editor is 
 * storing the information about "what section is located on what page" and "what 
 * attribute is displayed in what section". Using the ids the section can be expanded or collapsed.
 * This is used in case if an error is detected and the error marker is installed on the corresponding field.
 *  
 * As an example, here is how the constant SEC_WHAT_IS_THE_MODEL is used. 
 * The constant is given as an argument to the ValidateableConstantSectionPart
 * constructor in the createBodyContent method of MainModelPage, which gives it 
 * to its super, the ValidateableTableSectionPart constructor, which calls
 * page.getDataBindingManager().bindSection that puts it in the hash table
 * sectionsForPage with key the id of the page and value a vector of
 * all section ids that were registered with bindSection.  That value is e.G.
 * read by DataBindingManager.setAllSectionsEnabled which is called
 * in BasicFormPage.setEnabled, which is called by BasicFormPage.refresh,
 * which is called by:
 *  - BasicFormPage.createFormContent
 *  - a listener installed in ModelEditor by a ModelHelper.installModelModificationResourceChangeListener
 *  - MainModelPage.refresh() 
 *
 * @see {@link DataBindingManager}
 * @author <NAME>, <NAME>
 * @version $Id$
 */
public interface ISectionConstants
{
    // sections of the Main page
    public final static String SEC_COMMENTS = "__what_is_the_description";

    public final static String SEC_WHAT_IS_THE_SPEC = "__what_is_the_spec";
    public final static String SEC_WHAT_TO_CHECK = "__what_to_check";
    public final static String SEC_WHAT_TO_CHECK_INVARIANTS = "__what_to_check_invariants";
    public final static String SEC_WHAT_TO_CHECK_PROPERTIES = "__what_to_check_properties";
    
    public final static String SEC_WHAT_IS_THE_MODEL = "__what_is_the_model";
    public final static String SEC_HOW_TO_RUN = "__how_to_run";
    
    
    // sections on the Spec Options page
    public final static String SEC_NEW_DEFINITION = "__additional_definition";
    public final static String SEC_DEFINITION_OVERRIDE = "__definition_override";
    public final static String SEC_STATE_CONSTRAINT = "__state_constraints";
    public final static String SEC_ACTION_CONSTRAINT = "__action_constraints";
    public final static String SEC_MODEL_VALUES = "__model_values";
    
    
    // sections on the TLC Options page
    public final static String SEC_TLCOPT_CONFIGURATION = "__tlc_opt_config";
    public final static String SEC_TLCOPT_CHECK_MODE = "__tlc_opt_check_mode";
    public final static String SEC_TLCOPT_FEATURES = "__tlc_opt_features";
    public final static String SEC_TLCOPT_PARAMS = "__tlc_opt_params";

    
    // sections of the Results page
    public final static String SEC_GENERAL = "__general"; // General Section
    public final static String SEC_OUTPUT = "__output"; // User output
    public static final String SEC_STATISTICS = "__coverage"; // Statistics
    public static final String SEC_ERRORS = "__errors"; 
    public static final String SEC_PROGRESS = "__progress"; // Progress output
    public static final String SEC_EXPRESSION = "__expression"; // Eval Constant Expressions

}

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/ITLAReserveredWords.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import util.TLAConstants;

/**
 * TLA+ Reserved words
 * TODO complete the word list
 * @author <NAME>, <a href="http://simon.zambrovski.org">http://simon.zambrovski.org</a> 
 */
public interface ITLAReserveredWords
{
    public final static String ASSUME = "ASSUME";
    public final static String ASSUMPTION = "ASSUMPTION";
    public final static String AXIOM = "AXIOM";
    public final static String CASE = "CASE";
    public final static String CHOOSE = "CHOOSE";
    public final static String CONSTANT = TLAConstants.KeyWords.CONSTANT;
    public final static String CONSTANTS = TLAConstants.KeyWords.CONSTANTS;
    public final static String DOMAIN = "DOMAIN";
    public final static String ELSE = "ELSE";
    public final static String ENABLED = "ENABLED";
    public final static String EXCEPT = "EXCEPT";
    public final static String EXTENDS = "EXTENDS";
    public final static String IF = "IF";
    public final static String IN = "IN";
    public final static String INSTANCE = "INSTANCE";
    public final static String LET = "LET";
    public final static String LOCAL = "LOCAL";
    public final static String MODULE = "MODULE";
    public final static String OTHER = "OTHER";
    public final static String SF_ = "SF_";
    public final static String SUBSET = "SUBSET";
    public final static String THEN = "THEN";
    public final static String THEOREM = "THEOREM";
    public final static String UNCHANGED = "UNCHANGED";
    public final static String UNION = "UNION";
    public final static String VARIABLE = TLAConstants.KeyWords.VARIABLE;
    public final static String VARIABLES = VARIABLE + "S";
    public final static String WF_ = "WF_";
    public final static String WITH = "WITH";

    public final static String[] ALL_WORDS_ARRAY = new String[] { ASSUME, ASSUMPTION, AXIOM, CASE, CHOOSE, CONSTANT,
            CONSTANTS, DOMAIN, ELSE, ENABLED, EXCEPT, EXTENDS, IF, IN, INSTANCE, LET, LOCAL, MODULE, OTHER, SF_,
            SUBSET, THEN, THEOREM, UNCHANGED, UNION, VARIABLE, VARIABLES, WF_, WITH };

    public final static Set<String> ALL_WORDS_SET = new HashSet<String>(Arrays.asList(ALL_WORDS_ARRAY));
}

/*
 * $Log: ITLAReserveredWords.java,v $
 * Revision 1.1  2005/08/22 15:43:33  szambrovski
 * sf cvs init
 *
 * Revision 1.2  2004/10/13 14:45:00  sza
 * operators added
 *
 * Revision 1.1  2004/10/12 16:21:38  sza
 * initial commit
 *
 * Revision 1.1  2004/10/12 09:55:11  sza
 * additions
 *
 * Revision 1.1  2004/10/06 01:02:29  sza
 * initial commit
 *
 * Revision 1.1  2004/10/06 00:59:04  sza
 * initial commit
 *
 *
 */

<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/VectorCharReader.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS VectorCharReader EXTENDS CharReader                                *
*                                                                          *
* This class turns a vector of strings into a CharReader.  (See the        *
* CharReader class.)                                                       *
***************************************************************************/
package tla2tex;
import java.util.Vector;

public class VectorCharReader extends CharReader
  { private Vector vec ;
      /*********************************************************************
      * This is the vector providing the input characters.                 *
      *********************************************************************/

    private int nextLine = 0 ;
      /*********************************************************************
      * The next element of vec to be returned by innerGetNextLine.        *
      *********************************************************************/
      
    public VectorCharReader(Vector vector, int firstLine) 
      /*********************************************************************
      * The class constructor.  The fileName argument is the name of the   *
      * file.  It exits TLATeX if the file cannot be found.                *
      *********************************************************************/
      { this.line = firstLine ;
        this.vec = vector ;
      } ;

    public String innerGetNextLine()
      /*********************************************************************
      * The abstract innerGetNextLine method of CharReader is implemented  *
      * with the readLine method of java.io.BufferedReader.  It aborts     *
      * TLATeX if there is an IOException.                                 *
      *********************************************************************/
      { if (nextLine == vec.size())
         { return null ; } ;
        nextLine = nextLine + 1;
        return (String) vec.elementAt(nextLine - 1);
      } ;

    public void close()
      /*********************************************************************
      * Implements CharReader's abstract close() method.                   *
      *********************************************************************/
      { 
      };
  }


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/test/org/lamport/tla/toolbox/tool/tlc/AllTests.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.lamport.tla.toolbox.tool.tlc.output.data.DataTests;
import org.lamport.tla.toolbox.tool.tlc.ui.util.UtilTests;

public class AllTests
{

    public static Test suite()
    {
        TestSuite suite = new TestSuite("Test for org.lamport.tla.toolbox.tool.tlc");
        // $JUnit-BEGIN$
        suite.addTest(DataTests.suite());
        suite.addTest(UtilTests.suite());
        // $JUnit-END$
        return suite;
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/TBParTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.AbortException;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.xml.SymbolContext;
import tlc2.util.Context;
import util.UniqueString;

public class TBParTest {

	@Test
	public void testParticleClosureInconsistentConstantLevel() {
		final TBPar tbPar = new TBPar();
		// Positive form (negation pushed down), and, thus, locally inconsistent.
		tbPar.addElement(new LNBool(false));
		tbPar.addElement(new LNNeg(new LNBool(false)));
		assertEquals(0, tbPar.particleClosure().size());
	}

	@Test
	public void testParticleClosureInconsistentStateLevel() {
		final TBPar tbPar = new TBPar();
		// Positive form (negation pushed down), and, thus, locally inconsistent.
		final LiveExprNode p = new LNStateAST(new DummyOpApplNode("p"), Context.Empty);
		tbPar.addElement(p);
		tbPar.addElement(new LNNeg(p));
		assertEquals(0, tbPar.particleClosure().size());
	}

	@Test
	public void testParticleClosureConsistentConstantLevel() {
		final TBPar tbPar = new TBPar();
		tbPar.addElement(new LNBool(false));
		tbPar.addElement(new LNNeg(new LNBool(true)));
		assertEquals(1, tbPar.particleClosure().size());
	}

	@Test
	public void testParticleClosureConsistentStateLevel() {
		final TBPar tbPar = new TBPar();
		final LiveExprNode p = new LNStateAST(new DummyOpApplNode("p"), Context.Empty);
		tbPar.addElement(p);
		tbPar.addElement(new LNNeg(new LNNeg(p)));
		assertEquals(1, tbPar.particleClosure().size());
	}

	@Test
	public void testParticleClosureExampleConstLevel() {
		// <>p \/ []~p from page 454 of Manna & Pnueli book with p constant-level
		// expression.
		final LiveExprNode p = new LNBool(true);
		
		final TBPar tbPar = new TBPar();
		final LNEven evenP = new LNEven(p);
		// Because the same LNStateAST instance appears in both disjuncts, there is no
		// need to tag it--LNState#equals behaves the same.
		final LNDisj phi = new LNDisj(evenP, new LNAll(new LNNeg(p)));
		tbPar.addElement(phi);

		// p 454 gives the expected particles.
		final TBParVec particleClosure = tbPar.particleClosure();
		assertEquals(3, particleClosure.size());

		// <>p \/ []~p, <>p, p
		assertEquals(phi, particleClosure.elementAt(0).elementAt(0));
		assertEquals(evenP, particleClosure.elementAt(0).elementAt(1));
		assertEquals(p, particleClosure.elementAt(0).elementAt(2));

		// <>p \/ []~p, <>p, ()<>p
		assertEquals(phi, particleClosure.elementAt(1).elementAt(0));
		assertEquals(evenP, particleClosure.elementAt(1).elementAt(1));
		// LN*#equals(Object) just object identify, thus, manually checked here. 
		final LiveExprNode nextEvenP = particleClosure.elementAt(1).elementAt(2);
		assertTrue(nextEvenP instanceof LNNext);
		assertEquals(evenP, ((LNNext) nextEvenP).getBody());

		// <>p \/ []~p, []~p, ()[]~p, ~p
		assertEquals(phi, particleClosure.elementAt(2).elementAt(0));
		// ...[]~p
		assertTrue(particleClosure.elementAt(2).elementAt(1) instanceof LNAll);
		assertTrue(((LNAll) particleClosure.elementAt(2).elementAt(1)).getBody() instanceof LNNeg);
		assertEquals(p, ((LNNeg) ((LNAll) particleClosure.elementAt(2).elementAt(1)).getBody()).getBody());
		assertEquals("[]-TRUE", particleClosure.elementAt(2).elementAt(1).toString());
		// ...~p
		assertTrue((particleClosure.elementAt(2).elementAt(2)) instanceof LNNeg);
		assertEquals(p, ((LNNeg) particleClosure.elementAt(2).elementAt(2)).getBody());
		assertEquals("-TRUE", particleClosure.elementAt(2).elementAt(2).toString());
		// ...()[]~p
		assertTrue(particleClosure.elementAt(2).elementAt(3) instanceof LNNext);
		assertTrue(((LNNext) particleClosure.elementAt(2).elementAt(3)).getBody() instanceof LNAll);
		assertTrue(((LNAll) ((LNNext) particleClosure.elementAt(2).elementAt(3)).getBody()).getBody() instanceof LNNeg);
		assertEquals("()[]-TRUE", particleClosure.elementAt(2).elementAt(3).toString());
	}

	@Test
	public void testParticleClosureExampleStateLevel() {
		// <>p \/ []~p from page 454 of Manna & Pnueli book with p state-level
		// expression.
		final LiveExprNode p = new LNStateAST(new DummyOpApplNode("p"), Context.Empty);

		final TBPar tbPar = new TBPar();
		final LNEven evenP = new LNEven(p);
		// Because the same LNStateAST instance appears in both disjuncts, there is no
		// need to tag it--LNState#equals behaves the same.
		final LNDisj phi = new LNDisj(evenP, new LNAll(new LNNeg(p)));
		tbPar.addElement(phi);

		// p 454 gives the expected particles.
		final TBParVec particleClosure = tbPar.particleClosure();
		assertEquals(3, particleClosure.size());

		// <>p \/ []~p, <>p, p
		assertEquals(phi, particleClosure.elementAt(0).elementAt(0));
		assertEquals(evenP, particleClosure.elementAt(0).elementAt(1));
		assertEquals(p, particleClosure.elementAt(0).elementAt(2));

		// <>p \/ []~p, <>p, ()<>p
		assertEquals(phi, particleClosure.elementAt(1).elementAt(0));
		assertEquals(evenP, particleClosure.elementAt(1).elementAt(1));
		// LN*#equals(Object) just object identify, thus, manually checked here. 
		final LiveExprNode nextEvenP = particleClosure.elementAt(1).elementAt(2);
		assertTrue(nextEvenP instanceof LNNext);
		assertEquals(evenP, ((LNNext) nextEvenP).getBody());

		// <>p \/ []~p, []~p, ()[]~p, ~p
		assertEquals(phi, particleClosure.elementAt(2).elementAt(0));
		// ...[]~p
		assertTrue(particleClosure.elementAt(2).elementAt(1) instanceof LNAll);
		assertTrue(((LNAll) particleClosure.elementAt(2).elementAt(1)).getBody() instanceof LNNeg);
		assertEquals(p, ((LNNeg) ((LNAll) particleClosure.elementAt(2).elementAt(1)).getBody()).getBody());
		assertEquals("[]-p", particleClosure.elementAt(2).elementAt(1).toString());
		// ...~p
		assertTrue((particleClosure.elementAt(2).elementAt(2)) instanceof LNNeg);
		assertEquals(p, ((LNNeg) particleClosure.elementAt(2).elementAt(2)).getBody());
		assertEquals("-p", particleClosure.elementAt(2).elementAt(2).toString());
		// ...()[]~p
		assertTrue(particleClosure.elementAt(2).elementAt(3) instanceof LNNext);
		assertTrue(((LNNext) particleClosure.elementAt(2).elementAt(3)).getBody() instanceof LNAll);
		assertTrue(((LNAll) ((LNNext) particleClosure.elementAt(2).elementAt(3)).getBody()).getBody() instanceof LNNeg);
		assertEquals("()[]-p", particleClosure.elementAt(2).elementAt(3).toString());
	}

	
	public static class DummyOpApplNode extends OpApplNode {

		public DummyOpApplNode(String name) {
			super(new DummySymbolNode(name));
		}

		@Override
		public String toString() {
			return this.operator.toString();
		}
		
		private static class DummySymbolNode extends SymbolNode {
			
			protected DummySymbolNode(String name) {
				super(1, SyntaxTreeNode.nullSTN, UniqueString.uniqueStringOf(name));
			}
			
			@Override
			public int getArity() {
				throw new UnsupportedOperationException("not implemented");
			}
			
			@Override
			public boolean isLocal() {
				throw new UnsupportedOperationException("not implemented");
			}
			
			@Override
			public boolean match(OpApplNode test, ModuleNode mn) throws AbortException {
				throw new UnsupportedOperationException("not implemented");
			}
			
			@Override
			protected Element getSymbolElement(Document doc, SymbolContext context) {
				throw new UnsupportedOperationException("not implemented");
			}
			
			@Override
			protected String getNodeRef() {
				throw new UnsupportedOperationException("not implemented");
			}
			
			@Override
			public String toString() {
				return name.toString();
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/module/Bags.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at  9:18:39 PST by lamport
//      modified on Tue Jan  2 11:40:25 PST 2001 by yuanyu

package tlc2.module;

import tlc2.output.EC;
import tlc2.tool.EvalControl;
import tlc2.tool.EvalException;
import tlc2.tool.impl.TLARegistry;
import tlc2.util.Vect;
import tlc2.value.IBoolValue;
import tlc2.value.ValueConstants;
import tlc2.value.Values;
import tlc2.value.impl.Applicable;
import tlc2.value.impl.BoolValue;
import tlc2.value.impl.FcnRcdValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.SetEnumValue;
import tlc2.value.impl.Value;
import tlc2.value.impl.ValueVec;
import util.Assert;

public class Bags implements ValueConstants
{
	public static final long serialVersionUID = 20160822L;

    static
    {
		// The following entries in TLARegistry each defines a mapping from a TLA+ infix
		// operator to a Java method, e.g. the TLA+ infix operator \\oplus (which is the
		// same as (+) ) is mapped to and thus implemented by the Java method
		// tlc2.module.Bags.BagCup(Value, Value) below.
        Assert.check(TLARegistry.put("BagCup", "\\oplus") == null, EC.TLC_REGISTRY_INIT_ERROR, "BagCup");
        Assert.check(TLARegistry.put("BagDiff", "\\ominus") == null, EC.TLC_REGISTRY_INIT_ERROR, "BagDiff");
        Assert.check(TLARegistry.put("SqSubseteq", "\\sqsubseteq") == null, EC.TLC_REGISTRY_INIT_ERROR, "SqSubseteq");
    }

    public static Value EmptyBag()
    {
        return FcnRcdValue.EmptyFcn;
    }

    public static IBoolValue IsABag(final Value b)
    {
        final FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        if (fcn == null)
        {
        	// MAK 02/23/2018 Changed to return ValFalse instead of exception when Value is not a bag.
            //throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "IsBag",
            //        "a function with a finite domain", Value.ppr(b.toString()) });
        	return BoolValue.ValFalse;
        }
        final Value[] vals = fcn.values;
        for (int i = 0; i < vals.length; i++)
        {
            if (!(vals[i] instanceof IntValue) || ((IntValue) vals[i]).val <= 0)
            {
                return BoolValue.ValFalse;
            }
        }
        return BoolValue.ValTrue;
    }

    public static IntValue BagCardinality(Value b)
    {
        FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        if (fcn == null)
        {
            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagCardinality",
                    "a function with a finite domain", Values.ppr(b.toString()) });
        }
        int num = 0;
        Value[] vals = fcn.values;
        for (int i = 0; i < vals.length; i++)
        {
            if (vals[i] instanceof IntValue)
            {
                int cnt = ((IntValue) vals[i]).val;
                if (cnt > 0)
                {
                    num += ((IntValue) vals[i]).val;
                } else
                {
                    throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagCardinality", "a bag",
                            Values.ppr(b.toString()) });
                }
            } else
            {
            	throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagCardinality", "a bag",
                        Values.ppr(b.toString()) });
            }
        }
        return IntValue.gen(num);
    }

    public static IBoolValue BagIn(final Value e, final Value b)
    {
        final FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        final Value[] values = fcn.values;
        final Value[] domain = fcn.getDomainAsValues();
        for (int i = 0; i < domain.length; i++)
        {
            if (e.equals(domain[i]))
            {
                if (values[i] instanceof IntValue)
                {
                    return (((IntValue) values[i]).val > 0) ? BoolValue.ValTrue : BoolValue.ValFalse;
                }
                throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "BagIn", "bag",
                        Values.ppr(b.toString()) });
            }
        }
        return BoolValue.ValFalse;
    }

    public static IntValue CopiesIn(final Value e, final Value b)
    {
        final FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        final Value[] values = fcn.values;
        final Value[] domain = fcn.getDomainAsValues();
        for (int i = 0; i < domain.length; i++)
        {
            if (e.equals(domain[i]))
            {
                if (values[i] instanceof IntValue)
                {
                    return (IntValue) values[i];
                }
                throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "CopiesIn", "bag",
                        Values.ppr(b.toString()) });
            }
        }
        return IntValue.ValZero;
    }

    public static Value BagCup(Value b1, Value b2)
    {
        FcnRcdValue fcn1 = (FcnRcdValue) b1.toFcnRcd();
        FcnRcdValue fcn2 = (FcnRcdValue) b2.toFcnRcd();
        if (!IsABag(fcn1).getVal())
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "first", "(+)", "bag",
                    Values.ppr(b1.toString()) });
        }
        if (!IsABag(fcn2).getVal())
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "(+)", "bag",
                    Values.ppr(b2.toString()) });
        }
        Value[] domain1 = fcn1.getDomainAsValues();
        Value[] values1 = fcn1.values;
        Value[] domain2 = fcn2.getDomainAsValues();
        Value[] values2 = fcn2.values;
        Vect<Value> dVec = new Vect<>(domain1.length);
        Vect<Value> vVec = new Vect<>(domain1.length);
        for (int i = 0; i < domain1.length; i++)
        {
            dVec.addElement(domain1[i]);
            vVec.addElement(values1[i]);
        }
        for (int i = 0; i < domain2.length; i++)
        {
            boolean found = false;
            for (int j = 0; j < domain1.length; j++)
            {
                if (domain2[i].equals(domain1[j]))
                {
                    int v1 = ((IntValue) values1[j]).val;
                    int v2 = ((IntValue) values2[i]).val;
                    vVec.setElementAt(IntValue.gen(v1 + v2), j);
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                dVec.addElement(domain2[i]);
                vVec.addElement(values2[i]);
            }
        }
        Value[] domain = new Value[dVec.size()];
        Value[] values = new Value[dVec.size()];
        for (int i = 0; i < domain.length; i++)
        {
            domain[i] = dVec.elementAt(i);
            values[i] = vVec.elementAt(i);
        }
        return new FcnRcdValue(domain, values, false);
    }

    public static Value BagDiff(Value b1, Value b2)
    {
        FcnRcdValue fcn1 = (FcnRcdValue) b1.toFcnRcd();
        FcnRcdValue fcn2 = (FcnRcdValue) b2.toFcnRcd();
        if (fcn1 == null)
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "first", "(-)", "bag",
                    Values.ppr(b1.toString()) });
        }
        if (fcn2 == null)
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "(-)", "bag",
                    Values.ppr(b2.toString()) });
        }
        Value[] domain1 = fcn1.getDomainAsValues();
        Value[] values1 = fcn1.values;
        Value[] domain2 = fcn2.getDomainAsValues();
        Value[] values2 = fcn2.values;
        Vect<Value> dVec = new Vect<>(domain1.length);
        Vect<Value> vVec = new Vect<>(domain1.length);
        for (int i = 0; i < domain1.length; i++)
        {
            int v1 = ((IntValue) values1[i]).val;
            for (int j = 0; j < domain2.length; j++)
            {
                if (domain1[i].equals(domain2[j]))
                {
                    int v2 = ((IntValue) values2[j]).val;
                    v1 -= v2;
                    break;
                }
            }
            if (v1 > 0)
            {
                dVec.addElement(domain1[i]);
                vVec.addElement(IntValue.gen(v1));
            }
        }
        Value[] domain = new Value[dVec.size()];
        Value[] values = new Value[vVec.size()];
        for (int i = 0; i < domain.length; i++)
        {
            domain[i] = dVec.elementAt(i);
            values[i] = vVec.elementAt(i);
        }
        return new FcnRcdValue(domain, values, fcn1.isNormalized());
    }

    public static Value BagUnion(final Value s)
    {
        final SetEnumValue s1 = (SetEnumValue) s.toSetEnum();
        if (s1 == null)
        {
            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagUnion",
                    "a finite enumerable set", Values.ppr(s.toString()) });
        }
        // MAK 02/20/2018:
        // Need to normalize s in cases where it is an unnormalized set of identical
        // bags, such as h == [ i \in 1..3 |-> 1 ] and BagUnion({h, h}). In other
        // words, let b be a bag, BagUnion({b,b}) = b and not b (+) b. This
        // unfortunately degrades performance due to sorting s1's elements.
        s1.normalize();

        ValueVec elems = s1.elems;
        int sz = elems.size();
        if (sz == 0) {
        	return FcnRcdValue.EmptyFcn;
        }
        if (sz == 1) {
        	return elems.elementAt(0);
        }
        ValueVec dVec = new ValueVec();
        ValueVec vVec = new ValueVec();
        FcnRcdValue fcn = (FcnRcdValue) elems.elementAt(0).toFcnRcd();
        if (fcn == null)
        {
            throw new EvalException(EC.TLC_MODULE_BAG_UNION1, Values.ppr(s.toString()));
        }
        Value[] domain = fcn.getDomainAsValues();
        Value[] values = fcn.values;
        for (int i = 0; i < domain.length; i++)
        {
            dVec.addElement(domain[i]);
            vVec.addElement(values[i]);
        }
        for (int i = 1; i < sz; i++)
        {
            fcn = (FcnRcdValue) elems.elementAt(i).toFcnRcd();
            if (fcn == null)
            {

                throw new EvalException(EC.TLC_MODULE_BAG_UNION1, Values.ppr(s.toString()));
            }
            domain = fcn.getDomainAsValues();
            values = fcn.values;
            for (int j = 0; j < domain.length; j++)
            {
                boolean found = false;
                for (int k = 0; k < dVec.size(); k++)
                {
                    if (domain[j].equals(dVec.elementAt(k)))
                    {
                        int v1 = ((IntValue) vVec.elementAt(k)).val;
                        int v2 = ((IntValue) values[j]).val;
                        vVec.setElementAt(IntValue.gen(v1 + v2), k);
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    dVec.addElement(domain[j]);
                    vVec.addElement(values[j]);
                }
            }
        }
        Value[] dom = new Value[dVec.size()];
        Value[] vals = new Value[vVec.size()];
        for (int i = 0; i < dom.length; i++)
        {
            dom[i] = dVec.elementAt(i);
            vals[i] = vVec.elementAt(i);
        }
        return new FcnRcdValue(dom, vals, false);
    }

    public static IBoolValue SqSubseteq(Value b1, Value b2)
    {
        FcnRcdValue fcn1 = (FcnRcdValue) b1.toFcnRcd();
        FcnRcdValue fcn2 = (FcnRcdValue) b2.toFcnRcd();
        if (fcn1 == null)
        {
            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "\\sqsubseteq",
                    "a function with a finite domain", Values.ppr(b1.toString()) });
        }
        if (fcn2 == null)
        {

            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "\\sqsubseteq",
                    "a function with a finite domain", Values.ppr(b2.toString()) });
        }
        Value[] domain1 = fcn1.getDomainAsValues();
        Value[] values1 = fcn1.values;
        Value[] domain2 = fcn2.getDomainAsValues();
        Value[] values2 = fcn2.values;
        for (int i = 0; i < domain1.length; i++)
        {
            int v1 = ((IntValue) values1[i]).val;
            for (int j = 0; j < domain2.length; j++)
            {
                if (domain1[i].equals(domain2[j]))
                {
                    int v2 = ((IntValue) values2[j]).val;
                    v1 -= v2;
                    break;
                }
            }
            if (v1 > 0)
                return BoolValue.ValFalse;
        }
        return BoolValue.ValTrue;
    }

    public static Value BagOfAll(Value f, Value b)
    {
        if (!(f instanceof Applicable))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "first", "BagOfAll", "operator",
                    Values.ppr(f.toString()) });
        }
        FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        if (fcn == null)
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "BagOfAll",
                    "function with a finite domain", Values.ppr(b.toString()) });
        }
        Applicable ff = (Applicable) f;
        ValueVec dVec = new ValueVec();
        ValueVec vVec = new ValueVec();
        Value[] domain = fcn.getDomainAsValues();
        Value[] values = fcn.values;
        Value[] args = new Value[1];
        for (int i = 0; i < domain.length; i++)
        {
            args[0] = domain[i];
            Value val = ff.apply(args, EvalControl.Clear);
            boolean found = false;
            for (int j = 0; j < dVec.size(); j++)
            {
                if (val.equals(dVec.elementAt(j)))
                {
                    int v1 = ((IntValue) vVec.elementAt(j)).val;
                    int v2 = ((IntValue) values[i]).val;
                    vVec.setElementAt(IntValue.gen(v1 + v2), j);
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                dVec.addElement(val);
                vVec.addElement(values[i]);
            }
        }
        Value[] dom = new Value[dVec.size()];
        Value[] vals = new Value[vVec.size()];
        for (int i = 0; i < dom.length; i++)
        {
            dom[i] = dVec.elementAt(i);
            vals[i] = vVec.elementAt(i);
        }
        return new FcnRcdValue(dom, vals, false);
    }

    /******
     // For now, we do not override SubBag. So, We are using the TLA+ definition.
    public static Value SubBag(Value b) {
      FcnRcdValue fcn = b.toFcnRcd();
      if (fcn == null) {
        String msg = "Applying SubBag to the following value, which is\n" +
    "not a function with a finite domain:\n" + Value.ppr(b.toString());
        throw new EvalException(msg);
      }
      throw new EvalException("SubBag is not implemented.");
    }
    ******/

    public static Value BagToSet(Value b)
    {
        FcnRcdValue fcn = (FcnRcdValue) b.toFcnRcd();
        if (fcn == null)
        {
            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagToSet",
                    "a function with a finite domain", Values.ppr(b.toString()) });
        }
        return fcn.getDomain();
    }

    public static Value SetToBag(Value b)
    {
        SetEnumValue s1 = (SetEnumValue) b.toSetEnum();
        if (s1 == null)
        {
            throw new EvalException(EC.TLC_MODULE_APPLYING_TO_WRONG_VALUE, new String[] { "BagToSet",
                    "a function with a finite domain", Values.ppr(b.toString()) });
        }
        // The following `if' added by LL on 5 Mar 2012 to correct a bug found by <NAME>,
        // in which SetToBag creates a function with multiple copies of the elements in its
        // domain, and this causes BagToSet to report an error.
        if (!s1.isNormalized()) {
        	s1.normalize();
        }
        ValueVec elems = s1.elems;
        Value[] domain = new Value[elems.size()];
        Value[] values = new Value[elems.size()];
        for (int i = 0; i < elems.size(); i++)
        {
            domain[i] = elems.elementAt(i);
            values[i] = IntValue.ValOne;
        }
        return new FcnRcdValue(domain, values, s1.isNormalized());
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/update/revert-update.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<HEAD>

<meta name="copyright" content="Copyright (c) IBM Corporation and others 2008. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." >

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="../style.css" rel="stylesheet" CHARSET="ISO-8859-1" TYPE="text/css">
<title>Reverting to a previous install version</title>
</HEAD>

<BODY BGCOLOR="#ffffff">
<h1>Reverting to a previous Toolbox version</h1>
<p>As you upgrade the Toolbox, previous versions of the Toolbox are kept in a history.&nbsp;  
  To revert to a saved version:
</p>

<ol>
<li>Click <b>Help &gt; About</b> and then click
  <a class="command-link" href='javascript:executeCommand("org.eclipse.ui.help.installationDialog")'>
  <img src="PLUGINS_ROOT/org.eclipse.help/command_link.png">
  <b>Installation Details...</b></a> to open a dialog. </li>
  
  <li> Click the <b>Installation History</b> tab to see a list of previously saved versions.&nbsp;
    Selecting the date in the upper list
  will show you what version was installed in the bottom list.&nbsp;
    When you have found the version
  to which you want to revert, click <b>Revert</b>.</li>
  
  <li>Click <b>Yes</b> when asked to exit and restart the Toolbox for the changes 
    to take effect.</li>
</ol>

<p>
If you reinstall the Toolbox manually from a zip file, you cannot revert to a previous version.
</p>

<hr>
<a href="run-update.html">&uarr; Updating the Toolbox</a>
</hr>

</BODY>
</HTML>


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/OpenSavedModuleHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.editor.basic.TLAEditorReadOnly;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.util.UIHelper;

/**
 * Opens a module in a read-only editor. This handler has one required
 * parameter, the String representing the full file system path to the
 * module to be opened. This String should be created using {@link Path#toPortableString()}.
 * 
 * @author <NAME>
 *
 */
public class OpenSavedModuleHandler extends AbstractHandler implements IHandler
{

    public static final String COMMAND_ID = "toolbox.tool.tlc.commands.open.savedModule";
    /**
     * String parameter giving the full file system path to the module to be opened.
     * This String should have been created using {@link Path#toPortableString()}.
     */
    public static final String PARAM_MODULE_PATH = "toolbox.tool.tlc.commands.open.savedModule.modulePath";

    public Object execute(ExecutionEvent event) throws ExecutionException
    {
        String pathString = event.getParameter(PARAM_MODULE_PATH);
        if (pathString != null)
        {
            /*
             * Try to get the module from the path passed in as a parameter.
             */
            IPath modulePath = Path.fromPortableString(pathString);
            IFile module = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(modulePath);
            if (module != null && module.exists())
            {
                /*
                 * Check to see if the module is part of the currently opened
                 * spec. The project containing the module is the project of the
                 * spec of the module. If this is not equal to the project of the
                 * currently opened spec, it is a bug.
                 */
                final Spec currentSpec = ToolboxHandle.getCurrentSpec();
				if (module.getProject().equals(currentSpec.getProject()))
                {
                    /*
                     * The parent of the module is the model folder, so it is the name
                     * of the model.
                     */
					Model model = currentSpec.getAdapter(TLCSpec.class).getModel(module.getParent().getName());
                    ModelEditor modelEditor = (ModelEditor) UIHelper.openEditor(ModelEditor.ID, model.getLaunchConfiguration().getFile());
                    if (modelEditor != null)
                    {
                        try
                        {
                            /*
                             * First, we determine if the model editor already has a TLAEditorReadOnly
                             * open on the saved module.
                             * 
                             * If the model editor does have a TLAEditorReadOnly on the saved module,
                             * we set the input to be the new editor input on the module. It is necessary
                             * to reset the input even though the editor is already open on that module
                             * because the saved version of the module may have changed.
                             * 
                             * If the model editor does not have a TLAEditorReadOnly open on the saved module
                             * then we create a new instance and open it in the model editor.
                             * 
                             * Whether the editor was previously open or not, we always activate
                             * that page.
                             */
                            FileEditorInput editorInput = new FileEditorInput(module);

                            /*
                             * The only method to get currently opened editors in the model
                             * editor is findEditors(editorInput) which returns an array
                             * of currently opened editors on the input. This should only
                             * have length one, but for whatever reason we may decide in
                             * the future to have more than one editor open on a given input
                             * in the model editor.
                             * 
                             * We iterate through this array of editors until we find one
                             * that is a TLAEditorReadOnly. We then set the input to be the
                             * editor input.
                             */
                            IEditorPart[] editors = modelEditor.findEditors(editorInput);
                            TLAEditorReadOnly moduleEditor = null;
                            for (int i = 0; i < editors.length; i++)
                            {
                                if (editors[i] instanceof TLAEditorReadOnly)
                                {
                                    moduleEditor = (TLAEditorReadOnly) editors[i];
                                    moduleEditor.setInput(editorInput);
                                    break;
                                }
                            }

                            /*
                             * Create a new instance if there is not already
                             * an editor open.
                             */
                            if (moduleEditor == null)
                            {
                                moduleEditor = new TLAEditorReadOnly();
                                modelEditor.addPage(moduleEditor, editorInput);
                            }

                            // always activate the editor page.
                            modelEditor.setActiveEditor(moduleEditor);
                        } catch (PartInitException e)
                        {
                            TLCUIActivator.getDefault().logError("Error adding saved module read-only editor for module "
                                    + modulePath + " to model " + model.getName(), e);
                        }
                    } else
                    {
                        TLCUIActivator.getDefault().logDebug("Could not open model editor for model " + model.getName());
                    }
                } else
                {
                    TLCUIActivator.getDefault()
                            .logDebug("OpenSavedModuleHandler was passed a module file path that is not part of the currently opened spec."
                                    + "This is a bug. The path is " + modulePath);
                }
            }
        }
        return null;
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/TLAExpr.java<|end_filename|>
/***************************************************************************
* CLASS TLAExpr                                                            *
*                                                                          *
* A TLAExpr is a representation of any part of a TLA+ specification.  It   *
* usually represents an expression, but can be used to represent           *
* sequences of declarations and definitions--including the complete        *
* translation.                                                             *
*                                                                          *
* A TLAExpr expr contains the following fields and methods:                *
*                                                                          *
*    tokens       : A vector of lines, where a line is a vector of tokens. *
*                   We say that expr is NORMALIZED iff expr.tokens has     *
*                   no non-empty line, or it has a non-empty line whose    *
*                   first token is in column 0.                            *
*                                                                          *
*    anchorTokens : An array of TLAToken's of the same length as           *
*                   expr.tokens, where expr.anchorTokens[i] is the anchor  *
*                   of line i.  (The definition of an anchor token is in   *
*                   the rule for preserving formatting in the comments at  *
*                   the end of this file.)                                 *
*                                                                          *
*    anchorTokCol : An array of int's, of the same length as expr.tokens,  *
*                   where if expr.anchorTokens[i] is non-null, then        *
*                   expr.anchorTokCol[i] was the value of                  *
*                   (expr.anchorTokens[i]).column when the normalize       *
*                   method was called.                                     *
*                                                                          *
* If expr comes from an expression taken directly from the algorithm,      *
* then it evolves as follows.  First, expr is built up token by token,     *
* using the methods expr.addToken and expr.addLine methods.  It is then    *
* normalized and expr.anchorTokCol and expr.anchorTokens are computed by   *
* calling expr.normalize().  Additional tokens may then be added.  Adding  *
* a token modifies the columns of the tokens to the right, but it does     *
* not modify expr.anchorTokens or expr.anchorTokCol.  The renormalize      *
* method should be called after adding a sequence of tokens (such as by    *
* substituting an expression for a token) to adjust the anchorTokens and   *
* anchorTokCol fields before any more tokens are added to the expression.  *
*                                                                          *
* Here are the methods.                                                    *
*                                                                          *
*    addToken(tok) : Adds the TLAToken tok to the end of the last line.    *
*                    Note that tok.column must have the proper value       *
*                    for the expression produced by the method to be       *
*                    sensible.                                             *
*                                                                          *
*    addTokenOffset(tok, offset) :                                         *
*                    Adds the TLAToken tok to the end of the last line,    *
*                    setting tok's column so the token appears offset      *
*                    characters to the right of the last token on the      *
*                    line.  (Added 30 Aug 2007.)                           *
*                                                                          *
*    addLine()     : Adds an empty line to the end.  (Must be called       *
*                    before the first call of addToken.)                   *
*                                                                          *
*    normalize()   : Removes empty lines at the end of the expression      *
*                    and computes anchorTokens and anchorTokCol as         *
*                    explained above.                                      *
*                                                                          *
*    renormalize() : Recomputes anchorTokens and anchorTokCol as           *
*                    explained above.                                      *
*                                                                          *
*    toStringVector() :                                                    *
*      Equals a Vector of strings, each being the ASCII representation     *
*      of the corresponding line of expr.  If expr.anchorTokens[i] is      *
*      non-null, then an extra                                             *
*                                                                          *
*         (expr.anchorTokens[i]).column - expr.anchorTokCol[i]             *
*                                                                          *
*      spaces are added to the beginning of line i to maintain the         *
*      original indentation.                                               *
*                                                                          *
*    toString() :                                                          *
*       This converts an expr into a string that is its TLA+               *
*       representation in the AST module.  It is used for                  *
*       the -spec option, and for debugging.                               *
*                                                                          *
*    cloneAndNormalize() :                                                 *
*       Used to create a clone of the current expression.                  *
*                                                                          *
*    prepend(expr, spaces) :                                               *
*       Prepends the expression expr to the current expression,            *
*       leaving `spaces' spaces between the end of expr and the            *
*       first token of the original expression.                            *
*                                                                          *
*    substituteForAll(exprs, strs, parenthesize) :                         *
*       Substitutes the expressions in the vector exprs of TLAExpr         *
*       objects for the identifiers in the vector strs of strings.         *
*       If parenthesize = true, then put parentheses around the            *
*       substituted expression unless it or the current expression         *
*       consists of just one token.                                        *
*                                                                          *
*    substituteForAll(exprs, strs) :                                       *
*       Same as substituteForAll(exprs, strs, true).  (Kept for            *
*       compatibility after the third argument was added.)                 *
*                                                                          *
*    SeqSubstituteForAll(expVec, exprs, strs) :                            *
*       A vector of expressions obtained from the vector expVec of         *
*       expressions by cloning each of them and then                       *
*       substituting the expressions in the vector exprs of TLAExpr        *
*       objects for the identifiers in the vector strs of strings.         *
*                                                                          *
* There are quite a few other methods used to implement these that might   *
* be of use for manipulating expressions.  Search below for "SUBSTITUTING  *
* IN EXPRESSIONS" to find them.                                            *
***************************************************************************/
package pcal;
import java.util.Vector;

import pcal.exception.TLAExprException;
import pcal.exception.UnrecoverableException;
import tla2tex.Debug;

public class TLAExpr
  { 
  
    /**
     * A TLAExpr object represents a TLA+ expression.  The tokens vector is 
     * a vector of vectors of TLAToken objects.  Each 
     * subvector contains the tokens in one line of the expression.
     */
    public Vector tokens       = new Vector(4);
    public TLAToken[] anchorTokens = null;
    public int[]      anchorTokCol = null;
    
    /**
     * If this object represents an expression in the PCal code, then
     * origin is the region from the beginning of the first token to the
     * end of the last token.
     * 
     * If this object is an expression substituted for a token, then
     * origin is the region is the source region of that token.
     */
    private Region origin = null;

    public Region getOrigin() {
		return origin;
	}

	public void setOrigin(Region origin) {
		this.origin = origin;
	}

	TLAExpr()
      /*********************************************************************
      * A constructor for an empty object of class TLAExpr.                *
      *********************************************************************/
    { }
      
    TLAExpr(Vector t)
      /*********************************************************************
      * A constructur that builds a new, unnormalized TLAExpr with a       *
      * given tokens Vector.                                               *
      *********************************************************************/
     {tokens = t ;
      anchorTokens = null;
      anchorTokCol = null;
     }

    public void addToken(TLAToken tok)
      { ((Vector) tokens.elementAt(tokens.size()-1)).addElement(tok) ;
      } ;


    /***********************************************************************
    * The addTokenOffset method was added by LL on 30 Aug 2007 to fix the  *
    * following bug.  When a prime or "[self]" is appended to a variable   *
    * v, the sustituteForAll() method is called to replace the token "v"   *
    * with an expression consisting of a line having the sequence of       *
    * tokens                                                               *
    *                                                                      *
    *    "v"  "'"   or   "v" "[" "self" "]"                                *
    *                                                                      *
    * However, every token in this expression had column 0, which caused   *
    * the renormalize() method to mess up alignment and even halt with     *
    * the error                                                            *
    *                                                                      *
    *   "TLAExpr.renormalize() found anchor has moved to left."            *
    *                                                                      *
    * To fix this, the calls in PcalTLAGen.java to addToken() that were    *
    * used to create the new expression were replaced by calls to          *
    * addTokenOffset.                                                      *
    ***********************************************************************/
    public void addTokenOffset(TLAToken tok, int offset)
      {  Vector lastLine = (Vector) tokens.elementAt(tokens.size()-1) ;
         int newCol = offset ;
         if (lastLine.size() > 0) 
           { TLAToken lastTok = 
                (TLAToken) lastLine.elementAt(lastLine.size()-1) ;
            newCol = newCol + lastTok.column + lastTok.string.length() ;
           } ;
         tok.column = newCol ;
         lastLine.addElement(tok) ;
      }

    public void addLine() 
      { /*******************************************************************
        * The new line is set to an empty vector.                          *
        *******************************************************************/
        tokens.addElement(new Vector()) ;
      }

    public void normalize() 
      { /*******************************************************************
        * Remove empty lines at beginning and end of tokens.               *
        *******************************************************************/
        while (    (tokens.size() > 0)
                   /********************************************************
                   * I don't think we should ever get an empty             *
                   * expression, but we'll check just in case.             *
                   ********************************************************/
                && (((Vector) tokens.elementAt(0)).size() == 0 )
              )
          { tokens.removeElementAt(0) ;
          } ;

        while (    (tokens.size() > 0)
                   /********************************************************
                   * I don't think we should ever get an empty             *
                   * expression, but we'll check just in case.             *
                   ********************************************************/
                && (((Vector) tokens.elementAt(tokens.size()-1)).size() == 0)
              )
          { tokens.removeElementAt(tokens.size()-1) ;
          } ;

        /*******************************************************************
        * Set minCol to minimum column number.                             *
        *******************************************************************/
        int minCol = 999999 ;
        int i = 0 ;
        
        while (i < tokens.size())
          { if ( ((Vector) tokens.elementAt(i)).size() > 0 )
              { TLAToken tok = 
                   (TLAToken) ((Vector) tokens.elementAt(i)).elementAt(0);
                if (tok.column < minCol) {minCol = tok.column;} ;
              }
            i = i + 1;
          };

        /*******************************************************************
        * Subtract minCol from tok.column for all tokens tok.              *
        *******************************************************************/
        i = 0;
        while (i < tokens.size())
          { int j = 0 ;
            Vector curLine = (Vector) tokens.elementAt(i) ;
            while (j < curLine.size())
              { TLAToken tok = (TLAToken) curLine.elementAt(j) ;
                tok.column = tok.column - minCol ;
                j = j + 1;
              };
            i = i + 1;
          } ;

        /*******************************************************************
        * Compute anchorTokens and anchorTokCol.                           *
        *                                                                  *
        * Loop with index i through all lines.                             *
        *******************************************************************/
        anchorTokens = new TLAToken[tokens.size()];
        anchorTokCol = new int[tokens.size()];
        i = 0 ;
        while (i < tokens.size())
          { Vector curLine = (Vector) tokens.elementAt(i) ;
            if (curLine.size() > 0)
              { int curLineFirstCol = 
                      ((TLAToken) curLine.elementAt(0)).column;
                /***********************************************************
                * Loop backwards with loop index j through lines (i-1) ->  *
                * 0, exiting when anchor line found.                       *
                ***********************************************************/
                int j = i-1 ;
                boolean lineNotFound = true ;
                while ((j >= 0) && lineNotFound)
                  { Vector ancLine = (Vector) tokens.elementAt(j) ;
                    if (   (ancLine.size() > 0)
                        && ( ((TLAToken) ancLine.elementAt(0)).column
                                <= curLineFirstCol
                           ) )
                      { /***************************************************
                        * This line contains the anchor token.             *
                        ***************************************************/
                        lineNotFound = false;

                        /***************************************************
                        * Loop indexed by k starting at 1 through tokens   *
                        * on ancLine until reaching end or a token to the  *
                        * right of curLineFirstCol.                        *
                        ***************************************************/
                        int k = 0 ;             
                        while (   (k+1 < ancLine.size()) 
                               && ( ((TLAToken) 
                                       ancLine.elementAt(k+1)).column
                                         <= curLineFirstCol)
                              )
                          { k = k+1 ;} ;

                        TLAToken tok = (TLAToken) ancLine.elementAt(k) ;
                        anchorTokens[i] = tok ;
                        anchorTokCol[i] = tok.column ;
                       }; //END if
                    j = j - 1;
                  }; //END while j
              };
            i = i + 1;
          }; //END while i      
      } //END normalize

    public void renormalize() throws TLAExprException
      /*********************************************************************
      * Used to renormalize the expression so anchorTokCol[i] equals the   *
      * actual column of the anchorTokens[i].  It should be called every   *
      * time new tokens have been inserted into the expression.            *
      *                                                                    *
      * This is done as follows.  For each i from 0 to the maximum line    *
      * number, if the anchor token of line i has moved k tokens to the    *
      * right, then anchorTokCol[i] and the columns of every token in      *
      * line i are incremented by k.                                       *
      *********************************************************************/
      { int i = 0 ;
        while (i < tokens.size())
          { if (anchorTokens[i] != null)
              { Vector line = (Vector) tokens.elementAt(i) ;
                int k = anchorTokens[i].column - anchorTokCol[i] ;
                anchorTokCol[i] = anchorTokens[i].column ;
                if (k < 0)
                  { throw new TLAExprException(
                     "TLAExpr.renormalize() found anchor has moved to left.");
                  } ;
                int j = 0 ;
                while (j < line.size())
                  { TLAToken tok = (TLAToken) line.elementAt(j) ;
                    tok.column = tok.column + k ;
                    j = j + 1;
                  } ;
               } ;
            i = i + 1;
          }
      }
      
    public Vector toStringVector()
      { Vector result = new Vector(tokens.size()) ;
        int i = 0 ;
        while (i < tokens.size())
          { Vector curTokLine = (Vector) tokens.elementAt(i) ;
            String curString = "" ;
            TLAToken curAncTok = anchorTokens[i] ;
            int      curAncCol = anchorTokCol[i] ; 
            if (curAncTok != null)
              {curString = SpacesString(curAncTok.column - curAncCol) ;} 

            TLAToken curTok = null ;
            TLAToken lastTok = null ;
            int j = 0 ;
            while (j < curTokLine.size())
              { curTok = (TLAToken) curTokLine.elementAt(j);
                if (j == 0)
                  {curString = curString + SpacesString(curTok.column) ; }
                else
                  {curString = 
                     curString +
                     SpacesString( curTok.column - lastTok.column
                                     - lastTok.getWidth()) ;}
                /***********************************************************
                * Need to add the quotes for a string token.               *
                ***********************************************************/
                if (curTok.type == TLAToken.STRING)
                     {curString = curString + "\"" + curTok.string + "\""; }
                else { curString = curString + curTok.string ; };
                lastTok = curTok ;
                j = j + 1;
              }
            result.addElement(curString) ;
            i = i + 1;
          }
        return result;
      }

    /**
     * Returns a Vector of Vectors of {@link MappingObject} objects, which 
     * represents the TLA+ to PlusCal mapping for the expression as if that
     * expression were the complete spec.  That is, the returned value contains
     * the same number of lines as the expression has, and the columns of
     * Begin/EndTlaToken and SourceToken objects are obtained directly from
     * the columns of the tokens.  The returned value does NOT contain LeftParen
     * and RightParen MappingObjects enclosing the entire expression.
     *  
     * @return
     */
    public Vector toMappingVector () {
        Vector result = new Vector(4) ;
        for (int i = 0; i < this.tokens.size(); i++) {
            Vector mapLine = new Vector() ;
            Vector expLine = (Vector) this.tokens.elementAt(i);
            MappingObject.SourceToken sourceTok = null ;
            for (int j = 0; j < expLine.size(); j ++) {
              TLAToken tok = (TLAToken) expLine.elementAt(j) ;
              int tokEndCol = tok.column + tok.string.length() ;
              for (int k = 0 ; k < tok.getBeginSubst().size(); k++) {
                  mapLine.addElement(new MappingObject.LeftParen(
                                       (PCalLocation) tok.getBeginSubst().elementAt(k)));
              }
              if (tok.source == null) {
                  if(sourceTok == null || ! tok.isAppended()) {                
                    mapLine.addElement(new MappingObject.BeginTLAToken(tok.column)) ;
                    mapLine.addElement(
                       new MappingObject.EndTLAToken(tokEndCol)) ;
                    sourceTok = null ;
                  } else {
                      /* {
                       * 
                       * Make this TLA token part of sourceTok
                       */
                      sourceTok.setEndColumn(tokEndCol) ;
                  }
              } else {

                      sourceTok = new MappingObject.SourceToken(
                                     tok.column, tokEndCol, tok.source) ;
                      mapLine.addElement(sourceTok) ;
              }
              for (int k = tok.getEndSubst().size()-1 ; k >= 0; k--) {
                  mapLine.addElement(new MappingObject.RightParen(
                         (PCalLocation) tok.getEndSubst().elementAt(k)));
              }
            }
            result.addElement(mapLine) ;
        }
        return result ;
    }
    public String toString()
      { String result = "<< " ;
        int i = 0;
        boolean nonempty = false ;
        while (i < tokens.size() )
         { if (i > 0)
             { result = result + "\n" ; } ;
           Vector curLine = (Vector) tokens.elementAt(i);
           int j = 0 ;
           while (j < curLine.size())
             { if (nonempty)
                 { result = result + ", " ; } ;
               nonempty = true ;
               TLAToken tok = (TLAToken) curLine.elementAt(j) ;
               
               if (tok.type == TLAToken.STRING)
                 { result = result + "\"\\\"\", \"" + tok.string 
                                + "\", \"\\\"\"" ;
                 }
//               else if (tok.type == TLAToken.BEGIN_REPLACEMENT) {
//            	   result = result + "(map" ;
//               }
//               else if (tok.type == TLAToken.END_REPLACEMENT) {
//            	   result = result + "map)" ;
//               }
               else if (tok.string.equals("\\/"))
                 { result = result + String.format("\"(col%s) \\\\/\"", tok.column); }
               else if (tok.string.charAt(0) == '\\')
                 { result = result + "\"\\" + tok.string + "\""; }
               else if (tok.string.equals("/\\"))
                 { result = result + String.format("\"(col%s) /\\\\\"", tok.column); }
               else
                 { result = result + "\"" + tok.string + "\""; }
               j = j + 1 ;
             }
           i = i + 1;
         }
        return result + " >>" ;
      }

   public void appendExpr(Vector expr, int spaces) throws UnrecoverableException
     { 
       // DEADCODE
       throw new UnrecoverableException("appendExpr not yet implemented");
     }


/***************************************************************************
*        METHODS FOR SEARCHING AND SUBSTITUTING IN EXPRESSIONS             *
*                                                                          *
* The tokens field of a TLAExpr is a vector of lines, where a line is a    *
* vector of tokens.  The "Java coordinates" of a token in the expression   *
* is a pair (ln, itm) such that the token is item number itm in line       *
* number ln, where the numbering of lines and items starts at 0.  Note     *
* that the first token of an expression always has coordinates (0, 0).     *
* Java coordinates are passed as arguments and returned as values as       *
* IntPair objects.                                                         *
***************************************************************************/
    public TLAExpr cloneAndNormalize() 
      /*********************************************************************
      * Creates a clone of the current TLAExpr by cloning all the tokens   *
      * and then calling normalize to compute anchorTokens and             *
      * anchorTokCol.   Sets the origin region of the clone to that of the *
      * original.                                                          *
      *********************************************************************/
      { TLAExpr result = new TLAExpr() ;
        result.tokens = new Vector() ;
        int i = 0 ;
        while (i < this.tokens.size() )
          { Vector newline = new Vector() ;
            Vector line = (Vector) this.tokens.elementAt(i) ;
            int j = 0 ;
            while (j < line.size())
              { newline.add(((TLAToken) line.elementAt(j)).Clone()) ;
                j = j + 1 ;
              } ;
            result.tokens.add(newline) ;
            i = i + 1 ;
          } ;
        result.setOrigin(this.getOrigin()) ;
        result.normalize() ;
        return result ;
      }

    public void prepend(TLAExpr expr, int spaces) throws TLAExprException 
      /*********************************************************************
      * Prepends the expression expr to the front of the current           *
      * expression, leaving `spaces' number of spaces between the last     *
      * token of expr and the first token of the current expression.       *
      *********************************************************************/
      { /*******************************************************************
        * Prepend all but the last line of expr to the current expression. *
        *******************************************************************/
        int i = 0 ;
        while (i < expr.tokens.size()-1)
          { this.tokens.add(i, expr.tokens.elementAt(i)) ;
            i = i + 1 ;
          } ;
        /*******************************************************************
        * Set exprLine to the last line of expr and thisLine to what was   *
        * the first line of the current expression.                        *
        *******************************************************************/
        Vector exprLine = (Vector) expr.tokens.elementAt(i) ;
        Vector thisLine = (Vector) this.tokens.elementAt(i) ;

        /*******************************************************************
        * Increment the columns of the tokens in thisLine.                 *
        *******************************************************************/
        TLAToken tok = (TLAToken) exprLine.lastElement() ;
        int incr = tok.column + tok.getWidth() + spaces ;
        int j = 0 ;
        while (j < thisLine.size())
          { tok = (TLAToken) thisLine.elementAt(j) ;
            tok.column = tok.column + incr ;
            j = j + 1 ;
          } ;

        /*******************************************************************
        * Prepend the last line of expr to the first line of this          *
        * expression.                                                      *
        *******************************************************************/
        j = 0 ;
        while (j < exprLine.size())
          { thisLine.add(j, exprLine.elementAt(j)) ;
            j = j + 1 ;
          } ;        

        /*******************************************************************
        * Modify anchorTokens and anchorTokCol.                            *
        *******************************************************************/
        TLAToken[] newAToks = new TLAToken[this.tokens.size()] ;
        int[]      newATCol = new int[this.tokens.size()] ;

        j = 0 ;
        while (j < expr.tokens.size())
          { newAToks[j] = expr.anchorTokens[j] ;
            newATCol[j] = expr.anchorTokCol[j] ;
            j = j + 1 ;
          } ;

        while (j < this.tokens.size())
           { newAToks[j] = this.anchorTokens[j - expr.tokens.size() + 1] ;
             newATCol[j] = this.anchorTokCol[j - expr.tokens.size() + 1] ;
             j = j + 1 ;
          } ;
        this.anchorTokens = newAToks ;
        this.anchorTokCol = newATCol ;
        
        this.renormalize() ;
        return ;
      }
    
      /*
       * The following method does not seem to be called from anywhere, so LL
       * deleted it on 6 Dec 2011.
       */
//    public void insertNewToken(String str, IntPair coord) throws TLAExprException
//      /*********************************************************************
//      * Inserts a new token into expr right after the token with Java      *
//      * coordinates coord.  The token has string str and some type other   *
//      * than STRING.                                                       *
//      *********************************************************************/
//      { int lineNum = coord.one ;
//        int tokNum  = coord.two ;
//        if (lineNum >= tokens.size())
//          { PcalDebug.ReportBug("insertNewToken called with lineNum too big");}
//        Vector curLine = (Vector) tokens.elementAt(lineNum) ;
//
//        if (tokNum >= curLine.size())
//          { PcalDebug.ReportBug("insertNewToken called with tokNum too big"); }
//    
//        TLAToken curTok = ((TLAToken) curLine.elementAt(tokNum)) ;
//
//        curLine.insertElementAt(new 
//                                  TLAToken(str, 
//                                           curTok.column + curTok.getWidth(), 
//                                           TLAToken.BUILTIN),
//                                tokNum + 1);
//
//        /*******************************************************************
//        * Increment the columns of later tokens in the line by the length  *
//        * of str.                                                          *
//        *******************************************************************/
//        int i = tokNum + 2;
//        while (i < curLine.size())
//          { ((TLAToken) curLine.elementAt(i)).column =
//              ((TLAToken) curLine.elementAt(i)).column + str.length() ;
//            i = i + 1;
//          };
//        this.renormalize() ;
//      }  

    public static Vector SeqSubstituteForAll(Vector expVec, // of TLAExpr
                                             Vector exprs,  // of TLAExpr
                                             Vector strs) throws TLAExprException   // of String
      /*********************************************************************
      * Produces a vector of new expressions obtained by cloning each      *
      * expression in expVec and then applying substituteForAll(exprs,     *
      * strs) to the clone.                                                *
      *********************************************************************/
      { Vector result = new Vector() ;
        int i = 0 ;
        while (i < expVec.size())
          { TLAExpr e = ((TLAExpr) expVec.elementAt(i)).cloneAndNormalize() ;
            e.substituteForAll(exprs, strs) ;
            result.add(e) ;
            i = i + 1 ;
          } ;
        return result ;
      }      

    /**
     * Substitutes clones of the expressions in exprs for the corresponding
     * strings of strs in the current expression.
     * 
     * This is called with parenthesize = true only during the initial parsing 
     * phase (the execution of ParseAlgorithm.getAlgorithm).  It is called with 
     * parenthesize = false by:
     * 
     *   PcalFixIDs.FixExpr : replaces the string of an IDENT token with a
     *     new one to perform renaming in case of name conflicts.
     *     
     *   PcalTLAGen.AddSubscriptsToExpr: adds the primes and "[self]" subscripts
     *     to variables when needed.
     *  
     *  This method was modified by LL on 10 August 2012 to do the substitutions
     *  "simultaneously" rather than one after the other.  The original code 
     *  first did all the substitutions for the first string, then all the
     *  substitutions for the second string, etc.  This yielded a bug if the
     *  expression substituted for the first string contained the second
     *  string.  For example, the substitutions
     *  
     *     a <- F(b), b <- c
     *     
     *  in  a + b  produced  F(c) + c  instead of the correct  F(b) + c .
     *  

     * @param exprs  A vector of TLAExpr objects
     * @param strs   A vector of strings
     * @param parenthesize  A boolean that is true iff 
     * @throws TLAExprException
     */
    public void substituteForAll( Vector exprs , // of TLAExpr
                                  Vector strs    // of String
                                ) throws TLAExprException
      { substituteForAll(exprs, strs, true); }

    /**
     * 
     * @param exprs
     * @param strs
     * @param parenthesize
     * @throws TLAExprException
     */
    public void substituteForAll( Vector exprs , // of TLAExpr
                                  Vector strs ,  // of String
                                  boolean parenthesize
                                ) throws TLAExprException {
        TLAExpr[] expArray  = new TLAExpr[exprs.size()] ;
        String[]  strArray  = new String[strs.size()] ;
        IntPair[] nextArray = new IntPair[expArray.length] ;
        
        // Set expArray and strArray to array versions of exprs and strs.
        // Initialize nextArray with the  positions of the first
        // instances of all the strings in strs.
        for (int i = 0; i < nextArray.length; i++) {
            expArray[i] = (TLAExpr) exprs.elementAt(i) ;
            strArray[i] = (String) strs.elementAt(i) ;
            nextArray[i] = findNextInstanceIn(strArray[i], new IntPair(0, 0)) ;
        }
        
        boolean notDone = true ;
        while (notDone) {
            IntPair nextPos = null ;
            int nextIdx = -1 ;
            
            // Set nextPos to the smallest non-null IntPair in nextArray, and
            // nextIdx to its index in nextArray.  The value of nextPos
            // is set to null if all the elements of nextArray are null;
            for (int i = 0; i < nextArray.length; i++) {
                IntPair pos = nextArray[i] ;
                if (pos != null) {
                    if (nextPos == null) {
                        nextPos = pos ;
                        nextIdx = i ;
                    }
                    else if (   (pos.one < nextPos.one)
                             || (   (pos.one == nextPos.one)
                                 && (pos.two < nextPos.two))) {
                        nextPos = pos ;
                        nextIdx = i ;
                    }  
                }
            }
            
            if (nextPos == null) {
                notDone = false ;
            }
            else {
                IntPair afterNextPos = stepCoord(nextPos, 1) ;
                   // This is the next token after nextPos, which will

                IntPair newPos = substituteAt(expArray[nextIdx], nextPos, parenthesize) ;
                
                
                nextArray[nextIdx] =  (newPos == null) ?
                                         null :
                                         findNextInstanceIn(strArray[nextIdx], newPos) ;
                
                // The values of nextArray[i] for all i # nextIdx need to be adjusted
                // if the substitution replaced parameter number nextIdx by an
                // expression consisting of more than a single token-- which is the
                // case iff newPos # afterNextPos.  We now move those positions
                // accordingly.  Note that if newPos is null, then there are no tokens
                // in any position after the replaced token, so nextArray[i] should
                // be null for all i.
                for (int i = 0; i < nextArray.length; i++) {
                    if ((i != nextIdx) && (nextArray[i] != null)) {
                        Debug.Assert(newPos != null , "Doing substitutions in wrong order.") ;
                                                
                        if (afterNextPos.one == newPos.one) {
                            // The substituted expression occupies a single line.
                            // Must move nextArray[i] to the right iff it is on the
                            // same line as nextPos
                            if (nextArray[i].one == nextPos.one) {
                                nextArray[i].two = nextArray[i].two + (newPos.two - afterNextPos.two) ; 
                                Debug.Assert(nextArray[i].two > nextPos.two, "Wrong substitution order.") ; 
                            }
                        }
                        else {
                            // The substituted expression occupies more than one line.  We have
                            // to increment the line number, but do it separately in the
                            // following two cases.
                            //
                            // Have to change nextArray[i] iff it was pointing at the same line as nextPos
                            if (nextArray[i].one == nextPos.one) {
                                nextArray[i].one = nextArray[i].one + (newPos.one - afterNextPos.one) ;
                                Debug.Assert(nextArray[i].two > nextPos.two, "Wrong substitution order.") ; 
                                nextArray[i].two = nextArray[i].two + (newPos.two - afterNextPos.two) ; 
                                   // Note: nextArray[i] comes after nextPos implies that, since they
                                   // are on the same line, nextArray[i].two should be >= afterNextPos.two,
                                   // so this sets nextArray[i].two to a non-negative number 
                            }
                            else {
                                nextArray[i].one = nextArray[i].one + (newPos.one - afterNextPos.one) ;
                            }
                        }
                    }
                }
            }
        }
        return ;
    }                              
                                
//      /*********************************************************************
//      * Substitute each of the expressions in exprs for the corresponding  *
//      * string in strs.  (The vectors must have the same lengths.)         *
//      * If parenthesize = true, then parentheses are put around the        *
//      * substituted string unless it or the current expression consists    *
//      * of just one token.                                                 *
//      *********************************************************************/
//      { 
//        int i = 0 ;
//        while (i < exprs.size())
//          { TLAExpr exp = (TLAExpr) exprs.elementAt(i) ;
//            String  st  = (String)  strs.elementAt(i) ;
//            substituteFor(exp, st, parenthesize) ;
//            i = i + 1;
//          };
//        return;
//      }      

     public void substituteFor(TLAExpr expr, String id, boolean parenthesize) throws TLAExprException
      /*********************************************************************
      * Substitutes expression expr for all tokens in the current          *
      * expression representing the identifier id -- that is, instances    *
      * in which id does not represent the name of a record field.         *
      * If parenthesize = true, then parentheses are put around the        *
      * substituted string unless it or the current expression consists    *
      * of just one token.                                                 *
      *********************************************************************/
      { IntPair next =  new IntPair(0, 0) ;
        while (next != null)
          { next = this.findNextInstanceIn(id, next) ;
            if (next != null)
                { next = this.substituteAt(expr, next, parenthesize) ;
              }
          }
      }


      public IntPair substituteAt(TLAExpr expr, IntPair coord, boolean par) throws TLAExprException 
      /*********************************************************************
      * Replaces the token tok with coordinates coord in the current       *
      * expression with the expression expr (adding parentheses when       *
      * needed if par = true), and return the coordinates of the token     *
      * immediately past the substituted expression (or null if the        *
      * substitution was for the last token).  The trick is to do this is  *
      * a way that preserves the alignment information.  In particular,    *
      * we have to be concerned with the possibility that token tok might  *
      * be an anchor token.  If the current expression consists of a       *
      * single token, then we just replace its fields the fields obtained  *
      * by cloning expr.  Otherwise, there are two cases.                  *
      *                                                                    *
      * Case 1: expr consists of a single token etok.                      *
      *    In this case, the `string' and `type' fields of tok are         *
      *    set to the corresponding fields of etok, and the                *
      *    remainder tokens on the current line are shifted                *
      *    to the right if the new string has more characters than the     *
      *    original.                                                       *
      *                                                                    *
      * Case 2: expr consists of multiple tokens.                          *
      *    In this case, tok is changed to "(", and copies of the tokens   *
      *    of expr followed by a ")" token are inserted into the current   *
      *    expression, creating one new line for every line of expr other  *
      *    than the first.  The column of each token from expr is          *
      *    incremented by 1 plus the column number of tok.  The tokens     *
      *    from the current expression that follow on the same line as the *
      *    last line of the newly inserted tokens are incremented by the   *
      *    appropriate amount to shift them to the right of the inserted   *
      *    tokens.                                                         *
      *                                                                    *
      *    Note: if you want to change this method so it doesn't always    *
      *    put parentheses around multi-token expressions, then see the    *
      *    comments preceding TLAToken.beginSubst before doing anything.   *
      *********************************************************************/
      { /*******************************************************************
        * First handle of the case when current expression has a single    *
        * token.                                                           *
        *******************************************************************/
    	  /*
    	   * Note that in this case, the origin field of this TLAExpr object
    	   * should be unchanged.
    	   */
        TLAToken tok = this.tokenAt(coord) ;
        Region tokSource= tok.source;
        if (this.isOneToken())
          { TLAExpr cloned = expr.cloneAndNormalize() ;
            if (tokSource != null) {
               cloned.firstToken().getBeginSubst().addAll(tok.getBeginSubst());
               cloned.firstToken().getBeginSubst().addElement(tokSource.getBegin());
               cloned.lastToken().getEndSubst().addAll(tok.getEndSubst());
               cloned.lastToken().getEndSubst().addElement(tokSource.getEnd());
            }
            this.tokens = cloned.tokens ;
            this.anchorTokens = cloned.anchorTokens ;
            this.anchorTokCol = cloned.anchorTokCol ;

// The approach of adding dummy tokens to an expression to indicate 
// substitution produced an error when normalizing the expression.  Rather
// than risking any further bugs appearing because of it, I'm backing out
// of that and doing something else that cannot make any changes to the
// existing translation.
//
//            /**
//             * Insert BEGIN/END_REPLACEMENT tokens
//             */
//            Region tokSource = tok.source ;
//            if (tokSource != null) {
//                Vector line = (Vector) this.tokens.elementAt(0) ;
//                line.insertElementAt(new TLAToken("", tok.column, TLAToken.BEGIN_REPLACEMENT, 
//                          new Region (tokSource.getBegin(), 
//                                      tokSource.getBegin())), 0) ;
//                line.add(new TLAToken("", tok.column, TLAToken.END_REPLACEMENT, 
//                          new Region (tokSource.getEnd(), 
//                                      tokSource.getEnd()))) ;
//                
//            }

            return null ;
          } ;

        /*******************************************************************
        * Set                                                              *
        *                                                                  *
        *    tok = the token being substituted for,                        *
        *    spaces = number of spaces between tok and token to its right, *
        *             or 0 if tok at end of line.                          *
        *    restOfLine = a vector of the tokens to the right of tok,      *
        *                                                                  *
        * and delete tokens to right of tok from expr.                     *
        *******************************************************************/
        Vector tokLine = (Vector) this.tokens.elementAt(coord.one) ;
        int spaces = 0 ;
        if (coord.two + 1 < tokLine.size())
          { TLAToken nextTok = (TLAToken) tokLine.elementAt(coord.two + 1) ;
            spaces = nextTok.column - (tok.column + tok.getWidth()) ;
          } ;
        Vector restOfLine = new Vector() ;
        
        while (coord.two + 1 < tokLine.size())
          { restOfLine.add(tokLine.elementAt(coord.two + 1)) ;
            tokLine.remove(coord.two + 1) ;
          }

        /*******************************************************************
        * curLine will be set to the line number and line to the line at   *
        * the end of which the tokens in restOfLine will be appended.      *
        *******************************************************************/
        int curLine = coord.one ;
        Vector line = (Vector) this.tokens.elementAt(curLine) ;        
        /*******************************************************************
        * Insert the new tokens into the expression.                       *
        *******************************************************************/
        if (    (expr.tokens.size() == 1)
             && ( ((Vector) expr.tokens.elementAt(0)).size() == 1)
           )
          { /***************************************************************
            * There is a single token etok.                                *
            ***************************************************************/
            TLAToken etok = 
                (TLAToken) ((Vector) expr.tokens.elementAt(0)).elementAt(0) ;
            tok.string = etok.string ;
            tok.type   = etok.type ;
            tok.source = etok.source;
            /*
             * Set tok.begin/endSubst to the sequence 
             * 
             *   tok.begin/EndSubst \o << tok.source.begin/end >>
             *      \o etok.begin/EndSubst
             */
            if (tokSource != null) {
                tok.getBeginSubst().addElement(tokSource.getBegin());
                tok.getEndSubst().addElement(tokSource.getEnd());
            }
            tok.getBeginSubst().addAll(etok.getBeginSubst());
            tok.getEndSubst().addAll(etok.getEndSubst());
          } 
        else
          { /***************************************************************
            * Replace tok by "(" token if par = true, and set indent to    *
            * the amount to indent the first line of inserted tokens.      *
            ***************************************************************/
            int indent = ((par) ?  1 : 0) + tok.column ; 

            /***************************************************************
            * Set doInsert to true iff the token being substituted for     *
            * must be replaced with the first token of the expression,     *
            * otherwise set it to false and substitute a "(" for it.       *
            ***************************************************************/
            boolean doInsert = true;
            if (par) {
                /*
                 * Turn tok into a new "(" token.  Must reset its
                 * source, beginSubst, and endSubst fields, and add its
                 * original source begin/end to the begin/endSubst vectors
                 * if it's not null.
                 */
                tok.string = "(" ;
                tok.type   = TLAToken.BUILTIN ;
                doInsert = false ;
                tok.source = null ;
                /*
                 * Append tokSource to tok.beginSubst.
                 * We need to set tok.endSubst to << >>, but we
                 * do that when we add the ")" token, because we
                 * need to set its endSubst to tok.endSubst \o tokSource.
                 */
                if (tokSource != null) {
                    tok.getBeginSubst().addElement(tokSource.getBegin());
                }       
            }
            int i = 0 ;
            TLAExpr newExpr = expr.cloneAndNormalize() ;
            /**
             * If we're not going to insert a parenthesis and tok has a source,
             * then add its beginning to the first token's beginSubst vector and
             * its end to the last token's endSubst vector.
             */
            if ((! par) && (tokSource != null)) {
                newExpr.firstToken().getBeginSubst().addElement(tokSource.getBegin());
                newExpr.lastToken().getEndSubst().addElement(tokSource.getEnd());
            }
            while (i < newExpr.tokens.size())
              { Vector eline = (Vector) newExpr.tokens.elementAt(i) ;
                int j = 0 ;
                while (j < eline.size())
                  { TLAToken nextTok = 
                               (TLAToken) eline.elementAt(j) ;
                    nextTok.column = nextTok.column + indent ;
                    if (doInsert) {
                        tok.string = nextTok.string ;
                        tok.type = nextTok.type ;
                        
                        /*
                         * We need to merge the begin/end subst information of tok
                         * with that of the substituted expression newExpr.  The 
                         * parens represented by the substitution information of newExpr
                         * should go inside those represented by the substitution
                         * information of tok.  The left parens represented by
                         * the beginSubst entries of a token go in the same order as
                         * in the beginSubst vector, and the inverse is true of right parens.
                         * Hence, the beginSubst entries of the first token of newExpr
                         * should go after those of tok, and the endSubst entries 
                         * of tok should go after those of the last token of newExpr.
                         * 
                         * We also have to set tok.endSubst to nextTok.endSubst
                         * so we don't lose those substitutions.
                         */
                        tok.getBeginSubst().addAll(nextTok.getBeginSubst());
                        newExpr.lastToken().getEndSubst().addAll(tok.getEndSubst());
                        tok.setEndSubst(nextTok.getEndSubst());

                        doInsert = false ; 
                    }
                    else line.add(nextTok) ;
                    j = j + 1 ;
                  }
                i = i + 1;
                if (i < newExpr.tokens.size())
                  { /*******************************************************
                    * Increment curLine, insert a new empty line into      *
                    * expr at this position, insert                        *
                    * newExpr.anchorTokens[curLine] into                   *
                    * this.anchorTokens as item i, and similarly for       *
                    * anchorTokCol.                                        *
                    *******************************************************/
                    indent = 0 ;
                    curLine = curLine + 1 ;
                    this.tokens.insertElementAt(new Vector() , curLine) ;
                    line = (Vector) this.tokens.elementAt(curLine) ;
                    TLAToken[] aTok  = new TLAToken[this.tokens.size()] ;
                    int[]      aTCol = new int[this.tokens.size()] ;
                    int k = 0 ;
                    while (k < this.tokens.size())
                      { if (k < curLine)
                          { aTok[k]  = this.anchorTokens[k];
                            aTCol[k] = this.anchorTokCol[k];
                          }
                        else if (k == curLine)
                          { aTok[k]  = newExpr.anchorTokens[i];
                            aTCol[k] = newExpr.anchorTokCol[i];
                          }
                        else
                          { aTok[k]  = this.anchorTokens[k-1];
                            aTCol[k] = this.anchorTokCol[k-1];
                          }
                        k = k + 1;
                      } ;
                     this.anchorTokens = aTok ;
                     this.anchorTokCol = aTCol ;
                  } ;
              } ;
            TLAToken lastTok = (TLAToken) line.elementAt(line.size() - 1) ;
            int nextTokColumn = lastTok.column + lastTok.getWidth();
            if (par) {
                /**
                 * Create the new ")" token, and add if the replaced token's
                 * source is not null, then add its right endpoint location to 
                 * the ")" token's endSubst vector.
                 */
                TLAToken rParen =
                    new TLAToken(")",
                                 lastTok.column + lastTok.getWidth(),
                                 TLAToken.BUILTIN );
                rParen.setEndSubst(tok.getEndSubst());
                if (tokSource != null) {
                    rParen.getEndSubst().addElement(tokSource.getEnd());
                }
                /*
                 * Can now reset tok.endSubst.
                 */
                tok.setEndSubst(new Vector(2)); 
                line.add(rParen) ;
                nextTokColumn++;
            }
            
// Removing the replacement tokens because putting them in was apparently
// not a safe thing to do.
            /*
             * Add the BEGIN_ and END_REPLACEMENT tokens to the expression,
             * first adding the END_REPLACEMENT. 
             *  
             * Note: the REPLACEMENT tokens are simply stuck into the
             * expression rather than inserted by calling insertNewToken.
             * I think this is safe to do for a zero-width token.
             */
//            if (tok.source != null) {
//              line.add(new TLAToken("", tok.column, TLAToken.END_REPLACEMENT, 
//        		      new Region (tok.source.getEnd(), tok.source.getEnd()))) ;
//            }
//            /*
//             * Add a BEGIN_REPLACEMENT token.
//             */
//            if (tok.source != null) {
//               ((Vector) this.tokens.elementAt(coord.one)).insertElementAt(
//            		new TLAToken("", tok.column, TLAToken.BEGIN_REPLACEMENT, 
//              		      new Region (tok.source.getBegin(), 
//              		    		      tok.source.getBegin())), coord.two) ;
//            }
          } 

        IntPair result = new IntPair(curLine, line.size()-1);
        /*******************************************************************
        * Put the tokens from restOfLine back into the expression.         *
        *******************************************************************/
        if (restOfLine.size() > 0)
          { TLAToken prevTok  = (TLAToken) line.elementAt(line.size() - 1) ;
            TLAToken firstTok = (TLAToken) restOfLine.elementAt(0);
            int indent = prevTok.column + prevTok.getWidth() 
                           + spaces - firstTok.column ;
            int i = 0 ;
            while (i < restOfLine.size())
              { TLAToken oldTok = (TLAToken) restOfLine.elementAt(i) ;
// Correction made 25 Aug 2005.
// For some reason I no longer understand, I was replacing the original
// tokens with new ones.  This was wrong because any anchorToken that
// pointed to one of those tokens was now pointing to the wrong
// TLAToken object.  Here's the bad code:
//
//                TLAToken newTok = new TLAToken(oldTok.string,
//                                               oldTok.column + indent ,
//                                               oldTok.type) ;
//                line.add(newTok) ;
                oldTok.column = oldTok.column + indent ;
                line.add(oldTok) ;
                i = i + 1 ;
              }
          } ;
        this.renormalize() ;
//System.out.println("Begin to Return") ;
//System.out.println(this.toString());
//for (int i = 0; i < this.tokens.size(); i++) {
//	System.out.println("line " + i + ":") ;
//	Debug.printVector((Vector) this.tokens.elementAt(i), "theline") ;
//}
//Debug.printVector(this.tokens, "foo");
//System.out.println("Return");
        return this.stepCoord(result, 1);
      }     

    public IntPair findNextInstanceIn(String  id,
                                      IntPair start)
      /*********************************************************************
      * If expr is a TLAExpr, then expr.findNextInstanceIn(id, start)      *
      * returns the Java coordinates of the first token with Java          *
      * coordinates at or after "start" with string id that represents an  *
      * identifier.  It ignores tokens with string id that represent       *
      * record labels.  However, in certain exceptional cases, it will     *
      * ignore an instance that binds the identifier id in a quantified    *
      * expression--for example, in the expression "\E x, id : ...".       *
      * This method should therefore not be used in the case when id       *
      * could legally be a bound identifier of a quantified expression.    *
      *                                                                    *
      * The search is performed as if the first token of the expression    *
      * were the one with Java coordinates `start'.  This means that the   *
      * method will mistakenly return `start' if it is the Java            *
      * coordinates of a record label.  For example, if the method is      *
      * invoked for the expression "[id |-> 17]" with `start' equal to     *
      * the coordinates of the token id, then the method will return       *
      * `start', even though id does not represent an identifier in the    *
      * whole expression.                                                  *
      *                                                                    *
      * The method regards an id to be a record label iff it appears in    *
      * the following contexts:                                            *
      *                                                                    *
      *    . id                                                            *
      *    [ id :                                                          *
      *    , id :                                                          *
      *    [ id |->                                                        *
      *    , id :                                                          *
      *                                                                    *
      * I believe this works except that it misidentifies id as a record   *
      * label when it appears as a bound identifier in an unbounded        *
      * quantifier expression such as                                      *
      *                                                                    *
      *    \E x, id : ...                                                  *
      *********************************************************************/
      { IntPair result = new IntPair(start.one, start.two) ;
        if (this.isEmpty()) { result = null ; } ;
        while (result != null)
          { TLAToken tok = this.tokenAt(result) ;
            if (tok.type == TLAToken.STRING)
              { result = this.stepCoord(result, 1) ;
              }
            else if (tok.string.equals("."))
                   { result = this.stepCoord(result, 2) ;
                   }
            else if (    (    tok.string.equals("[")
                           || tok.string.equals(",") 
                         )
                      && (this.stepCoord(result, 2) != null)
                      && (this.tokenAt(this.stepCoord
                               (result, 2)).type != TLAToken.STRING )
                      && (    this.tokenAt(this.stepCoord
                               (result, 2)).string.equals(":") 
                           || this.tokenAt(this.stepCoord
                               (result, 2)).string.equals("|->") 
                         )
                     )
                   { result = this.stepCoord(result, 3); }
            else if (tok.string.equals(id))
                   { return result ;} 
            else { result = this.stepCoord(result, 1); }
            
          }
        return null ;
      }

   public TLAToken tokenAt(IntPair coord)
     /**********************************************************************
     * exp.tokenAt(coord) is the TLAToken in TLAExpr exp with Java         *
     * coordinates coord.                                                  *
     **********************************************************************/
     { return  (TLAToken) 
                 ((Vector) 
                     this.tokens.elementAt(coord.one)).elementAt(coord.two) ;
     }

   public IntPair stepCoord(IntPair coord, int incr) 
     /**********************************************************************
     * exp.stepCoord(coord, incr) returns the Java coordinates of the      *
     * token in exp that is incr tokens past the one with Java             *
     * coordinates coord.  If there is no such token, then it returns      *
     * null.                                                               *
     **********************************************************************/
     { /********************************************************************
       * Check that coord is a valid coordinate pair.                      *
       ********************************************************************/
       if (tokens.size() <= coord.one)
         { PcalDebug.ReportBug(
                "TLAExpr.StepCoord called with line too big") ; } ;
       Vector line = (Vector) tokens.elementAt(coord.one) ;
       if (line.size() <= coord.two)
         {PcalDebug.ReportBug(
                 "TLAExpr.StepCoord called with col too big") ; } ;

       IntPair result = new IntPair(coord.one, coord.two) ;
       int i = 0 ;
       while (i < incr)
         { result.two = result.two + 1 ;
           if (line.size() == result.two)
             { result.two = 0 ;
               result.one = result.one + 1 ;
               while (   (result.one < tokens.size())
                      && ( ((Vector) tokens.elementAt(result.one )).size()
                              == 0) )
                 { result.one = result.one + 1 ;
                 } ;
               if (result.one == tokens.size())
                 { return null ; } ;
               line = (Vector) tokens.elementAt(result.one) ;
             }
           i = i + 1;
         } ;
       return result ;
     }

   public boolean isEmpty()
     {return    (tokens == null)
             || (tokens.size() == 0) ;
     }

   public boolean isOneToken()
     {return    (! this.isEmpty())
             && (tokens.size() == 1)
             && ( ((Vector) tokens.elementAt(0)).size() == 1 ) ;
     }
   
   public TLAToken firstToken() {
       Vector line = (Vector) this.tokens.elementAt(0);
       return (TLAToken) line.elementAt(0);
   }
   
   public TLAToken lastToken() {
       Vector line = (Vector) this.tokens.elementAt(this.tokens.size()-1);
       return (TLAToken) line.elementAt(line.size()-1);
   }
  /***************** private and debugging methods *********************/

   private static String SpacesString(int n)
    /***********************************************************************
    * A string of n spaces.                                                *
    ***********************************************************************/
    { int i = 0 ;
      String result = "" ;
      if (i < 0) {PcalDebug.ReportBug(
                    "SpacesString called with negative argument");}
      while (i < n)
       { result = result + " ";
         i = i + 1;
       }
      return result;
    }




    /************************************************************************
    * For debugging, the following prints a TLAExpr with an indicated name. *
    ************************************************************************/
    public void print(String name) 
      { PcalDebug.print2DVector(tokens, name + ".tokens") ;
        PcalDebug.printObjectArray(anchorTokens, name + ".anchorTokens") ;
        PcalDebug.printIntArray(anchorTokCol, name + ".anchorTokCol") ;
      }

/***************************************************************************
* Appending Vectors:                                                       *
*                                                                          *
* For any distinct vectors v and v2, the method v.addAll(v2)               *
* apparently appends v2 to the end of v, and returns true iff this v2 is   *
* non-empty, so this changes v.                                            *
***************************************************************************/

  }
/***************************************************************************
* RULE FOR PRESERVING THE FORMATTING WHEN REWRITING AN EXPRESSION.         *
*                                                                          *
* I first define some terminology for describing an expression.  A TOKEN   *
* t consists of a symbol t.symbol and a column t.column that is a          *
* positive integer.  For example, in                                       *
*                                                                          *
*    (a = 0) => /\ B                                                       *
*               /\ C                                                       *
*                                                                          *
* the => is represented by a token t with t.symbol = => and t.column =     *
* 9, since the = of => occurs in the 9th column of the expression.  (I     *
* assume that column numbers are normalized so the left-most token of an   *
* expression occurs in column 1.)  A LINE is a sequence <<t_{1}, \ldots,   *
* t_{n}>> of tokens, where t_{i}.column < t_{i+1}.column for               *
* i=1,\ldots,n-1.  An EXPRESSION is a sequence of one or more lines        *
* beginning and ending with a nonempty line.                               *
*                                                                          *
* If line number n is nonempty, define column(n) to be the column of       *
* its first (left-most) token.  I say that line m COVERS line              *
* n iff lines m and n are nonempty, m < n, and column(m) \leq column(n).   *
* The covering line of line number n is the largest line number m such     *
* that m covers n, if such an m exists.                                    *
*                                                                          *
* If line n has a covering line m, then the ANCHOR of line                 *
* n is defined as follows.  Let T be the set of all tokens t in            *
* line m such that t.column \leq column(n) and t.symbol equals             *
* /\ or \/.  If T is nonempty, then the anchor of n is                     *
* the token t in T with the largest value of t.column.  Otherwise,         *
* the anchor of n is the first token of line m.  If n has no               *
* covering line, then it is defined to have no anchor.  The first line     *
* of any expression has no anchor.  In the example above, the anchor of    *
* line 2 is the /\ token in line 1.                                        *
*                                                                          *
* The rule for preserving indentation is: (1) if a line has an anchor,     *
* then its indentation from its anchor must be preserved in the            *
* rewriting, and (2) if a line has no anchor, then its indentation from    *
* the left margin is preserved.  I now state this rule more precisely.     *
*                                                                          *
* The rewriting of an expression exp by the compiler consists of           *
* inserting additional tokens into lines and modifying the column          *
* numbers of some existing tokens to form a new expression newExp.         *
* For any token t of exp, let f(t) be the same token in                    *
* newExp---in other words, the token in newExp that corresponds to         *
* token t in exp.  The mapping f satisfies:                                *
*                                                                          *
* - If token t occurs in line n of exp, then f(t) occurs in                *
*   line n of newExp.                                                      *
*                                                                          *
* - If token t is the first token on its line in exp, then                 *
*   f(t) is the first token on its line in newExp.                         *
*   The following is the rule for formatting the expression newExp         *
*   obtained by rewriting expression exp.                                  *
*                                                                          *
* For any nonempty line n of exp with first token s:                       *
*                                                                          *
*     If n has an anchor t, then                                           *
*        f(s).column - f(t).column = s.column - t.column                   *
*                                                                          *
*     If n has no anchor, then s.column = f(s).column                      *
*                                                                          *
* This rule is actually stronger than necessary.  In case (1), it is       *
* only necessary that                                                      *
*                                                                          *
*    (i) s.column = t.column implies f(s).column = f(t).column and         *
*   (ii) s.column > t.column implies f(s).column > f(t).column.            *
*                                                                          *
* In other words, only the relations "in the same column" and "to the      *
* right of" between a column and its anchor must be preserved.  However,   *
* the stronger rule seems better because it should produce a rewritten     *
* expression that looks as much as possible like the original.             *
*                                                                          *
***************************************************************************/


/* last modified on Fri 31 Aug 2007 at 14:03:38 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/EvalExceptionTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool;

import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import tlc2.output.EC;
import tlc2.tool.liveness.ModelCheckerTestCase;

public class EvalExceptionTest extends ModelCheckerTestCase {
    public EvalExceptionTest() {
        super("DistBakery", new String[] { "-config", "DistBakery.tla" }, EC.ExitStatus.ERROR);
    }

    @Override
	protected boolean doCoverage() {
		return false;
	}

	@Test
    public void testSpec() {
        assertTrue(recorder.recorded(EC.TLC_FINISHED));
        assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "24", "17", "5"));

        // Error: The first argument of <= should be an integer, but instead it is:
        // (-1 :> 0)
		assertTrue(recorder.recordedWithStringValues(EC.TLC_MODULE_ARGUMENT_ERROR_AN,
				"first", "<=", "integer", "(-1 :> 0)"));

		final List<String> expectedTrace = new ArrayList<String>(6);
		expectedTrace.add("/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 0))\n"
				+ "/\\ net = (-2 :> (-1 :> <<>>) @@ -1 :> (-2 :> <<>>))\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"ncs\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"ncs\" )");
		expectedTrace.add("/\\ num = (-2 :> 0 @@ -1 :> 0)\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 0))\n"
				+ "/\\ net = (-2 :> (-1 :> <<>>) @@ -1 :> (-2 :> <<>>))\n"
				+ "/\\ acks = (-2 :> {} @@ -1 :> {})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"enter\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"ncs\" )");
		expectedTrace.add("/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 0))\n"
				+ "/\\ net = (-2 :> (-1 :> <<[type |-> \"write\", num |-> 1]>>) @@ -1 :> (-2 :> <<>>))\n"
				+ "/\\ acks = (-2 :> {-2} @@ -1 :> {})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"e1\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"ncs\" )");
		expectedTrace.add("/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 0))\n"
				+ "/\\ net = (-2 :> (-1 :> <<[type |-> \"write\", num |-> 1]>>) @@ -1 :> (-2 :> <<>>))\n"
				+ "/\\ acks = (-2 :> {-2} @@ -1 :> {})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"e1\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"enter\" )");
		expectedTrace.add("/\\ num = (-2 :> 1 @@ -1 :> 0)\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 1))\n"
				+ "/\\ net = (-2 :> (-1 :> <<>>) @@ -1 :> (-2 :> <<[type |-> \"ack\"]>>))\n"
				+ "/\\ acks = (-2 :> {-2} @@ -1 :> {})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"e1\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"enter\" )");
		expectedTrace.add("/\\ num = (-2 :> 1 @@ -1 :> (-1 :> 0))\n"
				+ "/\\ rnum = (-2 :> (-1 :> 0) @@ -1 :> (-2 :> 1))\n"
				+ "/\\ net = ( -2 :> (-1 :> <<>>) @@\n"
				+ "  -1 :> (-2 :> <<[type |-> \"ack\"], [type |-> \"write\", num |-> (-1 :> 0)]>>) )\n"
				+ "/\\ acks = (-2 :> {-2} @@ -1 :> {-1})\n"
				+ "/\\ pc = ( [node |-> -2, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -2, type |-> \"mutex\"] :> \"e1\" @@\n"
				+ "  [node |-> -1, type |-> \"msg\"] :> \"a\" @@\n"
				+ "  [node |-> -1, type |-> \"mutex\"] :> \"e1\" )");
		assertTraceWith(recorder.getRecords(EC.TLC_STATE_PRINT2), expectedTrace);

		assertTrue(recorder.recordedWithStringValues(EC.TLC_NESTED_EXPRESSION,
				"0. Line 209, column 5 to line 209, column 32 in DistBakery\n"
				+ "1. Line 209, column 22 to line 209, column 32 in DistBakery\n"
				+ "\n"));
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/Generator.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
//
// last modified on Mon  9 November 2009 at 17:14:53 PST by lamport

//
//  4/9/2006 Added a check in RecordConstructor for duplicate fields
//  ........ Added processing for \exists

// XXXXXXXXXXXXXX THINGS TO DO: see file tla/inria/bugs.txt
////   Fix Bug  9 in tla/inria/bugs.txt
////   Fix Bug 10 in tla/inria/bugs.txt  (this looks easy)
////   
////   Test the implementation of labeling of ASSUME/PROVE nodes.

package tla2sany.semantic;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.stream.Stream;

import tla2sany.parser.Operators;
import tla2sany.parser.SyntaxTreeNode;
import tla2sany.parser.TLAplusParserConstants;
import tla2sany.st.SyntaxTreeConstants;
import tla2sany.st.TreeNode;
import tla2sany.utilities.Stack;
import tla2sany.utilities.Strings;
import tla2sany.utilities.Vector;
import tlc2.output.EC;
import tlc2.output.MP;
import util.UniqueString;
import util.WrongInvocationException;

// This class generates a semantic graph from a parse tree. It also uses
// the list of modules to access contexts to instantiate or extend.

// The construction of the graph follows from the grammar and the API.

// The first invocation of the translation of a module is going to be
// done with the global context, which contains external symbols. The
// embedded modules will use the context of the englobing module.

// SymbolTable and Context must be suitably initialized *before*
// generateModule is invoked, since we do not know in which context we
// are working from the inside.

/***************************************************************************
 * Only one object of class Generator is ever created--namely, the object * gen
 * in drivers/SANY.java. So it seems like all fields and methods of * this class
 * could have been made static. *
 ***************************************************************************/

public class Generator implements ASTConstants, SyntaxTreeConstants, LevelConstants, TLAplusParserConstants {

	private Context context; // current context, not very useful.
	private SymbolTable symbolTable; // symbol table used throughout the spec.
										// except for embedded modules
	/***********************************************************************
	 * A SymbolTable is actually a stack of contexts, where a context is a * mapping
	 * from symbols to their meanings. Elements are looked up in * a SymbolTable by
	 * going through the stack of contexts from the top * down. * * symbolTable
	 * appears to contain the definitions and declarations of * all symbols that are
	 * currently defined or declared. When a * construct containing local
	 * definitions or declarations is * entered--for example, when constructing the
	 * ExprNode for a LET/IN, * a new context is pushed onto symbolTable to hold
	 * those local defs * or decls. It appears that after the complete semantic
	 * ModuleNode * has been created, symbolTable should contain only a single
	 * context, * which becomes the ModuleNode's context. * * symbolTable entries
	 * are made for SymbolNode objects (objects * belonging to a subclass of
	 * SymbolNode). It appears that all of * those objects are added (to the context
	 * at the top of the stack) * symbolTable by the SymbolNode object's
	 * constructor. *
	 ***********************************************************************/

	private ExternalModuleTable moduleTable;
	public Errors errors;
	private Stack excStack; // Holds stack of OpApplNodes for $Except
							// operators; used for @
	private Stack excSpecStack; // Holds stack of OpApplNode for @Pair
								// operators representing ExceptSpecs;
								// also used for @

	// dummy definitions; used during the creation of the "-- TLA+ BUILTINS --"
	// phony module,
	// before real modules are processed; also used somewhat inconsistently to avoid
	// returning
	// null values, and to allow semantic analysis to proceed when an error is
	// detected
	private SubstInNode nullSubstIn;
	private FormalParamNode[] nullParam;
	private OpDefNode nullODN;
	protected OpApplNode nullOAN;
	protected LabelNode nullLabelNode;
	/***********************************************************************
	 * This is a special OpApplNode that gets returned in various places * when an
	 * error is detected. This allows semantic analysis to * continue, presumably by
	 * preventing a NullPointerException. *
	 ***********************************************************************/
	protected OpArgNode nullOpArg;

	private final static UniqueString S_e = UniqueString.uniqueStringOf("\\E");
	private final static UniqueString S_ex = UniqueString.uniqueStringOf("\\exists");
	private final static UniqueString S_f = UniqueString.uniqueStringOf("\\A");
	private final static UniqueString S_fx = UniqueString.uniqueStringOf("\\always");
	private final static UniqueString S_te = UniqueString.uniqueStringOf("\\EE");
	private final static UniqueString S_tf = UniqueString.uniqueStringOf("\\AA");
	private final static UniqueString S_a = UniqueString.uniqueStringOf("<<");
	private final static UniqueString S_brack = UniqueString.uniqueStringOf("[");
	private final static UniqueString S_sf = UniqueString.uniqueStringOf("SF_");
	private final static UniqueString S_wf = UniqueString.uniqueStringOf("WF_");
	private final static UniqueString S_at = UniqueString.uniqueStringOf("@");
	private final static UniqueString S_lambda = UniqueString.uniqueStringOf("LAMBDA");
	private final static UniqueString S_subexpression = UniqueString.uniqueStringOf("$Subexpression");

	class Function {
		/***********************************************************************
		 * The only object of this class ever created is `functions', declared * right
		 * after the class definition. So, I don't know why this * class's methods
		 * weren't just made ordinary methods of the Generator * class. Perhaps this was
		 * done so the subclass `pair' could be * defined within it without interfering
		 * with any other subclass by * that name. However, there is no other subclass
		 * by that name in the * Generator class. * * See the comments attached to the
		 * `functions' object for the class's * explanation. *
		 ***********************************************************************/
		class pair {
			UniqueString a;
			OpApplNode b;

			pair(UniqueString uniqueString, OpApplNode oan) {
				a = uniqueString;
				b = oan;
			}

			UniqueString uniqueString() {
				return a;
			}

			OpApplNode oan() {
				return b;
			}
		}

		Stack funcStack = new Stack();

		void push(UniqueString uniqueString, OpApplNode oan) {
			funcStack.push(new pair(uniqueString, oan));
		}

		void pop() {
			funcStack.pop();
		}

		// If same function found farther down on stack, then this is a recursive
		// function definition--change the operator to indicate so.
		boolean recursionCheck(UniqueString uniqueString) {
			for (int lvi = funcStack.size() - 1; lvi >= 0; lvi--) {
				if (uniqueString.equals(((pair) funcStack.elementAt(lvi)).uniqueString())) {
					// OA-rfs = recursive func spec
					((pair) funcStack.elementAt(lvi)).oan().resetOperator(OP_rfs);
					return true;
				}
			}
			return false;
		}

	} // end class Function

	// This is the only instance of class Function

	Function functions = new Function();

	/***********************************************************************
	 * This object is used to detect that a function definition is * recursive. It
	 * is a stack of <<UniqueString, OpApplNode>> pairs. * An element <<f, opAp>> in
	 * the stack indicates that the current node * being processed is inside the
	 * body of a function definition of the * form f[...] == body. The current
	 * context assigns to f an OpDefNode * whose body is the OpApplNode opAp whose
	 * operator is either * $RecursiveFcnSpec or $NonRecursiveFcnSpec having (an
	 * OpDeclNode * for) the bound identifier f and having the body of the
	 * definition * as its operand. The following methods can be applied: * *
	 * functions.push(UniqueString us, OpApplNode oan) * Pushes <<us, oan>> onto the
	 * stack. * * functions.pop() * Pops the last element off the stack. * *
	 * recursionCheck(UniqueString us) * If there is a pair <<us, oan>> on the
	 * stack, then the * operator of oan is set to $RecursiveFcnSpec. * * An entry
	 * for f is pushed on the stack before processing the body * f's definition, and
	 * popped upon return. * * When processing a FcnAppl syntax nodefor an
	 * expression f[...], * functions.recursionCheck is called to see the node
	 * occurs in the * body of the definition of f, in which case the definition
	 * body's * OpApplNode's operator is changed to indicate that f's definition is
	 * * recursive. *
	 ***********************************************************************/

	// This class represents a generalized identifier, e.g. a syntactic
	// phrase such as A(2)!B(x,y)!C!D(u,v,w) In this case the compoundID
	// would be A!B!C!D and the args array would contain [2,x,y]
	// (i.e. not including u,v,and w, because they are
	// args to the main operator, and not part of the GenID
	private class GenID {

		private TreeNode treeNode;
		// The syntax tree node holding this GenID
		private StringBuffer compoundID;
		// The string name of the compound op, with "!"'s, if any
		private Vector argsVector = new Vector();
		// Vector of arguments (ExprNodes and OpArgNodes)
		// that are embedded in the generalized identifier

		// The next three fields are null until the finalAppend
		// method has been called
		private UniqueString compoundIDUS;
		// UniqueString version of compoundID
		private SymbolNode fullyQualifiedOp;
		// SymbolNode for compoundID
		private ExprOrOpArgNode[] args;
		// Array with same contents as argsVector

		// Constructor
		public GenID(TreeNode node) {
			treeNode = node;
			compoundID = new StringBuffer("");
			compoundIDUS = null;
			fullyQualifiedOp = null;
			args = null;
		}

		public final UniqueString getCompoundIDUS() {
			return compoundIDUS;
		}

		public final SymbolNode getFullyQualifiedOp() {
			return fullyQualifiedOp;
		}

		public final ExprOrOpArgNode[] getArgs() {
			return args;
		}

		public final Vector getArgsVector() {
			return argsVector;
		}

		/** Append a new segment to the compound name of the operator */
		public final void append(String s) {
			compoundID.append(s);
		}

		/** Add a new argument to the vector of arguments being constructed */
		public final void addArg(ExprOrOpArgNode arg) {
			argsVector.addElement(arg);
		}

		/**
		 * Appends the final element of the fully-qualified name to the GenID that has
		 * been being built using addArg() and append(). Since it signals the completion
		 * of the construction of the name, this method converts the name from
		 * StringBuffer to UniqueString, resolves it to a SymbolNode, and converts the
		 * argument list from vector to array form.
		 */
		public final void finalAppend(String s, boolean unaryNegKludge) {
			// append the final segment of the compound name
			if (unaryNegKludge && s.equals("-")) {
				compoundID.append("-.");
			} else {
				compoundID.append(s);
			}

			// convert the full name to a UniqueString
			compoundIDUS = UniqueString.uniqueStringOf(compoundID.toString());

			// look up the full name in the SymbolTable (may return null)
			fullyQualifiedOp = symbolTable.resolveSymbol(Operators.resolveSynonym(compoundIDUS));

			if (fullyQualifiedOp == null && compoundIDUS != S_at) {
				// if not in the symbol table and not "@", then it is an unresolved symbol
				errors.addError(treeNode.getLocation(), "Could not find declaration or definition of symbol '"
						+ UniqueString.uniqueStringOf(compoundID.toString()) + "'.");
			}
		}

		public final void finalizeID() {
			// copy argsVector contents into args array
			args = new ExprOrOpArgNode[argsVector.size()];

			for (int i = 0; i < args.length; i++) {
				args[i] = (ExprOrOpArgNode) argsVector.elementAt(i);
			}
		}

		/**
		 * Special kluge to append a "." to the name of this ID; should be used ONLY to
		 * change unary "-" to "-."
		 */
		public final void appendDot() {
			compoundIDUS = UniqueString.uniqueStringOf(compoundIDUS.toString() + ".");
		}

		public final String toString(int n) {
			String ret = "compound ID: " + compoundID.toString() + "\nargs: " + args.length + "\n";
			for (int i = 0; i < args.length; i++) {
				ret += Strings.indent(2, args[i].toString(n));
			}
			return ret;
		}

	} // end GenID

	final UniqueString AtUS = UniqueString.uniqueStringOf("@");
	/***********************************************************************
	 * This is needed in a couple of places. (I didn't notice that this * is already
	 * defined to equal S_at.) *
	 ***********************************************************************/

	/*************************************************************************
	 * An object of subclass Selector is used to represent a the translation * of a
	 * GeneralId or an OpApplication whose operator is a GeneralId. It * contains
	 * the data represented in the Subexpression +cal algorithm by * the arrays ops
	 * and args. For example, the user expression * * Foo(a,b)!:!(c) * * produces
	 * the following in Subexpression algorithm: * * ops = << "Foo", ":", "null" >>
	 * * args = << <<a, b>>, << >>, << <<c>> >>, * * This is represented by a
	 * Selector object with four arrays of * length 3. The first is: * * int[] ops
	 * with ops[0] = NameSel * ops[1] = ColonSel * ops[2] = NullSel * * The set of
	 * all possible values of ops[i] are: * * An integer i >= 0 // Represents the i
	 * of "!i". * * One of the following integers < 0. *
	 *************************************************************************/

	final int NameSel = -1; // A name like "Foo" ;
	final int NullSel = -2; // A "(...)" selector ;
	final int GGSel = -3; // ">>" ;
	final int LLSel = -4; // "<<" ;
	final int ColonSel = -5; // ":" ;
	final int AtSel = -6; // "@" ;

	/*************************************************************************
	 * The remaining three arrays are: * * SyntaxTreeNode[] opsSTN with values equal
	 * to the syntax tree * nodes for the corresponding element * of ops. * *
	 * UniqueString[] opNames with opNames[0] = "Foo" * opNames[1] = ":" *
	 * opNames[2] = null * * SyntaxTreeNode[] args with args[0] = "(a, b)" * args[1]
	 * = null * args[2] = "(c)" * * Note: we can't turn the arguments into semantic
	 * nodes yet because we * want to use generateExprOrOpArg to do that, which
	 * requires that we * know the operator of which they're the arguments. Hence,
	 * that * computation has to be folded into the Subexpression algorithm. * *
	 * These arrays are initialized by the finish method, which is called * after
	 * all calls of addSelector have been issued. *
	 *************************************************************************/
	private class Selector {
		/**********************************************************************
		 * A single field for the syntax tree node of the entire selector. *
		 **********************************************************************/
		SyntaxTreeNode selSTN;

		/**********************************************************************
		 * The fields modified by addSelector: *
		 **********************************************************************/
		private Vector opVec = new Vector(); // of SyntaxTreeNode ;
		private Vector argVec = new Vector(); // of SyntaxTreeNode ;

		/**********************************************************************
		 * The fields set from opVec and argVec by finalize. *
		 **********************************************************************/
		int[] ops = null;
		UniqueString[] opNames = null;
		SyntaxTreeNode[] opsSTN = null;
		SyntaxTreeNode[] args = null;

		/**********************************************************************
		 * Constants not needed elsewhere. *
		 **********************************************************************/
		final UniqueString GGUS = UniqueString.uniqueStringOf(">>");
		final UniqueString LLUS = UniqueString.uniqueStringOf("<<");
		final UniqueString ColonUS = UniqueString.uniqueStringOf(":");

		/**********************************************************************
		 * The constructor. *
		 **********************************************************************/

		Selector(SyntaxTreeNode tn) {
			selSTN = tn;
		}

		void addSelector(SyntaxTreeNode stn, SyntaxTreeNode opargs) {
			/********************************************************************
			 * opargs is the args entry. * * stn is the syntax tree node representing the
			 * ops entry. If * there are no arguments, it should be null. For a NullSel
			 * entry * it should be the OpArgs node (the "(arg1, ... , argN)") that is *
			 * used as the second argument. *
			 ********************************************************************/
			opVec.addElement(stn);
			argVec.addElement(opargs);
		} // addSelector

		void finish() throws AbortException {
			int arrayLen = opVec.size();
			ops = new int[arrayLen];
			opNames = new UniqueString[arrayLen];
			opsSTN = new SyntaxTreeNode[arrayLen];
			args = new SyntaxTreeNode[arrayLen];
			for (int i = 0; i < arrayLen; i++) {
				args[i] = (SyntaxTreeNode) argVec.elementAt(i);
				SyntaxTreeNode stn = (SyntaxTreeNode) opVec.elementAt(i);
				opsSTN[i] = stn;
				opNames[i] = stn.getUS();
				switch (stn.getKind()) {
				case IDENTIFIER:
				case N_InfixOp:
				case N_NonExpPrefixOp:
				case N_PostfixOp:
				case N_PrefixOp:
				case ProofStepLexeme:
// xyz: following case added by LL on 13 Oct 2007
//           
				case ProofImplicitStepLexeme:
					ops[i] = NameSel;
					break;

				case N_StructOp:
					if (stn.heirs().length > 0) {
						/************************************************************
						 * This is a number. *
						 ************************************************************/
						TreeNode numNode = stn.heirs()[0].heirs()[0];
						ops[i] = Integer.parseInt(numNode.getImage());
					} else {
						/************************************************************
						 * This is not a number, so it is ">>", "<<", "@", or ":". *
						 ************************************************************/
						UniqueString us = stn.getUS();
						if (us == GGUS) {
							ops[i] = GGSel;
						} else if (us == LLUS) {
							ops[i] = LLSel;
						} else if (us == ColonUS) {
							ops[i] = ColonSel;
						} else if (us == AtUS) {
							ops[i] = AtSel;
						} else {
							errors.addAbort(stn.getLocation(),
									"Internal error: Unexpected selector `" + stn.getImage() + "'.");
						}
					} // if stn.heirs().length > 0
					break;

				case N_OpArgs:
					ops[i] = NullSel;
					break;

				default:
					/***************************************************************
					 * This error occurs on silly input like * * USE DEF <<1, 2>> * * It therefore
					 * seems better to report a mysterious error and * let processing continue in
					 * the hopes that it will generate * a later, more useful error. *
					 ***************************************************************/
//             errors.addAbort(
					errors.addError(stn.getLocation(),
//               "Internal error: Selector had unexpected node kind " + 
//               stn.getKind()) ;
							"Unexpected token found.");
					break;
				}
				;
			} // for
		}

		public String toString() {
			/********************************************************************
			 * For debugging. *
			 ********************************************************************/
			String retval = "Selector object:\n";
			for (int i = 0; i < ops.length; i++) {
				retval = retval + " elt " + i + " : ops = " + ops[i] + ", opNames = " + opNames[i].toString()
						+ ", opsSTN.kind = " + opsSTN[i].getKind() + ", args.kind = "
						+ ((args[i] == null) ? "null" : (args[i].getKind() + " ")) + "\n";
			}
			return retval;
		}

	} // class Selector

//  private ExprOrOpArgNode[] opArgsToArray(SyntaxTreeNode opArgNode) 
//    /***********************************************************************
//    * Converts an OpArgs node to the array of ExprOrOpArgNodes that it     *
//    * specifies.                                                           *
//    *                                                                      *
//    * opArgNode should be of kind N_OpArgs.                                *
//    ***********************************************************************/
//    throws AbortException {
//      SyntaxTreeNode[] heirs = opArgNode.heirs() ;
//      int arity = (heirs.length - 1) / 2 ;
//      ExprOrOpArgNode[] retval = new ExprOrOpArgNode[arity] ;
//      for (i = 0 ; i < arity ; i++) {
//        retval[i] = generateExprOrOpArg(
//                     ) ;
//       } // for      
//   } //  opArgsToArray

	private Selector genIdToSelector(SyntaxTreeNode genId) throws AbortException {
		/***********************************************************************
		 * Constructs a selector in which all the addSelector calls to * translate the
		 * GeneralId node genId have been made and finish has * been called. * * See the
		 * commments in tla+.jj before the OpOrExpr() production to * see what the tree
		 * structure of a GeneralId node looks like. *
		 ***********************************************************************/
		Selector retval = new Selector(genId);
		TreeNode prefix = genId.heirs()[0];
		TreeNode[] prefixElts = prefix.heirs();
		SyntaxTreeNode lastOp = (SyntaxTreeNode) genId.heirs()[1];
		for (int i = 0; i < prefixElts.length; i++) {
			TreeNode[] pe = prefixElts[i].heirs();
			if (pe.length == 0) {
				/*******************************************************************
				 * We reach this point when processing the nonsensical input * HIDE DEF X' * So
				 * we report a not very helpful error in the hopes that further * processing
				 * will produce a more useful error message. *
				 *******************************************************************/
				errors.addError(genId.getLocation(), "Was expecting a GeneralId.");
				break;
			}
			;
			SyntaxTreeNode thisPrefix = (SyntaxTreeNode) pe[0];
			switch (thisPrefix.getKind()) {
			case N_OpArgs:
				retval.addSelector(thisPrefix, thisPrefix);
				break;
			case N_StructOp:
				retval.addSelector(thisPrefix, null);
				break;
			default:
				/*****************************************************************
				 * This must be an identifier or operator. It may or may not * have arguments. *
				 *****************************************************************/
				if (prefixElts[i].heirs().length == 2) {
					/***************************************************************
					 * There are no arguments (the 2nd heir is the "!"). *
					 ***************************************************************/
					retval.addSelector(thisPrefix, null);
				} else {
					/***************************************************************
					 * There are arguments, which are heirs()[1]. *
					 ***************************************************************/
					if (prefixElts[i].heirs().length != 3) {
						// Note added 13 April 2015 by LL:
						// This error is caused by the spurious "(x)" in the leaf proof
						// BY ... DEF A!foo(x)
						// It would be nice if this produced a more helpful error
						// message, but I have no idea if there are other bad inputs
						// that can cause it.
						errors.addAbort(prefixElts[i].getLocation(),
								"Internal error: " + "IdPrefixElement has other than 2 or 3 heirs.");
					}
					;
					retval.addSelector(thisPrefix, (SyntaxTreeNode) prefixElts[i].heirs()[1]);
				} // if}
				break;
			} // switch
		}
		; // for i

		if (lastOp.getKind() == N_OpArgs) {
			retval.addSelector(lastOp, lastOp);
		} else {
			retval.addSelector(lastOp, null);
		}
		;

		retval.finish();
		return retval;
	} // genIdToSelector

	/***********************************************************************
	 * Constants for use in selectorToNode. *
	 ***********************************************************************/
	private final int FindingOpName = 11;
	private final int FollowingLabels = 22;
	private final int FindingSubExpr = 33;

	private final int ArgNum(int op, int arity) {
		/***********************************************************************
		 * This is the implementation of ArgNum in Subexpression.tla. Beware * that this
		 * is the human argument number (where the first argument is * argument 1), not
		 * the Java argument number. *
		 ***********************************************************************/
		if (op > 0) {
			if (op <= arity) {
				return op;
			}
			;
			return -1;
		}
		;
		if (op == LLSel) {
			return (arity > 0) ? 1 : -1;
		}
		;
		if (op == GGSel) {// if (arity == 1) {return 1;} ;
			/**************************************************
			 * Commented out on 9 Mar 2010 by LL. Apparently, * I once thought it was a good
			 * idea to let !>> * refer to the argument of a unary operator. I * no longer
			 * think so. *
			 **************************************************/
			if (arity == 2) {
				return 2;
			}
			;
		}
		;
		return -1;
	} // ArgNum

	LevelNode selectorToNode(Selector sel, // The selector.
			int expectedArity, boolean isFact, // true if looking for a fact
			boolean isDef, // true if looking for a DEF
							// clause item.
			ModuleNode cm) // The current module.
			throws AbortException {
		/***********************************************************************
		 * This is an implementation of the +cal algorithm in module *
		 * Subexpression.tla, which is attached as a comment to the end of * this file.
		 * If expectedArity >= 0, then it returns an * ExprOrOpArgNode, otherwise it
		 * returns an OpDefNode or a * ThmOrAssumpDefNode. On an error, it returns
		 * nullOAN which will * allow semantic analysis to continue. * * The +cal
		 * algorithm describes only the case isFact = false and isDef * = false. It
		 * should be updated to include the other case as well. * It also doesn't
		 * mention the case of a NumberedProofStepKind OpDef * node. * * This code was
		 * modified on 15 Oct 2007 by LL to allow the use of a * ModuleInstanceKind node
		 * (the M in "M == INSTANCE ...") as a fact or * a DEF in a BY, USE, or HIDE.
		 * Parameterized instances can be used in * a DEF (without the parameters), but
		 * only a non-parameterized module * instance can be used as a fact. * * It
		 * appears that, if an error has occurred, a call with * expectedArity>0 can
		 * return something other than an OpArgNode * (probably an OpApplNode). This
		 * caused a problem in one * place--namely, in generateOpArg. I didn't try
		 * figuring out whether * this is actually a bug in selectorToNode. Instead, I
		 * just kludged * something to handle that case. *
		 ***********************************************************************/
		Vector substInPrefix = new Vector(); // of SubstInNode
		Vector params = new Vector(); // of FormalParamNode
		Vector allArgs = new Vector(); // of ExprOrOpArgNode

		/***********************************************************************
		 * Local algorithm variables. *
		 ***********************************************************************/
		UniqueString curName = null;
		UniqueString newName = null; // Initial value set to make Eclipse happy.
		SemanticNode curNode = null;
		SemanticNode newNode;

		int idx = 0;
		/*********************************************************************
		 * We use the Java convention of counting from 0 instead of the * human
		 * convention of couunting from 1. *
		 *********************************************************************/
		int mode = FindingOpName;
		int prevMode = -999;
		/*********************************************************************
		 * The compiler is too dumb to figure out that it always gets set * before it's
		 * used. *
		 *********************************************************************/
		Context letInContext = null;
		/*********************************************************************
		 * This implements the algorithm's curContext variable when that * context is a
		 * LET/IN node's context. When mode = FindingOpName, * letInContext is null iff
		 * this is the first time that mode is * entered--i.e., for the name that is the
		 * initial part of the * selector. In this case, the algorithm's curContext is *
		 * represented by the method's "global variable" symbolTable, since * any name
		 * legal in that context can be referred to. When mode is * subsequently set to
		 * FindingOpName, it means that the name being * sought is from a LET/IN node.
		 * In that case, letInContext will * contain the Context that implements the
		 * algorithm's curContext * variable. *
		 *********************************************************************/
		int opDefArityFound = 0;
		Vector opDefArgs = new Vector(); // of ExprOrOpArgNode objects
		boolean firstFindingOpName = true;
		SymbolNode subExprOf = null;

		boolean inAPsuffices = false;
		/*********************************************************************
		 * Added 16 Feb 2009. An AssumeProveNode with suffices field true * represents
		 * SUFFICE ASSUME / PROVE, and the SUFFICES is treated as * if it were a
		 * 1-argument operator. This flag is set true when the * node is first
		 * encountered. *
		 *********************************************************************/

		while (idx < sel.args.length) {
			/*********************************************************************
			 * Check the one part of the algorithm's assert that should not * automatically
			 * hold -- the first conjunct of the last conjunct -- * for i = idx: *
			 *********************************************************************/
			if ((((sel.ops[idx] != NameSel) && (sel.ops[idx] != NullSel)) || (expectedArity != 0))
					&& (sel.args[idx] != null)) {
				errors.addError(sel.opsSTN[idx].getLocation(),
						"Selector `" + selectorItemToString(sel, idx) + "' should not have argument(s).");
				return nullOAN;
			} // if (sel.ops[idx] == NameSel) ... ;

			/*********************************************************************
			 * Check that, if sel.args[idx] != null, then it is an OpArgs node. *
			 *********************************************************************/
			if ((sel.args[idx] != null) && (sel.args[idx].getKind() != N_OpArgs)) {
				errors.addAbort(sel.args[idx].getLocation(), "Internal error: Unexpected syntax node kind.");
			}
			;

			switch (mode) {
			case FindingOpName:
				// Following code changed on 23 Sep 2009 to fix bug, and corrected
				// on 9 Nov 2009. See description in Subexpression.tla.
				SymbolNode newSymbolNode = null;
				Vector tempArgs = new Vector();
				// a vector of SyntaxTreeNode objects, one for each argument
				// found for an undefined operator name in the following loop

				while (newSymbolNode == null && idx < sel.args.length) {
					/******************************************************************
					 * +cal: newName := IF IsName(ops[idx]) ... ELSE null ; *
					 ******************************************************************/
					if (sel.ops[idx] == NameSel) {
						if (curName == null) {
							newName = Operators.resolveSynonym(sel.opNames[idx]);
							/************************************************************
							 * Need to call resolveSynonym so things like (+), aka * \oplus, are handled
							 * properly. *
							 ************************************************************/
						} else {
							newName = UniqueString.uniqueStringOf(
									curName.toString() + "!" + Operators.resolveSynonym(sel.opNames[idx]).toString());
						}
						;
					} // if (sel.ops[idx] = NameSel)
					else {
						newName = null;
					}
					;

					if ((curName == null) && (sel.ops[idx] != NameSel)) {
						if (idx == 0) {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"Need name or step number here, not `" + sel.opNames[idx] + "'.");
							return nullOAN;
						} else {
							errors.addAbort(sel.opsSTN[idx].getLocation(), "Internal error: should have name here.");
						}
						;
					}
					; // if (curName == null) ... ;
					if (newName != null) {
						if (letInContext == null) {
							/***************************************************************
							 * See the comments for the declaration of letInContext. *
							 ***************************************************************/
							newSymbolNode = symbolTable.resolveSymbol(newName);
						} else {
							newSymbolNode = letInContext.getSymbol(newName);
						}
						;
					}
					; // if (newName != null)
					if (newSymbolNode == null) {
						curName = newName;
						if (sel.args[idx] != null) {
							// sel.args[idx].heirs() is the array of SyntaxTreeNode objects
							// representing:
							// "(" "arg1" "," ... "," "arg_n" ")"
							// We add these SyntaxTreeNode objects to tempArgs.
							int numOfOpArgs = (sel.args[idx].heirs().length - 1) / 2;
							for (int i = 0; i < numOfOpArgs; i++) {
								tempArgs.addElement(sel.args[idx].heirs()[2 * i + 1]);
							}
						}
						idx++;
					}
				} // while (newNode == null)

				if (newSymbolNode == null) {
					int eidx = (idx < sel.args.length) ? idx : (sel.args.length - 1);
					errors.addError(sel.opsSTN[eidx].getLocation(),
							"Unknown operator: `" + selectorItemToString(sel, eidx) + "'.");
					return nullOAN;
				}
				;

				if (newSymbolNode.getKind() == ModuleKind) {
					errors.addError(sel.opsSTN[idx].getLocation(),
							"Module name (" + sel.opNames[idx].toString() + ") not allowed here.");
					return nullOAN;
				}
				; // if

				curNode = newSymbolNode;
				SymbolNode curSymbolNode = newSymbolNode;
				/****************************************************************
				 * A version of curNode "cast" as a SymbolNode. *
				 ****************************************************************/
				curName = newName;
				switch (curSymbolNode.getKind()) {
				case ConstantDeclKind:
				case VariableDeclKind:
				case FormalParamKind:
				case BuiltInKind:
				case NewConstantKind:
				case NewVariableKind:
				case NewStateKind:
				case NewActionKind:
				case NewTemporalKind:
				case NumberedProofStepKind:
					/**************************************************************
					 * This last case added by LL on 17 Aug 2007. I think it * fits in here nicely,
					 * but I wouldn't swear to it. *
					 **************************************************************/
					if (idx != 0) {
						errors.addAbort(sel.selSTN.getLocation(), "Internal error: impossible naming of declaration.");
					} else if (sel.ops.length != 1) {
						errors.addError(sel.opsSTN[idx].getLocation(),
								"Cannot take subexpression of `" + curName.toString() + "'.");
						return nullOAN;
					} // ;

					/****************************************************************
					 * Warning: horrible Java programming hack. There is * deliberately no break
					 * here, so this case "joins" the * following case. *
					 ****************************************************************/
					//$FALL-THROUGH$
				case UserDefinedOpKind:
				case ThmOrAssumpDefKind:
				case ModuleInstanceKind:
					/**************************************************************
					 * +cal: nodeArity := Arity(curNode) ; *
					 **************************************************************/
					int nodeArity = curSymbolNode.getArity();
					/**************************************************************
					 * +cal: if expectedArity = 0 *
					 **************************************************************/
					if (expectedArity == 0) {
						SyntaxTreeNode opArgs = sel.args[idx];
						int numOfOpArgs = 0;
						if (opArgs != null) {
							// if there are arguments, add them to tempArgs.
							/**********************************************************
							 * The heirs of an oparg node are * * "(" "arg1" "," ... "," "arg_n" ")" *
							 **********************************************************/
							numOfOpArgs = (opArgs.heirs().length - 1) / 2;
							for (int i = 0; i < numOfOpArgs; i++) {
								tempArgs.addElement(sel.args[idx].heirs()[2 * i + 1]);
							}
							;

						}
						;
						/**************************************************************
						 * +cal then if opDefArityFound + Len(tempArgs) # nodeArity *
						 **************************************************************/
						if (opDefArityFound + tempArgs.size() != nodeArity) {
							errors.addError((opArgs == null) ? sel.selSTN.getLocation() : sel.args[idx].getLocation(),
									"The operator " + curName.toString() + " requires " + (nodeArity - opDefArityFound)
											+ " arguments.");
							return nullOAN;
						}
						; // if
						ExprOrOpArgNode[] opArgNodes = new ExprOrOpArgNode[tempArgs.size()];
						/**********************************************************
						 * The array of semantic nodes generated by the arguments. *
						 **********************************************************/
						for (int i = 0; i < tempArgs.size(); i++) {
							/**********************************************************
							 * Call generateExprOrOpArg to generate the semantic * nodes for the arguments
							 * and add them to the vector * opDefArgs. Note that curSymbolNode is used as
							 * the * argument to generateExprOrOpArg that specifies the * operator to which
							 * the arguments are being given. (The * comments for that method assumes that
							 * the operator * arguments appear in an OpApplication node, but the * method
							 * doesn't really care; it just uses that operator * to check the arity of the
							 * arguments.) Note that * argument number i of sel.args[idx] represents
							 * argument * number i + opDefArityFound of the operator described * by
							 * curSymbolNode. *
							 **********************************************************/
							opDefArgs.addElement(generateExprOrOpArg(curSymbolNode, sel.opsSTN[idx],
									i + opDefArityFound, (TreeNode) tempArgs.elementAt(i), cm));
						}
						; // end for

					} // if expectedArity = 0
					/**************************************************************
					 * +cal: else if expectedArity > 0) *
					 **************************************************************/
					else {
						if (expectedArity > 0) {
							/**********************************************************
							 * Subexpression.tla has a test to report an error if a * higher-order operator
							 * is specified, since such an * operator can't be used as an operator argument.
							 * That * test is eliminated here because this error should be * caught by the
							 * caller of the selectorToNode method. *
							 **********************************************************/
						}
					}
					; // else [expectedArity != 0]
					opDefArityFound = nodeArity;

					if (curNode.getKind() == ModuleInstanceKind) {
						if ((idx == sel.ops.length - 1) && !(isDef || isFact)) {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"Operator name " + curName.toString() + " is incomplete.");
							return nullOAN;
						}
						;
					} else {
						/**************************************************************
						 * curNode.getKind() \in * {UserDefinedOpKind, ThmOrAssumpDefKind, *
						 * ConstantDeclKind, VariableDeclKind, FormalParamKind, * BuiltInKind,
						 * BoundSymbolKind, NumberedProofStepKind} *
						 **************************************************************/
						/**************************************************************
						 * +cal: then if /\ curNode.kind = UserDefinedOpKind ... *
						 **************************************************************/
						if ((curNode.getKind() == UserDefinedOpKind) && (!((OpDefNode) curNode).isDefined)
								&& (sel.ops.length != 1)) {
							errors.addError(sel.opsSTN[idx].getLocation(), "Subexpression of  `" + curName.toString()
									+ "' used inside the operator's definition.");
							return nullOAN;
						}
						;

						/**************************************************************
						 * +cal: if /\ firstFindingOpName ... *
						 **************************************************************/
						if (firstFindingOpName && ((curNode.getKind() == UserDefinedOpKind)
								|| (curNode.getKind() == ThmOrAssumpDefKind))) {
							subExprOf = (SymbolNode) curNode;
						}
						/**************************************************************
						 * +cal: idx # Len(ops) *
						 **************************************************************/
						if (idx != sel.ops.length - 1) {
							FormalParamNode[] opParams;
							if (curNode.getKind() == UserDefinedOpKind) {
								opParams = ((OpDefNode) curNode).getParams();
								newNode = ((OpDefNode) curNode).getBody();
							} // if
							else { // curNode.getKind() == ThmOrAssumpDefKind
								opParams = ((ThmOrAssumpDefNode) curNode).getParams();
								newNode = ((ThmOrAssumpDefNode) curNode).getBody();
							}
							;
							for (int i = 0; i < opParams.length; i++) {
								params.addElement(opParams[i]);
							}
							; // for
							curName = null;
							if (sel.ops[idx + 1] == NameSel) {
								mode = FollowingLabels;
							} else {
								mode = FindingSubExpr;
							}
							;
							for (int i = 0; i < opDefArgs.size(); i++) {
								allArgs.addElement(opDefArgs.elementAt(i));
							}
							; // for
							opDefArityFound = 0;
							opDefArgs = new Vector();

							/************************************************************
							 * If newNode = null, then I think there's an error. It * should be caught
							 * later. *
							 ************************************************************/
							if (newNode != null) {
								while (newNode.getKind() == SubstInKind) {
									substInPrefix.addElement(newNode);
									newNode = ((SubstInNode) newNode).getBody();
								}
								; // while
								while (newNode.getKind() == APSubstInKind) {
									substInPrefix.addElement(newNode);
									newNode = ((APSubstInNode) newNode).getBody();
								}
								; // while
							}
							;
							if (mode == FindingSubExpr) {
								curNode = newNode;
							}
							;
						} // if (idx != sel.ops.length - 1)
					} // else curNode.getKind() \in {UserDefinedOpKind, ...}
					prevMode = FindingOpName;
					break;

				default:
					errors.addAbort(sel.opsSTN[idx].getLocation(), "Internal error: unexpected node kind.");
					break;
				}
				; // switch (curSymbolNode.getKind())

				break; // case FindingOpName

			case FollowingLabels:
				/******************************************************************
				 * Invariant: sel.ops[idx] = NameSel *
				 ******************************************************************/
				if (((prevMode == FindingOpName) && (curNode.getKind() != UserDefinedOpKind)
						&& (curNode.getKind() != ThmOrAssumpDefKind))
						|| ((prevMode != FindingOpName) && (curNode.getKind() != LabelKind))) {
					errors.addAbort(sel.selSTN.getLocation(), "Unexpected node kind in FollowingLabels mode.");
				}
				;

				LabelNode newLabelNode = ((OpDefOrLabelNode) curNode).getLabel(sel.opNames[idx]);

				if (newLabelNode == null) {
					errors.addError(sel.opsSTN[idx].getLocation(),
							"Cannot find label `" + sel.opNames[idx].toString() + "'.");
					return nullOAN;
				}
				;

				curNode = newLabelNode;

				if (illegalLabelRef(newLabelNode, sel.opsSTN[idx])) {
					errors.addError(sel.opsSTN[idx].getLocation(),
							"Accessing subexpression labeled `" + sel.opNames[idx].toString()
									+ "' of ASSUME/PROVE clause within the scope of "
									+ "a declaration\n from outside that declaration's scope.");
					return nullOAN;
				}
				;

				if (expectedArity == 0) {

					/****************************************************************
					 * Check that label has right number of arguments. *
					 ****************************************************************/
					if (newLabelNode
							.getArity() != ((sel.args[idx] == null) ? 0 : (sel.args[idx].heirs().length - 1) / 2)) {
						errors.addError(sel.opsSTN[idx].getLocation(),
								"Label `" + sel.opNames[idx].toString() + "' used with wrong number of arguments.");
						return nullOAN;
					}
					;
					for (int i = 0; i < newLabelNode.getArity(); i++) {
						allArgs.addElement(generateExpression(sel.args[idx].heirs()[2 * i + 1], cm));
					}
					;
				}
				; // if (expectedArity == 0)

				for (int i = 0; i < newLabelNode.getArity(); i++) {
					FormalParamNode pdecl = newLabelNode.params[i];
					params.addElement(pdecl);
				}
				;

				if ((idx < sel.ops.length - 1) && (sel.ops[idx + 1] != NameSel)) {
					mode = FindingSubExpr;
				}
				;

				if ((mode == FindingSubExpr) || (idx == sel.ops.length)) {
					curNode = newLabelNode.getBody();
				}
				;

				prevMode = FollowingLabels;
				break; // case FollowingLabels

			case FindingSubExpr:
				if (sel.ops[idx] == ColonSel) {
					if ((prevMode == FindingSubExpr) || !(((idx == sel.ops.length - 1) && (prevMode == FindingOpName))
							|| ((idx < sel.ops.length - 1) && (sel.ops[idx + 1] == NameSel)))) {
						errors.addError(sel.opsSTN[idx].getLocation(),
								"`!:' can be used only after a name and either at the "
										+ "end after an\noperator name or before an operator name.");
						return nullOAN;
					} // if ( (prevMode == FindingSubExpr) ...)
				} // if (sel.ops[idx] == ColonSel)
				else if (curNode == null) {
					errors.addError(sel.opsSTN[idx].getLocation(), "Subexpression selection failed, probably due to "
							+ "an error in the selected expression.");
					return nullOAN;
				} else if (curNode.getKind() == LetInKind) {
					if (ArgNum(sel.ops[idx], 1) == 1) {
						curNode = ((LetInNode) curNode).getBody();
					} else {
						errors.addError(sel.opsSTN[idx].getLocation(), "A LET/IN expression has only one operand.");
						return nullOAN;
					}
					;
				} // else if (curNode.getKind() == LetInKind)

				else if (curNode.getKind() == OpApplKind) {
					OpApplNode curOpApplNode = (OpApplNode) curNode;
					ExprOrOpArgNode[] curArgs = curOpApplNode.getArgs();
					SymbolNode opNode = curOpApplNode.getOperator();
					if ((opNode.getKind() == FormalParamKind) || (opNode.getKind() == ConstantDeclKind)
							|| (opNode.getKind() == UserDefinedOpKind)) {
						int temp = ArgNum(sel.ops[idx], opNode.getArity());
						if (temp == -1) {
							reportSelectorError(sel, idx);
//               errors.addError(sel.opsSTN[idx].getLocation(),
//                               "NoNexistent operand specified by `"
//                                + sel.opNames[idx].toString() + "'.");
							return nullOAN;
						}
						;
						curNode = curArgs[temp - 1];
					} // if (opNode.getKind() == FormalParamKind) || ...

					else if (opNode.getKind() == BuiltInKind) {
						if ((opNode.getName() == OP_rc) // $RcdConstructor
								|| (opNode.getName() == OP_sor)) { // $SetOfRcds

							int temp = ArgNum(sel.ops[idx], curArgs.length);
							if (temp == -1) {
//                 errors.addError(sel.opsSTN[idx].getLocation(),
//                                 "NonExistent operand specified by `"
//                                  + sel.opNames[idx].toString() + "'.");
								reportSelectorError(sel, idx);
								return nullOAN;
							}
							;
							curOpApplNode = (OpApplNode) curArgs[temp - 1];
							if (curOpApplNode.getOperator().getName() != OP_pair) {
								errors.addAbort(sel.opsSTN[idx].getLocation(),
										"Internal error: Expecting $Pair and didn't find it.");
							}
							;
							curNode = curOpApplNode.getArgs()[1];
						} // if opNode.name == $RcdConstructor or $SetOfRcds

						else if (opNode.getName() == OP_case) { // $Case
							if (idx == sel.ops.length - 1) {
								errors.addError(sel.opsSTN[idx].getLocation(),
										"Subexpression of CASE must have form !i!j.");
								return nullOAN;
							}
							;
							int temp = ArgNum(sel.ops[idx], curArgs.length);
							if (temp == -1) {
								reportSelectorError(sel, idx);
								return nullOAN;
							}
							;
							curOpApplNode = (OpApplNode) curArgs[temp - 1];
							if (curOpApplNode.getOperator().getName() != OP_pair) {
								errors.addAbort(sel.opsSTN[idx].getLocation(),
										"Internal error: Expecting $Pair and didn't find it.");
							}
							;
							idx = idx + 1;
							temp = ArgNum(sel.ops[idx], 2);
							if (temp == -1) {
								errors.addError(sel.opsSTN[idx].getLocation(),
										"Second selector for CASE subexpression must specify "
												+ " one of two operands.");
								return nullOAN;
							}
							;
							curNode = curOpApplNode.getArgs()[temp - 1];
							if (curNode == null) {
								errors.addError(sel.opsSTN[idx].getLocation(), "Selecting OTHER in a CASE statement.");
								return nullOAN;
							}
							;
						} // if opNode.name = $Case

						else if (opNode.getName() == OP_exc) { // $Except
							/************************************************************
							 * In an $Except node representing * * [exp_1 ELSE !... = exp_2, ..., !... =
							 * exp_n] * * operand i names exp_i. *
							 ************************************************************/
							int temp = ArgNum(sel.ops[idx], curArgs.length);
							if (temp == -1) {
								reportSelectorError(sel, idx);
								return nullOAN;
							}
							;
							/************************************************************
							 * Selection of subexpressions of EXCEPT have been outlawed * because they may
							 * contain a dangling "@". This doesn't * seem to be worth fixing because it's
							 * unlikely that * anyone will actually want to refer to such a * subexpression.
							 * * Change made 25 Oct 2007. *
							 ************************************************************/
							if (temp > 1) {
								errors.addError(sel.opsSTN[idx].getLocation(),
										"Selecting subexpression of an " + "EXCEPT not yet implemented.");
								return nullOAN;
							}
							;
							curNode = curArgs[temp - 1];
							if (isNullSelection(curNode, sel, idx)) {
								return nullOAN;
							}
							;
							if (temp > 1) {
								curOpApplNode = (OpApplNode) curNode;
								if (curOpApplNode.getOperator().getName() != OP_pair) {
									errors.addAbort(sel.opsSTN[idx].getLocation(),
											"Internal error: Expecting $Pair and didn't find it.");
								}
								;
								curNode = curOpApplNode.getArgs()[1];
							}
							; // if (temp > 1)
						} // if opNode.name = $Except

						else { // Handled by standard procedure
							if ((curOpApplNode.getNumberOfBoundedBoundSymbols() == 0)
									&& ((curOpApplNode.getUnbdedQuantSymbols() == null)
											|| (curOpApplNode.getUnbdedQuantSymbols().length == 0))
							/*****************************************************
							 * I'm not sure getUnbdedQuantSymbols always returns * null if there are no such
							 * symbols. *
							 *****************************************************/
							) {
								/**********************************************************
								 * Current subexpression has no bound variables. *
								 **********************************************************/
								int temp = ArgNum(sel.ops[idx], curOpApplNode.getArgs().length);
								if (temp == -1) {
									reportSelectorError(sel, idx);
									return nullOAN;
								}
								;
								curNode = curOpApplNode.getArgs()[temp - 1];
							} // if current subexpression has no bound variables
							else {
								/**********************************************************
								 * Current subexpression has bound variables. *
								 **********************************************************/
								if ((sel.ops[idx] == NullSel) || (sel.ops[idx] == AtSel)) {
									/********************************************************
									 * Set temp to the array of FormalParamNodes for the * parameters. *
									 ********************************************************/
									FormalParamNode[] temp;
									if (curOpApplNode.getNumberOfBoundedBoundSymbols() > 0) {
										FormalParamNode[][] symbs = curOpApplNode.getBdedQuantSymbolLists();
										int numSymbs = 0;
										for (int i = 0; i < symbs.length; i++) {
											numSymbs = numSymbs + symbs[i].length;
										}
										; // for
										temp = new FormalParamNode[numSymbs];
										int k = 0;
										for (int i = 0; i < symbs.length; i++) {
											for (int j = 0; j < symbs[i].length; j++) {
												temp[k] = symbs[i][j];
												k++;
											}
											; // for j
										}
										; // for i
									} // if (curOpApplNode.getNumberOf... > 0)
									else {
										temp = curOpApplNode.getUnbdedQuantSymbols();
									}
									; // else not (curOpApplNode.getNumberOf... > 0)

									/*******************************************************
									 * Add the elements of temp to the params vector. *
									 *******************************************************/
									for (int i = 0; i < temp.length; i++) {
										params.addElement(temp[i]);
									}
									; // for i

									if (sel.ops[idx] == NullSel) {
										/*****************************************************
										 * Add the arguments to allArgs, checking if there * are the right number. *
										 *****************************************************/
										int numOfArgs = (sel.args[idx].heirs().length - 1) / 2;
										if (temp.length != numOfArgs) {
											errors.addError(sel.opsSTN[idx].getLocation(),
													"Selector with " + numOfArgs
															+ " argument(s) used for quantifier with " + temp.length
															+ " bound identifier(s).");
											return nullOAN;
										}
										;
										for (int i = 0; i < numOfArgs; i++) {
											allArgs.addElement(
													generateExpression(sel.args[idx].heirs()[2 * i + 1], cm));
										}
										; // for i
									}
									; // if (sel.ops[idx] == NullSel)
									curNode = curOpApplNode.getArgs()[0];
								} // if (sel.ops[idx] == NullSel) || ...
								else {
									int temp = ArgNum(sel.ops[idx], curOpApplNode.getBdedQuantBounds().length);
									if (temp == -1) {
										reportSelectorError(sel, idx);
										return nullOAN;
									}
									;
									curNode = curOpApplNode.getBdedQuantBounds()[temp - 1];
								}
								; // else
							}
							; // else Current subexpression has bound variables
						}
						; // Handled by standard procedure
					} // else if (opNode.getKind() == BuiltInKind)

					else {
						errors.addError(sel.opsSTN[idx].getLocation(), "Choosing operand `"
								+ selectorItemToString(sel, idx) + "' of subexpression with no operands.");
						return nullOAN;
					}
					;

				} // else if ((curNode.getKind() == OpApplKind)

				else if (curNode.getKind() == AssumeProveKind) {
					AssumeProveNode curAPNode = (AssumeProveNode) curNode;

					/****************************************************************
					 * 16 Feb 2009: Case of curAPNode.suffices true added. *
					 ****************************************************************/
					if ((curAPNode.isSuffices()) && (!inAPsuffices)) {
						/**************************************************************
						 * In this case, the selector must be 1, and the curNode is * left equal to the
						 * AssumeProve, but with inAPsuffices set * to true. *
						 **************************************************************/
						if (ArgNum(sel.ops[idx], 1) != 1) {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"Accessing non-existent subexpression of " + "a SUFFICES");
							return nullOAN;
						}
						;
						inAPsuffices = true;
					} // if (curAPNode.isSuffices())
					else {
						inAPsuffices = false;
						/************************************************************
						 * Added 16 Feb 2009 by LL. *
						 ************************************************************/
						int temp = ArgNum(sel.ops[idx], 1 + curAPNode.getAssumes().length);
						if (temp == -1) {
							reportSelectorError(sel, idx);
							return nullOAN;
						}
						;

						if (illegalAPPosRef(curAPNode, temp)) {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"Accessing ASSUME/PROVE clause within the scope of "
											+ "a declaration\n from outside that declaration's scope.");
							return nullOAN;
						}
						;
						if (temp <= curAPNode.getAssumes().length) {
							curNode = curAPNode.getAssumes()[temp - 1];
							if (isNullSelection(curNode, sel, idx)) {
								return nullOAN;
							}
							;
							if ((curNode.getKind() == NewSymbKind) && (idx != sel.args.length - 1)) {
								/************************************************************
								 * Extra conjunct added to if test to allow selection of a * NEW clause as a
								 * fact. *
								 ************************************************************/
								errors.addError(sel.opsSTN[idx].getLocation(),
										"Selected a subexpression of a NEW clause of an ASSUME.");
								return nullOAN;
							}
						} else {
							curNode = curAPNode.getProve();
						}
						;
					} // else if (curAPNode.isSuffices())
				} // else if (curNode.getKind() == AssumeProveKind)

				else if (curNode.getKind() == OpArgKind) {
					SymbolNode opNode = ((OpArgNode) curNode).getOp();
					if ((opNode.getKind() != UserDefinedOpKind) || (opNode.getName() != S_lambda)) {
						errors.addError(sel.opsSTN[idx].getLocation(),
								"Trying to select subexpression of an operator argument.");
						return nullOAN;
					}
					;
					OpDefNode opDefOpNode = (OpDefNode) opNode;
					if ((sel.ops[idx] != NullSel) && (sel.ops[idx] != AtSel)) {
						errors.addError(sel.opsSTN[idx].getLocation(),
								"Cannot use !" + sel.opNames[idx].toString() + " to select subexpression of a LAMBDA.");
						return nullOAN;
					}
					;
					if (sel.ops[idx] == NullSel) {
						int numOfArgs = (sel.args[idx].heirs().length - 1) / 2;
						if (opDefOpNode.getArity() != numOfArgs) {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"Selector with " + numOfArgs + "arguments used for LAMBDA expression taking "
											+ opDefOpNode.getArity() + " arguments.");
							return nullOAN;
						}
						;
						for (int i = 0; i < numOfArgs; i++) {
							allArgs.addElement(generateExpression(sel.args[idx].heirs()[2 * i + 1], cm));
						}
						;
					}
					; // if (sel.ops[idx] == NullSel)
					for (int i = 0; i < opDefOpNode.getArity(); i++) {
						params.addElement(opDefOpNode.getParams()[i]);
					}
					;
					curNode = opDefOpNode.getBody();
				} // else if (curNode.getKind() == OpArgKind)

				else if ((curNode.getKind() == UserDefinedOpKind) || (curNode.getKind() == BuiltInKind)
						|| (curNode.getKind() == NumberedProofStepKind)) {
					errors.addAbort(sel.opsSTN[idx].getLocation(),
							"Internal error: " + " Should not have been able to select this node.");
				} // else if (curNode.getKind() == UserDefinedOpKind) || ...

				else if ((curNode.getKind() == AtNodeKind) || (curNode.getKind() == DecimalKind)
						|| (curNode.getKind() == NumeralKind) || (curNode.getKind() == StringKind)
						|| (curNode.getKind() == FormalParamKind) || (curNode.getKind() == ConstantDeclKind)
						|| (curNode.getKind() == VariableDeclKind) || (curNode.getKind() == BoundSymbolKind)) {
					errors.addError(sel.opsSTN[idx].getLocation(),
							"Selecting subexpression of expression that has none.");
					return nullOAN;
				} // else if (curNode.getKind() == AtNodeKind) || ...

				else if (curNode.getKind() == LabelKind) {
					curNode = ((LabelNode) curNode).getBody();
					idx = idx - 1;
				} // else if (curNode.getKind() == LabelKind)

				else {
					errors.addAbort(sel.opsSTN[idx].getLocation(), "Internal error: " + " Unknown node kind.");
				}
				; // end last else of if sel.ops[idx] != ColonSel

				if (isNullSelection(curNode, sel, idx)) {
					return nullOAN;
				}
				;

				if (idx != sel.ops.length - 1) {
					if (sel.ops[idx + 1] == NameSel) {
						while (curNode.getKind() == LabelKind) {
							curNode = ((LabelNode) curNode).getBody();
							if (isNullSelection(curNode, sel, idx)) {
								return nullOAN;
							}
							;
						}
						; // while
						if (curNode.getKind() == LetInKind) {
							letInContext = ((LetInNode) curNode).context;
							mode = FindingOpName;
							firstFindingOpName = false;
						} else {
							errors.addError(sel.opsSTN[idx].getLocation(),
									"A name selector here must be from a LET clause.");
							return nullOAN;
						}
					} // if (sel.ops[idx+1] == NameSel)
					else if (sel.ops[idx + 1] == ColonSel) {
						errors.addError(sel.opsSTN[idx].getLocation(), "!: should not follow an operand selector.");
						return nullOAN;
					}
				}
				; // if (idx != sel.ops.length - 1)

				prevMode = FindingSubExpr;
				break; // case FindingSubExpr

			default:
				errors.addAbort(sel.selSTN.getLocation(), "Internal error: Unexpected mode");
			} // switch (mode)
			idx++;
		} // while idx <
		/**********************************************************************
		 * +cal: end while ; *
		 **********************************************************************/

		/***********************************************************************
		 * +cal: if curNode.kind = AssumeProveKind ... end if * * Modified 17 Feb 2009
		 * by LL to allow ASSUME/PROVE to be used as a * fact. This seems to have been a
		 * bug in the original. * * Not corrected in the PlusCal code because that code
		 * doesn't talk * about the isFact case. *
		 ***********************************************************************/
		if (curNode.getKind() == AssumeProveKind) {
			if (isFact) {
				return (AssumeProveNode) curNode;
			}
			;
			errors.addError(sel.selSTN.getLocation(), "Selected ASSUME/PROVE instead of expression.");
			return nullOAN;
		}
		;

		/***********************************************************************
		 * The following added to allow naming of NEW constructs of an * ASSUME/PROVE in
		 * facts. *
		 ***********************************************************************/
		if (curNode.getKind() == NewSymbKind) {
			if (isFact) {
				return (LevelNode) curNode;
			}
			;
			errors.addError(sel.selSTN.getLocation(), "Selected a NEW declaration as an expression or operator.");
			return nullOAN;
		}
		;

		/***********************************************************************
		 * +cal: if expectedArity < 0 ... end if; *
		 ***********************************************************************/
		if (expectedArity < 0) {
			if ((prevMode != FindingOpName) || !((curNode.getKind() == UserDefinedOpKind)
					|| (curNode.getKind() == ThmOrAssumpDefKind) || (curNode.getKind() == NumberedProofStepKind) || // This
																													// clause
																													// added
																													// by
																													// LL
																													// 15
																													// Oct
																													// 2007,
																													// not
																													// in
																													// +cal
																													// code
					((curNode.getKind() == ModuleInstanceKind) && isDef))) {
				errors.addError(sel.selSTN.getLocation(), "DEF clause entry should describe a defined operator.");
				return nullOAN;
			}
			;
			if ((curNode.getKind() == NumberedProofStepKind)
					&& (((OpDefNode) curNode).getStepNode().getKind() != DefStepKind)) {
				errors.addError(sel.selSTN.getLocation(), "DEF clause entry refers to a non-definition step.");
				return nullOAN;
			}
			return (LevelNode) curNode;
		}
		; // if (expectedArity < 0)

		if (curNode.getKind() == NumberedProofStepKind) {
			errors.addError(sel.selSTN.getLocation(), isFact ? "Step number of non-fact used as a fact"
					: "Step number of non-expression step used as an expression.");
			return nullOAN;
		}

		/***********************************************************************
		 * +cal: if expectedArity > 0 ... end if *
		 ***********************************************************************/
		if (expectedArity > 0) {
			int temp = params.size();
			if (curNode.getKind() == OpArgKind) {
				temp = temp + ((OpArgNode) curNode).getArity();
			} else if (prevMode == FindingOpName) {
				temp = temp + ((SymbolNode) curNode).getArity();
			}
			;

			if (expectedArity != temp) {
				errors.addError(sel.selSTN.getLocation(),
						"Expected arity " + expectedArity + " but found operator of arity " + temp + ".");
				return nullOAN;
			}
			;
		}
		; // if (expectedArity > 0)

		/***********************************************************************
		 * If opDefArgs is non-empty, we will need to convert it to an array, * so we
		 * might as well do it here. *
		 ***********************************************************************/
		ExprOrOpArgNode[] opDefArgArray = new ExprOrOpArgNode[opDefArgs.size()];
		for (int i = 0; i < opDefArgs.size(); i++) {
			opDefArgArray[i] = (ExprOrOpArgNode) opDefArgs.elementAt(i);
		}
		; // for

		/***********************************************************************
		 * +cal: if /\ prevMode = "FindingOpName" ... end if; *
		 ***********************************************************************/
		if ((prevMode == FindingOpName) && (params.size() + substInPrefix.size() > 0)) {

			/*********************************************************************
			 * Set nodeParams to the +cal program's curNode.params value. *
			 *********************************************************************/
			FormalParamNode[] nodeParams = null;
			if (curNode.getKind() == UserDefinedOpKind) {
				nodeParams = ((OpDefNode) curNode).getParams();
			} else {
				if (curNode.getKind() != ThmOrAssumpDefKind) {
					errors.addAbort(sel.opsSTN[sel.opsSTN.length - 1].getLocation(),
							"Internal Error: " + " Found unexpected node kind after FindingOpName");
				}
				;
				nodeParams = ((ThmOrAssumpDefNode) curNode).getParams();
			}
			;

			for (int i = 0; i < opDefArgs.size(); i++) {
				allArgs.addElement(opDefArgArray[i]);
			}
			; // for

			ExprOrOpArgNode[] temp = new ExprOrOpArgNode[nodeParams.length];
			for (int i = 0; i < nodeParams.length; i++) {
				FormalParamNode pm = nodeParams[i];
				/*******************************************************************
				 * Set newpm to a "clone" of pm. *
				 *******************************************************************/
				FormalParamNode newpm = new FormalParamNode(pm.getName(), pm.getArity(), pm.stn, null, cm);

				/*******************************************************************
				 * Set eoag to the ExprOrOpArgNode constructed from newpm. *
				 *******************************************************************/
				ExprOrOpArgNode eoag = null;
				if (pm.getArity() == 0) {
					/*****************************************************************
					 * Formal parameter eoag is an ordinary (non-operator) parameter. *
					 *****************************************************************/
					eoag = new OpApplNode(newpm, new ExprNode[0], sel.selSTN, cm);
				} else {
					/*****************************************************************
					 * Formal parameter eoag is an operator parameter. *
					 *****************************************************************/
					eoag = new OpArgNode(newpm, sel.selSTN, cm);
				}
				;
				temp[i] = eoag;
				params.addElement(newpm);
			}
			; // for
			SymbolNode curSymNode = (SymbolNode) curNode;
			curNode = new OpApplNode(curSymNode, temp, // opDefArgArray,
					sel.selSTN, // TreeNode
					cm);

		}
		;// if (prevMode == FindingOpName) ...

		/***********************************************************************
		 * +cal: if curNode.kind = OpArgKind *
		 ***********************************************************************/
		if (curNode.getKind() == OpArgKind) {
			OpArgNode curOpArgNode = (OpArgNode) curNode;

			/*********************************************************************
			 * +cal: if expectedArity = 0 then ... elsif *
			 *********************************************************************/
			if (expectedArity == 0) {
				errors.addError(sel.selSTN.getLocation(), "Selected operator argument when expression expected.");
				return nullOAN;
			}
			;

			/*********************************************************************
			 * +cal: elsif expectedArity # Len(params) + ... else *
			 *********************************************************************/
			int temp = params.size() + curOpArgNode.getArity();
			if (expectedArity != temp) {
				errors.addError(sel.selSTN.getLocation(), "Expected operator of arity " + expectedArity
						+ " but selected operator has arity " + temp + ".");
				return nullOAN;
			}
			;

			/*********************************************************************
			 * +cal: else ... end if *
			 *********************************************************************/
			if (params.size() + substInPrefix.size() > 0) {
				FormalParamNode[] temp2 = new FormalParamNode[curOpArgNode.getArity()];
				for (int i = 0; i < temp2.length; i++) {
					UniqueString temp3 = UniqueString.uniqueStringOf("NewParam" + i);
					temp2[i] = new FormalParamNode(temp3, // name
							0, // arity
							new SyntaxTreeNode(temp3), // syntax tree node
							null, // symbol table
							cm); // module
					params.addElement(temp2[i]);
				}
				; // for
				curNode = new OpApplNode(curOpArgNode.getOp(), opDefArgArray, sel.selSTN, // TreeNode
						cm);
			}
			; // if (params.size() + ...)

		}
		; // if (curNode.getKind() == OpArgKind)

		/***********************************************************************
		 * This code doesn't seem to be present in the +cal code. I forget * why not;
		 * perhaps I added it without correcting the +cal. * * Modified 19 May 2008 by
		 * LL because of addition of labeled * ASSUME/PROVE nodes. *
		 ***********************************************************************/
		if (!isFact && (((curNode.getKind() == ThmOrAssumpDefKind)
				&& (((ThmOrAssumpDefNode) curNode).getBody().getKind() == AssumeProveKind))
				/***********************************************************
				 * curNode is an ASSUME/PROVE theorem. *
				 ***********************************************************/
				|| ((curNode.getKind() == LabelKind) && (((LabelNode) curNode).isAssumeProve)))
		/***********************************************************
		 * curNode is a LabelNode naming an ASSUME/PROVE. *
		 ***********************************************************/
		) {
			errors.addError(sel.selSTN.getLocation(), "ASSUME/PROVE used where an expression is required.");
			return nullOAN;
		}
		;

		/***********************************************************************
		 * The following code added 18 Oct 2007 to check if a * pseudo-expression like
		 * "HAVE P" or "PICK ..." was used as an * expression. *
		 ***********************************************************************/
		if ((!isFact) && (curNode.getKind() == ThmOrAssumpDefKind)
				&& (((ThmOrAssumpDefNode) curNode).getBody().getKind() == OpApplKind)) {
			UniqueString opName = ((OpApplNode) ((ThmOrAssumpDefNode) curNode).getBody()).getOperator().getName();
			String exprType = null;
			if (opName == OP_qed) {
				exprType = "QED step";
			} else if (opName == OP_pfcase) {
				exprType = "CASE";
			} else if (opName == OP_have) {
				exprType = "HAVE";
			} else if (opName == OP_take) {
				exprType = "TAKE";
			} else if (opName == OP_pick) {
				exprType = "PICK";
			} else if (opName == OP_witness) {
				exprType = "WITNESS";
			} else if (opName == OP_suffices) {
				exprType = "SUFFICES";
			}
			;
			/*******************************************************************
			 * OP_suffices added by LL 16 Feb 2009. *
			 *******************************************************************/
			if (exprType != null) {
				errors.addError(sel.selSTN.getLocation(), exprType + " proof step selected instead of expression.");
				return nullOAN;
			}
			;
		} // if

		/***********************************************************************
		 * +cal: if curNode.kind \in {UserDefinedOpKind, ConstantDeclKind... *
		 ***********************************************************************/
		if ((curNode.getKind() == UserDefinedOpKind) || (curNode.getKind() == ConstantDeclKind)
				|| (curNode.getKind() == VariableDeclKind) || (curNode.getKind() == FormalParamKind)
				|| (curNode.getKind() == BuiltInKind) || (curNode.getKind() == BoundSymbolKind)
				|| (curNode.getKind() == ThmOrAssumpDefKind) || (curNode.getKind() == NewConstantKind)
				|| (curNode.getKind() == NewVariableKind) || (curNode.getKind() == NewStateKind)
				|| (curNode.getKind() == NewActionKind) || (curNode.getKind() == NewTemporalKind)) {
			SymbolNode curSymbolNode = (SymbolNode) curNode;
			if (expectedArity > 0) {
				return new OpArgNode(curSymbolNode, sel.selSTN, cm);
			}

			/*********************************************************************
			 * +cal: elsif expectedArity = 0 then *
			 *********************************************************************/
			else {
				/*******************************************************************
				 * expectedArity = 0 *
				 *******************************************************************/
				OpApplNode oan = new OpApplNode(curSymbolNode, opDefArgArray, sel.selSTN, cm);
				oan.subExpressionOf = subExprOf;
				return oan;
			} // if (expectedArity > 0)
		}
		; // if (curNode.getKind() == UserDefinedOpKind)

		/***********************************************************************
		 * +cal: elsif curNode.kind = OpArgKind then *
		 ***********************************************************************/
		if (curNode.getKind() == OpArgKind) {
			return (OpArgNode) curNode;
		}
		;

		/***********************************************************************
		 * +cal: else *
		 ***********************************************************************/

		/***********************************************************************
		 * The following test is not in Subexpression.tla and should not be, * having
		 * been added to allow the use of a ModuleInstanceKind as a * Fact or Def. The
		 * else case should not occur because if it would be * the case, then the error
		 * should have been caught earlier (I think). *
		 ***********************************************************************/
		if (curNode.getKind() == ModuleInstanceKind) {
			if (isFact || isDef) {
				return (OpDefNode) curNode;
			} else {
				errors.addError(sel.selSTN.getLocation(), "Module instantiation selected instead of expression.");
				return nullOAN;
			}
		}
		;
		/***********************************************************************
		 * curNode should be an expression node. *
		 ***********************************************************************/
		if (!(curNode instanceof ExprNode)) {
			errors.addAbort(sel.selSTN.getLocation(), "Internal error: Expected expression node.");
		}
		;
		ExprNode curExprNode = (ExprNode) curNode;
		int temp = substInPrefix.size();

		/***********************************************************************
		 * +cal: while temp > 0 do ... end while *
		 ***********************************************************************/
		while (temp > 0) {
			// Modified on 13 Nov 2009 by LL to handle the case of a subexpression
			// of a Theorem or Assumption.
			Object substOb = substInPrefix.elementAt(temp - 1);
			if (substOb instanceof SubstInNode) {
				SubstInNode subst = (SubstInNode) substOb;
				curExprNode = new SubstInNode(subst.stn, subst.getSubsts(), curExprNode, subst.getInstantiatingModule(),
						subst.getInstantiatedModule());
			} else {
				APSubstInNode subst = (APSubstInNode) substOb;
				curExprNode = new SubstInNode(subst.stn, subst.getSubsts(), curExprNode, subst.getInstantiatingModule(),
						subst.getInstantiatedModule());

			}
			temp = temp - 1;
		}
		; // while

		/***********************************************************************
		 * Will need params as an array. *
		 ***********************************************************************/
		FormalParamNode[] paramsArray = new FormalParamNode[params.size()];
		for (int i = 0; i < params.size(); i++) {
			paramsArray[i] = (FormalParamNode) params.elementAt(i);
		}
		;

		/***********************************************************************
		 * If there are params, will need a Lambda operator. *
		 ***********************************************************************/
		OpDefNode newLambda = null;
		if (paramsArray.length > 0) {
			newLambda = new OpDefNode(S_lambda, // The operator name is "LAMBDA"
					UserDefinedOpKind, // The node kind
					paramsArray, // the array of formal parameters
					false, // localness, which is meaningless
					curExprNode, // the body
					cm, // the module
					null, // the symbol table
					sel.selSTN, // syntax-tree node
					true, // Is defined.
					null); // Source
		}
		;

		/***********************************************************************
		 * +cal: if expectedArity > 0 *
		 ***********************************************************************/
		if (expectedArity > 0) {
			if (paramsArray.length != expectedArity) {
				errors.addError(sel.selSTN.getLocation(), "Expected operator argument with arity " + expectedArity
						+ " but found one of arity " + paramsArray.length + ".");
				return nullOAN;
			}
			;
			return new OpArgNode(newLambda, sel.selSTN, cm);
		} // if (expectedArity > 0)

		/***********************************************************************
		 * expectedArity = 0 * +cal: else if Len(params) # Len(allArgs) *
		 ***********************************************************************/
		if (paramsArray.length != allArgs.size()) {
			errors.addError(sel.selSTN.getLocation(),
					"Expected " + paramsArray.length + " arguments but found " + allArgs.size() + ".");
			return nullOAN;
		}
		;
		/***********************************************************************
		 * +cal: if Len(params) = 0 then *
		 ***********************************************************************/
		if (paramsArray.length == 0) {
			/*********************************************************************
			 * In this case, we don't have to construct a new LAMBDA or OpAppl * node.
			 * However, we want to have a new node to which to attach the * SyntaxTree node.
			 * So, we create an OpApplNode with the dummy * builtin operator $Nop and return
			 * it. *
			 *********************************************************************/
			ExprOrOpArgNode[] args = new ExprOrOpArgNode[1];
			args[0] = curExprNode;
			OpApplNode ln = new OpApplNode(OP_nop, args, sel.selSTN, cm);
			ln.subExpressionOf = subExprOf;
			return ln;
		}

		/***********************************************************************
		 * +cal: else *
		 ***********************************************************************/
		/***********************************************************************
		 * Will need allArgs as an array. *
		 ***********************************************************************/
		ExprOrOpArgNode[] allArgsArray = new ExprOrOpArgNode[allArgs.size()];
		for (int i = 0; i < allArgs.size(); i++) {
			allArgsArray[i] = (ExprOrOpArgNode) allArgs.elementAt(i);
		}
		;

		OpApplNode oan = new OpApplNode(newLambda, allArgsArray, sel.selSTN, cm);
		oan.subExpressionOf = subExprOf;
		return oan;

	} // selectorToNode

	private static String selectorItemToString(Selector sel, int idx) {
		String selStr = sel.opNames[idx].toString();
		if (selStr.equals("N_StructOp")) {
			selStr = "argument selector " + sel.opsSTN[idx].heirs()[0].heirs()[0].getImage();
		} else if (selStr.equals("N_OpArgs")) {
			selStr = "!(...)";
		}
		;
		return selStr;
	}

	private void reportSelectorError(Selector sel, int idx) {
		/***********************************************************************
		 * Just a method to perform error reporting when an error is detected * when
		 * executing selectorToNode. *
		 ***********************************************************************/
		errors.addError(sel.opsSTN[idx].getLocation(),
				"Nonexistent operand specified by `" + selectorItemToString(sel, idx) + "'.");
	}

	private boolean isNullSelection(SemanticNode node, Selector sel, int idx) {
		/***********************************************************************
		 * A method for use in selectorToNode to test if a a null node has * been
		 * selected. This should happen only if the null node was * created as a result
		 * of a previous error. If the node is null, then * an error is reported and
		 * true is returned. *
		 ***********************************************************************/
		boolean val = (node == null);
		if (val) {
			errors.addError(sel.opsSTN[idx].getLocation(), "An unexpected null node specified by "
					+ selectorItemToString(sel, idx) + "'." + "\nThis is probably due to a previous error.");
		}
		;
		return val;
	}

	// Constructor
	public Generator(ExternalModuleTable moduleTable, Errors errs) {
		nullParam = new FormalParamNode[0];
		nullODN = new OpDefNode(UniqueString.uniqueStringOf("nullODN"));
		nullOAN = new OpApplNode(nullODN);
		nullOpArg = new OpArgNode(UniqueString.uniqueStringOf("nullOpArg"));
		nullLabelNode = new LabelNode(nullOAN);
		this.errors = errs;
		this.moduleTable = moduleTable;
		this.symbolTable = new SymbolTable(moduleTable, errors);
		this.excStack = new Stack();
		this.excSpecStack = new Stack();
	}

	public final SymbolTable getSymbolTable() {
		return symbolTable;
	}

	public final ModuleNode generate(TreeNode treeNode) throws AbortException {
		/*************************************************************************
		 * This is the method called to generate the semantic graph for a module. *
		 *************************************************************************/
//System.out.println("TRUE = " + symbolTable.resolveSymbol(
//                      UniqueString.uniqueStringOf("TRUE"))) ;
//System.out.println("$SetEnumerate = " + symbolTable.resolveSymbol(
//                      UniqueString.uniqueStringOf("$SetEnumerate"))) ;

		if (treeNode.isKind(N_Module)) {
			this.context = symbolTable.getContext();
			return this.generateModule(treeNode, null);
		}
		return null;
	}

	private final Context getContext(UniqueString us) {
		ModuleNode symbolNode = symbolTable.resolveModule(us);

		if (symbolNode == null) {
			return moduleTable.getContext(us);
		}
		return symbolNode.getContext();
	}

	private final ModuleNode generateModule(TreeNode treeNode, ModuleNode parent) throws AbortException {
		moduleNestingLevel++;
		TreeNode[] children = treeNode.heirs(); // Array of heirs of the module root
		TreeNode[] definitions = null;
		// Array of definitions in the module
		/*********************************************************************
		 * Actually, the array of all syntactic nodes that are heirs of the * module's
		 * body node--that is, definitions, theorems, parameter * declarations, etc. *
		 *********************************************************************/
		TreeNode[] ss = children[0].heirs(); // Array of heirs of the module header
												// ss[1] is always the module name
		String moduleName = ss[1].getImage(); // the module name
		ModuleNode currentModule = new ModuleNode(ss[1].getUS(), context, treeNode);
		currentModule.nestingLevel = moduleNestingLevel;
		// if this is an internal module, add its ModuleNode to the end of
		// the list of definitions for the parent
		if (parent != null) {
			parent.appendDef(currentModule);
		}

		symbolTable.setModuleNode(currentModule);
		// children[1] == extends
		// children[1] is always the Extend's list (even if none)
		processExtendsList(children[1].heirs(), currentModule);

		// children[2] == body
		// children[2] is always the module body note that this line
		// redefines "children" to be the array of definitions in the
		// module
		definitions = children[2].heirs();

		// for each declaration, op definition, etc. in the body...
		for (int lvi = 0; lvi < definitions.length; lvi++) {
			switch (definitions[lvi].getKind()) {
			case N_VariableDeclaration:
				checkIfInRecursiveSection(definitions[lvi], "A VARIABLE declaration");
				processVariables(definitions[lvi].heirs(), currentModule);
				break;

			case N_ParamDeclaration:
				checkIfInRecursiveSection(definitions[lvi], "A declaration");
				processParameters(definitions[lvi].heirs(), currentModule);
				break;

			case N_OperatorDefinition:
				processOperator(definitions[lvi], null, currentModule);
				break;

			case N_FunctionDefinition:
				processFunction(definitions[lvi], null, currentModule);
				break;

			case N_ModuleDefinition:
// We now allow INSTANCEs in recursive sections.
//        checkIfInRecursiveSection(definitions[lvi], "An INSTANCE") ;
				processModuleDefinition(definitions[lvi], null, null, currentModule);
				break;

			case N_Module:
				// Modules can be nested, but inner ones need to keep a
				// separate SymbolTable of their own.
				checkIfInRecursiveSection(definitions[lvi], "A MODULE ");
				SymbolTable oldSt = symbolTable;
				symbolTable = new SymbolTable(moduleTable, errors, oldSt);
				context = new Context(moduleTable, errors);
				symbolTable.pushContext(context);
				ModuleNode mn = generateModule(definitions[lvi], currentModule);
				symbolTable.popContext();
				symbolTable = oldSt;

				// Add the inner module's name to the context of the outer module
				symbolTable.addModule(mn.getName(), mn);

				/*******************************************************************
				 * Append the opDefsInRecursiveSection field of the inner module * to that of
				 * the current module. *
				 *******************************************************************/
				for (int i = 0; i < mn.opDefsInRecursiveSection.size(); i++) {
					currentModule.opDefsInRecursiveSection.addElement(mn.opDefsInRecursiveSection.elementAt(i));
				}
				;
				// System.err.println(mn.getName() + " added to SymbolTable for " +
				// currentModule.getName());
				break;

			case N_Instance:
// We now allow INSTANCEs in recursive sections.
//        checkIfInRecursiveSection(definitions[lvi], "An INSTANCE") ;
				generateInstance(definitions[lvi], currentModule, true);
				break;

			case N_Proof:
				checkIfInRecursiveSection(definitions[lvi], "A proof");
				break;

			case N_Theorem:
				checkIfInRecursiveSection(definitions[lvi], "A THEOREM");
				processTheorem(definitions[lvi], currentModule);
				break;

			case N_Assumption:
				checkIfInRecursiveSection(definitions[lvi], "An ASSUME");
				processAssumption(definitions[lvi], currentModule);
				break;

			case N_UseOrHide:
				checkIfInRecursiveSection(definitions[lvi], "A USE or HIDE");
				UseOrHideNode uohn = generateUseOrHide(definitions[lvi], currentModule);
				uohn.factCheck();
				// Added 4 Mar 2009.
				if (uohn.facts.length + uohn.defs.length == 0) {
					errors.addError(definitions[lvi].getLocation(), "Empty USE or HIDE statement.");
				}
				;
				currentModule.addTopLevel(uohn);
				break;

			case SEPARATOR:
				/*******************************************************************
				 * This code was originally * * case 35 * // Intended to handle "---------".
				 * Kludge for a parser bug. * * I have no idea why 35 was used instead of
				 * SEPARATOR, and what * kind of parser bug mentioned was encountered. The
				 * original * code did not import parser.TLAplusParserConstants where *
				 * SEPARATOR was used, so perhaps there was some reason why this * class could
				 * not be imported. *
				 *******************************************************************/
				break;

			case N_Recursive:
				processRecursive(definitions[lvi], currentModule);
				break;
			default:
				errors.addAbort(definitions[lvi].getLocation(), "Internal error: Syntax node of kind "
						+ definitions[lvi].getKind() + " unsupported " + definitions[lvi].getImage(), true);
				break;
			}
		}

		checkForUndefinedRecursiveOps(currentModule);

		Vector vec = currentModule.recursiveOpDefNodes;
		for (int i = 0; i < vec.size(); i++) {
			OpDefNode node = (OpDefNode) vec.elementAt(i);
// System.out.println("symbol " + node.getName() + ": recSect = " 
//                    + node.recursiveSection + ", inRecSect = " 
//                    + node.inRecursiveSection + ", letInLevel = "
//                    + node.letInLevel);
		}
		;

		moduleNestingLevel--;
		return currentModule;

	} // generateModule

	// This method must be extended so that the Extends list hangs off of
	// the ModuleNode to support a getExtends() method that might reasonably
	// be in the API.
	private final void processExtendsList(TreeNode treeNodes[], ModuleNode cm) throws AbortException {
		Vector extendeeVector = new Vector(2);

		if (treeNodes != null) {
			// module names in the EXTENDS list are separated by commas; hence incr by 2
			for (int lvi = 1; lvi < treeNodes.length; lvi += 2) {
				// Try to find the ModuleNode for the module being EXTENDED in the symbolTable
				UniqueString extendeeID = treeNodes[lvi].getUS();
				ModuleNode extendee = symbolTable.resolveModule(extendeeID);

				// It must be an external module if it isn't in the symbolTable;
				// try to find it in moduleTable (it cannot be in both places)
				if (extendee == null) {
					extendee = moduleTable.getModuleNode(extendeeID);
					if (extendee == null) {
						errors.addAbort(treeNodes[lvi].getLocation(), "Could not find module " + extendeeID, false);
					}
				}

				extendeeVector.addElement(extendee);

				Context context = this.getContext(extendeeID);
				if (context != null) {
					symbolTable.getContext().mergeExtendContext(context);
				} else {
					errors.addError(treeNodes[lvi].getLocation(),
							"Couldn't find context for module `" + extendeeID + "'.");
				}

				// copy nonlocal Assumes and Theorems
				cm.copyAssumes(extendee);
				cm.copyTheorems(extendee);
				cm.copyTopLevel(extendee);
			}
		}
		cm.createExtendeeArray(extendeeVector);
	} // processExtendsList

	// This method must be extended so that the variable declarations list
	// hangs off of the module node to support the getVariableDecls method
	// of the API.
	private final void processVariables(TreeNode treeNodes[], ModuleNode cm) {
		for (int lvi = 1; lvi < treeNodes.length; lvi += 2) {
			UniqueString us = treeNodes[lvi].getUS();

			if (us == S_at) {
				errors.addError(treeNodes[lvi].getLocation(), "Attempted to declare '@' as a variable.");
			}

			// The next line has its side-effects in the constructor; in particular,
			// the new OpDeclNode is placed in the symbolTble there.
			new OpDeclNode(us, VariableDeclKind, 1, 0, cm, symbolTable, treeNodes[lvi]);
		}
	}

	private final OpDeclNode buildParameter(TreeNode treeNode, int declKind, int declLevel, ModuleNode cm,
			boolean declare) {
		/***********************************************************************
		 * This method was originally called only by the processParameters * method to
		 * build an OpDeclNode for a module-level CONSTANT * declaration. For a
		 * declaration "CONSTANT foo(_), _+_" it would be * called twice, once with
		 * treeNode the node for "foo(_)", and once * with it equal to the node for
		 * "_+_". The OpDeclNode is not returned * because its constructor adds the node
		 * to symbolTable. * * It was modified by LL on 22 Mar 2007 for use in the
		 * generateNewSymb * method as well. The modifications consisted of returning
		 * the * OpDeclNode and adding arguments to specify the kind and level of * the
		 * OpDeclNode. * * Further modified by LL on 6 Apr 2007 for use in the *
		 * processRecursive method as well. The modification consisted of * adding the
		 * declare argument. If true, it calls the OpDeclNode * constructor with symbol
		 * table symbolTable, so the symbol is added * to the current symbol table. If
		 * false, it calls the constructor * with a null symbol table, so nothing is
		 * declared. The * processRecursive method just uses the name and arity from the
		 * * returned OpDeclNode. *
		 ***********************************************************************/
		UniqueString us = null;
		int arity = 0;
		TreeNode[] ss = treeNode.heirs();

		if (treeNode.isKind(N_IdentDecl)) {
			us = ss[0].getUS();
			arity = (ss.length - 1) / 2;
		} else if (treeNode.isKind(N_PrefixDecl)) {
			us = ss[0].getUS();
			arity = 1;
		} else if (treeNode.isKind(N_InfixDecl)) {
			us = ss[1].getUS();
			arity = 2;
		} else if (treeNode.isKind(N_PostfixDecl)) {
			us = ss[1].getUS();
			arity = 1;
		} else {
			errors.addError(treeNode.getLocation(), "Unknown parameter declaration `" + treeNode.getUS() + "'.");
		}
//    SymbolNode symbolNode = 
		SymbolTable st = null;
		if (declare) {
			st = symbolTable;
		}
		;

		/**********************************************************************
		 * Changed us to Operators.resolveSynonym(us) in the following so * constant
		 * declarations work with any synonym for an operator--e.g., * with both (+) and
		 * \oplus. *
		 **********************************************************************/
		return new OpDeclNode(Operators.resolveSynonym(us), declKind, declLevel, arity, cm, st, treeNode);
	}

	private final void processParameters(TreeNode treeNodes[], ModuleNode cm) {
		for (int lvi = 1; lvi < treeNodes.length; lvi += 2) {
			if (treeNodes[lvi].getUS() == S_at) {
				errors.addError(treeNodes[lvi].getLocation(), "Attempted to declare '@' as a constant.");
			}
			;
			OpDeclNode odn = buildParameter(treeNodes[lvi], ConstantDeclKind, ConstantLevel, cm, true);
			/*******************************************************************
			 * We throw away the OpDeclNode because, when it was constructed, * it was added
			 * to symbolTable, whose top context should be the * top-level context of the
			 * module. *
			 *******************************************************************/
		}
	}

	/**
	 * Processes the LHS of an operator definition, in several ways, depending on
	 * whether it is a prefix, infix, postfix, or a parameter-free or parameter-ful
	 * function-notation operator. Also creates context entries for the operator and
	 * its parameters.
	 */
	/************************************************************************
	 * Processes a syntactic node of type N_OperatorDefinition. It is * called by
	 * generateModule (with defs = null) when processing an * outer-level definition
	 * and by processLetIn (with defs /= null) when * processing a LET definition.
	 * It creates an OpDef node and puts it * in ModuleNode cm's set of definitions.
	 * *
	 ************************************************************************/
	private final void processOperator(TreeNode treeNode, Vector defs, ModuleNode cm) throws AbortException {
		TreeNode syntaxTreeNode = treeNode;
		UniqueString name = null;
		int arity = 0;
		boolean local = syntaxTreeNode.zero() != null;
		TreeNode[] children = syntaxTreeNode.one();
		TreeNode[] ss = children[0].heirs();
		FormalParamNode[] params = null;
		Context ctxt = new Context(moduleTable, errors);
		boolean isRecursive = false;
		/*********************************************************************
		 * Will be set to true if this operator was declared in a RECURSIVE * statement.
		 * *
		 *********************************************************************/
		// New context needed because parameter symbols may have to be
		// added if the operator being defined takes params
		symbolTable.pushContext(ctxt);

		// If the operator is an identifier (possibly with params), as
		// opposed to a prefix, infix, or postfix symbol
		if (children[0].isKind(N_IdentLHS)) {
			if (ss.length > 2) {
				// If the operator has arguments
				params = new FormalParamNode[(ss.length - 2) / 2];
				for (int lvi = 2; lvi < ss.length; lvi += 2) {
					TreeNode sss[] = ss[lvi].heirs();
					if (ss[lvi].isKind(N_IdentDecl)) {
						// parameter is simple identifier
						name = sss[0].getUS();
						arity = (sss.length - 1) / 2;
					} else if (ss[lvi].isKind(N_InfixDecl)) {
						// parameter is infix operator
						// Call of Operators.resolveSynonym added by LL on 27 Mar 2013
						name = sss[1].getUS();

						// Following added by LL on 27 Mar 2013
						// to handle parameters like _(+)_
						name = Operators.resolveSynonym(name);

						arity = 2;
					} else if (ss[lvi].isKind(N_PrefixDecl)) {
						// parameter is prefix operator
						name = sss[0].getUS();
						arity = 1;
					} else {
						// parameter must be postfix operator
						// SZ Jul 13, 2009: added the message to the assert
						if (!ss[lvi].isKind(N_PostfixDecl)) {
							throw new WrongInvocationException(MP.getMessage(EC.TLC_PARAMETER_MUST_BE_POSTFIX));
						}
						name = sss[1].getUS();
						arity = 1;
					}
					params[(lvi - 2) / 2] = new FormalParamNode(name, arity, ss[lvi], symbolTable, cm);
				}
			} else {
				// The operator has no arguments
				params = new FormalParamNode[0];
			}
			name = ss[0].getUS();
		} else if (children[0].isKind(N_PrefixLHS)) { // operator is a prefix operator
			// Process the parameter
			params = new FormalParamNode[1];
			params[0] = new FormalParamNode(ss[1].getUS(), 0, ss[1], symbolTable, cm);

			// Process the operator
			name = Operators.resolveSynonym(ss[0].getUS());
		} else if (children[0].isKind(N_InfixLHS)) { // operator is an infix operator
			params = new FormalParamNode[2];
			// Process the first param
			params[0] = new FormalParamNode(ss[0].getUS(), 0, ss[0], symbolTable, cm);

			// Process the second param
			params[1] = new FormalParamNode(ss[2].getUS(), 0, ss[2], symbolTable, cm);

			// Process the operator
			name = Operators.resolveSynonym(ss[1].getUS());
		} else if (children[0].isKind(N_PostfixLHS)) { // operator is a postfix operator
			// Process the parameter
			params = new FormalParamNode[1];
			params[0] = new FormalParamNode(ss[0].getUS(), 0, ss[0], symbolTable, cm);

			// Process the operator
			name = Operators.resolveSynonym(ss[1].getUS());
		} else {
			errors.addError(children[0].getLocation(), "Unknown parameter declaration `" + children[0].getUS() + "'.");
		}

		/***********************************************************************
		 * The following code added by LL on 1 April 2007 to handle * recursively
		 * defined operators. *
		 ***********************************************************************/
		OpDefNode odn = null;
		/***********************************************************************
		 * Check if this operator has already been declared or defined. If * so, if it
		 * was declared in a RECURSIVE statement at this let/in * level and not yet
		 * defined, then set the OpDefNode's fields * appropriately, otherwise report an
		 * error. *
		 ***********************************************************************/
		SymbolNode symbolNode = symbolTable.resolveSymbol(name);

		if (symbolNode != null) {
			/*********************************************************************
			 * The symbol has already been defined or declared. Check if it was * declared
			 * in a RECURSIVE statement. *
			 *********************************************************************/
			if (symbolNode instanceof OpDefNode) {
				odn = (OpDefNode) symbolNode;
			}
			;
			if ((odn != null) && odn.inRecursive && (!odn.isDefined)) {
				if (odn.letInLevel == curLevel) {
					isRecursive = true;

					/*****************************************************************
					 * Check that the parameters of the definition match the ones in * the RECURSIVE
					 * declaration. *
					 *****************************************************************/
					boolean paramsMatch = (odn.getParams().length == params.length);
					if (paramsMatch) {
						for (int i = 0; i < params.length; i++) {
							paramsMatch = (params[i].getArity() == 0);
						}
						;
					}
					; // if
					if (!paramsMatch) {
						errors.addError(treeNode.getLocation(), "Definition of " + odn.getName()
								+ " has different arity than " + "its RECURSIVE declaration.");
					}
					;

					odn.setParams(params);
					/***************************************************************
					 * Here's where the params field of the OpDefNode is set for an * operator
					 * declared in a RECURSIVE statement. *
					 ***************************************************************/
				} // if (odn.letInLevel == curLevel)
				else {
					errors.addError(treeNode.getLocation(),
							"Recursive operator " + name.toString() + " defined at wrong LET/IN level.");
					odn = null;
				} // else
			} // if (odn != null) ...
			else {
				errors.addError(treeNode.getLocation(),
						"Operator " + name.toString() + " already defined or declared.");
			}
		} // if (symbolNode != null)

		pushLS();
		/*********************************************************************
		 * Start fresh processing of labels. *
		 *********************************************************************/
		// Generate expression that is the body of the operator
		ExprNode exp = generateExpression(children[2], cm);

		// Restore old context, popping off the context containing the parameters
		symbolTable.popContext();

		if (isRecursive) {
			endOpDefNode(odn, exp, syntaxTreeNode);
		} else {
			// Create OpDefNode using symbolTable whose top context contains the
			// parameter symbols
			/********************************************************************
			 * This comment appears to be incorrect, because it looks like the * parameter
			 * symbols were just popped off symbolTable. *
			 ********************************************************************/
			odn = new OpDefNode(name, UserDefinedOpKind, params, local, exp, cm, symbolTable, syntaxTreeNode, true,
					null);
			symbolNode = odn;
			/*******************************************************************
			 * Keeping symbolNode for historical reasons--I'm too lazy to * rearrange the
			 * code to get rid of the redundant identifier. *
			 *******************************************************************/

			setOpDefNodeRecursionFields(odn, cm);

		} // else

		Hashtable ht = popLabelNodeSet();
		/*********************************************************************
		 * Succeed or fail, we must execute popLabelNodeSet to match the * previous
		 * pushLS. *
		 *********************************************************************/
		if (odn != null) {
			odn.setLabels(ht);
		}
		;
		/*********************************************************************
		 * If there was no error, then odn is an OpDefNode and we must set * it labels
		 * field. *
		 *********************************************************************/
		cm.appendDef(symbolNode);
		/*******************************************************************
		 * Add the new OpDefNode to the current module's set of * definitions. *
		 *******************************************************************/
		// defs is non-null iff this definition is in the Let part of a
		// Let-In expression
		if (defs != null)
			defs.addElement(symbolNode);
	} // processOperator

	private final void processQuantBoundArgs(TreeNode[] treeNodeA, // node whose children include
																	// the bounded quants
			int offset, // nodes to skip to get to first
						// "quantifier"
			FormalParamNode[][] odna, boolean[] bt, // set to true if arg is a tuple;
													// otherwise false
			ExprNode[] ena, ModuleNode cm)
			/***********************************************************************
			 * Despite the incoherent and/or incorrect comments, here's what I * think is
			 * going on: * * - odna, ena, and bt have the same length N. * * - treeNodeA is
			 * an array of nodes containing a subsequence of * N_QuantBound nodes of length
			 * N that starts at * treeNodeA[offset]. * * - odna, ena, and bt are set to the
			 * arguments for the OpApplNode * constructor that produces an OpApplNode for
			 * the operator * having this sequence of N_QuantBound nodes. *
			 ***********************************************************************/

			throws AbortException {
		// For each quantifier, evaluate the bound in the context of the
		// current symbol table, i.e. before the quantified variables are
		// added to the new context, since the quantified vars may not
		// appear in the bounds.
		for (int lvi = 0; lvi < bt.length; lvi++) {
			// Make ss point to each N_QuantBound node in turn.
			TreeNode[] ss = treeNodeA[offset + 2 * lvi].heirs();
			// the last element in ss is expression for the quantifier bound
			ena[lvi] = generateExpression(ss[ss.length - 1], cm);
		}

		// Now for each quantifier, process the variable names
		for (int lvi = 0; lvi < bt.length; lvi++) {
			TreeNode treeNode = treeNodeA[offset + 2 * lvi];

			// The variable bound to the "quantifier"
			TreeNode[] ss = treeNode.heirs();

			if (ss[0].isKind(N_IdentifierTuple)) { // three elements only, go into node
				bt[lvi] = true;
				TreeNode[] sss = ss[0].heirs();
				odna[lvi] = new FormalParamNode[sss.length / 2];

				for (int lvj = 0; lvj < sss.length / 2; lvj++) {
					odna[lvi][lvj] = new FormalParamNode(sss[2 * lvj + 1].getUS(), 0, sss[2 * lvj + 1], symbolTable,
							cm);
				}
			} else { // gotta be N_Identifier
				bt[lvi] = false;
				odna[lvi] = new FormalParamNode[(ss.length - 1) / 2];

				for (int lvj = 0; lvj < (ss.length - 1) / 2; lvj++) {
					odna[lvi][lvj] = new FormalParamNode(ss[2 * lvj].getUS(), 0, ss[2 * lvj], symbolTable, cm);
				}
			}
		}
	}

	// Process a function definition
	private final void processFunction(TreeNode treeNode, Vector defs, ModuleNode cm) throws AbortException {
		TreeNode syntaxTreeNode = treeNode;
		boolean local = syntaxTreeNode.zero() != null;
		TreeNode[] ss = syntaxTreeNode.one();
		// Heirs to N_FunctionDefinition node
		int ql = (ss.length - 4) / 2;
		// number of QuantBound's
		OpApplNode oan;
		OpDefNode odn = null;
		FormalParamNode[][] quants = new FormalParamNode[ql][0];
		FormalParamNode[] fcnDeclForRecursion = new FormalParamNode[1];
		/*********************************************************************
		 * This is an array of length 1 instead of just an OpDeclNode * because it is
		 * needed in such an array to pass as an argument to * new OpApplNode. *
		 *********************************************************************/
		boolean[] tuples = new boolean[ql];
		ExprNode[] domains = new ExprNode[ql];
		ExprNode[] lhs = new ExprNode[1];
		Context newContext = new Context(moduleTable, errors);
		boolean isRecursive = false;
		/*********************************************************************
		 * Will be set to true if this operator was declared in a RECURSIVE * statement.
		 * *
		 *********************************************************************/

		// Fill arrays with quantifier-related information; must be called
		// in scope of *new* context, since it adds parameter symbols to
		// the context.
		symbolTable.pushContext(newContext);
		processQuantBoundArgs(ss, 2, quants, tuples, domains, cm);

		UniqueString name = ss[0].getUS();
		SymbolNode symbolNode = symbolTable.resolveSymbol(name);

		// This is in anticipation of the possibility that the function is
		// recursive. We are creating a new bound symbol of the same name
		// as the function to stand in the body for the function. The
		// arity of the bound symbol is 0 because a function formally has
		// arity 0 as an operator, even if it has several arguments as a
		// function.
		/***********************************************************************
		 * If the function name is already defined (which should happen only * if it was
		 * declared in a RECURSIVE statement, then there is no need * to add this
		 * OpDeclNode to the symbol table. As near as I can tell * (which might not be
		 * near enough), this OpDeclNode's entry in the * symbol table is needed only so
		 * the name will be declared in case * of a recursive call. The check for
		 * whether a function call in the * body actually is recursive is made by
		 * calling the recursionCheck * method of the Function subclass to see if the
		 * OpApplNode is in the * Function object's funcStack. *
		 ***********************************************************************/
		SymbolTable st = null;
		if (symbolNode == null) {
			st = symbolTable;
		}
		;
		fcnDeclForRecursion[0] = new FormalParamNode(name, 0, treeNode, st, cm);
		symbolTable.popContext();

		// Create OpApplNode to hold the function body; type is assumed to
		// be non-recursive function (OP_nrfs); if the body is recursive,
		// this will be discovered during generateExpression() for the
		// body
		oan = new OpApplNode(OP_nrfs, fcnDeclForRecursion, new ExprNode[0], quants, tuples, domains, syntaxTreeNode,
				cm);
		// constructor 5

		/***********************************************************************
		 * The following code added by LL on 19 April 2007 to handle * recursively
		 * defined operators. *
		 ***********************************************************************/
		if (symbolNode == null) {
			odn = new OpDefNode(ss[0].getUS(), UserDefinedOpKind, nullParam, local, oan, cm, symbolTable,
					syntaxTreeNode, true, null);
			setOpDefNodeRecursionFields(odn, cm);
		} else {
			/*********************************************************************
			 * The symbol has already been defined or declared. Check if it was * declared
			 * in a RECURSIVE statement. *
			 *********************************************************************/
			if (symbolNode instanceof OpDefNode) {
				odn = (OpDefNode) symbolNode;
			}
			;
			if ((odn != null) && odn.inRecursive && (!odn.isDefined)) {
				if (odn.letInLevel == curLevel) {
					isRecursive = true;
					/*****************************************************************
					 * Check that the RECURSIVE declaration had no paramters. *
					 *****************************************************************/
					if (odn.getArity() == 0) {
						endOpDefNode(odn, oan, syntaxTreeNode);
					} else {
						/*************************************************************
						 * RECURSIVE declaration had parameters. *
						 *************************************************************/
						errors.addError(treeNode.getLocation(), "Function " + odn.getName()
								+ " has operator arguments in " + "its RECURSIVE declaration.");
					}
					;
				} // if (odn.letInLevel == curLevel)
				else {
					errors.addError(treeNode.getLocation(),
							"Recursive function " + name.toString() + " defined at wrong LET/IN level.");
					odn = null;
				} // else
			} // if (odn != null) ...
			else {
				errors.addError(treeNode.getLocation(),
						"Function name `" + name.toString() + "' already defined or declared.");
			}
		} // else (symbolNode != null)

		// Create OpDefNode to hold the function definition, including
		// reference to the function body ("oan")
		if (odn != null) {
			/*********************************************************************
			 * There was no error, so the OpDefNode was created. *
			 *********************************************************************/
			cm.appendDef(odn);

			// defs is non-null iff this function definition is in the Let
			// part of a Let-In expression. If so, then we have to accumulate
			// these defs in a vector.
			if (defs != null)
				defs.addElement(odn);

			// Function body must be processed in the scope of the new
			// context, including the parms
			symbolTable.pushContext(newContext);

		}
		; // if (odn != null)

		// Keep stack of nested function defs to enable detection of recursion
		functions.push(ss[0].getUS(), oan);

		// Create semantic graph function body in the inner context including parameters
		pushLS();
		pushFormalParams(flattenParams(quants));
		/*********************************************************************
		 * Push a new empty label set onto LS, and push the function * definition's
		 * formal parameters onto Last(LS).paramSeq for * processing the function body.
		 * *
		 *********************************************************************/
		lhs[0] = generateExpression(ss[ss.length - 1], cm);
		popFormalParams();
		/*********************************************************************
		 * Pop the formal params from Last(LS).paramSeq, which should now be * empty.
		 * This isn't really necessary, since we're going to pop the * LS stack below,
		 * but I hate to have a push without a pop. *
		 *********************************************************************/
		Hashtable ht = popLabelNodeSet();
		/*********************************************************************
		 * The matching pop for the pushLS above. *
		 *********************************************************************/
		if (odn != null) {
			odn.setLabels(ht);
		}
		;
		/*********************************************************************
		 * If there was no error and we created an OpDefNode, then set its * label set.
		 * *
		 *********************************************************************/
		functions.pop();

		oan.setArgs(lhs);
		/***********************************************************************
		 * Test for odn != null added 2 Jul 2009 to avoid bug that caused * popping of
		 * empty symbol table when the function name was * already declared to be a
		 * variable. *
		 ***********************************************************************/
		if (odn != null) {
			// Restore old context
			symbolTable.popContext();
		}

		// if the function body turned out to be non-recursive, then we
		// should null-out the fcnDefForRecursion ref put in place above,
		// since it is unnecessary for a nonrecursive func
		if (oan.getOperator().getName() == OP_nrfs) {
			oan.makeNonRecursive();
		}
	} // end processFunction()

	private final ExprNode processLetIn(TreeNode treeNode, TreeNode[] children, ModuleNode cm) throws AbortException {
		TreeNode[] syntaxTreeNode = children[1].heirs(); // extract LetDefinitions
		Vector defVec = new Vector(4);
		Vector instVec = new Vector(1);

		Context letCtxt = new Context(moduleTable, errors);
		symbolTable.pushContext(letCtxt);
		/*********************************************************************
		 * Create a new sub-Context for the IN expression, containing the * LET
		 * definitions *
		 *********************************************************************/

		/***********************************************************************
		 * Increment curLevel. *
		 ***********************************************************************/
		if (curLevel < MaxLetInLevel) {
			curLevel++;
		} else {
			errors.addAbort(treeNode.getLocation(), "LETs nested more than " + MaxLetInLevel + " deep.");
		}
		;
		unresolvedCnt[curLevel] = 0;
		/*********************************************************************
		 * Will not have been initialized if we haven't yet reached this * LET/IN
		 * nesting depth. *
		 *********************************************************************/

		for (int lvi = 0; lvi < syntaxTreeNode.length; lvi++) {
			/*********************************************************************
			 * Note: LL changed from an "if" and a sequence of "elseif"s to a * switch
			 * statement on 7 Apr 2007 when adding the N_Recursive case. *
			 *********************************************************************/
			switch (syntaxTreeNode[lvi].getKind()) {
			case N_OperatorDefinition:
				processOperator(syntaxTreeNode[lvi], defVec, cm);
				break;

			case N_FunctionDefinition:
				processFunction(syntaxTreeNode[lvi], defVec, cm);
				break;

			case N_ModuleDefinition:
				processModuleDefinition(syntaxTreeNode[lvi], defVec, instVec, cm);
				break;

			case N_Recursive:
				processRecursive(syntaxTreeNode[lvi], cm);
				break;

			default:
				errors.addAbort(syntaxTreeNode[lvi].getLocation(),
						"Internal error: found unexpected syntax " + "tree node in LET.");
			} // switch
		} // for

		checkForUndefinedRecursiveOps(cm);

		/***********************************************************************
		 * Decrement curLevel. *
		 ***********************************************************************/
		curLevel--;
		if (curLevel < 0) {
			curLevel = 0;
		}
		;

		ExprNode body = generateExpression(children[3], cm);

		/***********************************************************************
		 * Convert from Vector to array of SymbolNode, whose elements may be * OpDefNode
		 * or ThmOrAssumpDefNode objects. *
		 ***********************************************************************/
		SymbolNode[] opDefs = new SymbolNode[defVec.size()];
		for (int i = 0; i < opDefs.length; i++) {
			opDefs[i] = (SymbolNode) defVec.elementAt(i);
		}

		InstanceNode[] insts = new InstanceNode[instVec.size()];
		for (int i = 0; i < insts.length; i++) {
			insts[i] = (InstanceNode) instVec.elementAt(i);
		}
		LetInNode letIn = new LetInNode(treeNode, opDefs, insts, body, letCtxt);
		symbolTable.popContext();
		return letIn;
	} // end processLetIn

	private final ExprNode generateExpression(TreeNode treeNode, ModuleNode cm) throws AbortException {
		/***********************************************************************
		 * Must return an ExprNode that represents an expression, and not a * labeled
		 * ASSUME/PROVE *
		 ***********************************************************************/
		return generateExpressionOrLAP(treeNode, cm, false);
	}

	private final ExprNode generateExpressionOrLAP(TreeNode treeNode, ModuleNode cm, boolean allowLabeledAP)
			/***********************************************************************
			 * Can return a LabelNode labeling an ASSUME/PROVE iff allowLabeledAP * = true.
			 * Otherwise, it can return only an ExprNode that represents * an expression. *
			 ***********************************************************************/
			throws AbortException {
		TreeNode[] children = treeNode.heirs();
		TreeNode[] ss = null; // grandchildren
		SymbolNode opn = null;
		TreeNode op = null;
		GenID genID;
		ExprOrOpArgNode[] sns; // a ExprNode list used for arguments

		switch (treeNode.getKind()) {

		case N_Real:
			return new DecimalNode(children[0].getImage(), children[2].getImage(), treeNode);

		case N_Number:
			return new NumeralNode(children[0].getImage(), treeNode);

		case N_String:
			return new StringNode(treeNode, true);

		case N_ParenExpr:
			return generateExpression(children[1], cm);

		case N_InfixExpr:
			genID = generateGenID(children[1], cm);

			sns = new ExprOrOpArgNode[2];
			opn = symbolTable.resolveSymbol(Operators.resolveSynonym(genID.getCompoundIDUS()));
			if (opn == null) {
				errors.addError(treeNode.getLocation(),
						"Couldn't resolve infix operator symbol `" + genID.getCompoundIDUS() + "'.");
				return null;
			}

			sns[0] = generateExpression(children[0], cm);
			sns[1] = generateExpression(children[2], cm);
			return new OpApplNode(opn, sns, treeNode, cm);

		case N_PrefixExpr:
			// 1 get gen operator node
			ss = children[0].heirs();

			// 2 get rightmost part of the possibly compound Op itself;
			op = ss[1];
			genID = generateGenID(children[0], cm, true);
			sns = new ExprOrOpArgNode[1];
			opn = symbolTable.resolveSymbol(Operators.resolveSynonym(genID.getCompoundIDUS()));

			if (opn == null) {
				errors.addError(treeNode.getLocation(),
						"Couldn't resolve prefix operator symbol `" + genID.getCompoundIDUS() + "'.");
				return null;
			}

			sns[0] = generateExpression(children[1], cm);
			return new OpApplNode(opn, sns, treeNode, cm); // constructor 2

		case N_PostfixExpr:
			genID = generateGenID(children[1], cm);

			sns = new ExprNode[1];
			opn = symbolTable.resolveSymbol(Operators.resolveSynonym(genID.getCompoundIDUS()));
			if (opn == null) {
				errors.addError(treeNode.getLocation(),
						"Couldn't resolve postfix " + "operator symbol `" + genID.getCompoundIDUS() + "'.");
				return null;
			}

			sns[0] = generateExpression(children[0], cm);
			return new OpApplNode(opn, sns, treeNode, cm); // constructor 2

		case N_Times: // or cartesian product
			sns = new ExprNode[(children.length + 1) / 2];

			for (int lvi = 0; lvi < sns.length; lvi++) {
				sns[lvi] = generateExpression(children[2 * lvi], cm);
			}
			return new OpApplNode(OP_cp, sns, treeNode, cm); // constructor 3

		case N_SetEnumerate:
			int size = (children.length - 1) / 2;
			sns = new ExprNode[size];
			for (int lvi = 0; lvi < size; lvi++) {
				sns[lvi] = generateExpression(children[2 * lvi + 1], cm);
			}
			return new OpApplNode(OP_se, sns, treeNode, cm); // constructor 3

		case N_GeneralId:
			// This is a zero-ary operator; it should show in the syntax
			// tree as an OpApp, but it does not. Hence, an OpApplication
			// node with zero arguments must be constructed for it
			// if we get here, the GeneralID really is an OpApplication with 0
			// primary arguments, but with any number of prefix arguments

			// process the generalized identifier, complete with its
			// embedded argument lists (if any)

			/*********************************************************************
			 * If the N_GeneralId represents the identifier "@", then check for * errors and
			 * return an AtNode if none. *
			 *********************************************************************/
			SyntaxTreeNode sTreeNode = (SyntaxTreeNode) treeNode;
			if ((sTreeNode.heirs()[1].getKind() == IDENTIFIER) && (sTreeNode.heirs()[1].getUS() == AtUS)
					&& (((SyntaxTreeNode) sTreeNode.heirs()[0]).heirs().length == 0)) {
				if (excStack.empty() || excSpecStack.empty()) {
					// if either stack is empty, then @ used in improper EXCEPT context
					errors.addError(sTreeNode.getLocation(), "@ used where its meaning is not defined.");
					return nullOAN;
				} else {
					// So, the context for @ is proper, then construct the
					// AtNode and return it
					return new AtNode((OpApplNode) excStack.peek(), (OpApplNode) excSpecStack.peek());
				}
			}
			;

			ExprNode retVal = (ExprNode) selectorToNode(genIdToSelector(sTreeNode), 0, false, false, cm);

			/*********************************************************************
			 * A function definition generates an OpDefNode whose body is an * OpApplNode
			 * whose operator is either $RecursiveFcnSpec or * $NonRecursiveFcnSpec, the
			 * latter when the definition is * recursive. However, in SANY1 the definition *
			 * * f[x \in S] == ... * * was found to be recursive only if a subexpression
			 * f[...] occurs * in the body. It was not marked as recursive if another
			 * instance * of f occurs, such as Foo(f). To fix this, we need to check if *
			 * this genID is actually the Identifier of a function currently * being
			 * defined. The following call to functions.recursionCheck * does that. *
			 *********************************************************************/
			if (retVal.getKind() == OpApplKind) {
				functions.recursionCheck(((OpApplNode) retVal).getOperator().getName());
			}
			;

			return retVal;
		/**************************
		 * old version genID = generateGenID(treeNode, cm);
		 * 
		 * // if the symbol is "@" then check for errors and // return an AtNode if
		 * none. if (genID.getCompoundIDUS() == S_at) { if (excStack.empty() ||
		 * excSpecStack.empty()) { // if either stack is empty, then @ used in improper
		 * EXCEPT context errors.addError(treeNode.getLocation(), "@ used where its
		 * meaning is not defined."); } else { // So, the context for @ is proper, then
		 * construct the // AtNode and return it return new
		 * AtNode((OpApplNode)excStack.peek(), (OpApplNode)excSpecStack.peek()); } }
		 * else if (genID.getFullyQualifiedOp() == null || genID.getArgs() == null) { //
		 * If it is not an "@" symbol, it may still be an unresolved symbol return
		 * nullOAN; } else if (genID.getFullyQualifiedOp().getKind() == ModuleKind) {
		 * errors.addError( treeNode.getLocation(), "Module name '" +
		 * genID.getFullyQualifiedOp().getName() + "' used as operator."); return
		 * nullOAN; } else { // but if there are no problems then we are in a situation
		 * in // which return the appropriate OpApplNode an N_GenID node in // the
		 * syntax tree really stands for an OpApplication
		 * 
		 * // ********************************************************************* // *
		 * Modified on 20 Apr 2007 by LL to correct the following bug. * // * * // * A
		 * function definition generates an OpDefNode whose body is an * // * OpApplNode
		 * whose operator is either $RecursiveFcnSpec or * // * $NonRecursiveFcnSpec,
		 * the latter when the definition is * // * recursive. However, the definition *
		 * // * * // * f[x \in S] == ... * // * * // * was found to be recursive only if
		 * a subexpression f[...] occurs * // * in the body. It was not marked as
		 * recursive if another instance * // * of f occurs, such as Foo(f). To fix
		 * this, we need to check if * // * this genID is actually the Identifier of a
		 * function currently * // * being defined. The call to functions.recursionCheck
		 * was added * // * here to do that. * //
		 * *********************************************************************
		 * SymbolNode symNode = genID.getFullyQualifiedOp() ;
		 * 
		 * if (symNode.getKind() == ThmOrAssumpDefKind) {
		 * errors.addError(treeNode.getLocation(), "Theorem or Assumption name used as
		 * expression.") ; }; OpApplNode retVal = // return new OpApplNode(symNode,
		 * genID.getArgs(), treeNode, cm); functions.recursionCheck(symNode.getName());
		 * return retVal ; }
		 ******************************* 
		 * old version
		 ******************/
		case N_OpApplication:
			// for an operator with arguments
			// Note: in neither case can this be an operator passed as an argument;
			// the opAppl argument forces the return of an Operator application
			// operators passed as arguments generate OpArg nodes, and that
			// can happen only in certain contexts, not in every context where an
			// expression can occur, which is the context we are in here

			SyntaxTreeNode genIdNode = (SyntaxTreeNode) treeNode.heirs()[0];
			SyntaxTreeNode opApplNode = (SyntaxTreeNode) treeNode.heirs()[1];

			/*********************************************************************
			 * First a check. It appears that the children of an OpApplication * node must
			 * be a GeneralId node and an OpArgs node, but let's be * sure. *
			 *********************************************************************/
			if ((genIdNode.getKind() != N_GeneralId) || (opApplNode.getKind() != N_OpArgs)) {
				errors.addAbort(treeNode.getLocation(), "Internal error: OpAppl node with unexpected children.", true);
			}
			;

			Selector sel = genIdToSelector(genIdNode);
			sel.args[sel.args.length - 1] = opApplNode;
			sel.selSTN = (SyntaxTreeNode) treeNode;
			/*******************************************************************
			 * For error reporting, make the syntax tree node of the selector * include both
			 * the general ID node and its argument. *
			 *******************************************************************/
			return (ExprNode) selectorToNode(sel, 0, false, false, cm);

		/*****************
		 * old version ********************* return generateOpAppl(treeNode, cm);
		 ************************/

		case N_Tuple:
			size = (children.length - 1) / 2;
			sns = new ExprNode[size];
			for (int lvi = 0; lvi < size; lvi++) {
				sns[lvi] = generateExpression(children[2 * lvi + 1], cm);
			}
			return new OpApplNode(OP_tup, sns, treeNode, cm); // Constructor 3

		case N_FcnAppl: // Apparent function application
			// Number of arguments to the apparent func app
			int numArgs = (children.length - 2) / 2;

			// Function appl involves two semantic nodes: 1 for function,
			// and 1 for arg or args tuple.
			sns = new ExprNode[2];

			// Generate expression tree for the function itself
			sns[0] = generateExpression(children[0], cm);

			if (sns[0] == null) {
				return null;
			}
			;
			/*******************************************************************
			 * sns[0] can be null if the parsing the function generates an * error (which is
			 * the case if the function is missing). * Added by LL on 29 Feb 2008 *
			 *******************************************************************/

			// If the function is an OpApplNode (and could it be otherwise?)
			if (sns[0].getKind() == OpApplKind) {
				// Note if this is a recursive function, and change the top level
				functions.recursionCheck(((OpApplNode) sns[0]).getOperator().getName());
			}

			// We next check that the number of arguments to a user-defined
			// function is correct, if possible.

			// Retrieve the expression that represents the function being
			// applied, i.e. the 1st arg to $FcnApply
			ExprOrOpArgNode fcn = sns[0];

			// The entire next conditional is for one purpose: to make sure
			// that a function symbol is applied to the right number of
			// arguments, when it is possible to do that during semantic
			// analysis. This means that if a function is declared with,
			// say, 3 parameters, e.g. "f[a,b,c] == {a,b,c}", then it is
			// never used with 2 or 4 arguments. However, it can appear
			// with zero arguments as the expression "f" (not as "f[]"), and
			// it can appear with one argument, as in "f[e]", because e
			// might be a 3-tuple value. (Whether it always is or not
			// cannot be determined at the time of semantic analysis.)
			// Furthermore a function declared with exactly one parameter
			// can appear with any number of argument expressions because,
			// e.g. f[1,2,3,4] is considered just an alternate way of
			// writing f[<<1,2,3,4>>], so there is really just one argument
			// value.

			// If it is an OpApplNode (as opposed to, say, an OpDeclNode)
			if (fcn instanceof OpApplNode) {
				// Retrieve the function being applied
				SymbolNode funcOperator = ((OpApplNode) fcn).getOperator();

				// If the function being applied is a user-defined function
				// (as opposed to OpDeclNode, FormalParamNode, builtin
				// operator, or expression)
				if (funcOperator instanceof OpDefNode && funcOperator.getKind() == UserDefinedOpKind) {
					// Retrieve the function body expression
					ExprOrOpArgNode funcBody = ((OpDefNode) funcOperator).getBody();

					// if the function body is an OpApplNode (as opposed to,
					// say, NumeralNode, DecimalNode, etc.)
					if (funcBody instanceof OpApplNode && (((OpApplNode) funcBody).getOperator().getName() == OP_nrfs
							|| ((OpApplNode) funcBody).getOperator().getName() == OP_rfs)) {

						// find out how many arguments it is SUPPOSED to have
						int numParms = ((OpApplNode) funcBody).getNumberOfBoundedBoundSymbols();

						// If the function appears with numArgs >= 2 argument
						// expressions, it must be declared with exactly numArgs
						// parameters; and a function with numParms parameters in
						// its definition should be applied to exactly numParms
						// expressions, or 1 expression (representing arguments in
						// tuple form), or 0 expressions (representing the
						// function itself). Note: one cannot define a function
						// with 0 arguments in TLA+.
						if (numArgs >= 2 && numParms != numArgs) {
							errors.addError(treeNode.getLocation(),
									"Function '" + ((OpApplNode) sns[0]).getOperator().getName() + "' is defined with "
											+ numParms + " parameters, but is applied to " + numArgs + " arguments.");
							return nullOAN;
						} // end if
					} // end if
				} // end if
			} // end if

			// Assert.check(numArgs > 0);
			if (numArgs == 1) {
				sns[1] = generateExpression(children[2], cm);
			} else {
				// If there is more than one arg we have to create a tuple for the arguments.
				ExprOrOpArgNode[] exprs = new ExprNode[numArgs]; // One for each of the arguments

				// For each argument...
				for (int lvi = 0; lvi < numArgs; lvi++) {
					// Create the expression for that argument
					exprs[lvi] = generateExpression(children[2 + 2 * lvi], cm);
				}
				// Create an application of $Tuple
				sns[1] = new OpApplNode(OP_tup, exprs, treeNode, cm);
			}
			// Create the function application node.
			return new OpApplNode(OP_fa, sns, treeNode, cm);

		case N_UnboundOrBoundChoose:
			return processChoose(treeNode, children, cm);

		case N_BoundQuant:
			return processBoundQuant(treeNode, children, cm);

		case N_UnboundQuant:
			return processUnboundQuant(treeNode, children, cm);

		case N_IfThenElse:
			sns = new ExprNode[3];
			sns[0] = generateExpression(children[1], cm);
			sns[1] = generateExpression(children[3], cm);
			sns[2] = generateExpression(children[5], cm);
			return new OpApplNode(OP_ite, sns, treeNode, cm);

		case N_Case:
			return processCase(treeNode, children, cm);

		case N_DisjList:
		case N_ConjList:
			sns = new ExprNode[children.length];
			for (int lvi = 0; lvi < sns.length; lvi++) {
				sns[lvi] = generateExpression(children[lvi].heirs()[1], cm);
			}
			if (treeNode.isKind(N_DisjList))
				return new OpApplNode(OP_dl, sns, treeNode, cm);
			else
				return new OpApplNode(OP_cl, sns, treeNode, cm);

		case N_RecordComponent: // really RcdSelect in the API
			sns = new ExprNode[2];
			sns[0] = generateExpression(children[0], cm);
			sns[1] = new StringNode(children[2], false);
			return new OpApplNode(OP_rs, sns, treeNode, cm);

		case N_SetOfFcns: /* [S -> T] */
			sns = new ExprNode[2];
			sns[0] = generateExpression(children[1], cm);
			sns[1] = generateExpression(children[3], cm);

			return new OpApplNode(OP_sof, sns, treeNode, cm);

		case N_SubsetOf:
			return processSubsetOf(treeNode, children, cm);

		case N_SetOfAll:
			return processSetOfAll(treeNode, children, cm);

		case N_RcdConstructor:
			return processRcdForms(OP_rc, treeNode, children, cm);

		case N_SetOfRcds:
			return processRcdForms(OP_sor, treeNode, children, cm);

		case N_FcnConst:
			return processFcnConst(treeNode, children, cm);

		case N_ActionExpr:
		case N_FairnessExpr:
			return processAction(treeNode, children, cm);

		case N_Except:
			return processExcept(treeNode, children, cm);

		case N_LetIn:
			return processLetIn(treeNode, children, cm);

		case N_Lambda:
			errors.addError(treeNode.getLocation(), "LAMBDA expression used where an expression is required.");
			return null;

		case N_Label:
			LabelNode ln = generateLabel(treeNode, cm);
			if (ln.isAssumeProve && !allowLabeledAP) {
				errors.addError(treeNode.getLocation(), "Labeled ASSUME/PROVE used where an expression is required.");
			}
			return ln;

		default:
			errors.addError(treeNode.getLocation(), "Unsupported expression type `" + treeNode.getImage() + "'.");
			return null;

		} // end switch

	} // end generateExpression()

	/***************************************************************************
	 * The following variables are used in the processing of ASSUME/PROVE * nodes,
	 * and the labels that lie within them. *
	 ***************************************************************************/
	private int assumeProveDepth = 0;
	/***********************************************************************
	 * The nesting depth of ASSUME/PROVEs within which the node corrently * being
	 * processed lies. In * * THEOREM ASSUME P PROVE Q * * the nodes for P and Q are
	 * at depth 1 (not 0). *
	 ***********************************************************************/

	private ThmOrAssumpDefNode currentGoal = null;
	private int currentGoalClause;
	/***********************************************************************
	 * currentGoal is the named theorem or proof-step node within * which lies the
	 * current node that is being processed, or null if * we're not inside such a
	 * step. If currentGoal != null, and we're * within an ASSUME/PROVE step (which
	 * is true iff assumeProveDepth > * 0), then then currentGoalClause equals the
	 * clause of within which * the node being processed lies. (If we're processing
	 * Q in ASSUME P * PROVE Q, then Q = 1.) *
	 ***********************************************************************/

	private static final int maxAPDepth = 100;
	/***********************************************************************
	 * Maximum allowed nesting depth of ASSUME/PROVES. 100 ought to * suffice. *
	 ***********************************************************************/

	private boolean[] inScopeOfAPDecl = new boolean[maxAPDepth];

	/***********************************************************************
	 * For all i \leq assumeProveDepth, inScopeOfAPDecl[i] = true iff the * node
	 * currently being processed lies within a declaration made at *
	 * assumeProveDepth = i. Thus in * * THEOREM ASSUME NEW x \in S, * P, * ASSUME R
	 * , ACTION A PROVE T * PROVE Q * * inScopeOfAPDecl[1] equals false when S is
	 * being processed and * equals true when P, Q, R, and T are being processed. *
	 * * inScopeOfAPDecl[2] equals false when R is being processed and true * when T
	 * is being processed. *
	 ***********************************************************************/

	private boolean noLabelsAllowed() {
		/***********************************************************************
		 * This returns true if we are inside an ASSUME/PROVE node where a * label is
		 * not allowed because we are in the scope of a declaration * from an inner
		 * ASSUME/PROVE. *
		 ***********************************************************************/
		for (int i = 2; i <= assumeProveDepth; i++) {
			if (inScopeOfAPDecl[i]) {
				return true;
			}
			;
		}
		;
		return false;
	}

	private final boolean illegalLabelRef(LabelNode ln, SyntaxTreeNode stn) throws AbortException {
		/***********************************************************************
		 * True iff we are currently in a point where a reference to this * label is
		 * illegal because it lies inside an ASSUME/PROVE clause from * outside the
		 * scope of a symbol it may contain. See the comments in * AssumeProveNode.java
		 * for an explanation of this method. *
		 ***********************************************************************/
		ThmOrAssumpDefNode goal = ln.goal;
		if (goal == null) {
			return false;
		}
		;
		if ((goal.getBody() == null) || (goal.getBody().getKind() != AssumeProveKind)) {
			errors.addAbort(stn.getLocation(),
					"Internal error: Expecting label to be in AssumeProveNode, " + "but it's not.");
		}
		;
		AssumeProveNode ap = (AssumeProveNode) goal.getBody();
		return ap.inScopeOfDecl[ln.goalClause] && (goal.isSuffices() == ap.inProof);
	} // illegalLabelRef

	private final boolean illegalAPPosRef(AssumeProveNode ap, int pos) {
		/***********************************************************************
		 * True iff it is illegal for the node currently being processed to * access the
		 * clause number pos of AssumeProve node ap because it is * not in the scope of
		 * symbols declared in previous ASSUME clauses of * ap. See the comments in
		 * AssumeProveNode.java for an explanation of * this method. *
		 ***********************************************************************/
		return ap.inScopeOfDecl[pos - 1] && ((ap.getGoal() == null) || (ap.getGoal().isSuffices() == ap.inProof));
	}

// XXXX Currently, this handles both label and positional subexpression
// specifiers.  To handle positional ones, we need to know what
// the position is.
//  private final boolean withinScopeOf(SemanticNode goal) {
	/*************************************************************************
	 * Returns true iff the node currently being processed lies within the * scope
	 * of (the declarations made in the ASSUME clauses) of goal, which * will be a
	 * TheoremNode or a proof-step node. * * XXXXX Dummy implementation for now. *
	 *************************************************************************/
//  return true;
//    if (goal == null) {return true;} ;
//    return false ;  
//    }         

	// The following objects added 10 Feb 2011 by LL are used to check that
	// a []ASSUME does not lie within the scope of (the assumptions of)
	// an ordinary ASSUME. It does this by declaring the dummy OpDeclNode
	// InAssumeDummyNode as if it were declared within the ASSUME and then
	// checking if it's defined where the []ASSUME is used.
	private final static UniqueString S_InAssume = UniqueString.uniqueStringOf("$$InAssume");
	private final static OpDeclNode InAssumeDummyNode = new OpDeclNode(S_InAssume, 0, 0, 0, null, null, null);

	private final AssumeProveNode generateAssumeProve(TreeNode treeNode, ModuleNode cm)
			/***********************************************************************
			 * Added by LL on 17 Mar 2007. *
			 ***********************************************************************/
			throws AbortException {
		// The following flag is used to record if this is a
		// Following code added on 9 Nov 2009 so that the goal
		// field of the AssumeProveNode is null unless this is
		// a top-level Assume/Prove.
		ThmOrAssumpDefNode cg = null;
		if (assumeProveDepth == 0) {
			cg = currentGoal;
		}
		;
		assumeProveDepth++;
		AssumeProveNode apn = new AssumeProveNode(treeNode, cg);
		TreeNode[] children = treeNode.heirs();
		int numOfChildren = children.length;
		if (numOfChildren % 2 != 0) {
			throw new WrongInvocationException("AssumeProve has odd number of children");
		}
		;
		int numOfAssumptions = (numOfChildren - 2) / 2;
		// Check if this is a []ASSUME and that the PROVE matches
		// the ASSUME.
		boolean isBoxAssumeProve = false;
		String proveString = children[children.length - 2].getImage();
		if (children[0].getImage().equals("[]ASSUME")) {
			isBoxAssumeProve = true;
			if (!proveString.equals("[]PROVE")) {
				errors.addError(children[0].getLocation(), "[]ASSUME matched by PROVE instead of []PROVE");
			}
		} else {
			if (!proveString.equals("PROVE")) {
				errors.addError(children[0].getLocation(), "ASSUME matched by []PROVE instead of PROVE");
			}
		}
		apn.setIsBoxAssumeProve(isBoxAssumeProve);

		apn.assumes = new LevelNode[numOfAssumptions];
		boolean inDeclScope = false;
		/******************************************************************
		 * Set true when after we've processed a declaration. *
		 ******************************************************************/
		apn.inScopeOfDecl = new boolean[numOfAssumptions + 1];
		apn.inScopeOfDecl[0] = false;
		inScopeOfAPDecl[assumeProveDepth] = false;
		if (assumeProveDepth != 1) {
			/******************************************************************
			 * The context is pushed by the top-level caller of * generateAssumeProve, which
			 * is processTheorem. *
			 ******************************************************************/
			symbolTable.pushContext(new Context(moduleTable, errors));
			/******************************************************************
			 * I don't understand exactly what's going on here, but this * seems to be the
			 * magic incantation for starting a new context * into which declarations among
			 * the assumptions should be put * for interpreting expressions later in the
			 * assumption list and * in the "prove" expression. *
			 ******************************************************************/
		} // if

		if (isBoxAssumeProve) {
			if (symbolTable.resolveSymbol(S_InAssume) != null) {
				errors.addError(children[0].getLocation(),
						"[]ASSUME used within the scope of an ordinary ASSUME's assumptions");
			}
		} else {
			if (symbolTable.resolveSymbol(S_InAssume) == null) {
				symbolTable.addSymbol(S_InAssume, InAssumeDummyNode);
			}
		}

		if (assumeProveDepth == 1) {
			currentGoalClause = 0;
		}
		;
		for (int i = 0; i < numOfAssumptions; i++) {
			/******************************************************************
			 * The current assumption is assumption number i+1 (in human * numbering). *
			 ******************************************************************/
			apn.inScopeOfDecl[i + 1] = apn.inScopeOfDecl[i];
			TreeNode tn = children[2 * i + 1];
			switch (tn.getKind()) {
			case N_AssumeProve:
				apn.assumes[i] = generateAssumeProve(tn, cm);
				break;
			case N_NewSymb:
				apn.assumes[i] = generateNewSymb(tn, cm);
				apn.inScopeOfDecl[i + 1] = true;
				inScopeOfAPDecl[assumeProveDepth] = true;
				OpDeclNode[] odn = new OpDeclNode[1];
				odn[0] = ((NewSymbNode) apn.assumes[i]).getOpDeclNode();
				break;
			default:
				/**************************************************************
				 * Should be an expression node or a labeled ASSUME/PROVE. *
				 **************************************************************/
//             apn.assumes[i] = generateExpression(tn, cm) ;
				apn.assumes[i] = generateExpressionOrLAP(tn, cm, true);
				break;
			}
			; // end switch
			if (assumeProveDepth == 1) {
				currentGoalClause = currentGoalClause + 1;
			}
			;
		}
		; // end for

		apn.prove = generateExpression(children[numOfChildren - 1], cm);

		if (assumeProveDepth != 1) {
			symbolTable.popContext();
			/****************************************************************
			 * Restore the current context, removing the declarations by * the assumptions.
			 * assumption list. *
			 ****************************************************************/
		}
		;
		assumeProveDepth--;
		return apn;
	}

	private final NewSymbNode generateNewSymb(TreeNode treeNode, ModuleNode cm)
			/***********************************************************************
			 * Added by LL on 21 Mar 2007. *
			 ***********************************************************************/
			throws AbortException {
		TreeNode[] children = treeNode.heirs();
		int numOfChildren = children.length;

		/*********************************************************************
		 * Determine if this node should have a non-null "set" field, which * is the
		 * case iff the declaration ends with "\in S", in which case * set the set field
		 * to the ExprNode for S. *
		 *********************************************************************/
		ExprNode set = null;
		if (children[numOfChildren - 2].getKind() == IN) {
			set = generateExpression(children[numOfChildren - 1], cm);
		}
		;

		int declKind;
		int declLevel;
		/*********************************************************************
		 * Set declKind to the kind of the NewSymbNode object's OpDeclNode. * Set
		 * declLevel to its level. * * Start by setting i to 1 or 0 depending on whether
		 * the declaration * begins with a NEW token. *
		 *********************************************************************/
		int i = 0;
		if (children[0].getKind() == NEW) {
			i = 1;
		}
		;

		/*********************************************************************
		 * Set declKind, and leave i so that children[i+1] is the syntax * tree node
		 * describing the declared symbol and its arity. * * We do this by seeing if the
		 * next token is "CONSTANT", "VARIABLE", * etc. If it isn't, then the
		 * declaration begins "NEW id", so it's * a CONSTANT declaration and i must be
		 * set to 0. *
		 *********************************************************************/
		switch (children[i].getKind()) {
		case CONSTANT:
			declKind = NewConstantKind;
			declLevel = ConstantLevel;
			break;
		case VARIABLE:
			declKind = NewVariableKind;
			declLevel = VariableLevel;
			break;
		case STATE:
			declKind = NewStateKind;
			declLevel = VariableLevel;
			break;
		case ACTION:
			declKind = NewActionKind;
			declLevel = ActionLevel;
			break;
		case TEMPORAL:
			declKind = NewTemporalKind;
			declLevel = TemporalLevel;
			break;
		default:
			declKind = NewConstantKind;
			declLevel = ConstantLevel;
			i = 0;
		}
		; // switch
		return new NewSymbNode(buildParameter(children[i + 1], declKind, declLevel, cm, true), set, treeNode);
	}

	private final ExprNode processChoose(TreeNode treeNode, TreeNode[] children, ModuleNode cm) throws AbortException {
		ExprNode[] semanticNode = new ExprNode[1];
		TreeNode[] syntaxTreeNode = children[2].heirs();
		OpApplNode result;

		symbolTable.pushContext(new Context(moduleTable, errors));

		if (syntaxTreeNode == null || syntaxTreeNode.length == 0) {
			// unbounded case
			FormalParamNode[] odn;
			boolean tuple;

			// either Tuple or single identifier
			if (children[1].isKind(N_IdentifierTuple)) {
				syntaxTreeNode = children[1].heirs();
				odn = new FormalParamNode[syntaxTreeNode.length / 2];
				for (int lvj = 0; lvj < syntaxTreeNode.length / 2; lvj++) {
					odn[lvj] = new FormalParamNode(syntaxTreeNode[2 * lvj + 1].getUS(), 0, syntaxTreeNode[2 * lvj + 1],
							symbolTable, cm);
				}
				tuple = true;
			} else {
				odn = new FormalParamNode[1];
				odn[0] = new FormalParamNode(children[1].getUS(), 0, children[0], symbolTable, cm);
				tuple = false;
			}
			pushFormalParams(odn);
			/*******************************************************************
			 * Push formal parameters on Last(LS).paramSeq for processing the * body. *
			 *******************************************************************/
			semanticNode[0] = generateExpression(children[4], cm);
			popFormalParams();

			result = new OpApplNode(OP_uc, semanticNode, odn, treeNode, cm);
		} else {
			// bounded case
			FormalParamNode[][] odna = new FormalParamNode[1][0];
			boolean[] tuples = new boolean[1];
			ExprNode[] exprs = new ExprNode[1];

			// syntaxTreeNode can be reused further down.
			exprs[0] = generateExpression(syntaxTreeNode[1], cm);

			if (children[1].isKind(N_IdentifierTuple)) {
				syntaxTreeNode = children[1].heirs();
				odna[0] = new FormalParamNode[syntaxTreeNode.length / 2];
				for (int lvj = 0; lvj < syntaxTreeNode.length / 2; lvj++) {
					odna[0][lvj] = new FormalParamNode(syntaxTreeNode[2 * lvj + 1].getUS(), 0,
							syntaxTreeNode[2 * lvj + 1], symbolTable, cm);
				}
				tuples[0] = true;
			} else {
				odna[0] = new FormalParamNode[1];
				odna[0][0] = new FormalParamNode(children[1].getUS(), 0, children[1], symbolTable, cm);
				tuples[0] = false;
			}
			pushFormalParams(flattenParams(odna));
			/*******************************************************************
			 * Push the bound variables on Last(LS).paramSeq and process the * body of the
			 * CHOOSE. *
			 *******************************************************************/
			semanticNode[0] = generateExpression(children[4], cm);
			popFormalParams();

			result = new OpApplNode(OP_bc, null, semanticNode, odna, tuples, exprs, treeNode, cm);
		}
		symbolTable.popContext();
		return result;
	}

	private final ExprNode processBoundQuant(TreeNode treeNode, TreeNode[] children, ModuleNode cm)
			throws AbortException {
		// Create data structures for all parameters
		int length = (children.length - 2) / 2;
		FormalParamNode[][] odna = new FormalParamNode[length][0];
		boolean[] bt = new boolean[length];
		ExprNode[] ea = new ExprNode[length];

		// then process parameters
		symbolTable.pushContext(new Context(moduleTable, errors));
		processQuantBoundArgs(children, 1, odna, bt, ea, cm);

		// process expression
		ExprNode semanticNode[] = new ExprNode[1];
		pushFormalParams(flattenParams(odna));
		/*******************************************************************
		 * Push the bound variables on Last(LS).paramSeq and process the * body of the
		 * quantified expression. *
		 *******************************************************************/
		semanticNode[0] = generateExpression(children[children.length - 1], cm);
		popFormalParams();

		symbolTable.popContext();

		// then return new node.
		// which variety? look under first child.
		boolean isExists = children[0].getUS().equals(S_e) || children[0].getUS().equals(S_ex);
		if (isExists) {
			return new OpApplNode(OP_be, null, semanticNode, odna, bt, ea, treeNode, cm);
		} else {
			return new OpApplNode(OP_bf, null, semanticNode, odna, bt, ea, treeNode, cm);
		}
	}

	private final ExprNode processUnboundQuant(TreeNode treeNode, TreeNode[] children, ModuleNode cm)
			throws AbortException {
		// which variety? look under first child.
		UniqueString us = children[0].getUS();
		UniqueString r_us;
		int level;

		if (us.equals(S_e)) {
			r_us = OP_ue;
			level = 0;
		} // \E
		else if (us.equals(S_ex)) {
			r_us = OP_ue;
			level = 0;
		} // \exists
		else if (us.equals(S_f)) {
			r_us = OP_uf;
			level = 0;
		} // \A
		else if (us.equals(S_fx)) {
			r_us = OP_uf;
			level = 0;
		} // \always
		else if (us.equals(S_te)) {
			r_us = OP_te;
			level = 1;
		} // \EE
		else {
			r_us = OP_tf;
			level = 1;
		} // \AA

		// Process all identifiers bound by thus quantifier
		int length = (children.length - 2) / 2;
		FormalParamNode odn[] = new FormalParamNode[length];
		symbolTable.pushContext(new Context(moduleTable, errors));

		for (int lvi = 0; lvi < length; lvi++) {
			odn[lvi] = new FormalParamNode(children[2 * lvi + 1].getUS(), 0, children[2 * lvi + 1], symbolTable, cm);
		}

		// now the expression
		ExprNode semanticNode[] = new ExprNode[1];
		pushFormalParams(odn);
		/**********************************************************************
		 * Push formal parameters on Last(LS).paramSeq for processing the * body. *
		 **********************************************************************/
		semanticNode[0] = generateExpression(children[children.length - 1], cm);
		popFormalParams();

		// wrap up.
		symbolTable.popContext();
		return new OpApplNode(r_us, semanticNode, odn, treeNode, cm);
	}

	private final ExprNode processCase(TreeNode treeNode, TreeNode[] children, ModuleNode cm) throws AbortException {
		// number of arms to CASE-expr, not counting the CASE nodse itself
		// or the []-separators
		int armCount = children.length / 2;
		ExprNode[] casePairs = new ExprNode[armCount];

		for (int lvi = 0; lvi < armCount; lvi++) {
			TreeNode caseArm = children[2 * lvi + 1];
			TreeNode[] ss = caseArm.heirs();
			ExprNode[] sops = new ExprNode[2];
			if (!caseArm.isKind(N_OtherArm)) {
				sops[0] = this.generateExpression(ss[0], cm);
			}
			sops[1] = this.generateExpression(ss[2], cm);
			casePairs[lvi] = new OpApplNode(OP_pair, sops, caseArm, cm);
		}
		return new OpApplNode(OP_case, casePairs, treeNode, cm);
	}

	private final ExprNode processSubsetOf(TreeNode treeNode, TreeNode children[], ModuleNode cm)
			throws AbortException {
		// cfr. unbounded choose
		ExprNode[] ops = new ExprNode[1];
		FormalParamNode[][] odna = new FormalParamNode[1][0];
		boolean[] tuples = new boolean[1];
		ExprNode[] exprs = new ExprNode[1];

		exprs[0] = generateExpression(children[3], cm);

		symbolTable.pushContext(new Context(moduleTable, errors));

		if (children[1].isKind(N_IdentifierTuple)) {
			TreeNode[] ss = children[1].heirs();
			odna[0] = new FormalParamNode[ss.length / 2];
			for (int lvj = 0; lvj < ss.length / 2; lvj++) {
				odna[0][lvj] = new FormalParamNode(ss[2 * lvj + 1].getUS(), 0, ss[2 * lvj + 1], symbolTable, cm);
			}
			tuples[0] = true;
		} else {
			odna[0] = new FormalParamNode[1];
			odna[0][0] = new FormalParamNode(children[1].getUS(), 0, children[1], symbolTable, cm);
			tuples[0] = false;
		}

		pushFormalParams(flattenParams(odna));
		/*********************************************************************
		 * Push the bound variables on Last(LS).paramSeq and process the * body of the
		 * CHOOSE. *
		 *********************************************************************/
		ops[0] = generateExpression(children[5], cm);
		popFormalParams();

		symbolTable.popContext();
		return new OpApplNode(OP_sso, null, ops, odna, tuples, exprs, treeNode, cm);
	}

	private final ExprNode processSetOfAll(TreeNode treeNode, TreeNode children[], ModuleNode cm)
			throws AbortException {
		ExprNode[] ops = new ExprNode[1];
		int length = (children.length - 3) / 2;
		FormalParamNode[][] odna = new FormalParamNode[length][0];
		boolean[] tuples = new boolean[length];
		ExprNode[] exprs = new ExprNode[length];

		symbolTable.pushContext(new Context(moduleTable, errors));
		processQuantBoundArgs(children, 3, odna, tuples, exprs, cm);

		pushFormalParams(flattenParams(odna));
		/*********************************************************************
		 * Push the bound variables on Last(LS).paramSeq and process the * body of the
		 * CHOOSE. *
		 *********************************************************************/
		ops[0] = generateExpression(children[1], cm);
		popFormalParams();

		symbolTable.popContext();

		return new OpApplNode(OP_soa, null, ops, odna, tuples, exprs, treeNode, cm);
	}

	private final ExprNode processFcnConst(TreeNode treeNode, TreeNode children[], ModuleNode cm)
			throws AbortException {
		ExprNode[] ops = new ExprNode[1];
		int length = (children.length - 3) / 2; // number of args to function constant
		FormalParamNode[][] odna = new FormalParamNode[length][0];
		boolean[] tuples = new boolean[length];
		ExprNode[] exprs = new ExprNode[length];

		symbolTable.pushContext(new Context(moduleTable, errors));
		processQuantBoundArgs(children, 1, odna, tuples, exprs, cm);

		pushFormalParams(flattenParams(odna));
		/*********************************************************************
		 * Push the bound variables on Last(LS).paramSeq and process the * body of the
		 * CHOOSE. *
		 *********************************************************************/
		ops[0] = generateExpression(children[children.length - 2], cm);
		popFormalParams();

		symbolTable.popContext();

		return new OpApplNode(OP_fc, null, ops, odna, tuples, exprs, treeNode, cm);
	}

	/**
	 * This method processes both the RecordConstructor construct and the
	 * SetOfRecords operator. The two are essentially identical except for which
	 * builtin operator is used.
	 */
	private final ExprNode processRcdForms(UniqueString operator, TreeNode treeNode, TreeNode children[], ModuleNode cm)
			throws AbortException {
		// handles RcdConstructor or SetOfRcds
		int length = (children.length - 1) / 2;

		// Create an array of pairs to handle all of the fields mentioned in the form
		ExprNode[] fieldPairs = new ExprNode[length];
		// Create an array of Unique Strings to check uniqueness of fields. Not very
		// efficient
		// but a HashTable may be overkill most of the time.
		// Remember a label is a string.
		UniqueString[] labels = new UniqueString[length];

		// For each field in the RcdConstructor or SetOfRecords
		for (int lvi = 0; lvi < length; lvi++) {
			TreeNode syntaxTreeNode[] = children[2 * lvi + 1].heirs();

			// Create a pair of SemanticNodes to represent one record component
			ExprNode sops[] = new ExprNode[2];

			// The first one gets a new StringNode indicating the field name
			sops[0] = new StringNode(syntaxTreeNode[0], false);
			labels[lvi] = ((StringNode) sops[0]).getRep();
			for (int cmpIndex = 0; cmpIndex < lvi; cmpIndex++) {
				if (labels[lvi].compareTo(labels[cmpIndex]) == 0) {
					errors.addError(syntaxTreeNode[0].getLocation(), "Non-unique fields in constructor.");
				}
			}

			// The second one gets the expression indicating the field value (or set of
			// values)
			sops[1] = generateExpression(syntaxTreeNode[2], cm);

			// Put the $Pair OpApplNode into the fieldPairs array
			fieldPairs[lvi] = new OpApplNode(OP_pair, sops, children[2 * lvi + 1], cm);
		}
		// Create the top-level OpApplNode, for either the SetOfRecords op
		// or the RcdConstructor op.
		return new OpApplNode(operator, fieldPairs, treeNode, cm);
	}

	private final ExprNode processAction(TreeNode treeNode, TreeNode children[], ModuleNode cm) throws AbortException {
		UniqueString match = children[0].getUS();
		if (match.equals(S_a))
			match = OP_aa;
		else if (match.equals(S_brack))
			match = OP_sa;
		else if (match.equals(S_sf))
			match = OP_sf;
		else if (match.equals(S_wf))
			match = OP_wf;

		ExprNode ops[] = new ExprNode[2];
		ops[0] = generateExpression(children[1], cm);
		ops[1] = generateExpression(children[3], cm);
		return new OpApplNode(match, ops, treeNode, cm);
	}

	private final ExprNode processExcept(TreeNode treeNode, TreeNode[] children, ModuleNode cm) throws AbortException {
		int numExcepts = (children.length - 3) / 2; // number of ExceptSpec's;
		ExprNode[] operands = new ExprNode[numExcepts + 1]; // 1 for each ExceptionSpec + first expr
		OpApplNode excNode; // Holds OpApplNode for $Except operator
		OpApplNode excSpecNode; // Holds $Pair node for ExceptSpec

		// The first operand of the $Except operator is the expression to
		// which the exceptions apply Note this first operand is generated
		// BEFORE the $Except node is stacked in the next couple of lines,
		// because an @ in the first expression does NOT refer to the
		// $Except node currently being generated, but to the next outer
		// $Except node.
		operands[0] = generateExpression(children[1], cm);

		// Create the $Except OpApplNode that will be returned by this
		// method. We create it now, and fill out its contents later,
		// because we need a reference to it in order to process @ properly.
		excNode = new OpApplNode(OP_exc, operands, treeNode, cm);

		// for each of the ExceptSpecs produce another element of the operands array
		for (int excSpecIx = 0; excSpecIx < numExcepts; excSpecIx++) {
			TreeNode[] syntaxTreeNode = children[3 + 2 * excSpecIx].heirs(); // extract ExceptSpec
			ExprNode[] sops = new ExprNode[2]; // Each ExceptionSpec is a $Pair
			int slength = syntaxTreeNode.length - 3; // # of ExceptComponents in ExceptSpec
			ExprNode[] ssops = new ExprNode[slength]; // to store ExceptComponents

			// Process the LHS of the ExceptSpec

			// for each ExceptComponent of the form .h or [i] or [i,j,k] add
			// an arg to $SEQ node and add build up the syntax tree for
			// exceptionTarget
			for (int excCompIx = 0; excCompIx < slength; excCompIx++) {
				// the heirs of an ExceptComponent
				TreeNode subSyntaxTreeNode[] = syntaxTreeNode[1 + excCompIx].heirs();

				if (subSyntaxTreeNode[0].getUS().equals(S_brack)) {
					// The first heir is "[" , indicates one or more fcn args;
					// add expressions as function args
					if (subSyntaxTreeNode.length > 3) {
						// if so, must generate a tuple for comma list of fcn args
						int sslength = (subSyntaxTreeNode.length - 1) / 2; // number of func args in comma list
						ExprNode[] sssops = new ExprNode[sslength]; // holds the comma list of fcn args

						// for each of multiple function args in the ExceptComponent
						for (int fArgIx = 0; fArgIx < sslength; fArgIx++) {
							sssops[fArgIx] = generateExpression(subSyntaxTreeNode[1 + 2 * fArgIx], cm);
						}

						// add one ExceptComponent to vector of ExceptComponents
						ssops[excCompIx] = new OpApplNode(OP_tup, sssops, syntaxTreeNode[2 * excCompIx + 1], cm);
					} else {
						// add one ExceptComponent to vector of ExceptComponents
						ssops[excCompIx] = generateExpression(subSyntaxTreeNode[1], cm);
					}
				} else {
					// otherwise a "." indicates record selection; add a
					// StringNode operand as record selector add one
					// ExceptComponent to vector of ExceptComponents
					ssops[excCompIx] = new StringNode(subSyntaxTreeNode[1], false);
				}
			} // end for (each ExceptionComponent)

			// Create OpAppl for $SEQ applied to array of ExceptComponents
			// following record or func expr or !
			// This is the LHS of an ExceptionSpec
			sops[0] = new OpApplNode(OP_seq, ssops, children[3 + 2 * excSpecIx], cm);

			// Process the RHS of the ExceptionSpec

			// Create exceptSpec node now, so that it can be available in
			// case the RHS expression of this ExceptSpec contains an @
			excSpecNode = new OpApplNode(OP_pair, sops, children[3 + 2 * excSpecIx], cm);

			// Push the except node and the except spec node on stacks so
			// that the RHS of the ExceptSpec, which might contain an @, can
			// be evaluated in their "context".
			excSpecStack.push(excSpecNode);
			excStack.push(excNode);

			// Generate the expression constituting the RHS of the
			// ExceptionSpec allow @ in the context of this expression.
			sops[1] = generateExpression(syntaxTreeNode[syntaxTreeNode.length - 1], cm);

			// Pop them back off
			excSpecStack.pop();
			excStack.pop();

			// Store excSpecNode as another operand of $Except
			operands[excSpecIx + 1] = excSpecNode;
		} // end for (each ExceptionSpec)

		return excNode;
	} // end processExcept()

	/**
	 * This method generates an expression tree or an OpArgNode as an argument to an
	 * OpApplNode
	 * 
	 * mainOp is the operator under that node mainSTN is the "parent" OpApplNode,
	 * used in case an error message must be generated argPosition is the argument
	 * position (counting from 0) that treeNode represents argRoot is the argument
	 * syntax tree that either becomes an ExprNode or an OpArgNode mn is the module
	 * these expressions are part of
	 */
	private ExprOrOpArgNode generateExprOrOpArg(SymbolNode mainOp, TreeNode mainSTN, int argPosition, TreeNode argRoot,
			ModuleNode mn) throws AbortException {
		SymbolNode argOp = null;
		// the SymbolNode that heads the argRoot expression
		int argArity;
		// number of actual arguments under argRoot
		int arityExpected;
		// arity that mainOp expects of argument number <argPosition>

		if (mainOp == null) {
			errors.addError(mainSTN.getLocation(), "Unable to generate expression or operator argument; "
					+ "this is probably because of previously reported errors.");
			return nullOAN;
		}

		// Are we sure the "operator" is not a ModuleNode?
		if (mainOp instanceof ModuleNode) {
			errors.addError(mainSTN.getLocation(), "Module name '" + mainOp.getName() + "' used as operator.");
			return nullOAN;
		}

		// Are there too many arguments to mainOp?
		if (argPosition + 1 > mainOp.getArity()) {
			errors.addError(mainSTN.getLocation(), "Too many arguments for operator '" + mainOp.getName()
					+ "'.  There should be only " + mainOp.getArity() + ".");

			return nullOAN;
		}

		// For user-defined mainOp check the FormalParamNodes array
		// associated with the mainOp to find out whether it expects an
		// operator argument or an ordinary expression argument in
		// position number argPosition. (Only UserDefined ops can have
		// other multi-arg ops passed to them as params, so we can just
		// assign arityExpected = 0 in other cases.)
		/***********************************************************************
		 * In SANY2, mainOp can also be a ModuleInstanceKind, so the if test * was
		 * modified appropriately. *
		 ***********************************************************************/
		if ((mainOp.getKind() == UserDefinedOpKind) || (mainOp.getKind() == ModuleInstanceKind)) {
			final OpDefNode opDefNode = (OpDefNode) mainOp;
			FormalParamNode[] params = opDefNode.getParams();
			
			// MAK 07/2021: Added this check to prevent an ArrayIndexOutOfBoundsException
			// that occurs if a RECURSIVE operator declaration has more arguments (higher
			// arity) than its definition:
			//
			//  RECURSIVE ReachableFrom(_,_)                    \* 2-arity!
            //  ReachableFrom(S) == LET R == SetNbrs(S)
            //                      IN  IF R \subseteq S THEN S
            //                          ELSE ReachableFrom(R \cup S)
            //
			// This check expects that code elsewhere (in case of RECURSIVE e.g.
			// processOperator(..)) has already produced a corresponding error message,
			// such as "Definition of ReachableFrom has different arity than its RECURSIVE
			// declaration."
			if (params.length <= argPosition) {
				return nullOAN;
			}
			arityExpected = ((OpDefNode) mainOp).getParams()[argPosition].getArity();
		} else {
			arityExpected = 0;
		}
		;

		// if mainOp expects zero arguments, then it expects an ordinary
		// expression arg in this position, so generate an expression.
		// Any errors will be found in the generateExpression method.
		if (arityExpected == 0) {
			return generateExpression(argRoot, mn);
		} else {
			// otherwise, we are expecting an OpArg or Lambda
			/*********************************************************************
			 * The following test was originally * * if
			 * (argRoot.getImage().equals("N_OpApplication")) * * However, that was not
			 * sufficient, because there are lots of other * nodes that represent
			 * expressions. At best, these caused weird * error messages. At worst, as in
			 * the case of a number or string, * they caused an array out of bounds
			 * exception when generateGenID * was called a few lines later. I hope that the
			 * following test * covers all the cases in which this should be called with
			 * argRoot * not an expression. * * Change made by LL on 9 May 2007. *
			 *********************************************************************/
			if (!(argRoot.getImage().equals("N_GeneralId") || argRoot.getImage().equals("N_GenInfixOp")
					|| argRoot.getImage().equals("N_GenNonExpPrefixOp") || argRoot.getImage().equals("N_GenPostfixOp")
					|| argRoot.getImage().equals("N_GenPrefixOp") || argRoot.getImage().equals("N_Lambda"))) {
				errors.addError(argRoot.getLocation(),
						"An expression appears as argument number " + (argPosition + 1)
								+ " (counting from 1) to operator '" + mainOp.getName()
								+ "', in a position an operator is required.");
				return nullOAN;
			} // end if

			if (argRoot.getKind() == N_Lambda) {
				/*******************************************************************
				 * The argument is a lambda expression. *
				 *******************************************************************/
				argOp = generateLambda(argRoot, mn);
				if (arityExpected == argOp.getArity()) {
					return new OpArgNode(argOp, argRoot, mn);
				} // if
				else {
					errors.addError(mainSTN.getLocation(),
							"Lambda expression with arity " + argOp.getArity() + " used as argument "
									+ (argPosition + 1) + " of operator `" + mainOp.getName()
									+ "', \nbut an operator of arity " + arityExpected + " is required.");
					return nullOpArg;
				} // else
			} // if (argRoot.kind == N_Lambda)
			else {
				/*******************************************************************
				 * The argument is not a lambda expression. *
				 *******************************************************************/

				/*******************************************************************
				 * If the argument is a GeneralId node, then we use * genIdToSelector and
				 * selectorToNode to generate the OpArg node. *
				 *******************************************************************/
				if (argRoot.getKind() == N_GeneralId) {
					return (ExprOrOpArgNode) selectorToNode(genIdToSelector((SyntaxTreeNode) argRoot), arityExpected,
							false, false, mn);
				}
				;

				/*******************************************************************
				 * If the argument is not a GeneralId node, we use the code from * SANY1 to
				 * generate the OpArg node. *
				 *******************************************************************/
				GenID genID = generateGenID(argRoot, mn);
				argOp = genID.getFullyQualifiedOp();
				;

				// If the symbol has not been defined, then indicate an error and
				// return a nullOAN, allowing semantic analysis to continue
				if (argOp == null)
					return nullOAN;

				argArity = argOp.getArity();
				if (arityExpected == argArity && genID.getArgs().length == 0) {
					return new OpArgNode(genID.getFullyQualifiedOp(), argRoot, mn);
				} else if (genID.getArgs().length > 0) {
					// expression (with or without correct number of args) being
					// used where operator should be
					errors.addError(mainSTN.getLocation(),
							"Expression used in argument position " + (argPosition + 1)
									+ " (counting from 1) of operator `" + mainOp.getName()
									+ "', whereas an operator of arity " + arityExpected + " is required.");
					return nullOpArg;
				} else {
					// operator of the wrong arity is being passed as argument
					errors.addError(mainSTN.getLocation(),
							"Operator with incorrect arity passed as argument. " + "\nOperator '" + argOp.getName()
									+ "' of arity " + argArity + " is argument number " + (argPosition + 1)
									+ " (counting from 1) to operator `" + mainOp + "', \nbut an operator of arity "
									+ arityExpected + " was expected.");
					return nullOpArg;
				}
			} // else of non-Lambda expression case
		} // end else of if (arityExpected == 0)
	} // end generateExprOrOpArgOrLambda

	/**
	 * Process the General ID syntax tree, i.e. the part that contains an expression
	 * of the form A(x,y)!B!C(u,v,w)!D (with no params to D) and represents an
	 * operator. A General ID occurs in the syntax in only a few places: as an
	 * operator in an operator application; as an operator used as an operand to
	 * another operator, and as an operator being substituted for a suitable
	 * constant in module instantiation.
	 *
	 * Returns a GenID object, which must be further processed.
	 */
	private GenID generateGenID(TreeNode syntaxTreeNode, ModuleNode mn) throws AbortException {
		return generateGenID(syntaxTreeNode, mn, false);
	}

	/*************************************************************************
	 * It appears that this is called with unaryNegKludge = true only when *
	 * processing a prefix operator. *
	 *************************************************************************/
	private GenID generateGenID(TreeNode syntaxTreeNode, ModuleNode mn, boolean unaryNegKludge) throws AbortException {
		GenID genID; // Holds components of the generalized ID for this operator
		TreeNode[] children = syntaxTreeNode.heirs(); // To contain N_IdPrefix node and the main operator
		TreeNode[] prefix = null; // Contains array of prefix elements
									// This is the array of N_IdPrefixElements for the operator,
									// i.e. A!B(3)!C has 2 N_IdPrefixElements, A and B(3).
		TreeNode[] prefixElt; // a prefixElement; 2- or 3-elem array: [op, (args), "!"]
		TreeNode[] allArgs = null; // to collect arg arrays from prefix
		TreeNode[] argsList = null; // Will hold an arg list tree

		if (children == null || children.length <= 0) {
			// almost certainly an @ used outside of EXCEPT, which is detected elsewhere
			return null;
		}

		prefix = children[0].heirs();

		// Allocate object to hold the Generized ID that is part of this OpAppl
		genID = new GenID(syntaxTreeNode);

		// Number of elements in the prefix
		int len = prefix.length;

		// Allocate array of SyntaxTreeNodes, one for each prefix element
		allArgs = new SyntaxTreeNode[len];

		// Process all of the prefix elements; construct the compound
		// identifier (with embedded !-characters), and also accumulate an
		// array of argument arrays (allArgs) for each prefix element
		for (int i = 0; i < len; i++) {
			// prefixElt becomes a 2- or 3-element array containing
			// [operator, args (optional), and "!"]
			prefixElt = prefix[i].heirs();

			// Append the next part of compound identifier name and a "!"
			genID.append(prefixElt[0].getImage());
			genID.append("!");

			// allArgs[i] = array of arg syntax trees for next prefix
			// element (if any) or "!" (if not)
			allArgs[i] = prefixElt[1]; // Note: whether this is args or a "!" is checked below
		}

		// Append the primary (rightmost) operator name to compoundID;
		// calling "finalAppend" signals that the appending is finished,
		// i.e. that the string can be converted to a UniqueString and to
		// a SymbolNode inside the genID object
		genID.finalAppend(children[1].getImage(), unaryNegKludge);

		// for each argument in each potential argument list in the prefix,
		// generate the expression or opArg corresponding to it

		// for each argument list in prefix
		int iarg = 0;
		for (int i = 0; i < allArgs.length; i++) {
			// if there is an actual arg list here (instead of a "!" or null)
			if (allArgs[i] != null && allArgs[i].isKind(N_OpArgs)) {
				// pick up array of arg list syntax elements
				argsList = allArgs[i].heirs();

				// The odd numbered syntax elements are the args expressions;
				// the even numbered ones are parens and commas.
				for (int ia = 1; ia < argsList.length; ia += 2) {
					// Each arg may be an ordinary expression, or it may be an OpArg;
					// produce appropriate semantic tree or node for it.
					// Note that operators can be used in place of expressions in only two contexts:
					// as argument to suitable user-defined ops, and in the RHS of a substitution
					// in module instantiation
					genID.addArg(
							generateExprOrOpArg(genID.getFullyQualifiedOp(), syntaxTreeNode, iarg, argsList[ia], mn));
					iarg++;
				}
			}
		}

		// "finalize the GenID object (i.e. convert argument vector to array)
		genID.finalizeID();
		return genID;
	}

	/*************************************************************************
	 * Added by LL on 27 March 2007. * * A lambda expression is represented as an
	 * OpDefNode. Since it is * always used only as an operator argument, this
	 * OpDefNode will appear * in an OpArgNode. *
	 *************************************************************************/
	private final OpDefNode generateLambda(TreeNode syntaxTreeNode, ModuleNode cm) throws AbortException {
		TreeNode[] children = syntaxTreeNode.heirs();
		int arity = (children.length - 2) / 2;
		/*********************************************************************
		 * children = <<"LAMBDA", arg_1, ",", ... , "," , arg_arity, ":", * body>> * so
		 * children.length = 3 + arity + arity-1 * so arity = (children.length - 2) / 2.
		 * *
		 *********************************************************************/
		Context ctxt = new Context(moduleTable, errors);
		symbolTable.pushContext(ctxt);
		/*********************************************************************
		 * The context ctxt will hold the parameters of the lambda * expression, which
		 * may appear in its body. *
		 *********************************************************************/
		FormalParamNode[] params = new FormalParamNode[arity];
		int argPos = 1;
		/*********************************************************************
		 * children[argPos] is the next parameter's identifier node. *
		 *********************************************************************/
		for (int i = 0; i < arity; i++) {
			/*********************************************************************
			 * Set params[i] to the FormalParamNode for the i-th formal * parameter. *
			 *********************************************************************/
			params[i] = new FormalParamNode(children[argPos].getUS(), 0, // parameters of a lambda expression
																			// have arity 0.
					children[argPos], symbolTable, cm);
			argPos = argPos + 2;
		} // for

//    /***********************************************************************
//    * Convert the FormalParamNode array params to the OpDeclNode array     *
//    * odn.                                                                 *
//    ***********************************************************************/
//    OpDeclNode[] odn = new OpDeclNode[params.length] ;
//    for (int i = 0; i < params.length; i++) {
//      odn[i] = new OpDeclNode(params[i].getName(),
//                              BoundSymbolKind,
//                              ConstantLevel,
//                              params.length,  // arity
//                              cm,             // ModuleNode                     
//                              null,           // SymbolTable
//                              params[i].stn); // TreeNode
//      }; // for
		pushFormalParams(params);
		/*******************************************************************
		 * Push formal parameters on Last(LS).paramSeq for processing the * body
		 *******************************************************************/
		ExprNode body = generateExpression(children[children.length - 1], cm);
		/*********************************************************************
		 * Generate the lambda expression's body. *
		 *********************************************************************/
		popFormalParams();

		symbolTable.popContext();
		/*********************************************************************
		 * Restore original context. *
		 *********************************************************************/
		return new OpDefNode(S_lambda, // The operator name is "LAMBDA"
				UserDefinedOpKind, // The node kind for a lambda expression
				params, // the array of formal parameters
				false, // localness, which is meaningless
				body, // the body (an expression node)
				cm, // the module
				null, // the symbol table, which is null for an
						// OpDefNode representing a lambda expression.
				syntaxTreeNode, true, // Is defined. Its value should not matter.
				null); // Source
	} // generateLambda

	/**
	 * Generates an OpApplNode or an OpArgNode for a SyntaxTreeNode, according to
	 * whether the value of "typeExpected" is either opAppl or opArg.
	 */
	private final ExprNode generateOpAppl(TreeNode syntaxTreeNode, ModuleNode cm) throws AbortException {
		TreeNode primaryArgs = null;
		// points to syntax tree of primary arg list (if any); otherwise null
		boolean isOpApp = syntaxTreeNode.isKind(N_OpApplication);
		// true ==> to indicate this is an OpAppl; must have primary args
		// false ==> operator used as an argument (OpArg); has no primary args
		int primaryArgCount = 0;
		// total # of arguments, including those of prefix, if any
		int len;
		// number of prefix elements
		TreeNode[] children = syntaxTreeNode.heirs();
		// temp used for finding the prefix
		TreeNode[] prefix;
		// array of prefix elements
		TreeNode[] allArgs = null;
		// to collect arg arrays from both prefix and the main op (if any)
		TreeNode[] prefixElt;
		// a prefixElement; 2 or 3 elem array: [op, (args), "!"]
		UniqueString symbol;
		// UniqueString name of the fully-qualified operator
		SymbolNode fullOperator;
		// The SymbolNode for the fully-qualified operator
		int iarg = 0;
		// loop counter for actual args (as opposed to
		// arg syntax elements like commas and parens)
		TreeNode[] argsList = null;
		// Will hold an array of arg syntax trees for primary operator
		ExprOrOpArgNode[] args = null;
		// Will hold an array of arg semantic trees for primary operator

		// Process the Generized ID that is the operator for this OpAppl
		GenID genID = generateGenID(children[0], cm);

		// Set up pointers to OpAppl's primary args
		primaryArgs = children[1];
		// Array of argument list syntax elements for the main
		// (rightmost) operator, including parens and commas;
		// should be an N_OpArgs node

		// calc number of primary args;
		// args are interspersed w/ parens & commas--hence the /2
		primaryArgCount = primaryArgs.heirs().length / 2;

		if (genID == null || genID.getFullyQualifiedOp() == null) {
			// if operator is @ or an unresolved symbol; error has already
			// been generated inside genID
			return nullOAN;
		}

		args = new ExprOrOpArgNode[primaryArgCount];
		// Array to hold semantic trees for primary args

		// pick up array of arg list syntax elements
		argsList = primaryArgs.heirs();

		// The odd numbered syntax elements are the args expressions; the
		// even numbered ones are parens and commas.
		// for each arg in this arg list ...
		for (int ia = 1; ia < argsList.length; ia += 2) {
			// Each arg may be an ordinary expression, or it may be an OpArg;
			// produce appropriate semantic tree or node for it.
			// Note that operators can be used in place of expressions
			// in only two contexts:
			// as argument to suitable user-defined ops, and in the RHS
			// of a substitution in module instantiation
			args[iarg] = generateExprOrOpArg(genID.getFullyQualifiedOp(), syntaxTreeNode, iarg, argsList[ia], cm);
			iarg++; // count the actual args
		} // end for

		// Concatenate the list of args in the GenID object to the
		// primary arg list just created
		Vector genIDArgList = genID.getArgsVector();
		ExprOrOpArgNode[] finalArgList = new ExprOrOpArgNode[genIDArgList.size() + iarg];

		// Copy the args from the prefix
		for (int i = 0; i < genIDArgList.size(); i++) {
			finalArgList[i] = (ExprOrOpArgNode) (genIDArgList.elementAt(i));
		}
		// Copy the primary args
		for (int i = 0, j = genIDArgList.size(); i < iarg; i++, j++) {
			finalArgList[j] = args[i];
		}

		// return an OpApplNode constructed from the fully-qualified
		// operator and the final arg list
		return new OpApplNode(genID.getFullyQualifiedOp(), finalArgList, syntaxTreeNode, cm);
	} // end generateOpAppl()

	/**
	 * Process a named, parameterixed instantiation, e.g. of the form D(p1,...pn) =
	 * INSTANCE M WITH a1 <- e1 ,..., ar <- er
	 */
	/*************************************************************************
	 * Note: the returned value does not seem to be used. *
	 *************************************************************************/
	private final OpDefNode processModuleDefinition(TreeNode treeNode, Vector defs,
			/*******************************************************
			 * This is non-null when called from inside a LET, in * which case the OpDef
			 * node is appended to defs. If * null, the OpDef node is appended to the *
			 * module-level lists of such nodes. *
			 *******************************************************/
			Vector insts,
			/*******************************************************
			 * If non-null, then a vector of InstanceNode objects * to which the current
			 * instance node is to be * appended. If null, cm.appendInstance is called to *
			 * put the InstanceNode onto the module-level lists of * such nodes. *
			 *******************************************************/
			ModuleNode cm) throws AbortException {
		// Start with a LHS for an instance: we must extract from it name
		// and possibly parameters. Then we need the external Context of
		// the module and to extract all non-local, non-builtin
		// symbols. Then build the proper symbol list and add it.

		// We must remember to identify explicitly whether or not the new
		// nodes would be local.

		// assert treeNode.isKind(N_ModuleDefinition)
		//
		// Note that this code does nothing about THEOREMS and ASSUMES in
		// modules being instantiated
		boolean localness = treeNode.zero() != null;
		TreeNode[] children = treeNode.one()[0].heirs(); // heirs of IdentLHS
		UniqueString name = children[0].getUS();

		// processing of LHS of the definition, i.e. the name and parameters
		FormalParamNode[] args = nullParam;
		Context parmCtxt = null;

		// If the operator being defined as a module instance has any parameters
		if (children.length > 1) {
			// Create new array of FormalParamNodes for the new operator
			args = new FormalParamNode[children.length / 2 - 1];

			// Push a new context in current module's SymbolTable
			parmCtxt = new Context(moduleTable, errors);
			symbolTable.pushContext(parmCtxt);

			// For each formal parameter declared for the op being defined
			for (int i = 0; i < args.length; i++) {
				TreeNode child = children[2 + 2 * i];
				UniqueString id = null;
				int count = 0;

				if (child.isKind(N_IdentDecl)) {
					id = child.heirs()[0].getUS();
					count = (child.heirs().length - 1) / 2;
				} else if (child.isKind(N_InfixDecl)) {
					id = child.heirs()[1].getUS();
					count = 2;
				} else if (child.isKind(N_PrefixDecl)) {
					id = child.heirs()[0].getUS();
					count = 1;
				} else if (child.isKind(N_PostfixDecl)) {
					id = child.heirs()[1].getUS();
					count = 1;
				} else {
					errors.addAbort(treeNode.getLocation(),
							"Internal error: Error in formal params part of parse tree.", true);
				}

				// If there was no error
				if (id != null) {
					// Create a new FormalParamNode for the defined Op and put
					// it in the SymbolTable
					args[i] = new FormalParamNode(id, count, child, symbolTable, cm);
				} // end if
			} // end for
		} // end if

		// processing RHS of the definition, starting with identification
		// of module being instantiated, followed by processing of the
		// WITH clause (if any)
		children = treeNode.one()[2].heirs(); // heirs of NonLocalInstance

		// Find the Context and ModuleNode for the module being instantiated
		Context instanceeCtxt = this.getContext(children[1].getUS());
		ModuleNode instanceeModule = symbolTable.resolveModule(children[1].getUS());

		if (instanceeCtxt == null) {
			errors.addError(children[1].getLocation(),
					"Module " + children[1].getImage() + " does not have a context.");
			return nullODN;
		}

		if (instanceeModule == null) {
			errors.addError(children[1].getLocation(),
					"Module name " + children[1].getImage() + " is not known" + " in current context.");
			return nullODN;
		}

		/*
		 * Set isInstantiated field of instancee. Added by LL 23 July 2013
		 */
		instanceeModule.setInstantiated(true);

		// Create a SubstInNode that will be used to wrap each definition
		// body in the module being defined. "children" is the array of
		// explicit substitution clauses used in the module definition.
		// Both instanceeCtxt and symbolTable are involved here since for
		// each substitution c <- e, c must be resolved in the
		// instanceeCtxt, and e must be interpreted in symbolTable
		SubstInNode substIn = processSubst(treeNode, children, symbolTable, instanceeCtxt, instanceeModule, cm);

		// We are done with the local context (if one was created because
		// of parameters)
		if (parmCtxt != null)
			symbolTable.popContext();

		// Create a vector of all of the OpDefNodes in the instancee module
		/***********************************************************************
		 * I have no idea why the module's getOpDefs method isn't used here. *
		 ***********************************************************************/
		Vector elts = instanceeCtxt.getByClass(OpDefNode.class);

		// For each definition in the instancee module, create a
		// corresponding definition in the instancer module
		for (int i = 0; i < elts.size(); i++) {
			// Find the OpDefNode to be instantiated
			OpDefNode odn = (OpDefNode) elts.elementAt(i);

			/**********************************************************************
			 * Ignore it if it is local or a builtin def. *
			 **********************************************************************/
			if (!odn.isLocal() && ((odn.getKind() == UserDefinedOpKind) || (odn.getKind() == ModuleInstanceKind))) {
				// Create the new name prepended with "name!"
				String compoundID = name + "!" + odn.getName();
				UniqueString qualifiedName = UniqueString.uniqueStringOf(compoundID);

				// Copy parameters for the op being defined
				FormalParamNode[] fpn = odn.getParams();
				FormalParamNode[] params = new FormalParamNode[fpn.length + args.length];
				System.arraycopy(args, 0, params, 0, args.length);
				System.arraycopy(fpn, 0, params, args.length, fpn.length);

				OpDefNode newOdn;
				if (odn.getKind() == UserDefinedOpKind) {
					if (substIn.getSubsts().length > 0) {
						// If there are substitutions, then the body of the new
						// definition instance must be wrapped in a SUBST-IN node.
						// Create the "wrapping" SubstInNode as a clone of "subst"
						// above, but with a body from the OpDefNode in the module
						// being instantiated
						SubstInNode substInNode = new SubstInNode(treeNode, substIn.getSubsts(), odn.getBody(), cm,
								instanceeModule);

						// MAK 02/2021: Store the individual segments of the compound id to not rely on
						// ad-hoc parsing later when a feature such as the debugger needs to know each
						// segment.
						// A!B!C!OP -> {A,B,C,OP}
						final UniqueString[] cID = Stream.of(new UniqueString[] { name }, odn.getCompoundId())
								.flatMap(Stream::of).toArray(UniqueString[]::new);

						// Create the OpDefNode for the new instance of this
						// definition; because of the new operator name, cm is the
						// module of origin for purposes of deciding of two defs are
						// "the same" or "different"
						newOdn = new OpDefNode(qualifiedName, UserDefinedOpKind, params, localness, substInNode, cm,
								symbolTable, treeNode, true, odn.getSource(), cID);
						setOpDefNodeRecursionFields(newOdn, cm);
						newOdn.setLabels(odn.getLabelsHT());
					} // if (substIn.getSubsts().length > 0)
					else {
						// no SUBST-IN node required; but because of the new
						// operator name, cm is the module of origin for purposes of
						// deciding of two defs are "the same" or "different"
						newOdn = new OpDefNode(qualifiedName, UserDefinedOpKind, params, localness, odn.getBody(), cm,
								symbolTable, treeNode, true, odn.getSource());
						setOpDefNodeRecursionFields(newOdn, cm);
						newOdn.setLabels(odn.getLabelsHT());
					} // else
				} // if (odn.kind == UserDefinedOpKind)
				else {
					/*****************************************************************
					 * This is a ModuleInstanceKind node. *
					 *****************************************************************/
					newOdn = new OpDefNode(qualifiedName, params, localness, odn.getOriginallyDefinedInModuleNode(),
							symbolTable, treeNode, odn.getSource());
				}
				; // else
				// defs is non-null iff this module definition is in the Let
				// part of a Let-In expression. Add this newly created OpDef
				// to either the LET list or the module cm's definition list.
				if (defs == null) {
					cm.appendDef(newOdn);
				} else {
					defs.addElement(newOdn);
				}
			} // if (!odn.isLocal()&& ... )
		} // for

		/**********************************************************************
		 * Import the ThmOrAssumpDefNode objects to the current module. The * following
		 * code for doing this was copied and modified without * much thinking from the
		 * code above for OpDefNode objects *
		 **********************************************************************/
		// Create a vector of all of the ThmOrAssumpDefNodes in the
		// instancee module
		Vector taelts = instanceeCtxt.getByClass(ThmOrAssumpDefNode.class);

		// For each definition in the instancee module, create a
		// corresponding definition in the instancer module
		for (int i = 0; i < taelts.size(); i++) {
			// Find the ThmOrAssumpDefNode to be instantiated
			ThmOrAssumpDefNode taOdn = (ThmOrAssumpDefNode) taelts.elementAt(i);

			/*********************************************************************
			 * There are no builtin ThmOrAssumpDefNode objects. *
			 *********************************************************************/
			// Ignore it if it is local
			if (!taOdn.isLocal()) {
				// Create the new name prepended with "name!"
				String compoundID = name + "!" + taOdn.getName();
				UniqueString qualifiedName = UniqueString.uniqueStringOf(compoundID);

				// Copy parameters for the op being defined
				/*******************************************************************
				 * Theorem or assumption definitions have no parameters. *
				 *******************************************************************/
				FormalParamNode[] fpn = taOdn.getParams();
				FormalParamNode[] params = new FormalParamNode[fpn.length + args.length];
				System.arraycopy(args, 0, params, 0, args.length);
				System.arraycopy(fpn, 0, params, args.length, fpn.length);

				ThmOrAssumpDefNode newtaOdn;
				if (substIn.getSubsts().length > 0) {
					// If there are substitutions, then the body of the new
					// definition instance must be wrapped in a SUBST-IN node.
					// Create the "wrapping" SubstInNode as a clone of "subst"
					// above, but with a body from the ThmOrAssumpDefNode in the module
					// being instantiated
					APSubstInNode substInNode = new APSubstInNode(treeNode, substIn.getSubsts(), taOdn.getBody(), cm,
							instanceeModule);

					// Create the ThmOrAssumpDefNode for the new instance of this
					// definition; because of the new operator name, cm is the
					// module of origin for purposes of deciding of two defs are
					// "the same" or "different"
					newtaOdn = new ThmOrAssumpDefNode(qualifiedName, taOdn.isTheorem(), substInNode, cm, symbolTable,
							treeNode, params, instanceeModule, taOdn.getSource());
					// Following statement added by LL on 30 Oct 2012 to handle locally
					// instantiated theorems and assumptions. Added setLabels call
					// on 31 Oct 2012.
					newtaOdn.setLocal(localness);
					newtaOdn.setLabels(taOdn.getLabelsHT());

					/*****************************************************************
					 * No recursion fields needed for a theorem or assumption * because it can't
					 * appear in a recursive section. *
					 *****************************************************************/
					// setThmOrAssumpDefNodeRecursionFields(newtaOdn, cm) ;
				} else {
					// no SUBST-IN node required; but because of the new
					// operator name, cm is the module of origin for purposes of
					// deciding if two defs are "the same" or "different"
					newtaOdn = new ThmOrAssumpDefNode(qualifiedName, taOdn.isTheorem(), taOdn.getBody(), cm,
							symbolTable, treeNode, params, instanceeModule, taOdn.getSource());
					// Following statement added by LL on 30 Oct 2012 to handle locally
					// instantiated theorems and assumptions. Added setLabels call
					// on 31 Oct 2012.
					newtaOdn.setLocal(localness);
					newtaOdn.setLabels(taOdn.getLabelsHT());
					/*****************************************************************
					 * No recursion fields needed for theorems or assumptions * because they can't
					 * appear in a recursive section. *
					 *****************************************************************/
					// setThmOrAssumpDefNodeRecursionFields(newtaOdn, cm) ;
				}

				// defs is non-null iff this module definition is in the Let
				// part of a Let-In expression. Add this newly created ThmOrAssumpDef
				// to either the LET list or the module cm's definition list.
				if (defs == null) {
					cm.appendDef(newtaOdn);
				} else {
					defs.addElement(newtaOdn);
				}
			} // if (!taOdn.isLocal()&& ... )
		} // for

		// Create a new InstanceNode to represent this INSTANCE stmt
		// in the current module
		InstanceNode inst = new InstanceNode(name, localness, args, instanceeModule, substIn.getSubsts(), treeNode);

		// Append this new InstanceNode to the vector of InstanceNodes
		// being accumulated for this module
		if (insts == null) {
			cm.appendInstance(inst);
		} else {
			insts.addElement(inst);
		}

		// Create new OpDefNode with ModuleInstanceKind. The reason for
		// doing this is to get the name in the symbol table so the name
		// cannot be re-used later in this module for a user-defined
		// operator.
		return new OpDefNode(name, args, localness, cm, symbolTable, treeNode, null);
		/*********************************************************************
		 * Note: the module's OpDefNode does not have recursive parameters * set. If the
		 * module definition statement occurs in a recursive * section, then it is the
		 * instantiated definitions that are * recursive, not the module definition
		 * itself. (The name under * which the module is instantiated cannot appear in a
		 * RECURSIVE * statement.) *
		 *********************************************************************/

	} // end processModuleDefinition()

	/**
	 * From a particular explicit substitution (substTarget <- substValue) check the
	 * legality of the substTarget, and if OK, generate the appropriate type of node
	 * for substValue
	 */
	private ExprOrOpArgNode generateSubst(Context instanceeCtxt, TreeNode substTarget, TreeNode substValue,
			ModuleNode mn) throws AbortException {
		SymbolNode targetSymbol = instanceeCtxt.getSymbol(substTarget.getUS());

		// if the targetSymbol cannot be found in the instancee context,
		// or if it does not correspond to a declaration, then it is an
		// illegal substitution target

		if (targetSymbol == null || !(targetSymbol instanceof OpDeclNode)) {
			errors.addError(substTarget.getLocation(), "Identifier '" + substTarget.getUS() + "' is not a legal"
					+ " target of a substitution. \nA legal target must be a declared"
					+ " CONSTANT or VARIABLE in the module being instantiated."
					+ " \n(Also, check for warnings about multiple declarations of" + " this same identifier.)");
			return nullOAN;
		}

		// but if the symbol is found, then if it has arity 0, the RHS
		// should be an expression, if arity > 0, the the RHS should be an OpArg
		ExprOrOpArgNode returnObject;

		if (targetSymbol.getArity() == 0) {
			// if the target of the substitution has arity 0,
			// then we expect an expression to be substituted for it
			returnObject = generateExpression(substValue, mn);
		} else {
			// if the target of the substitution has arity > 0,
			// then and operator must be substituted for it
			returnObject = generateOpArg(targetSymbol, substValue, mn);

			// and it better have the same arity as the target
			if (((OpArgNode) returnObject).getArity() != targetSymbol.getArity()) {
				errors.addError(substValue.getLocation(), "An operator must be substituted for symbol '"
						+ targetSymbol.getName() + "', and it must have arity " + targetSymbol.getArity() + ".");
			}
		}
		return returnObject;
	} // end generateSubst()

	/**
	 * Return an OpArgNode constructed from a GeneralId tree to be used in the RHS
	 * of a substitution
	 */
	private OpArgNode generateOpArg(SymbolNode targetSymbol, TreeNode opArgSyntaxNode, ModuleNode mn)
			throws AbortException {
		/***********************************************************************
		 * If this is a lambda expressiion, then just get it and go. *
		 ***********************************************************************/
		if (opArgSyntaxNode.isKind(N_Lambda)) {
			return new OpArgNode(generateLambda(opArgSyntaxNode, mn), opArgSyntaxNode, mn);
		}
		;
		// First, make sure that an operator ID is present, and not an expression
		if (!(opArgSyntaxNode.isKind(N_GeneralId) || opArgSyntaxNode.isKind(N_GenInfixOp)
				|| opArgSyntaxNode.isKind(N_GenPrefixOp) || opArgSyntaxNode.isKind(N_GenNonExpPrefixOp) ||
				/************************************************************
				 * This last disjunct was added by LL on 9 May 2007. * * The original parser
				 * phase produced an N_GenPrefixOp * here, but an N_GenNonExpPrefixOp for the
				 * syntactically * identical situation in an operator argument. The new * TLA+2
				 * parser produces N_GenNonExpPrefixOp nodes here, * but I left the
				 * N_GenPrefixOp case in here just in case * this is called somewhere else that
				 * I haven't found. *
				 ************************************************************/

				opArgSyntaxNode.isKind(N_GenPostfixOp))) {
			errors.addError(opArgSyntaxNode.getLocation(),
					"Arity " + targetSymbol.getArity() + " operator (not an expression) is expected"
							+ " \nto substitute for CONSTANT '" + targetSymbol.getName() + "'.");
			return nullOpArg;
		}

		/***********************************************************************
		 * If the argument is a GeneralId node, then we use * genIdToSelector and
		 * selectorToNode to generate the OpArg node. *
		 ***********************************************************************/
		if (opArgSyntaxNode.getKind() == N_GeneralId) {
			/*********************************************************************
			 * First, a sanity check to make sure we're never looking for an * expression
			 * argument. *
			 *********************************************************************/
			if (targetSymbol.getArity() <= 0) {
				errors.addAbort(opArgSyntaxNode.getLocation(), "Internal error: expected to find arity > 0.", true);
			}
			;

			LevelNode ln = selectorToNode(genIdToSelector((SyntaxTreeNode) opArgSyntaxNode), targetSymbol.getArity(),
					false, false, mn);

			/*******************************************************************
			 * Added 23 February 2009: It appears that, in case of an error, *
			 * selectorToNode can return something other than an OpArgNode * here. (In
			 * particular, an OpApplNode.) Rather than tix * selectorToNode, I am adding a
			 * kludge to simply ignore the * problem and hope that it can be caused only by
			 * some other * error. If no error has been found, then we abort and debug if *
			 * this is encountered. *
			 *******************************************************************/
			if (!(ln instanceof OpArgNode)) {
				if (errors.getNumErrors() > 0) {
					return nullOpArg;
				}
				errors.addAbort(opArgSyntaxNode.getLocation(),
						"Internal error: " + "Expected an operator argument but " + "found something else.");
			}
			;
			return (OpArgNode) ln;
		}
		;

		/*******************************************************************
		 * If the argument is not a GeneralId node, we use the code from * SANY1 to
		 * generate the OpArg node. *
		 *******************************************************************/

		// Assemble the (possibly compound) generalized identifier, and resolve it.
		GenID genID = generateGenID(opArgSyntaxNode, mn);

		// If the fully-qualified op is undefined, then a message has already been
		// put in errors, but we must insert a nullOpArgNode in the tree.
		if (genID.getFullyQualifiedOp() != null && genID.getArgs().length == 0) {
			// Create an OpArgNode from it.
			return new OpArgNode(genID.getFullyQualifiedOp(), opArgSyntaxNode, mn);
		} else if (genID.getArgs().length > 0) {
			// Expression being used where Operator is required
			errors.addError(opArgSyntaxNode.getLocation(),
					"Arity " + targetSymbol.getArity() + " operator (not an expression) is expected"
							+ " to substitute for CONSTANT '" + targetSymbol.getName() + "'.");
			return nullOpArg;
		} else {
			return nullOpArg;
		}
	} // end generateOpArg()

	/**
	 * Process the substitutions clause of a module definition or instantiation;
	 * returns a SubstInNode that can be used as a template for the wrapper that
	 * must be present around each OpDefNode body created from the module
	 * instantiation or module definition.
	 */
	private SubstInNode processSubst(TreeNode treeNode, TreeNode[] substNodes,
			// array of subst nodes [c1 <- e1, ... ,cn <- en]
			SymbolTable instancerST,
			// SymbolTable in which the ei must be resolved
			Context instanceeCtxt,
			// Context in which the ci must be resolved
			ModuleNode instanceeModule,
			// the ModuleNode of the module in which ci must be resolved
			ModuleNode mn) throws AbortException {
		TreeNode[] children; // find the substitution part of the syntax tree

		// Create a vector of all declarations of CONSTANTS and VARIABLES
		// in the context of the module being instantiated (instancee).
		// These are all the symbols that must have substitutions defined
		// for them in the instantiation, either explictly or implicitly.
		Vector decls = instanceeCtxt.getByClass(OpDeclNode.class);

		// Create a SubstInNode to be used as a template for the SubstInNodes
		// in the body of every newly instantiated OpDef in the module.
		// The substitutions in the returned SubstInNode object will be the
		// implicit substitutions of the form c<-c for all CONSTANTS and
		// VARIABLES c that are BOTH declared in instancee and for which the
		// same name is declared or defined in instancer. Note the instancerST
		// must be passed to this constructor because with a default substitution
		// LHS<-RHS the LHS is resolved in the instanceeCtxt, (done
		// in the previous line) and the RHS is resolved in the instancerST.
		SubstInNode substIn = new SubstInNode(treeNode, instancerST, decls, mn, instanceeModule);

		// For each explicit substitution in the syntax tree, overwrite or add
		// the corresponding default entry in SubstInNode just created
		for (int i = 3; i < substNodes.length; i += 2) {
			// pick up array of syntax elements for one substitution,
			// e.g. ["c","<-",expr]
			TreeNode sc[] = substNodes[i].heirs();

			// substRHS is the expression "exp" in "c <- exp"; this stmt first
			// checks that c is properly declared in the instancee context,
			// and then generates an ExprOrOpArgNode. If c is a constant
			// with parameters, then an OpArgNode is returned; otherwise it is
			// an ExprNode.
			ExprOrOpArgNode substRHS = generateSubst(instanceeCtxt, sc[0], sc[2], mn);

			// Overwrite an implicit substitution if there is one, or add a new one,
			// checking for duplicate substitutions for the same symbol
			substIn.addExplicitSubstitute(instanceeCtxt, sc[0].getUS(), sc[2], substRHS);
		}

		// Check if substitution is complete, i.e. that all constants and vars
		// have been substituted for.
		substIn.matchAll(decls);
		return substIn;
	} // end processSubst

	/**
	 * This method treats *unnamed* INSTANCE stmts NOTE: this code does nothing with
	 * ASSUMES or THEOREMS
	 */
	/*************************************************************************
	 * However, SANY2 imports ThmOrAssumpDef nodes. *
	 *************************************************************************/
	/**
	 * @param treeNode
	 * @param cm
	 * @param topLevel
	 * @return
	 * @throws AbortException
	 */
	/**
	 * @param treeNode
	 * @param cm
	 * @param topLevel
	 * @return
	 * @throws AbortException
	 */
	/**
	 * @param treeNode
	 * @param cm
	 * @param topLevel
	 * @return
	 * @throws AbortException
	 */
	/**
	 * @param treeNode
	 * @param cm
	 * @param topLevel
	 * @return
	 * @throws AbortException
	 */
	private final InstanceNode generateInstance(TreeNode treeNode, ModuleNode cm, boolean topLevel)
			throws AbortException {
		/**********************************************************************
		 * topLevel argument is true for a top-level INSTANCE statement, and * false
		 * elsewise--that is, for an INSTANCE inside a proof. *
		 **********************************************************************/
		TreeNode[] children;
		if (topLevel) {
			children = treeNode.one()[0].heirs();
		}
		// skip one generation below NonLocalInstance
		// because we know zero defines local in a
		// top-level INSTANCE
		else {
			children = treeNode.heirs();
		}
		;
		// id of module being instanced
		UniqueString moduleId = children[1].getUS();

		// If this module instance is declared "LOCAL" then all of the
		// definitions in it must be instanced as if they were "LOCAL"
		boolean localness = treeNode.local();

		// Create a list of all declarations for module moduleId.
		// Match them against either something in the substitutions or
		// something in the current context (symbol table) for the
		// substitution. Check that the symbol does occur in the module
		// and as a declaration.
		Context instanceeCtxt = this.getContext(moduleId);
		if (instanceeCtxt == null) {
			errors.addAbort(children[1].getLocation(),
					"Internal error: No context available for module `" + moduleId.toString() + "'.", true);
		}
		;
		// Try to find the ModuleNode for the module being instanced in
		// the symbolTable
		ModuleNode instanceeModuleNode = symbolTable.resolveModule(moduleId);

		// It must be an external module if it isn't in the symbolTable;
		// try to find it in moduleTable (it cannot be in both places, or
		// a name conflict would have resulted)
		if (instanceeModuleNode == null) {
			instanceeModuleNode = moduleTable.getModuleNode(moduleId);
		}

		if (instanceeModuleNode == null) {
			errors.addAbort(children[1].getLocation(), "Could not find module " + moduleId.toString(), false);
		}

		/*
		 * Set isInstantiated field of instancee. Added by LL 23 July 2013
		 */
		instanceeModuleNode.setInstantiated(true);

		// Create the SubstInNode that will act as a template "wrapper"
		// for each definition in the module being instantiated; this
		// SubstInNode itself gets discarded after being used as template
		// however many times is necessary
		SubstInNode subst = processSubst(treeNode, children, symbolTable, instanceeCtxt, instanceeModuleNode, cm);

		// Create a vector of all of the OpDefNodes in the module being
		// instantiated
		Vector defs = instanceeCtxt.getByClass(OpDefNode.class);

		OpDefNode odn; // OpDefNode in module being instantiated (instancee)
		OpDefNode newOdn; // Its counterpart current module (instancer)
		SubstInNode substInTemplate; // Template to be used for any
										// SubstInNode wrappers required

		// Duplicate the OpDef records from the module being INSTANCE'd
		for (int i = 0; i < defs.size(); i++) {
			odn = (OpDefNode) defs.elementAt(i);
			// OpDefNode in module being instantiated (instancee)

			// Do not instantiate built-in or local operators, or those
			// OpDefNodes created solely to prevent a ModuleName from being
			// used as an operator node.
			if (odn.getKind() == BuiltInKind || odn.getKind() == ModuleInstanceKind || odn.isLocal()) {
				continue;
			}

			// If there are parameters to the module being instantiated, then
			// a SubstInNode is required, and possibly a different module of
			// origin should be indicated
			if (!instanceeModuleNode.isParameterFree()) {
				// Create the OpDefNode for the new instance of this definition
				// Note that the new OpDefNode shares the array of FormalParamNodes
				// with the old OpDefNode, as well as large parts of its body
				// (all but the SubstInNode). Hence, changes by a tool to an Original
				// OpDefNode will likely be reflected in all instances of it.
				if (odn.getOriginallyDefinedInModuleNode().isParameterFree()) {

					/****************************************************************
					 * Originally, newOdn was set the way it now is if localness = * true. Here's
					 * the problem with it. Suppose the instantiated * module EXTENDS the Naturals
					 * module. Then this will add new * OpDefNodes for all the symbols defined in
					 * Naturals. If the * current module EXTENDS Naturals, this will lead to
					 * multiple * definitions. So, for nonlocal definitions, we just * set newOdn to
					 * odn. * * However, now the problem is: suppose the current module * does not
					 * EXTEND the Naturals module. Then the operators * defined in Naturals, which
					 * should be defined in the current * module, are not. So, we add them to
					 * symbolTable. This does * not lead to a multiple definition error because
					 * apparently * it's the addSymbol method that is smart enough to detect if * we
					 * are adding a definition that comes from the same source as * the original
					 * one. * * This fix was made by LL on 16 Feb 2009. * * On 6 June 2010, LL add
					 * "&& topLevel" to the following `if' * test. This was needed because an
					 * INSTANCE inside a proof * was producing a "Multiple declarations or
					 * definition" * warning if the INSTANCEd module and the current module both *
					 * EXTENDed Naturals. This fix seems to do the right thing, * but I have not
					 * extensively tested it and I have no idea what * problems may remain. *
					 ****************************************************************/
					if (localness && topLevel) {
						newOdn = new OpDefNode(odn.getName(), UserDefinedOpKind, odn.getParams(), localness,
								odn.getBody(), odn.getOriginallyDefinedInModuleNode(), symbolTable, treeNode, true,
								odn.getSource());
						/***************************************************************
						 * The following statement was added by LL on 16 Feb 2009, by * analogy with the
						 * corresponding code about 45 lines below. I * have no idea if it was
						 * originally omitted for a good reason. *
						 ***************************************************************/
						newOdn.setLabels(odn.getLabelsHT());
					} else {
						newOdn = odn;
						symbolTable.addSymbol(odn.getName(), odn);
					}
				} else {
					// Create the "wrapping" SubstInNode as a clone of "subst" above,
					// but with a body from the OpDefNode in the module being
					// instantiated
					substInTemplate = new SubstInNode(treeNode, subst.getSubsts(), odn.getBody(), cm,
							instanceeModuleNode);
					newOdn = new OpDefNode(odn.getName(), UserDefinedOpKind, odn.getParams(), localness,
							substInTemplate, cm, symbolTable, treeNode, true, odn.getSource());
					newOdn.setLabels(odn.getLabelsHT());

				}
			} else {
				// There are no parameters to the instancee module; this
				// means that a SubstInNode is not necessary, and also that
				// the new operator should be considered to be "originally
				// defined in" the same module as the old one for purposes of
				// telling whether they are "the same" or different definitions

				// Create an OpDefNode whose body is the same as the instancer's.

				if (localness) {
					/****************************************************************
					 * See the comments about the similar change made to the * setting of newOdn in
					 * the `then' clause, just above. * This entire change was made by LL on 16 Feb
					 * 2009. *
					 ****************************************************************/
					newOdn = new OpDefNode(odn.getName(), UserDefinedOpKind, odn.getParams(), localness, odn.getBody(),
							odn.getOriginallyDefinedInModuleNode(), symbolTable, treeNode, true, odn.getSource());
					newOdn.setLabels(odn.getLabelsHT());
				} else {
					newOdn = odn;
					symbolTable.addSymbol(odn.getName(), odn);
				}
			}
			cm.appendDef(newOdn);
			setOpDefNodeRecursionFields(newOdn, cm);
		} // end for

		/**********************************************************************
		 * Import the ThmOrAssumpDefNode objects to the current module. The * following
		 * code for doing this was copied and modified without * thinking from the code
		 * above for OpDefNode objects *
		 **********************************************************************/
		Vector tadefs = instanceeCtxt.getByClass(ThmOrAssumpDefNode.class);

		ThmOrAssumpDefNode tadn;
		// ThmOrAssumpDefNode in module being instantiated (instancee)
		ThmOrAssumpDefNode newTadn;
		// Its counterpart current module (instancer)
		APSubstInNode tasubstInTemplate; // Template to be used for any
		// SubstInNode wrappers required

		// Duplicate the OpDef records from the module being INSTANCE'd
		for (int i = 0; i < tadefs.size(); i++) {
			tadn = (ThmOrAssumpDefNode) tadefs.elementAt(i);
			// ThmOrAssumpDefNode in module being instantiated (instancee)

			// Following statement added by LL on 30 Oct 2012 to handle locally
			// instantiated theorems and assumptions.
			if (tadn.isLocal()) {
				continue;
			}

			// If there are parameters to the module being instantiated, then
			// a SubstInNode is required, and possibly a different module of
			// origin should be indicated
			if (!instanceeModuleNode.isParameterFree()) {
				// Create the ThmOrAssumpDefNode for the new instance of this
				// definition. Note that the new ThmOrAssumpDefNode shares the
				// array of FormalParamNodes with the old ThmOrAssumpDefNode,
				// as well as large parts of its body (all but the SubstInNode).
				// Hence, changes by a tool to an Original ThmOrAssumpDefNode will
				// likely be reflected in all instances of it.
				if (tadn.getOriginallyDefinedInModuleNode().isParameterFree()) {
					// Following if/else added by LL on 30 Oct 2012 to handle locally
					// instantiated theorems and assumptions.
					if (localness && topLevel) {
						newTadn = new ThmOrAssumpDefNode(tadn.getName(), tadn.isTheorem(), tadn.getBody(), cm,
								symbolTable, treeNode, tadn.getParams(), instanceeModuleNode, tadn.getSource());
						newTadn.setLocal(true);
					} else {
						newTadn = tadn;
						// On 30 Oct 2012, LL noticed that code was added on 16 Feb 2009
						// to the corresponding place in the code for an OpDefNode, but that
						// nothing was added here. I suspect that something should have been
						// that the 2009 code should also have been added here, but wasn't--
						// perhaps because there's no getLabelsHT method for a ThmOrAssumpDefNode.
						// This may mean that there's a bug in handling labels in the
						// instantiated theorem or assumption.
					}
					/*
					 * new ThmOrAssumpDefNode( tadn.getName(), UserDefinedOpKind, tadn.getParams(),
					 * localness, tasubstInTemplate, tadn.getOriginallyDefinedInModuleNode(),
					 * symbolTable, treeNode, true );
					 */
				} else {
					// Create the "wrapping" SubstInNode as a clone of "subst" above,
					// but with a body from the ThmOrAssumpDefNode in the module being
					// instantiated
					tasubstInTemplate = new APSubstInNode(treeNode, subst.getSubsts(), tadn.getBody(), cm,
							instanceeModuleNode);
					newTadn = new ThmOrAssumpDefNode(tadn.getName(), tadn.isTheorem(), tasubstInTemplate, cm,
							symbolTable, treeNode, tadn.getParams(), instanceeModuleNode, tadn.getSource());
					// Following if/else added by LL on 30 Oct 2012 to handle locally
					// instantiated theorems and assumptions.
					newTadn.setLocal(localness);
					// cm.appendDef(newTadn);
					newTadn.setLabels(tadn.getLabelsHT());

				}
			} else {
				// There are no parameters to the instancee module; this
				// means that a SubstInNode is not necessary, and also that
				// the new operator should be considered to be "originally
				// defined in" the same module as the old one for purposes of
				// telling whether they are "the same" or different definitions

				// Create a ThmOrAssumpDefNode whose body is the same as
				// the instancer's.
				if (localness && topLevel) {
					newTadn = new ThmOrAssumpDefNode(tadn.getName(), tadn.isTheorem(), tadn.getBody(),
							tadn.getOriginallyDefinedInModuleNode(), symbolTable, treeNode, tadn.getParams(),
							instanceeModuleNode, tadn.getSource());
					// Following if/else added by LL on 30 Oct 2012 to handle locally
					// instantiated theorems and assumptions.
					newTadn.setLocal(localness);
					newTadn.setLabels(tadn.getLabelsHT());
				} else {
					newTadn = tadn;
					symbolTable.addSymbol(tadn.getName(), tadn);
				}
			}
			if (topLevel) {
				cm.appendDef(newTadn);
			}
			;
			/********************************************************************
			 * No recursion fields needed for theorems or assumptions because * they can't
			 * appear in a recursive section. *
			 ********************************************************************/
			// setOpDefNodeRecursionFields(newTadn, cm) ;
		} // end for

		// Create a new InstanceNode to represent this INSTANCE stmt in
		// the current module
		InstanceNode inst = new InstanceNode(null /* no name */, localness, null /* no parms */, instanceeModuleNode,
				subst.getSubsts(), treeNode);

		// Append this new InstanceNode to the vector of InstanceNodes
		// being accumulated for this module
		if (topLevel) {
			cm.appendInstance(inst);
		}
		;
		return inst;

	} // void generateInstance

	private final void processTheorem(TreeNode stn, ModuleNode cm) throws AbortException {
		ThmOrAssumpDefNode tadn = null;
		LevelNode body;
		ProofNode proof = null;
		int bodyIndex = stn.heirs().length - 1;
		boolean isAssumeProve = false;
		/*********************************************************************
		 * Set true if the body is an ASSUME/PROVE. *
		 *********************************************************************/
		boolean hasProof = (stn.heirs()[bodyIndex].getKind() == N_Proof)
				|| (stn.heirs()[bodyIndex].getKind() == N_TerminalProof);
		if (hasProof) {
			bodyIndex--;
		}
		;

		if (bodyIndex > 1) {
			/*********************************************************************
			 * If this is a named theorem, start fresh processing of labels, * create the
			 * object. *
			 *********************************************************************/
			pushLS();
			UniqueString name = stn.heirs()[1].getUS();
			tadn = new ThmOrAssumpDefNode(name, stn);
		}
		;
		if (stn.zero()[bodyIndex]
				.isKind(N_AssumeProve)) { /*******************************************************************
											 * Theorem statement is an ASSUME/PROVE. Must set currentGoal. *
											 *******************************************************************/
			currentGoal = tadn;
			isAssumeProve = true;

			/*******************************************************************
			 * We want the symbols declared in top-level NEW statements of the * ASSUME
			 * clause to be visible in the proof. Therefore, we do the * context push for
			 * the top-level AssumeProveNode here instead of * in generateAssumeProve. *
			 *******************************************************************/
			symbolTable.pushContext(new Context(moduleTable, errors));
			body = generateAssumeProve(stn.heirs()[bodyIndex], cm);
			currentGoal = null;
		} else { /****************************************************************
					 * Theorem statement must be an ExprNode. *
					 ****************************************************************/
			body = generateExpression(stn.heirs()[bodyIndex], cm);
		}
		;
		if (bodyIndex > 1) {
			/**********************************************************************
			 * The theorem node has the form * THEOREM Ident == statement *
			 **********************************************************************/
			Context assumeContext = null;
			if (isAssumeProve) {
				/********************************************************************
				 * If the body is an ASSUME/PROVE, we must save in assumeContext * the context
				 * containing the symbols declared in the ASSUME * clause and pop it, so Ident
				 * is made visible outside the proof. *
				 ********************************************************************/
				assumeContext = symbolTable.getContext();
				symbolTable.popContext();
			}
			;
			UniqueString name = stn.heirs()[1].getUS();
			tadn.construct(true, body, cm, symbolTable, null);
			tadn.setLabels(popLabelNodeSet());
			cm.appendDef(tadn);
			if (isAssumeProve) {
				/********************************************************************
				 * After putting Ident into the symbol table, we push the ASSUME * context back
				 * onto symboltable. *
				 ********************************************************************/
				symbolTable.pushContext(assumeContext);
			}
			;
		}
		; // if (bodyIndex > 1)

		/************************************************************************
		 * Note: If this is a named theorem, then the name has been added to *
		 * symbolTable so it can be referred to within the theorem's proof (if * it has
		 * one). *
		 ************************************************************************/
		if (hasProof) {
			proof = generateProof(stn.heirs()[bodyIndex + 1], cm);
		}
		;

		if (isAssumeProve) {
			symbolTable.popContext();
			/********************************************************************
			 * Pop the context containing ASSUME declarations. *
			 ********************************************************************/
			((AssumeProveNode) body).inProof = false;
			/********************************************************************
			 * Reset the AssumeProve node's inProof field. *
			 ********************************************************************/
		}
		;
		cm.addTheorem(stn, body, proof, tadn);
	} // ProcessTheorem

	private final void processAssumption(TreeNode stn, ModuleNode cm) throws AbortException {
		ThmOrAssumpDefNode tadn = null;
		int lastIndex = stn.heirs().length - 1;
		if (lastIndex > 1) {
			pushLS();
		}
		;
		/*********************************************************************
		 * If this is a named assumption, start fresh processing of labels. *
		 *********************************************************************/
		ExprNode expr = generateExpression(stn.heirs()[lastIndex], cm);

		if (lastIndex > 1) {
			/**********************************************************************
			 * The assumption node has the form * ASSUME Ident == expression *
			 **********************************************************************/
			UniqueString name = stn.heirs()[1].getUS();
			tadn = new ThmOrAssumpDefNode(name, false, expr, cm, symbolTable, stn, null, null, null);
			tadn.setLabels(popLabelNodeSet());
			cm.appendDef(tadn);
		}
		;
		cm.addAssumption(stn, expr, symbolTable, tadn);
		return;
	} // processAssumption

	private final ProofNode generateProof(TreeNode stn, ModuleNode cm)
			/***********************************************************************
			 * Node stn is of kind N_TerminalProof or an N_Proof. The heirs of an * N_Proof
			 * node consist of an optional PROOF token followed by a * seequence of
			 * N_ProofStep nodes. The heirs of an N_ProofStep node * are a StartStep()
			 * token, a statement body, and an optional proof. * A statement body is one of
			 * the following node kinds: * * Have no proof: * N_DefStep N_UseOrHide
			 * N_NonLocalInstance N_HaveStep, * N_TakeStep N_WitnessStep * * Have a proof *
			 * N_QEDStep N_PickStep N_CaseStep N_AssertStep * * Each step produces the
			 * following kind of semantic node: * * N_DefStep : DefStepNode * * N_UseOrHide
			 * : UseOrNideNode * * N_NonLocalInstance : InstanceNode * * Others: TheoremNode
			 * * The type of statement is indicated by the body of the * node. For any step
			 * other than an N_AssertStep, the body * is an OpApplNode with the following
			 * dummy operator: * * N_HaveStep : $Have * N_CaseStep : $Pfcase * N_TakeStep :
			 * $Take * N_PickStep : $Pick * N_WitnessStep : $Witness * N_QEDStep : $Qed *
			 ***********************************************************************/
			throws AbortException {
		int numberOfPops = 0;
		/*********************************************************************
		 * For each SUFFICES ASSUME/PROVE step, we push a new context onto * the symbol
		 * table containing declarations of any NEW symbols. * These need to be popped
		 * off when through processing the proof. *
		 *********************************************************************/
		if (stn.getKind() == N_TerminalProof) {
			return generateLeafProof(stn, cm);
		}
		;

		Context pfCtxt = new Context(moduleTable, errors);
		symbolTable.pushContext(pfCtxt);
		/*********************************************************************
		 * Create a new sub-Context for the proof. *
		 *********************************************************************/

		TreeNode heirs[] = stn.heirs();
		int offset = 0;
		if (heirs[0].getKind() == TLAplusParserConstants.PROOF) {
			offset = 1;
		}
		;
		LevelNode[] steps = new LevelNode[heirs.length - offset];
		Vector iVec = new Vector();
		/*********************************************************************
		 * A vector to hold the InstanceNodes generated by steps of the form * Id ==
		 * INSTANCE ... so they can be level checked. *
		 *********************************************************************/

		/***********************************************************************
		 * At the beginning of each loop iteration, the variable prevIsInFix * equals
		 * true iff the previous step consists of a formula whose main * operator is an
		 * infix operator, including an "@-step" of the form "@ * infix-op expression".
		 * If it is true, then rhSide is the ExprNode * of the infix-op's
		 * right-hand-side expression. *
		 ***********************************************************************/
		boolean prevIsInfix = false;
		ExprNode prevRHS = null;

		for (int i = offset; i < heirs.length; i++) {
			/*********************************************************************
			 * Process proof step i. *
			 *********************************************************************/
			boolean isAssumeProve = false;
			/*******************************************************************
			 * Will be set true for an ASSUME/PROVE, so we can reset the * node's inProof
			 * field. *
			 *******************************************************************/
			boolean isSuffices = false;
			/*******************************************************************
			 * Will be set to true for a SUFFICES statement. This is used to * do the right
			 * thing with ASSUME declarations in an ASSUME/PROVE * step, and to set the
			 * suffices field of the ThmOrAssumpDefNode * if this is a named step. *
			 *******************************************************************/

			/*********************************************************************
			 * For an ASSUME/PROVE, we set assumeContext to a context containing * the
			 * declarations from the outer-most NEWs of the ASSUME. For an * ordinary
			 * ASSUME/PROVE, this context is pushed onto the symbol * table for statement's
			 * processing the proof. For a SUFFICE * ASSUME/PROVE, it is pushed onto the
			 * symbol table after processing * the statement's proof so the outermost NEW
			 * declarations are * visible for the rest of the current proof. * The handling
			 * of the assumeContext was changed on 1 Jul 2009 * because SUFFICE ASSUME/PROVE
			 * was not being handled properly. *
			 *********************************************************************/
			Context assumeContext = null;

			/*********************************************************************
			 * For "PICK x : exp", the symbol x is declared in exp, undeclared * in the
			 * proof of the step, and declared afterwards. (There'd be a * similar problem
			 * with TAKE if it took a proof.) The following * variables are used to
			 * manipulate this, with pickContext holding * the declarations of the symbols
			 * introduced by the PICK step. *
			 *********************************************************************/
			boolean isPick = false;
			Context pickContext = null;

			/*********************************************************************
			 * Set stepNumSTN, stepBodySTN, and stepPfSTN to the syntax tree * nodes of the
			 * step number, the body, and the proof (the latter * equal to null if there's
			 * no proof. *
			 *********************************************************************/
			TreeNode pfStepSTN = heirs[i];
			TreeNode stepNumSTN = pfStepSTN.heirs()[0];
			TreeNode stepBodySTN = pfStepSTN.heirs()[1];
			TreeNode stepPfSTN = null;
			if (pfStepSTN.heirs().length > 2) {
				stepPfSTN = pfStepSTN.heirs()[2];
			}
			;

			LevelNode pfNumNode = null;
			boolean makePfNumNode = true;
			/*******************************************************************
			 * For a numbered step that doesn't produce a TheoremNode, * pfNumNode is set to
			 * a node that will be the stepNode of a * NumberedProofStepKind OpDefNode. *
			 *******************************************************************/
			/*
			 * On 23 Feb 2014 LL added the following code to make step numbers like <*>13
			 * illegal, so <+> and <*> can be used only for unnamed steps. It would be most
			 * natural to make the change age the parsing level by changing the JavaCC code.
			 * However, that code is a Kludge that it is best not to touch unless absolutely
			 * necessary. Also, detecting the error here allows multiple instances of the
			 * error to be reported in a single execution of the parser.
			 * 
			 * The modification is based on the following empirical observation:
			 * 
			 * - For a step number like "<3>13." stepNumSTN.image = stepNumSTN.originalImage
			 * = "<3>13." - For a step number like "<*>13.", stepNumSTN.image = "<3>13." and
			 * stepNumSTN.originalImage = "<*>13." - For unnumbered steps,
			 * stepNumSTN.originalImage = null and stepNumSTN.image = the actual token.
			 */
			SyntaxTreeNode STN = (SyntaxTreeNode) stepNumSTN;
			if ((STN.originalImage != null) && (STN.originalImage != STN.image)) {
				String oimage = STN.originalImage.toString();
				if ((!oimage.equals(STN.image.toString()))
						&& ((oimage.charAt(1) == '*') || (oimage.charAt(1) == '+'))) {
					errors.addError(stepNumSTN.getLocation(), "<*> and <+> cannot be used for a named step.");
				}
			}

			/*********************************************************************
			 * Set stepNum to the step number, or null if its an unnumbered step. *
			 *********************************************************************/
			UniqueString stepNum = null;
			switch (stepNumSTN.getKind()) {
			// LL: On 25 Feb 2010 I discovered the following comment here:
			// XXXXXX xyz: need to add the following case
			// The ProofImplicitStepLexeme case (something like <*>3) seems to be
			// handled properly in tests. I presume that this is an obsolete
			// comment that I didn't remove when I added the case to the code.
			case TLAplusParserConstants.ProofImplicitStepLexeme:
			case TLAplusParserConstants.ProofStepLexeme:
				stepNum = stepNumSTN.getUS();
				break;
			case TLAplusParserConstants.ProofStepDotLexeme:
				String stNum = stepNumSTN.getUS().toString();
				stepNum = UniqueString.uniqueStringOf(stNum.substring(0, stNum.indexOf(".")));
				break;
			default:
				makePfNumNode = false;
				break;
			}
			; // switch

			/*********************************************************************
			 * If this is a numbered step, process labels. *
			 *********************************************************************/
			if (stepNum != null) {
				pushLS();
			}
			;

			/********************************************************************
			 * Construct the ThmOrOpDefNode if needed. (We need to do it now * because we
			 * have to set currentGoal before we generate the body.) *
			 ********************************************************************/
			ThmOrAssumpDefNode tadn = null;
			if (stepNum != null) {
				tadn = new ThmOrAssumpDefNode(stepNum, stepNumSTN);
			}
			;

			/*********************************************************************
			 * Set prevIsInfix false unless this is an AssertStep node. *
			 *********************************************************************/
			int stepKind = stepBodySTN.getKind();
			if (stepKind != N_AssertStep) {
				prevIsInfix = false;
			}
			;

			switch (stepKind) {
			case N_DefStep:
				/*****************************************************************
				 * Set defSTNs to the array of heirs, and defOffSet so that * defSTNs[defOffSet]
				 * ... defSTNs[defSTNs.length-1] is the * sequence of definitions. *
				 *****************************************************************/
				TreeNode[] defSTNs = stepBodySTN.heirs();
				int defOffSet = 0;
				if (defSTNs[0].getKind() == DEFINE) {
					defOffSet = 1;
				}
				;

				OpDefNode[] defs = new OpDefNode[defSTNs.length - defOffSet];
				/***************************************************************
				 * Will be set to the sequence of OpDefNodes for the * definitions. *
				 ***************************************************************/
				for (int j = defOffSet; j < defSTNs.length; j++) {
					TreeNode defSTN = defSTNs[j];
					;
					Vector vec = new Vector();
					switch (defSTN.getKind()) {
					/***************************************************************
					 * Need to check if it's an operator, function, or module * definition. *
					 ***************************************************************/
					case N_FunctionDefinition:
						processFunction(defSTN, vec, cm);
						break;
					case N_ModuleDefinition:
						/*************************************************************
						 * The call to processModuleDefinition sets defsVec to a * vector of all the
						 * definitions it makes, and adds the new * InstanceNode to iVec. For now, we're
						 * just throwing * away defsVec. (If defsVec were null, then *
						 * processModuleDefinition would add these definitions to to * the module's list
						 * of top-level definitions.) *
						 *************************************************************/
						Vector defsVec = new Vector();
						vec.addElement(processModuleDefinition(defSTN, defsVec, iVec, cm));
						break;
					case N_OperatorDefinition:
						processOperator(defSTN, vec, cm);
						/*************************************************************
						 * processOperator creates an OpDefNode, puts an entry for * it in symbolTable,
						 * and adds the OpDefNode to vec. *
						 *************************************************************/
						break;
					}
					; // switch (def.getKind())
					defs[j - defOffSet] = (OpDefNode) vec.elementAt(0);
				}
				; // for j
				pfNumNode = new DefStepNode(stepBodySTN, stepNum, defs);
				steps[i - offset] = pfNumNode;
				break;

			case N_UseOrHide:
				UseOrHideNode uohn = generateUseOrHide(stepBodySTN, cm);

				// Added by LL on 16 Jun 2010 so location returnedby getLocation() will
				// include the step number.
				uohn.stn = pfStepSTN;

				uohn.setStepName(stepNum); // Added 6 June 2010 by LL.

				if (uohn.facts.length + uohn.defs.length == 0) {
					errors.addError(stepBodySTN.getLocation(), "Empty USE or HIDE statement.");
				}
				;
				uohn.factCheck();
				// Added 4 Mar 2009.
				pfNumNode = uohn;
				steps[i - offset] = pfNumNode;
				break;

			case N_NonLocalInstance:
				// Code to set step name added by LL on 6 June 2010
				InstanceNode inst = generateInstance(stepBodySTN, cm, false);
				inst.setStepName(stepNum);
				pfNumNode = inst;
				steps[i - offset] = pfNumNode;
				break;

			default:
				makePfNumNode = false;
				TreeNode[] bodyHeirs = stepBodySTN.heirs();
				LevelNode body = null;
				/***************************************************************
				 * This will be set to the body of the TheoremNode or * ThmOrAssumpDefNode. *
				 ***************************************************************/
				UniqueString op = null;
				ExprNode[] args;
				/***************************************************************
				 * For anything but an N_Assert node, body is set to an * OpApplNode having
				 * these as its operator and arguments. *
				 ***************************************************************/

				switch (stepBodySTN.getKind()) {
				case N_AssertStep:
					int bodyNext = 0;
					if (bodyHeirs[0].getKind() == TLAplusParserConstants.SUFFICES) {
						bodyNext = 1;
						isSuffices = true;
						/************************************************************
						 * We can't have an "@" in a SUFFICES step. *
						 ************************************************************/
					}
					;
					if (bodyHeirs[bodyNext].getKind() == N_AssumeProve) {
						/************************************************************
						 * This is an AssumeProve node. *
						 ************************************************************/
						isAssumeProve = true;

						/************************************************************
						 * For an ASSUME/PROVE, we need save the symbol * declarations from top-level
						 * NEW statements in the ASSUME * to make them visible only in the statement's
						 * proof for * an ordinary ASSUME/PROVE, and only after the statement's * proof
						 * for a SUFFICES ASSUME/PROVE. *
						 ************************************************************/
						symbolTable.pushContext(new Context(moduleTable, errors));

						currentGoal = tadn;
						/**********************************************************
						 * Need to set currentGoal before generating the * AssumeProve node. *
						 **********************************************************/
						body = generateAssumeProve(bodyHeirs[bodyNext], cm);

						if (isSuffices) {
							((AssumeProveNode) body).setSuffices();
						}
						;
						/**********************************************************
						 * Added 16 Feb 2009 by LL. *
						 **********************************************************/
						currentGoal = null;
						assumeContext = symbolTable.getContext();
						symbolTable.popContext();
						prevIsInfix = false;
					} else {
						/************************************************************
						 * This is an ordinary expression. *
						 ************************************************************/
						TreeNode curExpr = bodyHeirs[bodyNext];

						/************************************************************
						 * Special handling of SUFFICES added by LL 16 Feb 2009. *
						 ************************************************************/
						if (isSuffices) {
							args = new ExprNode[1];
							args[0] = generateExpression(curExpr, cm);
							body = new OpApplNode(OP_suffices, args, stepBodySTN, cm);
						} // if (isSuffices)
						else {
							/************************************************************
							 * If the current expression is an infix expression, set * curLHS to its current
							 * LHS, otherwise set it to null. *
							 ************************************************************/
							SyntaxTreeNode curLHS = null;
							if (curExpr.getKind() == N_InfixExpr) {
								curLHS = (SyntaxTreeNode) curExpr.heirs()[0];
							}
							;
							/************************************************************
							 * If prevIsInfix is true and curLHS is an "@", then * process it, using as the
							 * right-hand side a new $Nop node * with prevRHS as its argument. *
							 ************************************************************/
							if (prevIsInfix && (curLHS != null) && (curLHS.heirs().length > 0)
							/***************************************************
							 * This test added 25 Feb 2010 because if curLHS * is a string, then
							 * curLHS.heirs() is a * zero-length array, so the following test threw * an
							 * out-of-bounds array index exception. Note * that curLHS.heirs() should never
							 * be null, * because the heirs() method can never return * null. *
							 ***************************************************/
									&& (((SyntaxTreeNode) curLHS.heirs()[0]).heirs().length == 0)
									&& (curLHS.heirs()).length > 1
									/***************************************************
									 * This test added 2 Mar 2009 to fix following * bug. When we are here and the
									 * left-hand side * is something like a number, then curLHS.heirs() * seems to
									 * have length 1 and the following test * causes an ArrayIndexOverflowException.
									 * *
									 ***************************************************/
									&& (curLHS.heirs()[1].getKind() == IDENTIFIER)
									&& (curLHS.heirs()[1].getUS() == AtUS)) {

								/**********************************************************
								 * The following code obtained by a simple modification * of the N_InfixExpr
								 * case of generateExpression. *
								 **********************************************************/
								TreeNode[] children = curExpr.heirs();
								GenID genID = generateGenID(children[1], cm);
								ExprNode[] sns = new ExprNode[2];
								SymbolNode opn = symbolTable
										.resolveSymbol(Operators.resolveSynonym(genID.getCompoundIDUS()));
								if (opn == null) {
									errors.addError(curExpr.getLocation(), "Couldn't resolve infix operator symbol `"
											+ genID.getCompoundIDUS() + "'.");
									return null;
								}
								;
								sns[1] = generateExpression(children[2], cm);
								/**********************************************************
								 * Set sns[1] to a new $Nop OpApplNode whose argument is * prevRHS. *
								 **********************************************************/
								ExprNode[] nopArgs = new ExprNode[1];
								nopArgs[0] = prevRHS;
								sns[0] = new OpApplNode(OP_nop, nopArgs, curLHS, cm);
								body = new OpApplNode(opn, sns, curExpr, cm);
							} // if ( prevIsInfix ...)
							else { // this is not an @-step
								body = generateExpression(curExpr, cm);
							}
							;

							/************************************************************
							 * If this is an infix ioperator, set prevIsInfix true and * prevRHS equal to
							 * its right-hand argument, else set * prevIsInfix false. *
							 ************************************************************/
							prevIsInfix = false;
							if ((curLHS != null)
									/*******************************************************
									 * The following conjuncts should be true unless there * was an error in the
									 * expression. *
									 *******************************************************/
									&& (body != null) && (body.getKind() == OpApplKind)
									&& (((OpApplNode) body).getArgs().length > 1)) {
								prevIsInfix = true;
								prevRHS = (ExprNode) ((OpApplNode) body).getArgs()[1];
							}
						}
					}
					; // else This is an ordinary expression.
					break;

				case N_HaveStep:
				case N_CaseStep:
					if (stepBodySTN.getKind() == N_HaveStep) {
						op = OP_have;
					} else {
						op = OP_pfcase;
					}
					;
					args = new ExprNode[1];
					args[0] = generateExpression(bodyHeirs[1], cm);
					body = new OpApplNode(op, args, stepBodySTN, cm);
					break;

				case N_TakeStep:
				case N_PickStep:
					if (stepBodySTN.getKind() == N_TakeStep) {
						op = OP_take;
					} else {
						op = OP_pick;
						isPick = true;
						/************************************************************
						 * Push a new context onto the symbolTable stack to get the * declarations of
						 * the PICK symbols. *
						 ************************************************************/
						symbolTable.pushContext(new Context(moduleTable, errors));
					}
					;

					if (bodyHeirs[1].getKind() == N_QuantBound) {
						/************************************************************
						 * The introduced identifiers are bounded--e.g., "TAKE id * \in Set". *
						 ************************************************************/

						/************************************************************
						 * Set quants to the number of N_QuantBound nodes. *
						 ************************************************************/
						int quants = 1;
						int nextTok = 2;
						while ((nextTok < bodyHeirs.length)
								&& (bodyHeirs[nextTok].getKind() == TLAplusParserConstants.COMMA)) {
							quants++;
							nextTok = nextTok + 2;
						}
						;
						FormalParamNode[][] params = new FormalParamNode[quants][0];
						boolean[] bt = new boolean[quants];
						ExprNode[] paramBounds = new ExprNode[quants];
						processQuantBoundArgs(bodyHeirs, 1, params, bt, paramBounds, cm);

						if (isPick) {
							/**********************************************************
							 * Save the declarations in pickContext. *
							 **********************************************************/
							pickContext = symbolTable.getContext();
							/**********************************************************
							 * This is a PICK step; get the ": expr". *
							 **********************************************************/
							nextTok++; // Skip over the ":"
							args = new ExprNode[1];
							pushFormalParams(flattenParams(params));
							/********************************************************
							 * Push the bound variables on Last(LS).paramSeq and * process the body of the
							 * PICK. *
							 ********************************************************/
							args[0] = generateExpression(bodyHeirs[nextTok], cm);
							popFormalParams();
							symbolTable.popContext();
							/********************************************************
							 * Remove the bound symbols from the symbol table so * they're undefined for the
							 * proof of the PICK. *
							 ********************************************************/
						} else {
							/**********************************************************
							 * This is a TAKE step. *
							 **********************************************************/
							args = new ExprNode[0];
						}
						;
						body = new OpApplNode(op, null, args, params, bt, paramBounds, stepBodySTN, cm);
					} else {
						/************************************************************
						 * The introduced identifiers are unbounded--e.g., "TAKE * id1, id2". *
						 ************************************************************/

						/************************************************************
						 * Set ids to the number of introduced identifiers. *
						 ************************************************************/
						int ids = 1;
						while ((2 * ids < bodyHeirs.length)
								&& (bodyHeirs[2 * ids].getKind() == TLAplusParserConstants.COMMA)) {
							ids++;
						}
						;

						/************************************************************
						 * Set params to the array of new FormalParamNodes for the * identifiers. The
						 * identifiers are added to the current * symbol table. *
						 ************************************************************/
						FormalParamNode[] params = new FormalParamNode[ids];
						for (int j = 0; j < ids; j++) {
							params[j] = new FormalParamNode(bodyHeirs[2 * j + 1].getUS(), 0, bodyHeirs[2 * j + 1],
									symbolTable, cm);
						}
						;

						if (isPick) {
							/**********************************************************
							 * Save the declarations in pickContext. *
							 **********************************************************/
							pickContext = symbolTable.getContext();

							/**********************************************************
							 * This is a PICK step; get the ": expr". *
							 **********************************************************/
							pushFormalParams(params);
							/********************************************************
							 * Push formal parameters on Last(LS).paramSeq for * processing the body. *
							 ********************************************************/
							args = new ExprNode[1];
							args[0] = generateExpression(bodyHeirs[2 * ids + 1], cm);
							popFormalParams();
							symbolTable.popContext();
							/********************************************************
							 * Remove the bound symbols from the symbol table so * they're undefined for the
							 * proof of the PICK. *
							 ********************************************************/
						} else {
							/**********************************************************
							 * This is a TAKE step. *
							 **********************************************************/
							args = new ExprNode[0];
						}
						;
						body = new OpApplNode(op, args, params, stepBodySTN, cm);
					}
					;

					break;

				case N_WitnessStep:
					/**************************************************************
					 * Set ids to the number of expressions. *
					 **************************************************************/
					int ids = 1;
					while ((2 * ids < bodyHeirs.length)
							&& (bodyHeirs[2 * ids].getKind() == TLAplusParserConstants.COMMA)) {
						ids++;
					}
					;

					args = new ExprNode[ids];
					for (int j = 0; j < ids; j++) {
						args[j] = generateExpression(bodyHeirs[2 * j + 1], cm);
					}
					;
					body = new OpApplNode(OP_witness, args, stepBodySTN, cm);
					break;

				case N_QEDStep:
					args = new ExprNode[0];
					body = new OpApplNode(OP_qed, args, stepBodySTN, cm);
					break;

				default:
					errors.addAbort(stn.getLocation(),
							"Internal error: Unexpected SyntaxTreeNode kind: " + heirs[i].getKind());
					break;
				}
				; // switch

				/********************************************************************
				 * Set the fields of the ThmOrOpDefNode if there is one, including * the
				 * suffices field. *
				 ********************************************************************/
				if (stepNum != null) {
					tadn.construct(true, body, cm, symbolTable, null);
					tadn.setLabels(popLabelNodeSet());
					if (isSuffices) {
						tadn.setSuffices();
					}
					;
				}
				;
				/***********************************************************************
				 * Set proof to the proof, or to null if there is none. There is no * check made
				 * to see if this is a kind of step that should have a * proof. Thus, adding a
				 * proof to something like a WITNESS statement * requires changing only the
				 * parsing phase (specified by tla+.jj). *
				 ***********************************************************************/
				ProofNode proof = null;
				if (stepPfSTN != null) {
					/******************************************************************
					 * For an ordinary ASSUME/PROVE, must make the ASSUME's * declarations visible
					 * in the statement's proof. *
					 ******************************************************************/
					if (isAssumeProve && !isSuffices) {
						symbolTable.pushContext(assumeContext);
					}
					;
					proof = generateProof(stepPfSTN, cm);
					if (isAssumeProve && !isSuffices) {
						symbolTable.popContext();
					}
					;
				}
				;

				/********************************************************************
				 * For a SUFFICES ASSUME/PROVE, must make the ASSUME's declarations * visible
				 * after the proof. This is done by pushing assumeContext * onto the symbol
				 * table and incrementing numberOfPops so it will * be popped at the end of the
				 * proof. *
				 ********************************************************************/
				if (isAssumeProve && isSuffices) {
					numberOfPops++;
					symbolTable.pushContext(assumeContext);
				}
				;
				if (isAssumeProve) {
					((AssumeProveNode) body).inProof = false;
				}
				;
				/******************************************************************
				 * For an ASSUME/PROVE, set the inProof field to false. *
				 ******************************************************************/
				TheoremNode thm = new TheoremNode(stepBodySTN, body, cm, proof, tadn);

				// Added by LL on 16 Jun 2010 so location returnedby getLocation() will
				// include the step number.
				thm.stn = pfStepSTN;

				thm.suffices = isSuffices;
				steps[i - offset] = thm;
			}
			; // switch
			if (makePfNumNode) {
				/*******************************************************************
				 * Make an OpDefNode for the numbered step and add any label * declarations to
				 * it. *
				 *******************************************************************/
				OpDefNode nodeMadeOnlyToBePutInSymbolTable = new OpDefNode(stepNum, pfNumNode, cm, symbolTable,
						pfStepSTN);
				nodeMadeOnlyToBePutInSymbolTable.setLabels(popLabelNodeSet());
			}
			if (isPick) {
				/*******************************************************************
				 * We have to take the symbol declarations from pickContext and * put them into
				 * the current symbol table. *
				 *******************************************************************/
				Enumeration e = pickContext.content();
				while (e.hasMoreElements()) {
					SymbolNode sym = ((Context.Pair) (e.nextElement())).getSymbol();
					symbolTable.addSymbol(sym.getName(), sym);
				}
			}
		}
		; // for i
		InstanceNode[] insts = new InstanceNode[iVec.size()];
		for (int i = 0; i < insts.length; i++) {
			insts[i] = (InstanceNode) iVec.elementAt(i);
		}
		;

		/***********************************************************************
		 * Pop the contexts that were pushed onto the symbol table for SUFFICE *
		 * ASSUME/PROVE steps. *
		 ***********************************************************************/
		for (int i = 0; i < numberOfPops; i++) {
			// Added by LL on 24 June 2010
			// Need to add the symbols in the context being popped to pfCtxt
			// so they will be put into the context of the NonLeafProofNode.
			Context topContext = symbolTable.getContext();
			Enumeration e = topContext.content();
			while (e.hasMoreElements()) {
				SymbolNode sym = ((Context.Pair) (e.nextElement())).getSymbol();
				pfCtxt.addSymbolToContext(sym.getName(), sym);
			}
			symbolTable.popContext();
		}
		;
		symbolTable.popContext();
		return new NonLeafProofNode(stn, steps, insts, pfCtxt);
		/*********************************************************************
		 * Pop the sub-Context. *
		 *********************************************************************/
	} // generateProof

	/***************************************************************************
	 * The following method is not used and I have no idea why it's still * here. *
	 ***************************************************************************/
	private final LevelNode generateNumerableStep(TreeNode stn,
//          TreeNode stmt, 
//          UniqueString stepNum,
//          TreeNode proof, 
			ModuleNode cm) throws AbortException {
		/***********************************************************************
		 * Used to generate the step for a NumerableStep or QEDStep token. * Returns a
		 * TheoremNode or ThmOrAssumpDefNode. * * The parsing into the syntactic tree
		 * makes it hard to rationalize * processing of an N_NumerableStep node because
		 * there are two * different ways such a step can be parsed * * 1. [step number]
		 * (sequence of tokens of the statement) [proof] * 2. [step number]
		 * (NonExprBody) [proof] * * where, in case 2, the NonExprBody node contains all
		 * the tokens of * the statement except the optional step number. Here are the *
		 * classes into which the different kinds of NumerableStep nodes fall. * * 1.
		 * CASE, (step number) expression. * * 2. WITNESS, TAKE, PICK, HAVE,
		 * ASSUME/PROVE, SUFFICES, * and PROVE expression *
		 ***********************************************************************/
		errors.addAbort(stn.getLocation(), "Uses generateNumerable_Step");
		UniqueString stepNum = null;
		TreeNode[] heirs = stn.heirs();
		int nextTok = 0;
		ThmOrAssumpDefNode tadn = null;
		boolean isSuffices = false;
		boolean isAssumeProve = false;
		/*********************************************************************
		 * Set true if this is an ASSUME/PROVE step, in which case some * messing with
		 * the symbol table is necessary so that symbols * declared in the ASSUME are
		 * visible in the proof of this step. * They should be visible in the rest of
		 * the proof iff this is a * SUFFICES ASSUME... step. *
		 *********************************************************************/
		Context assumeContext = null;
		/*********************************************************************
		 * For use with an ASSUME/PROVE. *
		 *********************************************************************/
		LevelNode body = null;
		/*********************************************************************
		 * This will be set to the body of the TheoremNode or * ThmOrAssumpDefNode. *
		 *********************************************************************/

		/***********************************************************************
		 * We now save the values of heirs and nextTok. If the tokens of the * statement
		 * are inside a NonExprBody node, we set heirs to the * children of that node,
		 * nextTok to 0, and hasNonExprBody true. * After processing the statement, we
		 * will reset heirs and set nextTok * to the its saved value plus 1. *
		 ***********************************************************************/
		TreeNode[] savedHeirs = heirs;
		int savedNextTok = nextTok;
		boolean hasNonExprBody = false;
		if (heirs[nextTok].getKind() == N_NonExprBody) {
			heirs = heirs[nextTok].heirs();
			nextTok = 0;
			hasNonExprBody = true;
		}
		;

		/***********************************************************************
		 * If next token is "SUFFICES", then skip over it and set isSuffices * true.
		 * With the current grammar, this is the case only for an * ordinary assertion
		 * (a statement or ASSUME/PROVE). *
		 ***********************************************************************/
		if (heirs[nextTok].getKind() == TLAplusParserConstants.SUFFICES) {
			nextTok++;
			isSuffices = true;
		}
		;

		/***********************************************************************
		 * Skip over the next token if it's "PROVE". With current grammar, * this only
		 * happens when nextTok = 0. *
		 ***********************************************************************/
		if (heirs[nextTok].getKind() == TLAplusParserConstants.PROVE) {
			nextTok++;
		}
		;

		/***********************************************************************
		 * If body will be an OpApplNode with a dummy operator (like $Pick), * then set
		 * op to the operator's name and move past the determining * token (like
		 * "PICK"). Otherwise, the body will be an ordinary * assertion and op is left
		 * null. *
		 ***********************************************************************/
		UniqueString op = null;
		switch (heirs[nextTok].getKind()) {
		case TLAplusParserConstants.QED:
			body = new OpApplNode(OP_qed, new ExprNode[0], heirs[nextTok], cm);
			nextTok++;
			break;

		case TLAplusParserConstants.CASE:
		case TLAplusParserConstants.HAVE:
			op = OP_have;
			if (heirs[nextTok].getKind() == TLAplusParserConstants.CASE) {
				op = OP_pfcase;
			}
			;
			nextTok++;
			ExprNode[] args = new ExprNode[1];
			args[0] = generateExpression(heirs[nextTok], cm);
			body = new OpApplNode(op, args, heirs[nextTok], cm);
			nextTok++;
			break;

		case TLAplusParserConstants.TAKE:
		case TLAplusParserConstants.PICK:
			op = OP_take;
			if (heirs[nextTok].getKind() == TLAplusParserConstants.PICK) {
				op = OP_pick;
			}
			;
			nextTok++;

			if (heirs[nextTok].getKind() == N_QuantBound) {
				int offset = nextTok;
				/*****************************************************************
				 * The introduced identifiers are bounded--e.g., * "TAKE id \in Set". *
				 *****************************************************************/
				/*****************************************************************
				 * Set quants to the number of N_QuantBound nodes. *
				 *****************************************************************/
				int quants = 1;
				nextTok++;
				while ((nextTok < heirs.length) && (heirs[nextTok].getKind() == TLAplusParserConstants.COMMA)) {
					quants++;
					nextTok = nextTok + 2;
				}
				;
				FormalParamNode[][] params = new FormalParamNode[quants][0];
				boolean[] bt = new boolean[quants];
				ExprNode[] paramBounds = new ExprNode[quants];
				processQuantBoundArgs(heirs, offset, params, bt, paramBounds, cm);

//          ExprNode[]          args ;
				if (op == OP_pick) {
					/****************************************************************
					 * This is a PICK step; get the ": expr". *
					 ****************************************************************/
					nextTok++; // Skip over the ":"
					args = new ExprNode[1];
					args[0] = generateExpression(heirs[nextTok], cm);
					nextTok++;
				} else {
					/****************************************************************
					 * This is a TAKE step. *
					 ****************************************************************/
					args = new ExprNode[0];
				}
				;
				body = new OpApplNode(op, null, args, params, bt, paramBounds, stn, cm);
			} else {
				/*****************************************************************
				 * The introduced identifiers are unbounded--e.g., * "TAKE id1, id2". *
				 *****************************************************************/
				/*****************************************************************
				 * Set ids to the number of introduced identifiers. *
				 *****************************************************************/
				int ids = 1;
				while ((nextTok + 2 * ids - 1 < heirs.length)
						&& (heirs[nextTok + 2 * ids - 1].getKind() == TLAplusParserConstants.COMMA)) {
					ids++;
				}
				;

				/*****************************************************************
				 * Set params to the array of new FormalParamNodes for the * identifiers. The
				 * identifiers are added to the current symbol * table. *
				 *****************************************************************/
				FormalParamNode[] params = new FormalParamNode[ids];
				for (int i = 0; i < ids; i++) {
					params[i] = new FormalParamNode(heirs[2 * i + nextTok].getUS(), 0, heirs[2 * i + nextTok],
							symbolTable, cm);
				}
				;
				/*****************************************************************
				 * Skip over the identifier-list tokens. *
				 *****************************************************************/
				nextTok = nextTok + 2 * ids - 1;

//          ExprNode[] args ;
				if (op == OP_pick) {
					/****************************************************************
					 * This is a PICK step; get the ": expr". *
					 ****************************************************************/
					nextTok++; // Skip over the ":"
					args = new ExprNode[1];
					args[0] = generateExpression(heirs[nextTok], cm);
					nextTok++;
				} else {
					/****************************************************************
					 * This is a TAKE step. *
					 ****************************************************************/
					args = new ExprNode[0];
				}
				;
				body = new OpApplNode(op, args, params, stn, cm);
			}
			;
			break;

		case TLAplusParserConstants.WITNESS:
			nextTok++;

			/*******************************************************************
			 * Set ids to the number of expressions. *
			 *******************************************************************/
			int ids = 1;
			while ((nextTok + 2 * ids - 1 < heirs.length)
					&& (heirs[nextTok + 2 * ids - 1].getKind() == TLAplusParserConstants.COMMA)) {
				ids++;
			}
			;
			ExprNode[] exprs = new ExprNode[ids];
			for (int i = 0; i < ids; i++) {
				exprs[i] = generateExpression(heirs[2 * i + nextTok], cm);
			}
			;

			body = new OpApplNode(OP_tup, exprs, stn, cm);
			nextTok = nextTok + 2 * ids - 1;
			break;

		default:
			/*******************************************************************
			 * This is an ordinary assertion--either an ExprNode or an * AssumeProve node. *
			 *******************************************************************/
			if (heirs[nextTok].getKind() == N_AssumeProve) {
				/*****************************************************************
				 * This is an AssumeProve node. * * For an ordinary ASSUME/PROVE, we need to
				 * save symbol * declarations from top-level NEW statements in the ASSUME to *
				 * make them visible only in the proof. If this is a SUFFICES * ASSUME/PROVE, we
				 * don't need to do that because we want those * symbol declarations to be
				 * visible outside the PROVE clause as * well. *
				 *****************************************************************/
				isAssumeProve = true;
				if (!isSuffices) {
					symbolTable.pushContext(new Context(moduleTable, errors));
// System.out.println("here") ;
				}
				;
// System.out.println("here and there") ;
				body = generateAssumeProve(heirs[nextTok], cm);
				if (!isSuffices) {
					assumeContext = symbolTable.getContext();
					symbolTable.popContext();
				}
				;
			} else {
				/*****************************************************************
				 * This is an ordinary expression. *
				 *****************************************************************/
				body = generateExpression(heirs[nextTok], cm);
			}
			;
			nextTok++;
			break;
		}
		; // switch

		/***********************************************************************
		 * Complete the ThmOrOpDefNode, if there is one. *
		 ***********************************************************************/
		if (stepNum != null) {
			// SZA: the next line commented, to prevent a NullPointerException
			// The method is not executed anyways.
			// tadn.construct(true, body, cm, symbolTable, null) ;
		}
		;

		/***********************************************************************
		 * Restore heirs and nextTok if the statement's tokens were inside a *
		 * NonExprBody node. *
		 ***********************************************************************/
		if (hasNonExprBody) {
			heirs = savedHeirs;
			nextTok = savedNextTok + 1;
		}
		;

		/***********************************************************************
		 * Set proof to the proof, or to null if there is none. There is no * check made
		 * to see if this is a kind of step that should have a * proof. Thus, adding a
		 * proof to something like a WITNESS statement * requires changing only the
		 * parsing phase (specified by tla+.jj). *
		 ***********************************************************************/
		ProofNode proof = null;
		if (heirs.length > nextTok) {
			if (isAssumeProve && !isSuffices) {
				symbolTable.pushContext(assumeContext);
			}
			;
			proof = generateProof(heirs[nextTok], cm);
			if (isAssumeProve && !isSuffices) {
				symbolTable.popContext();
			}
			;
		}
		;

		TheoremNode thm = new TheoremNode(stn, body, cm, proof, tadn);
		thm.suffices = isSuffices;
		return thm;

	} // generateNumerableStep

	private final LeafProofNode generateLeafProof(TreeNode stn, ModuleNode cm) throws AbortException {
		TreeNode heirs[] = stn.heirs();
		LevelNode[] facts;
		SymbolNode[] defs;
		int nextTok = 0;
		boolean omitted = false;

		/***********************************************************************
		 * Skip over an optional "PROOF" (which can occur in a BY statement). *
		 ***********************************************************************/
		if (heirs[0].getKind() == TLAplusParserConstants.PROOF) {
			nextTok++;
		}
		;

		boolean isOnly = false;

		if (heirs[nextTok].getKind() == TLAplusParserConstants.BY) {
			/*********************************************************************
			 * For a BY proof, call generate a UseOrHideNode and use its facts * and defs
			 * field. *
			 *********************************************************************/
			UseOrHideNode uh = generateUseOrHide(stn, cm);
			isOnly = uh.isOnly;
			facts = uh.facts;
			defs = uh.defs;
			/*********************************************************************
			 * The following check added by LL on 16 Feb 2009. *
			 *********************************************************************/
			if (facts.length + defs.length == 0) {
				errors.addError(stn.getLocation(), "Empty BY");
			}
			;
		} else {
			facts = new LevelNode[0];
			defs = new SymbolNode[0];
			if (heirs[nextTok].getKind() == TLAplusParserConstants.OMITTED) {
				omitted = true;
			}
			;
		}
		;
		return new LeafProofNode(stn, facts, defs, omitted, isOnly);
	}

	UseOrHideNode generateUseOrHide(TreeNode stn, ModuleNode cm) throws AbortException {
		/***********************************************************************
		 * Since a BY statement currently has essentially the same syntax as * USE and
		 * HIDE, this is also used to parse a BY statement. If given * a BY statement,
		 * it returns a UseOrHideNode that will be used to * form the LeafProofNode (and
		 * then thrown away). *
		 ***********************************************************************/
		int kind = UseKind;
		TreeNode heirs[] = stn.heirs();

		boolean isOnly = false;
		/*********************************************************************
		 * True iff this is an "ONLY" step--either a BY ONLY or a USE ONLY. * However,
		 * we may decide not to include USE ONLY in the language, * which wil require a
		 * simple modification of the javacc code. *
		 *********************************************************************/

		if (heirs[0].getKind() == TLAplusParserConstants.HIDE) {
			kind = HideKind;
		}
		;

		int nextTok = 1;

		/***********************************************************************
		 * Skip over an optional "PROOF" (which can occur in a BY statement). *
		 ***********************************************************************/
		if (heirs[0].getKind() == TLAplusParserConstants.PROOF) {
			nextTok++;
		}
		;

		if (nextTok >= heirs.length) {
			errors.addError(stn.getLocation(), "Empty BY, USE, or HIDE");
			return new UseOrHideNode(kind, stn, new LevelNode[0], new SymbolNode[0], isOnly);
		}
		Vector vec = new Vector();
		/*********************************************************************
		 * To hold the facts and then the defs. *
		 *********************************************************************/

		if (heirs[nextTok].getKind() == TLAplusParserConstants.ONLY) {
			isOnly = true;
			nextTok++;
		}
		;

		/***********************************************************************
		 * Get the facts. *
		 ***********************************************************************/
		while ((nextTok < heirs.length) && (heirs[nextTok].getKind() != TLAplusParserConstants.DF)) {
			if (heirs[nextTok].getKind() == TLAplusParserConstants.MODULE) {
				nextTok++;
				UniqueString moduleId = heirs[nextTok].getUS();
				ModuleNode moduleNode = symbolTable.resolveModule(moduleId);

				/*******************************************************************
				 * The following added 16 Oct 2007 to allow a fact to be the * current module.
				 * This will probably mean to use or hide facts * introduced so far in the
				 * current module. *
				 *******************************************************************/
				if ((moduleNode == null) && (moduleId == cm.getName())) {
					moduleNode = cm;
				}
				;
				if (moduleNode != null) {
					vec.addElement(moduleNode);
				} else {
					errors.addError(heirs[nextTok].getLocation(),
							"Module `" + moduleId + "' used without being extended or instantiated.");
				}
			} // if
			else {
				/*******************************************************************
				 * If the this token is an N_GeneralId, then we generate it here * using
				 * selectorToNode so we can call that method with the isFact * argument true.
				 * Otherwise, we just call generateExpression. *
				 *******************************************************************/
				if (heirs[nextTok].getKind() == N_GeneralId) {
					/*****************************************************************
					 * Here, we are using the fact that a theorem name must be a * GeneralId and not
					 * something like an N_GenInfixOp. *
					 *****************************************************************/
					vec.addElement(
							selectorToNode(genIdToSelector((SyntaxTreeNode) heirs[nextTok]), 0, true, false, cm));
				} else if (heirs[nextTok].getKind() == N_AssumeProve) {
					vec.addElement(generateAssumeProve(heirs[nextTok], cm));
				} else {
					vec.addElement(generateExpression(heirs[nextTok], cm));
				} // else
			} // else
			nextTok++;
			if ((nextTok < heirs.length) && (heirs[nextTok].getKind() == TLAplusParserConstants.COMMA)) {
				nextTok++;
			}
			;
		}
		; // while
		LevelNode[] facts = new LevelNode[vec.size()];
		for (int i = 0; i < vec.size(); i++) {
			facts[i] = (LevelNode) vec.elementAt(i);
		}
		;

		/***********************************************************************
		 * Get the defs. *
		 ***********************************************************************/
		SymbolNode[] defs;
		if (nextTok >= heirs.length) {
			defs = new SymbolNode[0];
		} else {
			vec = new Vector();
			nextTok++;
			while (nextTok < heirs.length) {
				if (heirs[nextTok].getKind() == TLAplusParserConstants.MODULE) {
					nextTok++;
					UniqueString moduleId = heirs[nextTok].getUS();
					ModuleNode moduleNode = symbolTable.resolveModule(moduleId);

					/*****************************************************************
					 * The following added 16 Oct 2007 to allow a fact to be the * current module.
					 * This will probably mean to use or hide * definitions introduced so far in the
					 * current module. *
					 *****************************************************************/
					if ((moduleNode == null) && (moduleId == cm.getName())) {
						moduleNode = cm;
					}
					;
					if (moduleNode != null) {
						vec.addElement(moduleNode);
					} else {
						errors.addError(heirs[nextTok].getLocation(),
								"Module `" + moduleId + "' used without being extended or instantiated.");
					}
				} // if
				else {
					Selector sel = genIdToSelector((SyntaxTreeNode) heirs[nextTok]);
					SemanticNode selToNd = selectorToNode(sel, -1, false, true, cm);
					if ((selToNd instanceof OpDefNode) || ((selToNd instanceof ThmOrAssumpDefNode) && // This conjunct
																										// added 4 Feb
																										// 2015 by LL to
																										// forbid step
																										// names in a
																										// DEF clause.
							(((ThmOrAssumpDefNode) selToNd).getName().toString().charAt(0) != '<'))) {
						SymbolNode def = (SymbolNode) selToNd;
						vec.addElement(def);
					} else {
						/***************************************************************
						 * This error is redundant, because it should have been caught * in
						 * selectorToNode. But a little redundancy can't hurt. * But a little redundancy
						 * can't hurt. *
						 ***************************************************************/
						errors.addError(heirs[nextTok].getLocation(),
								"DEF clause entry should describe a defined operator.");
					} // else
				} // else
				nextTok++;
				if ((nextTok < heirs.length) && (heirs[nextTok].getKind() == TLAplusParserConstants.COMMA)) {
					nextTok++;
				}
				;
			}
			; // while
			defs = new SymbolNode[vec.size()];
			for (int i = 0; i < vec.size(); i++) {
				defs[i] = (SymbolNode) vec.elementAt(i);
			}
			;
		} // else of if (nextTok >= heirs.length)
		return new UseOrHideNode(kind, stn, facts, defs, isOnly);
	} // generateUseOrHide

	void processRecursive(TreeNode tn, ModuleNode cm) {
		/***********************************************************************
		 * Process a RECURSIVE statement. Creates an OpDefNode for each of * the
		 * declared operators. *
		 ***********************************************************************/
		TreeNode[] children = tn.heirs();

		/***********************************************************************
		 * Increment unresolvedCnt unresolvedSum, and, if necessary, *
		 * recursiveSectionCount. This needs to be done before the calls to *
		 * startOpDefNode so that we are in a recursive section when it is * called.
		 * Note that for * * RECURSIVE op_1, ... , op_n * * children is the sequence of
		 * tokens * * "RECURSIVE", op_1, ",", ... , "," , op_n * * so children.length =
		 * 2*n and n = children.length / 2. *
		 ***********************************************************************/
		if (unresolvedSum == 0) {
			recursiveSectionCount++;
		}
		;
		int numOfDecls = children.length / 2;
		unresolvedCnt[curLevel] = unresolvedCnt[curLevel] + numOfDecls;
		unresolvedSum = unresolvedSum + numOfDecls;

		for (int i = 1; i < children.length; i = i + 2) {
			/*********************************************************************
			 * Process the i-th declaration in the RECURSIVE statement. *
			 *********************************************************************/
			TreeNode declNode = children[i];

			/*********************************************************************
			 * Set odn to an OpDeclNode made from the i-th declaration. *
			 *********************************************************************/
			OpDeclNode odn = buildParameter(declNode, ConstantDeclKind, // Value of argument doesn't matter.
					ConstantLevel, // Value of argument doesn't matter.
					cm, false); // Not adding OpDeclNode to symbolTable

			/*********************************************************************
			 * Set params to the array of parameters for the declared operator's *
			 * OpDefNode. *
			 *********************************************************************/
			FormalParamNode[] params = new FormalParamNode[odn.getArity()];
			for (int ip = 0; ip < params.length; ip++) {
				params[ip] = new FormalParamNode(null, 0, null, null, cm);
			}
			;
			OpDefNode node = startOpDefNode(odn.getName(), declNode, UserDefinedOpKind, params, false, // localness
					cm, symbolTable);
			/******************************************************************
			 * This node isn't saved anywhere. It will be found either by * looking up the
			 * operator when the N_OperatorDefinition node is * encountered, or else by
			 * looking through the module's * recursiveDecls vector when it is discovered
			 * that some operator * has been declared but not defined (by finding
			 * unresolvedCnt > * 0 when coming to the end of a LET or of the module). *
			 ******************************************************************/
			cm.recursiveOpDefNodes.addElement(node);

		} // for (int i = 1 ...)
	}

	/***************************************************************************
	 * LABEL HANDLING * * The following methods are used to create the labels fields
	 * of OpDefNode * and LabelNode objects. They are specified in terms of an
	 * abstract data * object LS which is an element of * * Seq( [labels : SUBSET
	 * LabelNode, * paramSeq : Seq (SUBSET OpDeclNode)] ) * * Thus, for all i \in
	 * 1..Len(LS) : * LS[i].labels is a set of LabelNode objects * LS[i].paramSeq is
	 * a sequence of sets of OpDeclNode objects. * * Initially, LS equals the empty
	 * sequence << >>. * * We define * Front(LS) == [i \in 1..Len(LS-1) |-> LS[i]] *
	 * Last(LS) == LS[Len(LS)] * * LS is a stack containing one element for each
	 * OpDefNode and LabelNode * within which we are currently processing nodes,
	 * where Last(LS) is the * inner-most such node. Last(LS).paramSeq is a stack
	 * containing one * element for each node that comes between the the preceding
	 * OpDefNode or * LabelNode and the current node that introduces bound
	 * variables. * Last(LS).paramSeq[j] is the set of bound variables introduced by
	 * the * j-th such node, where Last(Last(LS).paramSeq) is the most recent such *
	 * set of bound variables. *
	 ***************************************************************************/

	/***************************************************************************
	 * Code for handling labels was added in the following methods: *
	 * generateAssumeProve * generateLambda * processTheorem * processAssumption *
	 * processOperator * processFunction * processChoose * processBoundQuant *
	 * processUnboundQuant * processSubsetOf * processSetOfAll * processFcnConst *
	 * generateExpression * generateProof *
	 ***************************************************************************/

	LabelNode generateLabel(TreeNode stn, ModuleNode cm) throws AbortException {

		boolean isAssumeProve = false;
		/*********************************************************************
		 * Set true iff this is a labeled ASSUME/PROVE. *
		 *********************************************************************/

		if (!inOpDefNode()) {
			errors.addError(stn.getLocation(), "Label not in definition or proof step.");
			return nullLabelNode;
		}
		;

		if (noLabelsAllowed()) {
			errors.addError(stn.getLocation(),
					"Label not allowed within scope of declaration in " + "nested ASSUME/PROVE.");
			return nullLabelNode;
		}
		;

		/***********************************************************************
		 * For now at least, and probably forever, we are not allowing an * expression
		 * to be labeled if it lies inside an EXCEPT clause--which * means if it is used
		 * where an "@" could appear. The test for this * is taken from
		 * generateExpression. *
		 ***********************************************************************/
		if (!((excStack.empty() || excSpecStack.empty()))) {
			errors.addError(stn.getLocation(), "Labels inside EXCEPT clauses are not yet implemented.");
			return nullLabelNode;
		}
		;

		TreeNode[] labelExpChildren = stn.heirs();

		/***********************************************************************
		 * We first process the body, since we need it to create the LabelNode. *
		 ***********************************************************************/
		pushLS();
		LevelNode body;
		if (labelExpChildren[2].getKind() == N_AssumeProve) {
			body = generateAssumeProve(labelExpChildren[2], cm);
			isAssumeProve = true;
		} else {
			body = generateExpression(labelExpChildren[2], cm);
		}
		;
		Hashtable ht = popLabelNodeSet();

		/***********************************************************************
		 * We now create the LabelNode. *
		 ***********************************************************************/
		UniqueString name;
		FormalParamNode[] params;
		/*********************************************************************
		 * The label's name and parameter list. *
		 *********************************************************************/
		if (labelExpChildren[0].getKind() == N_GeneralId) {
			/*********************************************************************
			 * There are no arguments to the label. *
			 *********************************************************************/
			name = labelExpChildren[0].heirs()[1].getUS();
			params = new FormalParamNode[0];
		} else {
			/**********************************************************************
			 * The label should be represented as an N_OpApplication node. *
			 **********************************************************************/
			if (labelExpChildren[0].getKind() != N_OpApplication) {
				throw new WrongInvocationException("Label has unexpected syntax tree kind.");
			}
			;

			TreeNode[] opApplChildren = labelExpChildren[0].heirs();
			name = opApplChildren[0].heirs()[1].getUS();
			TreeNode[] opArgsChildren = opApplChildren[1].heirs();
			int numOfParams = (opArgsChildren.length - 1) / 2;
			params = new FormalParamNode[numOfParams];
			for (int i = 0; i < numOfParams; i++) {
				/*******************************************************************
				 * We have to get the FormalParamNode objects for the parameter * array params
				 * by looking them up in the current context, since * they could be either
				 * ConstantLevel (normal case) or StateLevel * (if they're introduced in a \AA
				 * or \EE expression). *
				 *******************************************************************/
				TreeNode argSyntaxNode = opArgsChildren[2 * i + 1];
				UniqueString argName = argSyntaxNode.heirs()[1].getUS();
				SymbolNode argNode = symbolTable.resolveSymbol(argName);
				FormalParamNode arg = null;
				if (argNode instanceof FormalParamNode) {
					arg = (FormalParamNode) argNode;
				} else {
					errors.addError(argSyntaxNode.getLocation(),
							"Illegal parameter " + argName.toString() + " of label `" + name.toString() + "'.");
					arg = new FormalParamNode(argName, 0, argSyntaxNode, null, cm);
					/**********************************************************
					 * Create a dummy FormalParamNode to prevent a null * pointer exception in later
					 * processing. *
					 **********************************************************/
				}
				;
				params[i] = arg;
			} // for
		}
		; // else
		SemanticNode cg = null;
		if (assumeProveDepth > 0) {
			cg = currentGoal;
		}
		;
		LabelNode retVal = new LabelNode(stn, name, params, currentGoal, currentGoalClause, body, isAssumeProve);
		retVal.setLabels(ht);
		boolean ignore = formalParamsEqual(retVal);
		/*********************************************************************
		 * We throw away the return value because if there's an error, it is * reported
		 * by the method. *
		 *********************************************************************/
		if (!addLabelNodeToSet(retVal)) {
			errors.addError(stn.getLocation(), "Duplicate label `" + name.toString() + "'.");
		}
		;
		return retVal;
	} // generateLabel

	Vector LSlabels = new Vector();
	/***********************************************************************
	 * LSlabels.elementAt(i) is a HashTable that represents * LS.labels[i+1]. The
	 * values in the Hashtable are LabelNode objects, * where ln.getName() is the
	 * key of object ln. The empty set is * represented by null. *
	 ***********************************************************************/

	Vector LSparamSeq = new Vector();

	/***********************************************************************
	 * LsparamSeq.elementAt(i) is a Vector whose elements are of type *
	 * FormalParamNode[] that represents LS.paramSeq[i+1]. In particular *
	 * LS.paramSeq[i+1][j+1] equals * LET foo == (FormalParamNode[]) * ((Vector)
	 * LsparamSeq.elementAt(i))).elementAt(j) * IN { (FormalParamNode) foo[j] : j
	 * \in 0 .. foo.length} *
	 ***********************************************************************/

	void pushLS() {
		/***********************************************************************
		 * Implements LS' = Append(LS, [labels |-> {}, paramSeq |-> << >>]) * That is,
		 * it pushes an "empty" record onto the end of LS. *
		 ***********************************************************************/
		LSlabels.addElement(null);
		LSparamSeq.addElement(new Vector());
	}

	Hashtable popLabelNodeSet() {
		/***********************************************************************
		 * Implements LS' = Front(LS) * return Last(LS).labels *
		 ***********************************************************************/
		int size = LSlabels.size();
		if (size == 0) {
			throw new WrongInvocationException("popLabelNodeSet called on empty stack.");
		}
		;
		Hashtable retVal = (Hashtable) LSlabels.elementAt(size - 1);
		LSlabels.removeElementAt(size - 1);
		LSparamSeq.removeElementAt(size - 1);
		return retVal;
	}

	boolean addLabelNodeToSet(LabelNode ln) {
		/***********************************************************************
		 * Implements * LET succ == \A eln \in Last(LS).labels : eln.name # ln.name * IN
		 * LS' = IF succ THEN [LS EXCEPT * ![Len(LS)].labels = @ \cup {ln}] * ELSE
		 * Labeling Stack * return succ * That is, it adds LabelNode ln to
		 * Last(LS).labels iff there is not * already a LabelNode with the same name in
		 * it, otherwise do nothing. * It returns true iff ln was added. *
		 ***********************************************************************/
		int size = LSlabels.size();
		if (size == 0) {
			throw new WrongInvocationException("addLabelNodeToSet called on empty stack.");
		}
		;
		Hashtable ht = (Hashtable) LSlabels.elementAt(size - 1);
		if (ht == null) {
			ht = new Hashtable();
			LSlabels.setElementAt(ht, size - 1);
		}
		boolean retVal = !ht.containsKey(ln.getName());
		if (retVal) {
			ht.put(ln.getName(), ln);
		}
		;
		return retVal;
	}

	void pushFormalParams(FormalParamNode[] odns) {
		/***********************************************************************
		 * Implements * * LS' = IF LS # << >> * THEN [LS EXCEPT ![Len(LS)].paramSeq = *
		 * Append(@, {odns[i] : i \in DOMAIN odns)] * ELSE LS * * That is, if LS is not
		 * empty, then it pushes the set of * FormalParamNode objects in the array odns
		 * onto the end of * Last(LS).paramSeq. *
		 ***********************************************************************/
		if (!inOpDefNode()) {
			return;
		}
		;
		Vector lastFormalParams = (Vector) LSparamSeq.elementAt(LSparamSeq.size() - 1);
		lastFormalParams.addElement(odns);
	}

	void popFormalParams() {
		/***********************************************************************
		 * Implements * * LS' = IF LS # << >> * THEN [LS EXCEPT ![Len(LS)].paramSeq =
		 * Front(@)] * ELSE LS * That is, if LS is not empty, then it removes the last
		 * item from * Last(LS).paramSeq. *
		 ***********************************************************************/
		if (!inOpDefNode()) {
			return;
		}
		;
		Vector lastFormalParams = (Vector) LSparamSeq.elementAt(LSparamSeq.size() - 1);
		int size = lastFormalParams.size();
		if (size == 0) {
			throw new WrongInvocationException("popFormalParams called on empty stack.");
		}
		;
		lastFormalParams.removeElementAt(size - 1);
	}

	boolean formalParamsEqual(LabelNode ln) {
		/***********************************************************************
		 * Returns LET odns == ln.params * IN /\ \A i, j \in DOMAIN odns : * (i # j) =>
		 * odns[i] # odns[j] * /\ {odns[i] : i \in DOMAINE odns} = * UNION
		 * {Last(LS).parmSeq[i] : * i \in DOMAIN Last(LS).parmSeq} * That is, it returns
		 * true iff all the FormalParamNode objects in * odns are distinct and the set
		 * of all thos objects equals the union * of all the sets in the sequence
		 * Last(LS).paramSeq. * * If this returns false, then an error message explains
		 * why. *
		 ***********************************************************************/
		boolean retVal = true;
		HashSet opParams = new HashSet();
		FormalParamNode[] odns = ln.params;
		for (int i = 0; i < odns.length; i++) {
			if (!opParams.add(odns[i])) {
				retVal = false;
				errors.addError(ln.stn.getLocation(), "Repeated formal parameter " + odns[i].getName().toString()
						+ " \nin label `" + ln.getName().toString() + "'.");
			}
			;
		} // for ;
		Vector lastFormalParams = (Vector) LSparamSeq.elementAt(LSparamSeq.size() - 1);
		int size = lastFormalParams.size();
		for (int i = 0; i < size; i++) {
			FormalParamNode[] ops = (FormalParamNode[]) lastFormalParams.elementAt(i);
			for (int j = 0; j < ops.length; j++) {
				if (!opParams.remove(ops[j])) {
					retVal = false;
					errors.addError(ln.stn.getLocation(), "Label " + ln.getName().toString()
							+ " must contain formal parameter `" + ops[j].getName().toString() + "'.");
				}
				;
			} // for j;
		} // for i;
		if (!opParams.isEmpty()) {
			retVal = false;
			Iterator iter = opParams.iterator();
			String res = "Label " + ln.getName().toString() + " declares extra parameter(s)  ";
			while (iter.hasNext()) {
				FormalParamNode nd = (FormalParamNode) iter.next();
				res = res + nd.getName().toString() + "  ";
			} // while
			errors.addError(ln.stn.getLocation(), res);
		} // if
		return retVal;
	}

	boolean inOpDefNode() {
		return LSlabels.size() > 0;
	}

	/***********************************************************************
	 * Returns true iff LS is not equal to the empty sequence << >>. *
	 ***********************************************************************/

	FormalParamNode[] flattenParams(FormalParamNode[][] array) {
		/***********************************************************************
		 * Flatten a 2-dimensional array of FormalParamNodes into a * 1-dimensional
		 * array. Used because the oan.boundedBoundSymbols * field for an OpApplNode is
		 * such a 2-dimensional array, since * "bounded bound symbols" may be tuples. *
		 ***********************************************************************/
		int size = 0;
		for (int i = 0; i < array.length; i++) {
			size = size + array[i].length;
		}
		;
		FormalParamNode[] res = new FormalParamNode[size];
		int k = 0;
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				res[k] = array[i][j];
				k++;
			}
			; // for j
		}
		; // for i
		return res;
	}

	/***************************************************************************
	 * Recursion Processing * * This is the code for setting the fields of OpDefNode
	 * objects that are * related to recursion--namely, letInLevel, inRecursive, *
	 * inRecursiveSection. See the description of these fields in *
	 * semantic/OpDefNode.java to see what they mean. * * A tool might also want to
	 * compute the strongly connected components of * the dependency graph--the
	 * graph of OpDefNode objects containing an edge * from n to m iff m's operator
	 * appears in the body of n. * * I originally thought that the dependency graph
	 * could be created while * the semantic graph was being constructed, and that
	 * the strongly * connected components could be computed incrementally by
	 * running a * connected-component algorithm at the end of each recursive
	 * section. I * thought that could be done easily by creating an OpDefNode for a
	 * * definition before processing the definition's body, and adding to a * field
	 * in that OpDefNode a list of the OpDefNodes that appeared in * OpApplNodes in
	 * the body. However, that didn't work because of * definitions like * * f ==
	 * LET f == ... * IN ... * * So, I abandoned that idea. It's probably easiest to
	 * compute the * connected components after the module is processed. * * If we
	 * ever do want to construct those connected components, we can run * a version
	 * of Tarjan's algorithm for computing strongly connected * components of a
	 * directed graph. A +cal coding of this algorithm is in * the file Tarjan.tla,
	 * a copy of which appears as a comment at the end of * this file. *
	 ***************************************************************************/

	/***************************************************************************
	 * The fields. *
	 ***************************************************************************/
	final int MaxLetInLevel = 100;
	/***********************************************************************
	 * It seems safe to assume that LETs won't be nested more than 100 * deep, so we
	 * can use arrays instead of having to deal with vectors * to allow arbitrary
	 * depths. *
	 ***********************************************************************/

	int curLevel = 0;
	/***********************************************************************
	 * The current LET/IN nesting level--that is, the number of LET/IN * statements
	 * within which the nodes we are currently processing lie. *
	 ***********************************************************************/

	int[] unresolvedCnt = new int[MaxLetInLevel];
	/***********************************************************************
	 * For i \in 0..curLevel, the value of unresolvedCnt[i] is the number * of
	 * operators declared in RECURSIVE statements at let/in level i that * have not
	 * yet been defined. *
	 ***********************************************************************/

	int unresolvedSum = 0;
	/***********************************************************************
	 * Equals the sum from i = 0 to curLevel of unresolvedCnt[i]. *
	 ***********************************************************************/

	int recursiveSectionCount = 0;
	/***********************************************************************
	 * This field is incremented whenever a new recursive section is * begun--that
	 * is, when unresolvedSum changes from 0 to a positive * value (which must be
	 * 1). *
	 ***********************************************************************/

//  Code to construct dependence graph removed by LL on 7 Apr 2007
//  OpDefNode[] defStack = new OpDefNode[MaxLetInLevel] ;
//  int defStackLen ;
//    /***********************************************************************
//    * The elements defStack[0] ... defStack[defStackLen-1] form the stack  *
//    * of OpDefNode objects representing definitions being processed.  For  *
//    * example, in                                                          *
//    *                                                                      *
//    *    Foo == LET Bar == LET FB == exp ..                                *
//    *                                                                      *
//    * while processing exp the stack will contain the OpDefNode objects    *
//    * for Foo, Bar, and FB. This stack is used to construct the nbrs       *
//    * field of the OpDefNode objects on the stack.                         *
//    *                                                                      *
//    * Note that defStackLen \leq curLevel.  It may be strictly less        *
//    * because we could be in the IN clause of some of the nested LET/IN    *
//    * statements.                                                          *
//    ***********************************************************************/

// Was put into the ModuleNode object, since otherwise it would contain
// nodes from all inner modules.
//  Vector recursiveDecls = new Vector(100) ;
//    /***********************************************************************
//    * The set of OpDefNode objects that originally appeared in a           *
//    * RECURSIVE declaration.  For now, it is used only to find operators   *
//    * that were declared in a RECURSIVE declaration but never defined.     *
//    * Perhaps some other use will be found for it, in which case it        *
//    * should be put into the module's ModuleNode object.                   *
//    ***********************************************************************/

	int max_dfs = 0;
	/***********************************************************************
	 * A variable used in the Tarjan algorithm. *
	 ***********************************************************************/

	Vector nstack = new Vector(10);
	/***********************************************************************
	 * A vector of OpDefNode objects, representing the stack of the Tarjan *
	 * algorithm. *
	 ***********************************************************************/

	int moduleNestingLevel = -1;

	/***********************************************************************
	 * When processing a module, this is its nesting level--that is, its * depth in
	 * the tree of inner modules of the outermost module. *
	 ***********************************************************************/

	/***************************************************************************
	 * Methods. *
	 ***************************************************************************/
	OpDefNode startOpDefNode(UniqueString us, TreeNode tn, int kind, FormalParamNode[] params, boolean localness,
			ModuleNode oModNode, SymbolTable st) {
		/***********************************************************************
		 * Called to create an OpDefNode for a RECURSIVE declaration. The * params
		 * argument should be an array of dummy FormalParamNode * objects, with null
		 * names. The OpDefNode's setParams method should * be used to add the actual
		 * formal parameter's to the object. * * Note: for an operator declared in a
		 * RECURSIVE statement, this * method is called when processing that statement
		 * with the Treenode * tn equal to the syntax tree node for the declaration. *
		 ***********************************************************************/
		OpDefNode odn = new OpDefNode(us, UserDefinedOpKind, params, localness, null, // the expression
				oModNode, st, tn, false, null);
//  was incrementing it twice
//    unresolvedCnt[curLevel] ++ ;
//    unresolvedSum = unresolvedSum ++ ;

		oModNode.recursiveDecls.addElement(odn);

		odn.letInLevel = curLevel;
		odn.inRecursive = true;
		odn.inRecursiveSection = true;
		odn.recursiveSection = recursiveSectionCount;
		oModNode.opDefsInRecursiveSection.addElement(odn);

// the participating and nbrs field have been removed from OpDefNode objects
//    odn.participating      = true ;
//    odn.nbrs               = new Vector(10);

//  Code to construct dependence graph removed by LL on 7 Apr 2007
//      if (! recursive) {
//        defStack[defStackLen] = odn ;
//        defStackLen ++ ;
//       } ;
		return odn;
	}

	void endOpDefNode(OpDefNode nd, ExprNode exp, TreeNode stn) {
		/***********************************************************************
		 * Called to complete the creation of an OpDefNode nd that was created * by an
		 * invocation of startOpDefNode. If we are processing recursive * definitions,
		 * then it modifies unresolvedCnt and unresolvedSum if * necessary. * * When
		 * called for an operator not declared in a RECURSIVE statement, * the TreeNode
		 * stn is the same one that startOpDefNode was called * with to create the
		 * OpDefNode. *
		 ***********************************************************************/
		nd.isDefined = true;

		/***********************************************************************
		 * Set the node's body and syntax-tree node. *
		 ***********************************************************************/
		nd.setBody(exp);
		nd.stn = stn;

//  Code to construct dependence graph removed by LL on 7 Apr 2007
//    if (unresolvedSum > 0) {
//      /*********************************************************************
//      * Pop OpDefNode off defStack.                                        *
//      *********************************************************************/
//      defStackLen -- ;
//     } ;

		if (nd.inRecursive) {
			unresolvedCnt[curLevel]--;
			unresolvedSum--;
//  Code to construct dependence graph removed by LL on 7 Apr 2007
//      if (unresolvedSum == 0) {
//        tarjan() ; 
//        for (int i = 0 ; i < participants.size(); i++) {        
//          ((OpDefNode) participants.elementAt(i)).participating = false ;
//         } ; // for
//        participants = new Vector(100) ;
//       } // if (unresolvedSum == 0)
			if (unresolvedSum < 0) {
				throw new WrongInvocationException(
						"Defined more recursive operators than were declared " + "in RECURSIVE statements.");
			}
			;
		} // if (nd.inRecursive)
	}

//  Code to construct dependence graph removed by LL on 7 Apr 2007
//  void registerSymbolNode(SymbolNode nd) {
//    /***********************************************************************
//    * Called upon creating an OpApplNode whose operator has SymbolNode     *
//    * nd.  If we are processing recursive definitions, and if nd is an     *
//    * OpDefNode that is a participant, then nd is added to dfnd.nbrs, for  *
//    * every node dfnd in defStack (if it's not already there).             *
//    ***********************************************************************/
//    if (   (unresolvedSum > 0)
//        && (nd instanceof OpDefNode)) {
//        OpDefNode odn = (OpDefNode) nd ;
//        if (odn.participating) {
//          for (int i = 0 ; i < defStackLen ; i++) {
//            defStack[i].nbrs.addElement(odn) ;
//           } ;
//         } ; // if
//     } ; // if
//   }

//  Code to construct dependence graph removed by LL on 7 Apr 2007
//  SymbolNode findSymbol(UniqueString name) {
//    /***********************************************************************
//    * To gather the data needed to compute the dependence graph, when      *
//    * processing a definition, the operator being defined is put into the  *
//    * symbol table before the body of the definition is processed.         *
//    * However, if the operator is not declared in a RECURSIVE statement,   *
//    * a use of it in the body must be reported as an error.  To do this,   *
//    * calls that of symbolTable.resolveSymbol have been replaced by calls  *
//    * to findSymbol, which checks if the found symbol is not defined or    *
//    * declared at this point, and returns null if that is the case.        *
//    ***********************************************************************/
//    SymbolNode nd = symbolTable.resolveSymbol(name) ;
//    if ((nd != null) && (nd instanceof OpDefNode)) {
//      OpDefNode ond = (OpDefNode) nd ;
//      if ((!ond.isDefined) && (!ond.inRecursive)) { nd = null; } ;
//     };
//    return nd ;
//   } // findSymbol

	void setOpDefNodeRecursionFields(OpDefNode odn, ModuleNode cm) {
		/***********************************************************************
		 * Called to set the field odn.letInLevel and the fields * odn.recursiveSection
		 * and odn.inRecursiveSection if they need * non-default values, and to add odn
		 * to cm.opDefsInRecursiveSection * if necessary. *
		 ***********************************************************************/
		odn.letInLevel = curLevel;
		if (unresolvedSum > 0) {
			odn.recursiveSection = recursiveSectionCount;
			odn.inRecursiveSection = (unresolvedCnt[curLevel] > 0);
			cm.opDefsInRecursiveSection.addElement(odn);
		}

	}

	void checkIfInRecursiveSection(TreeNode tn, String type) {
		/***********************************************************************
		 * Report an error if we are in a recursive section--between an * operator's
		 * declaration in a RECURSIVE statement and its definition. *
		 ***********************************************************************/
		if (unresolvedSum > 0) {
			errors.addError(tn.getLocation(), type + " may not appear within " + "a recursive definition section.");
		}
	}

	void checkForUndefinedRecursiveOps(ModuleNode cm) {
		/***********************************************************************
		 * Called at the end of a LET clause and at the end of processing a * module to
		 * check for operators that were declared in a RECURSIVE * statement but not
		 * defined. It calls errors.addError to report any * that it finds. *
		 ***********************************************************************/
		/***********************************************************************
		 * The number of operators declared in RECURSIVE statements within the * LET but
		 * not defined equals unresolvedCnt[curLevel]. *
		 ***********************************************************************/
		if (unresolvedCnt[curLevel] > 0) {
			/*********************************************************************
			 * Go through the module's recursiveDecls vector to find all symbols * declared
			 * at the current LET/IN level but not defined. *
			 *********************************************************************/
			for (int i = 0; i < cm.recursiveDecls.size(); i++) {
				OpDefNode odn = (OpDefNode) cm.recursiveDecls.elementAt(i);
				if ((odn.letInLevel == curLevel) && odn.inRecursive && (!odn.isDefined)) {
					errors.addError(odn.getTreeNode().getLocation(),
							"Symbol " + odn.getName().toString() + " declared in RECURSIVE statement but not defined.");
				}
				;
			}
			; // for

			unresolvedSum = unresolvedSum - unresolvedCnt[curLevel];
			/*******************************************************************
			 * Need to update unresolvedSum correct because we are effectively * setting
			 * unresolvedCnt[curLevel] to 0. *
			 *******************************************************************/
		}
		; // if (unresolvedCnt[curLevel] > 0)
	}

//  void tarjan() {
//    /***********************************************************************
//    * This is the Java version of the algorithm in the file Tarjan.tla, a  *
//    * copy of which appears below.                                         *
//    ***********************************************************************/
///***************************************************************************
//* XXXXXX: Not yet implemented.                                             *
//***************************************************************************/
//   }

}

/************************
 * file Tarjan.tla ***********************************
 * ------------------------------ MODULE Tarjan --------------------------------
 * (***************************************************************************)
 * (* This version of Tarjan's algorithm for computing the strongly *) (*
 * connected components of a directed graph was adapted from the version *) (*
 * of 27 Mar 2007 on the Wikipedia page *) (* *) (*
 * http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
 * *) (* *) (* One modification is that the set of connected components it
 * returns *) (* does not contain a singleton {n} unless n has an edge pointing
 * to *) (* itself. *) (* *) (* This is an implementation of the algorithm in
 * Tarjan.tla with data *) (* structures that correspond to the ones used in the
 * algorithm for *) (* constructing dependency components in semantic/Generator.
 * *) (* *) (* *) (* I have not rigorously verified this algorithm, but I think
 * I understand *) (* why it works. I have tested it only on the 10 graphs at
 * the end of *) (* this file. *)
 * (***************************************************************************)
 * 
 * EXTENDS Integers, Sequences, TLC
 * 
 * CONSTANT N, \* The number of nodes Neighbors \* A sequence of edges.
 * 
 * Node == 1..N
 * 
 * ASSUME Neighbors \in Seq(Node \X Node)
 * 
 * Min(a, b) == IF a < b THEN a ELSE b
 * 
 * Front(s) == [i \in 1 .. (Len(s)-1) |-> s[i]]
 * (*************************************************************************)
 * (* The sequence obtained from a sequence s by deleting the last item. *)
 * (*************************************************************************)
 * 
 * Last(s) == s[Len(s)]
 * (*************************************************************************)
 * (* The last item in the sequence s. *)
 * (*************************************************************************)
 * 
 * (***************************************************************************)
 * (* I believe the algorithm works because it maintains the following *) (*
 * invariants (at reasonable points in the code). We say that node *) (*
 * nstack[i] precedes nstack[j] iff i < j. *) (* *) (* - A node n is in nstack
 * iff n.dfs \geq 0 *) (* *) (* - For all nodes n # m in nstack, if n precedes m
 * then: *) (* /\ n.dfs < m.dfs. *) (* /\ there is a path from n to m in the
 * graph. *) (* *) (* - For every node n in nstack, *) (* /\ n.lowlink \leq
 * n.dfs and *) (* /\ there is a node m in nstack such that *) (* 1. n.lowlink =
 * m.dfs. *) (* 2. if m # n then there is a path from n to m in the graph. *) (*
 * /\ For every node m in the same connected component as n: *) (* m.examined =
 * TRUE implies m is in nstack *)
 * (***************************************************************************)
 * 
 * (************************* --algorithm Tarjan2 variables nstack = << >> ;
 * (***************************************************************) (* The
 * stack of nodes, where nstack[1] is the bottom of the *) (* stack. *)
 * (***************************************************************) max_dfs = 0
 * ; (***************************************************************) (*
 * Incremented by 1 every time a new element is added to the *) (* stack. *)
 * (***************************************************************)
 * 
 * data = [nd \in Node |-> [lowlink |-> -1, dfs |-> -1, examined |-> FALSE, nbrs
 * |-> << >>, (*****************************************) (* A sequence of nodes
 * to which there *) (* are edges from this node. The *) (* same node may appear
 * multiple *) (* times. *) (*****************************************) nxtDep
 * |-> -1 ]] ; (***************************************************************)
 * (* The information maintained for the nodes. Note that *) (* *) (* - Node nd
 * is on nstack iff data[nd].dfs \geq 0, in *) (* which case nstack[data[nd].dfs
 * + 1] = nd. *) (* *) (* - nbrs is set from Neighbors by the initialization
 * code. *) (* *) (* - nxtDep represents the nextDependency field of the *) (*
 * OpDefNode object, where a value of -1 represents *) (* null. Following nxtDep
 * pointers leads in a cycle of *) (* the node's connected component. See the
 * comments on *) (* the nextDependency field in semantic/OpDefNode. *)
 * (***************************************************************)
 * 
 * idx ; \* A counter variable.
 * 
 * procedure tarjan(n) variable nxt ; \* A counter variable nxtnbr ; \* An
 * abbreviation
 * 
 * begin data[n].lowlink := max_dfs || data[n].dfs := max_dfs ||
 * data[n].examined := TRUE ; max_dfs := max_dfs + 1; nstack := Append(nstack,
 * n) ; nxt := 1 ; while nxt \leq Len(data[n].nbrs) do nxtnbr :=
 * data[n].nbrs[nxt] ; if ~ data[nxtnbr].examined then
 * (***************************************************************) (* nxtnbr
 * is unexamined *)
 * (***************************************************************) call
 * tarjan(nxtnbr) ; data[n].lowlink := Min(data[n].lowlink,
 * data[nxtnbr].lowlink) ;
 * 
 * elsif data[nxtnbr].dfs \geq 0 then
 * (**********************************************************) (* nxtnbr is in
 * nstack *) (**********************************************************)
 * data[n].lowlink := Min(data[n].lowlink, data[nxtnbr].dfs) ; end if ; nxt :=
 * nxt + 1; end while ; if data[n].lowlink = data[n].dfs then
 * (*****************************************************************) (* The
 * set of all nodes on nstack from n to the end form a *) (* connected
 * component. *)
 * (*****************************************************************) nxtnbr :=
 * Last(nstack) ; \* save last node on stack. while n # Last(nstack) do
 * data[Last(nstack)].nxtDep := nstack[Len(nstack)-1] || data[Last(nstack)].dfs
 * := -1 ; (*************************************************************) (*
 * Make nxtDep field of last node on stack point to next to *) (* last node. *)
 * (*************************************************************) nstack :=
 * Front(nstack) ; end while ; if \/ n # nxtnbr \/ \E i \in 1..Len(data[n].nbrs)
 * : n = data[n].nbrs[i] then
 * (**********************************************************) (* Form a
 * connected component consisting of just n only *) (* if n is a neighbor of
 * itself. *) (**********************************************************)
 * data[n].nxtDep := nxtnbr; end if; data[n].dfs := -1 ; nstack := Front(nstack)
 * ; end if ; data[n].nbrs := << >> ;
 * (**********************************************************************) (*
 * Can garbage collect the sequence of neighbors. *)
 * (**********************************************************************)
 * return ; end procedure
 * 
 * begin
 * (************************************************************************) (*
 * Initialize the nbrs field of data elements from Neighbors. *)
 * (************************************************************************)
 * idx := 1 ; while idx \leq Len(Neighbors) do with edge = Neighbors[idx] do
 * data[edge[1]].nbrs := Append(data[edge[1]].nbrs, edge[2]) ; end with ; idx :=
 * idx + 1; end while ;
 * 
 * (************************************************************************) (*
 * while there is an unexamined node, call tarjan(nd) *) (* for any unexamined
 * node nd. *)
 * (************************************************************************)
 * idx := 1 ; while idx \leq N do if data[idx].lowlink < 0 then
 * (***************************************************************) (* idx is
 * unexamined *)
 * (***************************************************************) call
 * tarjan(idx) ; end if; idx := idx + 1 ; end while ;
 * 
 * (************************************************************************) (*
 * print result. *)
 * (************************************************************************)
 * idx := 1 ; while idx \leq N do if data[idx].nxtDep \geq 0 then print <<idx,
 * "->", data[idx].nxtDep>> end if ; idx := idx+1; end while end algorithm )
 * 
 * \* BEGIN TRANSLATION \* END TRANSLATION
 * 
 * \**** Test data
 * 
 * Node1 == {1, 2, 3, 4}
 * 
 * Nbrs1 == << <<1, 2>>, \* components 1 and 3,4 <<1, 2>>, \* components 1 and
 * 3,4 <<1, 1>>, <<1, 1>>, <<3, 4>> , <<3, 4>> , <<4, 3>> , <<4, 3>>, <<4, 3>>
 * >>
 * 
 * Nbrs2 == << <<1, 2>>, \* components 1 and 3,4 <<1, 1>>, <<1, 3>>, <<3, 4>>,
 * <<4, 3>> >> Nbrs3 == << <<1, 2>>, \* components 1 and 3,4 <<1, 1>>, <<3, 1>>,
 * <<3, 4>>, <<4, 3>> >> Nbrs4 == << <<1, 3>>, \* <<1, 8>>, \* componetns:
 * 2,3,4,5 and 7,8,9 <<1, 9>>, <<1, 9>>, <<1, 9>>, <<3, 2>>, <<3, 2>>, <<2, 4>>,
 * <<4, 5>>, <<4, 10>>, <<5, 3>>, <<8, 7>>, <<8, 7>>, <<9, 8>>, <<7, 9>>, <<7,
 * 9>>, <<9, 10>>, <<9, 10>>, <<9, 10>> >>
 * 
 * Nbrs5 == << <<1, 8>>, \* components 7,8,9 <<1, 9>>, <<4, 10>>, <<8, 7>>, <<9,
 * 8>>, <<7, 9>>, <<9, 10>> >>
 * 
 * Nbrs6 == << <<6, 4>>, \* components 2,3,4,5 <<3, 4>>, <<4, 5>>, <<5, 2>>,
 * <<2, 3>>, <<5, 1>>, <<2, 1>> >>
 * 
 * Nbrs7 == << <<1, 7>>, \* 1 component with 1..9 \ {3} <<1, 9>>, <<2, 1>>, <<3,
 * 2>>, <<3, 6>>, <<4, 6>>, <<5, 2>>, <<6, 5>>, <<6, 8>>, <<7, 5>>, <<7, 8>>,
 * <<8, 4>>, <<8, 10>>, <<9, 7>>, <<9, 10>> >> Nbrs8 == << <<1, 7>>, \* 1
 * component with 1..8 \ {3} <<2, 1>>, <<3, 2>>, <<3, 2>>, <<3, 2>>, <<3, 6>>,
 * <<4, 6>>, <<5, 2>>, <<6, 5>>, <<6, 8>>, <<6, 8>>, <<6, 8>>, <<7, 5>>, <<7,
 * 8>>, <<8, 4>>, <<8, 10>>, <<9, 7>>, <<9, 10>> >> Nbrs9 == << \* 4,6, 7,8,9,10
 * <<2, 1>>, <<3, 2>>, <<3, 6>>, <<4, 6>>, <<4, 6>>, <<4, 6>>, <<5, 2>>, <<6,
 * 5>>, <<6, 8>>, <<7, 5>>, <<7, 5>>, <<7, 5>>, <<7, 5>>, <<7, 8>>, <<8, 4>>,
 * <<8, 10>>, <<9, 7>>, <<10, 9>> >> Nbrs == << \* 1, 3, 4, 5 and 6 <<1, 4>>,
 * <<2, 1>>, <<2, 3>>, <<2, 3>>, <<2, 3>>, <<2, 5>>, <<3, 4>>, <<4, 1>>, <<4,
 * 5>>, <<4, 5>>, <<4, 5>>, <<5, 3>>, <<6, 5>>, <<6, 6>> >>
 * 
 * =============================================================================
 ************************** 
 * end file Tarjan.tla
 ******************************/

/*************************
 * file Subexpression.tla ********************** last modified on Fri 13
 * November 2009 at 14:11:05 PST by lamport ------------------------ MODULE
 * Subexpression ---------------------------
 * 
 * 
 * (***************************************************************************)
 * (* NAMING *) (* *) (* There are four kinds of Nameable Objects: *) (* -
 * Expressions *) (* - Operators that take an argument *) (* (and that can
 * appear as operator arguments) *) (* - Operator definitions (named in
 * BY/USE/HIDE statements) *) (* - ASSUME/PROVEs. *) (* *) (* There are three
 * relevant kinds of primitive names that appear in a *) (* TLA+ module. *) (*
 * *) (* Defined Module Name (ModuleName): *) (* It appears to the left of "==
 * INSTANCE...". It may or may not *) (* contain arguments. *) (* Primitive
 * Operator Name (PrimOpName): *) (* It appear to the left of the "==" in a
 * definition, theorem *) (* or assumption. It may or may not contain arguments.
 * *) (* Label: *) (* It appears before a "::" in an expression. *) (* *) (*
 * Examples of possible primitive names are "Foo" and "Bar(x+1, 42)". *) (* *)
 * (* The Built-In Operator names (like "SUBSET") will not be considered to *)
 * (* be primitive names in the following. *) (* *) (* To these explicit names
 * we add the following Operand Selector (OpSel) *) (* names: *) (* - numbers,
 * *) (* - "<<", ">>", *) (* - Things of the form (exp_1, ... , exp_n) where the
 * exp_i are *) (* expressions or operator arguments and n > 0. *) (* - "@", *)
 * (* *) (* A Compound Name is a sequence of primitive names, operand selectors,
 * *) (* and ":"s separated by "!"s. *) (* *) (* In TLA+1, the general way of
 * naming a non-built-in operator is with *) (* what I will call an Elementary
 * Operator Name (ElemOpName) which has *) (* the following syntax. For
 * simplicity, I will ignore the "!"s in the *) (* `formal' syntax. *) (* *) (*
 * ElemOpName ::= (ModuleName)* PrimOpName *) (* *) (* We consider this to name
 * both the operator and its definition (the *) (* expression to the right of
 * the "=="). How the two meanings are *) (* disambiguated will be explained
 * below. *) (* *) (* If EON is an ElemOpName and Lab_1, ... , Lab_n are a
 * sequence of *) (* label names, then EON ! Lab_1 ! ... ! Lab_N names the
 * expression *) (* labeled by Lab_N, where each Lab_(i+1) must be the name of a
 * labeled *) (* expression within the expression labeled by Lab_i with no
 * labels *) (* between Lab_i and Lab_(i+1). Thus a name described by *) (* *)
 * (* ElemOpName (Label)* *) (* *) (* describes an operator definition or a
 * labeled expression. To such a *) (* name, we can append a sequence of
 * OperandSelectors. By rules *) (* described later, the resulting name selects
 * a subexpression (or *) (* ASSUME/PROVE node) or Operator (appearing as an
 * operator argument) *) (* from the body of the operator definition or labeled
 * expression. If *) (* the labeled expression is a LET/IN, then to this name
 * can be appended *) (* an ElemOpName defined in the LET part, and the naming
 * process can then *) (* be iterated. The full syntax of a General Name is: *)
 * (* *) (* OperatorName ::= ElemOpName *) (* | ElemOpName (Label)* ((OpSel)+ |
 * ":") ElemOpName *) (* *) (* GeneralName ::= OperatorName (":" | (Label)*
 * (OpSeq)* ) *) (* *) (* Note that ":" is used in two ways: *) (* *) (* - An
 * OperatorName not followed by ":" names the operator; one *) (* followed by
 * ":" names the operator's definition. *) (* - Suppose a general name GN ending
 * in a label names a LET/IN *) (* expression and EON is an ElemOpName. Then GN
 * !: !EON names *) (* an operator defined in the LET. The general name GN ! Foo
 * would *) (* name an expression labeled by Foo inside the IN clause. *)
 * (***************************************************************************)
 * 
 * 
 * (***************************************************************************)
 * (* This +cal program describes an algorithm used in generating the *) (*
 * semantic tree for a parse tree consisting of a GeneralId node or an *) (*
 * OpApplication node whose first child is a GeneralId node. Two examples *) (*
 * are *) (* *) (* Foo(x)!Bar!<<!(a,b)!G *) (* Foo(x)!Bar!<<!(a,b)!G(c) *) (* *)
 * (* We assume that these are processed to yield two sequences of nodes: *) (*
 * op and args. The sequences for the first are *) (* *) (* op = << "Foo",
 * "Bar", "<<", "null", "G" >> *) (* args = << <<x>>, << >>, << >>, <<a, b>>,
 * <<>> >> *) (* *) (* and for the second are *) (* *) (* op = << "Foo", "Bar",
 * "<<", "null", "G" >> *) (* args = << <<x>>, << >>, << >>, <<a, b>>, <<c>> >>
 * *) (* *) (* where each symbol in args represents the semantic node produced
 * by that *) (* symbol. *) (* *) (* The other input to the algortithm is an
 * integer expectedArity. There *) (* are three cases: *) (* *) (* expectedArity
 * = 0 : *) (* The parser is expecting an expression. This is the case *) (*
 * when the expression occurs in the first part of a USE *) (* or HIDE
 * statement. *) (* *) (* expectedArity > 0 : The parser is expecting an
 * operator *) (* argument of this arity. *) (* *) (* expectedArity = -1 : *) (*
 * The parser is expecting the name of a definition. This is *) (* the case when
 * the expression occurs in the DEF clause of a USE *) (* or HIDE or BY
 * statement. *) (* *) (* If expectedArity # 0, then args equals a sequence each
 * of whose *) (* element is the empty sequence. *)
 * (***************************************************************************)
 * 
 * (***************************************************************************)
 * (* Note: This spec is assuming that proof-step numbers are treated like *) (*
 * operator names. That is, a step *) (* *) (* <3>2. foo > bar *) (* *) (* will
 * be represented by a ThmOrAssumpDefKind node just as if it were *) (* *) (*
 * THEOREM <3>2 == foo > bar *) (* *) (* If this is not the case, then
 * additional code needs to be added to deal *) (* with numbered steps. But
 * however it is handled, the "<3>2" will be a *) (* name in the current symbol
 * table. *)
 * (***************************************************************************)
 * 
 * EXTENDS Integers, Sequences, TLC
 * 
 * (***************************************************************************)
 * (* SeqSeqToSeq(ss) is defined to be the concatenation of the sequences *) (*
 * that are the elements of the sequence ss. *)
 * (***************************************************************************)
 * RECURSIVE SeqSeqToSeq(_) SeqSeqToSeq(ss) == IF ss = << >> THEN << >> ELSE
 * Head(ss) \o SeqSeqToSeq(Tail(ss))
 * 
 * (***************************************************************************)
 * (* These are kinds of semantic nodes that can be encountered by the *) (*
 * algorithm. See tlasany/sematic/ASTConstants.java. *)
 * (***************************************************************************)
 * ConstantDeclKind == "ConstantDecl" VariableDeclKind == "VariableDecl"
 * BoundSymbolKind == "BoundSymbol" UserDefinedOpKind == "UserDefinedOp"
 * ModuleInstanceKind == "ModuleInstance" BuiltInKind == "BuiltIn" OpArgKind ==
 * "OpArg" OpApplKind == "OpAppl" LetInKind == "LetIn" FormalParamKind ==
 * "FormalParam" TheoremKind == "Theorem" SubstInKind == "SubstIn"
 * AssumeProveKind == "AssumeProve" ProofKind == "Proof" NumeralKind ==
 * "Numeral" DecimalKind == "Decimal" StringKind == "String" AtNodeKind ==
 * "AtNode" AssumeKind == "Assume" InstanceKind == "Instance" ThmOrAssumpDefKind
 * == "ThmOrAssumpDef" LabelKind == "Label" APSubstInKind == "APSubstIn"
 * 
 * CONSTANT NodeId, \* The set of all node identifiers. Node, \* A mapping from
 * NodeId to nodes (which are records). GlobalContext, \* The initial context.
 * null, \* A special value not equal to anything else. debug \* Setting to TRUE
 * causes TLC to print a trace if the \* algorithm reports an error.
 * 
 * (***************************************************************************)
 * (* CONTEXTS *) (* *) (* A context is a mapping from names to NodeIds. There
 * are actually three *) (* different kinds of mappings from names to nodes in
 * the implementation *) (* that are all represented here as contexts: *) (* -
 * The symbolTable of the Generator. *) (* - The context field of a LetInNode *)
 * (* - The labels field of a LabelNode *)
 * (***************************************************************************)
 * IsContext(C) ==
 * (*************************************************************************)
 * (* True iff C is a context. *)
 * (*************************************************************************)
 * /\ DOMAIN C \subseteq STRING /\ \A str \in DOMAIN C : C[str] \in NodeId
 * 
 * LookUp(nm, ctxt) ==
 * (*************************************************************************)
 * (* The value assigned to name nm by context cxt, or null if there is no *) (*
 * value assigned. *)
 * (*************************************************************************)
 * IF nm \in DOMAIN ctxt THEN Node[ctxt[nm]] ELSE null
 * 
 * Param == [name : STRING, arity : Nat]
 * (*************************************************************************)
 * (* The set of parameters, which can appear in operator definitions. *)
 * (*************************************************************************)
 * 
 * (***************************************************************************)
 * (* For simplicity, we assume that argument numbers range from 1 to 9, and *)
 * (* we define the following mappings from to and from argument numbers to *)
 * (* their string representations. *)
 * (***************************************************************************)
 * NumberOp == {"1", "2", "3", "4", "5", "6", "7", "8", "9"} NumericVal(numOp)
 * == CASE numOp = "1" -> 1 [] numOp = "2" -> 2 [] numOp = "3" -> 3 [] numOp =
 * "4" -> 4 [] numOp = "5" -> 5 [] numOp = "6" -> 6 [] numOp = "7" -> 7 [] numOp
 * = "8" -> 8 [] numOp = "9" -> 9
 * 
 * NumToString(num) == CASE num = 1 -> "1" [] num = 2 -> "2" [] num = 3 -> "3"
 * [] num = 4 -> "4" [] num = 5 -> "5" [] num = 6 -> "6" [] num = 7 -> "7" []
 * num = 8 -> "8" [] num = 9 -> "9"
 * 
 * IsName(op) ==
 * (*************************************************************************)
 * (* A name is something other than an argument selector that can appear *) (*
 * in a compound name. *)
 * (*************************************************************************)
 * op \in STRING \ ({"<<", ">>", "@", ":", "null"} \cup NumberOp)
 * 
 * 
 * ArgNum(op, arity) ==
 * (*************************************************************************)
 * (* The argument number chosen by argument selector op for an operator *) (*
 * application with arity arguments. It equals -1 if op is not a legal *) (*
 * argument selector for this arity. *)
 * (*************************************************************************)
 * CASE op \in NumberOp -> IF NumericVal(op) <= arity THEN NumericVal(op) ELSE
 * -1 [] op = "<<" -> IF arity > 0 THEN 1 ELSE -1 [] op = ">>" -> CASE arity = 1
 * -> 1 [] arity = 2 -> 2 [] OTHER -> -1 [] OTHER -> -1
 * 
 * Arity(node) ==
 * (*************************************************************************)
 * (* The arity of a node--that is, the number of arguments it takes. *)
 * (*************************************************************************)
 * IF node.kind \in {UserDefinedOpKind, BuiltInKind, ModuleInstanceKind,
 * ThmOrAssumpDefKind, OpArgKind, LabelKind, ConstantDeclKind, FormalParamKind}
 * THEN node.arity ELSE 0
 * 
 * ParamArity(node, i) ==
 * (*************************************************************************)
 * (* The arity of the i-th parameter of the node of kind *) (*
 * UserDefinedOpKind, ThmOrAssumpDefKind, ModuleInstanceKind, *) (*
 * ConstantDeclKind, or FormalParamKind *)
 * (*************************************************************************)
 * IF node.kind \in {ConstantDeclKind, FormalParamKind} THEN 0 ELSE
 * node.params[i].arity
 * -----------------------------------------------------------------------------
 * 
 * (***************************************************************************)
 * (* The following assumptions define the data types--in particular, the *) (*
 * record components that each node type must contain. *)
 * (***************************************************************************)
 * ASSUME IsContext(GlobalContext)
 * 
 * ASSUME DOMAIN Node = NodeId
 * 
 * ASSUME /\ \A id \in NodeId : LET node == Node[id] IN /\ node.kind \in
 * {ConstantDeclKind, VariableDeclKind, BoundSymbolKind, UserDefinedOpKind,
 * ModuleInstanceKind, BuiltInKind, OpArgKind, OpApplKind, LetInKind,
 * FormalParamKind, TheoremKind, SubstInKind, AssumeProveKind, ProofKind,
 * NumeralKind, DecimalKind, StringKind, AtNodeKind, AssumeKind, InstanceKind,
 * ThmOrAssumpDefKind, LabelKind, APSubstInKind}
 * 
 * ASSUME /\ \A id \in NodeId : LET node == Node[id] IN /\ node.kind \in
 * {UserDefinedOpKind, BuiltInKind, ModuleInstanceKind, ThmOrAssumpDefKind,
 * LabelKind, ConstantDeclKind, FormalParamKind} => /\ node.name \in STRING /\
 * node.arity \in Nat \cup {-1} /\ (node.arity = -1) => (node.kind =
 * BuiltInKind)
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN node.kind \in
 * {UserDefinedOpKind, ThmOrAssumpDefKind} => /\ node.body \in NodeId /\
 * IsContext(node.labels) /\ node.params \in Seq(Param) /\ Len(node.params) =
 * node.arity /\ node.defined \in BOOLEAN /\ node.source \in {null} \cup NodeId
 * \* The original definition (before instantiation) \* or null if this is it.
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind = OpApplKind
 * => /\ node.operands \in Seq(NodeId) /\ node.operator \in NodeId /\
 * node.unboundedBoundSymbols \in Seq(STRING) /\ node.boundedBoundSymbols \in
 * Seq(Seq(STRING))
 * (**************************************************************) (* These are
 * actually arrays and arrays of arrays of *) (* FormalParamNode objects
 * (formerly OpDeclNode objects). *)
 * (**************************************************************) /\
 * node.ranges \in Seq(NodeId) /\ Len(node.ranges) =
 * Len(node.boundedBoundSymbols)
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind = LetInKind =>
 * /\ node.body \in NodeId /\ IsContext(node.context)
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind = OpArgKind =>
 * /\ node.op \in NodeId /\ IsName(node.name) /\ (node.arity \in Nat) /\
 * (node.arity > 0)
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind = LabelKind =>
 * /\ node.body \in NodeId /\ IsContext(node.labels) /\ node.params \in
 * Seq(Param)
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind = SubstInKind
 * => /\ node.body \in NodeId /\ node.subst \in STRING \* Just to identify it.
 * 
 * ASSUME \A id \in NodeId : LET node == Node[id] IN /\ node.kind =
 * AssumeProveKind => /\ node.assumes\in Seq(NodeId) /\ node.prove \in NodeId
 * 
 * 
 * RECURSIVE ExpandNode(_) ExpandNode(node) == CASE node.kind \in
 * {UserDefinedOpKind, LetInKind} -> [node EXCEPT !.body = ExpandNode(Node[@])]
 * [] node.kind = OpApplKind -> [node EXCEPT !.operands = [i \in DOMAIN @ |->
 * ExpandNode(Node[@[i]])], !.operator = ExpandNode(Node[@]), !.ranges = [i \in
 * DOMAIN @ |-> ExpandNode(Node[@[i]])]] [] OTHER -> node
 * 
 * 
 * -----------------------------------------------------------------------------
 * (***************************************************************************)
 * (* Test Data *) (* *) (* The algorithm has been tested on the following sets
 * of data, where each *) (* operator MCxxx is either substituted for constant
 * parameter xxx or is *) (* used as initial value of the algorithm's input
 * variable xxx. *)
 * (***************************************************************************)
 * 
 * 
 * (*****************************
 * 
 * 
 * (***************************************************************************)
 * (* ------------------------ MODULE M ------------------------ *) (* CONSTANT
 * C *) (* Op(Arg(_), p) == \A x \in {1,2}, <<y, z>> \in {3} : *) (* lab(x,y,z)
 * :: LET a + b == <<Arg(a), b>> *) (* IN 1 + label2 :: p + C *) (* Foo(u) ==
 * "FooBody(u)" *) (*
 * ============================================================= *) (* *) (*
 * Inst(d) == INSTANCE M WITH C <- "expr(d)" *)
 * (***************************************************************************)
 * 
 * \* MCNode == \* 1 :> [kind |-> UserDefinedOpKind, \* Op(Arg(_), p) == ... \*
 * name |-> "Op", \* body |-> 3, \* labels |-> "lab" :> 4, \* arity |-> 2, \*
 * params |-> <<[name |-> "Arg", arity |-> 1], \* [name |-> "p", arity |-> 0]>>,
 * \* defined |-> TRUE, \* source |-> null ] \* @@ \* 2 :> [kind |->
 * BuiltInKind, \* name |-> "$BoundedForall", \* arity |-> -1 \* ] \* @@ \* 3 :>
 * [kind |-> OpApplKind, \* \A x \in {1,2}, <<y, z>> \in {3} : ... \* operands
 * |-> << 4 >>, \* operator |-> 2, \* unboundedBoundSymbols |-> <<>>, \*
 * boundedBoundSymbols |-> << <<"x">>, <<"y", "z">> >>, \* ranges |-> << 19, 21
 * >>] \* @@ \* 4 :> [kind |-> LabelKind, \* lab(x,y,z) :: LET a + b ==
 * <<Arg(a), b>> \* name |-> "lab", \* IN 1 + label2 :: p + C \* body |-> 5, \*
 * arity |-> 3, \* params |-> <<[name |-> "x", arity |->0], \* [name |-> "y",
 * arity |->0], \* [name |-> "z", arity |->0] >>, \* labels |-> "label2" :> 15 ]
 * \* @@ \* 5 :> [kind |-> LetInKind, \* LET a + b == <<Arg(a), b>> \* context
 * |-> "+" :> 6, \* IN 1 + label2 :: p + C \* body |-> 13 ] \* @@ \* 6 :> [kind
 * |-> UserDefinedOpKind, \* a + b == <<Arg(a), b>> \* name |-> "+", \* body |->
 * 7, \* labels |-> << >>, \* arity |-> 2, \* params |-> <<[name |-> "a", arity
 * |-> 0], \* [name |-> "b", arity |-> 0]>>, \* defined |-> TRUE, \* source |->
 * null ] \* @@ \* 7 :> [kind |-> OpApplKind, \* <<Arg(a), b>> \* operands |->
 * << 9, 12 >>, \* operator |-> 8, \* unboundedBoundSymbols |-> <<>>, \*
 * boundedBoundSymbols |-> << >>, \* ranges |-> << >>] \* @@ \* 8 :> [kind |->
 * BuiltInKind, \* name |-> "$Tuple", \* arity |-> -1 \* ] \* @@ \* 9 :> [kind
 * |-> OpApplKind, \* Arg(a) \* operands |-> <<11 >>, \* operator |-> 10, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 10 :> [kind |-> FormalParamKind, \* name |-> "Arg", \*
 * arity |-> 1] \* \* @@ \* 11 :> [kind |-> FormalParamKind, \* name |-> "a", \*
 * arity |-> 0] \* @@ \* 12 :> [kind |-> FormalParamKind, \* name |-> "b", \*
 * arity |-> 0] \* @@ \* 13 :> [kind |-> OpApplKind, \* 1 + label2 :: p + C \*
 * operands |-> <<14, 15>>, \* operator |-> 6, \* unboundedBoundSymbols |->
 * <<>>, \* boundedBoundSymbols |-> << >>, \* ranges |-> << >>] \* @@ \* 14 :>
 * [kind |-> NumeralKind, \* val |-> 1] \* @@ \* 15 :> [kind |-> LabelKind, \*
 * label2 :: p + C \* name |-> "label2", \* body |-> 16, \* arity |-> 0, \*
 * params |-> <<>>, \* labels |-> << >>] \* @@ \* 16 :> [kind |-> OpApplKind, \*
 * p + C \* operands |-> <<17, 18>>, \* operator |-> 6, \* unboundedBoundSymbols
 * |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges |-> << >>] \* @@ \* 17
 * :> [kind |-> FormalParamKind, \* name |-> "p", \* arity |-> 0] \* @@ \* 18 :>
 * [kind |-> ConstantDeclKind, \* name |-> "C", \* arity |-> 0 ] \* @@ \* 19 :>
 * [kind |-> OpApplKind, \* {1,2} \* operands |-> << 14, 20 >>, \* operator |->
 * 8, \* Actually, specifying <<1, 2>> \* unboundedBoundSymbols |-> << >>, \*
 * boundedBoundSymbols |-> << >>, \* ranges |-> << >>] \* @@ \* 20 :> [kind |->
 * NumeralKind, \* val |-> 2] \* @@ \* 21 :> [kind |-> OpApplKind, \* {1,2} \*
 * operands |-> << 22>>, \* operator |-> 8, \* Actually, specifying <<1, 2>> \*
 * unboundedBoundSymbols |-> << >>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 22 :> [kind |-> NumeralKind, \* val |-> 3] \* @@ \* 23 :>
 * [kind |-> UserDefinedOpKind, \* Foo(u) == "FooBody(u)" \* name |-> "Foo", \*
 * body |-> 24, \* labels |-> << >>, \* arity |-> 1, \* params |-> <<[name |->
 * "u", arity |-> 0]>>, \* defined |-> TRUE, \* source |-> null ] \* @@ \* 24 :>
 * [kind |-> StringKind, \* val |-> "FooBody(u)"] \* @@ \* 25 :> [kind |->
 * StringKind, \* val |-> "string"] \* @@ \* 26 :> [kind |-> ModuleInstanceKind,
 * \* Inst(d) == INSTANCE M WITH C <- "expr(d)" \* name |-> "Inst", \* arity |->
 * 1, \* params |-> <<[name |-> "d", arity |-> 0] >>, \* defined |-> TRUE ]
 * \* @@ \* 27 :> [kind |-> SubstInKind, \* body |-> 24, \* subst |-> "expr(d)"]
 * \* @@ \* 28 :> [kind |-> UserDefinedOpKind, \* Foo(u) == "FooBody(u)" \* name
 * |-> "Inst!Foo", \* body |-> 27, \* labels |-> << >>, \* arity |-> 2, \*
 * params |-> << [name |-> "d", arity |-> 0], \* [name |-> "u", arity |-> 0]>>,
 * \* defined |-> TRUE, \* source |-> 23 ] \* @@ \* 29 :> [kind |->
 * UserDefinedOpKind, \* Op(Arg(_), p) == ... \* name |-> "Inst!Op", \* body |->
 * 30, \* labels |-> "lab" :> 4, \* arity |-> 3, \* params |-> <<[name |-> "d",
 * arity |-> 0], \* [name |-> "Arg", arity |-> 1], \* [name |-> "p", arity |->
 * 0]>>, \* defined |-> TRUE, \* source |-> 1 ] \* @@ \* 30 :> [kind |->
 * SubstInKind, \* body |-> 3, \* subst |-> "expr(d)"] \* @@ \* 31 :> [kind |->
 * StringKind, \* val |-> "Argm"] \* \* MCNodeId == 1..31 \* \* MCGlobalContext
 * == \* "Op" :> 1 \* @@ \* "Foo" :> 23 \* @@ \* "Inst" :> 26 \* @@ \*
 * "Inst!Foo" :> 28 \* @@ \* "Inst!Op" :> 29 \* \* \* Foo("string") \* \* MCops
 * == <<"Foo">> \* \* MCargs == << <<25>>>> \* \* MCexpectedArity == 0 \* \* \*
 * Op(Foo, "string") \* \* MCops == <<"Op">> \* \* MCargs == << <<23, 25>> >> \*
 * \* MCexpectedArity == 0 \* \* \* Op(Foo, "string")!lab(1,2,3) \* \* MCops ==
 * <<"Op", "lab">> \* \* MCargs == << <<23, 25>> , <<14, 20, 22 >> >> \* \*
 * MCexpectedArity == 0 \* \* \* Op(Foo, "string")!lab(1,2,3)!<< \* \* MCops ==
 * <<"Op", "lab", "<<">> \* \* MCargs == << <<23, 25>> , <<14, 20, 22>> , << >>
 * >> \* \* MCexpectedArity == 0 \* \* \* Op(Foo, "string")!lab(1,2,3)!<<!>> \*
 * \* MCops == <<"Op", "lab", "<<", ">>">> \* \* MCargs == << <<23, 25>> , <<14,
 * 20, 22>> , << >>, << >> >> \* \* MCexpectedArity == 0 \* \* \* Op(Foo,
 * "string")!lab(1,2,3)!label2 \* \* MCops == <<"Op", "lab", "label2">> \* \*
 * MCargs == << <<23, 25>> , <<14, 20, 22>> , << >> >> \* \* MCexpectedArity ==
 * 0 \* \* \* Op(Foo, "string")!lab(1,2,3)!label2!<< \* \* MCops == <<"Op",
 * "lab", "label2", "<<">> \* \* MCargs == << <<23, 25>> , <<14, 20, 22>> , <<
 * >>, << >> >> \* \* MCexpectedArity == 0 \* \* \* Op(Foo,
 * "string")!lab(1,2,3)!:!+(3,2) \* \* MCops == <<"Op", "lab", ":", "+" >> \* \*
 * MCargs == << <<23, 25>> , <<14, 20, 22>> , << >> , <<22, 20 >> >> \* \*
 * MCexpectedArity == 0 \* \* \* Op(Foo, "string")!lab(1,2,3)!:!+(3,2)!>> \* \*
 * MCops == <<"Op", "lab", ":", "+", ">>" >> \* \* MCargs == << <<23, 25>> ,
 * <<14, 20, 22>> , << >> , <<22, 20 >>, << >> >> \* \* MCexpectedArity == 0 \*
 * \* \* Op(Foo, "string")!(1,2,3) \* \* MCops == <<"Op", "null" >> \* \* MCargs
 * == << <<23, 25>> , <<14, 20, 22>> >> \* \* MCexpectedArity == 0 \* \* \*
 * Op(Foo, "string")!(1,2,3)!>>!>>!<< \* \* MCops == <<"Op", "null", ">>", ">>",
 * "<<" >> \* \* MCargs == << <<23, 25>> , <<14, 20, 22>>, << >>, << >>, << >>
 * >> \* \* MCexpectedArity == 0 \* \* \* Op(Foo, "string")!<<!>> \* \* MCops ==
 * <<"Op", "<<", ">>" >> \* \* MCargs == << <<23, 25>>, << >>, << >> >> \* \*
 * MCexpectedArity == 0 \* \* \* Inst("Argm")!Foo("string") \* \* MCops ==
 * <<"Inst", "Foo">> \* \* MCargs == << <<31>>, <<25>>>> \* \* MCexpectedArity
 * == 0 \* \* \* Inst("Argm")!Op(Foo, "string") \* \* MCops == <<"Inst", "Op">>
 * \* \* MCargs == << <<31>>, <<23, 25>> >> \* \* MCexpectedArity == 0 \* \* \*
 * Inst("Argm")!Op(Foo, "string")!lab(1,2,3) \* \* MCops == <<"Inst", "Op",
 * "lab">> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20, 22 >> >> \* \*
 * MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo, "string")!lab(1,2,3)!<< \*
 * \* MCops == <<"Inst", "Op", "lab", "<<">> \* \* MCargs == << <<31>>, <<23,
 * 25>> , <<14, 20, 22>> , << >> >> \* \* MCexpectedArity == 0 \* \* \*
 * Inst("Argm")!Op(Foo, "string")!lab(1,2,3)!<<!>> \* \* MCops == <<"Inst",
 * "Op", "lab", "<<", ">>">> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20,
 * 22>> , << >>, << >> >> \* \* MCexpectedArity == 0 \* \* \*
 * Inst("Argm")!Op(Foo, "string")!lab(1,2,3)!label2 \* \* MCops == <<"Inst",
 * "Op", "lab", "label2">> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20,
 * 22>> , << >> >> \* \* MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo,
 * "string")!lab(1,2,3)!label2!<< \* \* MCops == <<"Inst", "Op", "lab",
 * "label2", "<<">> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20, 22>> , <<
 * >>, << >> >> \* \* MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo,
 * "string")!lab(1,2,3)!:!+(3,2) \* \* MCops == <<"Inst", "Op", "lab", ":", "+"
 * >> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20, 22>> , << >> , <<22, 20
 * >> >> \* \* MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo,
 * "string")!lab(1,2,3)!:!+(3,2)!>> \* \* MCops == <<"Inst", "Op", "lab", ":",
 * "+", ">>" >> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20, 22>> , << >> ,
 * <<22, 20 >>, << >> >> \* \* MCexpectedArity == 0 \* \* \*
 * Inst("Argm")!Op(Foo, "string")!(1,2,3) \* \* MCops == <<"Inst", "Op", "null"
 * >> \* \* MCargs == << <<31>>, <<23, 25>> , <<14, 20, 22>> >> \* \*
 * MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo, "string")!(1,2,3)!>>!>>!<<
 * \* \* MCops == <<"Inst", "Op", "null", ">>", ">>", "<<" >> \* \* MCargs == <<
 * <<31>>, <<23, 25>> , <<14, 20, 22>>, << >>, << >>, << >> >> \* \*
 * MCexpectedArity == 0 \* \* \* Inst("Argm")!Op(Foo, "string")!<<!>> \* \*
 * MCops == <<"Inst", "Op", "<<", ">>" >> \* \* MCargs == << <<31>>, <<23, 25>>,
 * << >>, << >> >> \* \* MCexpectedArity == 0
 ***************************************** 
 * )
 * 
 * (***************************************************************************)
 * (* ------------------------ MODULE M ------------------------ *) (* CONSTANT
 * C, Arg1(_) *) (* Op(Arg, p) == \A x \in {1,2}, <<y, z>> \in {3} : *) (*
 * lab(x,y,z) :: LET a + b == <<Arg1(a), b>> *) (* IN 1 + label2 :: p + C *) (*
 * Bar(AOp(_)) == AOp(1) *) (* Foo(u) == Bar(Arg1) *) (* Foo2 == Bar(LAMBDA m, n
 * : <<m, n>>) *) (* THEOREM Thm == ASSUME Arg1(1) , Bar(Arg1) PROVE << C,
 * Bar(Arg1)>> *) (* UU == lab:: C *) (*
 * ============================================================= *) (* *) (*
 * Foo3 == \A x : LET Bar3 == 1 IN 2 *) (* Inst(d) == INSTANCE M WITH C <-
 * "expr(d)" *)
 * (***************************************************************************)
 * 
 * 
 * MCNode == 1 :> [kind |-> UserDefinedOpKind, \* Op(Arg, p) == ... name |->
 * "Op", body |-> 3, labels |-> "lab" :> 4, arity |-> 2, params |-> <<[name |->
 * "Arg", arity |-> 0], [name |-> "p", arity |-> 0]>>, defined |-> TRUE, source
 * |-> null ]
 * 
 * @@ 2 :> [kind |-> BuiltInKind, name |-> "$BoundedForall", arity |-> -1 ] @@ 3
 * :> [kind |-> OpApplKind, \* \A x \in {1,2}, <<y, z>> \in {3} : ... operands
 * |-> << 4 >>, operator |-> 2, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << <<"x">>, <<"y", "z">> >>, ranges |-> << 19, 21
 * >>] @@ 4 :> [kind |-> LabelKind, \* lab(x,y,z) :: LET a + b == <<Arg(a), b>>
 * name |-> "lab", \* IN 1 + label2 :: p + C body |-> 5, arity |-> 3, params |->
 * <<[name |-> "x", arity |->0], [name |-> "y", arity |->0], [name |-> "z",
 * arity |->0] >>, labels |-> "label2" :> 15 ] @@ 5 :> [kind |-> LetInKind, \*
 * LET a + b == <<Arg(a), b>> context |-> "+" :> 6, \* IN 1 + label2 :: p + C
 * body |-> 13 ] @@ 6 :> [kind |-> UserDefinedOpKind, \* a + b == <<Arg(a), b>>
 * name |-> "+", body |-> 7, labels |-> << >>, arity |-> 2, params |-> <<[name
 * |-> "a", arity |-> 0], [name |-> "b", arity |-> 0]>>, defined |-> TRUE,
 * source |-> null ] @@ 7 :> [kind |-> OpApplKind, \* <<Arg(a), b>> operands |->
 * << 9, 12 >>, operator |-> 8, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 8 :> [kind |->
 * BuiltInKind, name |-> "$Tuple", arity |-> -1 ] @@ 9 :> [kind |-> OpApplKind,
 * \* Arg1(a) operands |-> <<11 >>, operator |-> 10, unboundedBoundSymbols |->
 * <<>>, boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 10 :> [kind |->
 * ConstantDeclKind, name |-> "Arg1", arity |-> 1]
 * 
 * @@ 11 :> [kind |-> FormalParamKind, name |-> "a", arity |-> 0] @@ 12 :> [kind
 * |-> FormalParamKind, name |-> "b", arity |-> 0] @@ 13 :> [kind |->
 * OpApplKind, \* 1 + label2 :: p + C operands |-> <<14, 15>>, operator |-> 6,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>] @@ 14 :> [kind |-> NumeralKind, val |-> 1] @@ 15 :> [kind |-> LabelKind,
 * \* label2 :: p + C name |-> "label2", body |-> 16, arity |-> 0, params |->
 * <<>>, labels |-> << >>] @@ 16 :> [kind |-> OpApplKind, \* p + C operands |->
 * <<17, 18>>, operator |-> 6, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 17 :> [kind |->
 * FormalParamKind, name |-> "p", arity |-> 0] @@ 18 :> [kind |->
 * ConstantDeclKind, name |-> "C", arity |-> 0 ] @@ 19 :> [kind |-> OpApplKind,
 * \* {1,2} operands |-> << 14, 20 >>, operator |-> 8, \* Actually, specifying
 * <<1, 2>> unboundedBoundSymbols |-> << >>, boundedBoundSymbols |-> << >>,
 * ranges |-> << >>] @@ 20 :> [kind |-> NumeralKind, val |-> 2] @@ 21 :> [kind
 * |-> OpApplKind, \* {1,2} operands |-> << 22>>, operator |-> 8, \* Actually,
 * specifying <<1, 2>> unboundedBoundSymbols |-> << >>, boundedBoundSymbols |->
 * << >>, ranges |-> << >>] @@ 22 :> [kind |-> NumeralKind, val |-> 3] @@ 23 :>
 * [kind |-> UserDefinedOpKind, \* Foo(u) == Bar(Arg1) name |-> "Foo", body |->
 * 24, labels |-> << >>, arity |-> 1, params |-> <<[name |-> "u", arity |->
 * 0]>>, defined |-> TRUE, source |-> null ] @@ 24 :> [kind |-> OpApplKind, \*
 * Bar(Arg1) operands |-> <<34>>, operator |-> 32, unboundedBoundSymbols |->
 * <<>>, boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 25 :> [kind |->
 * StringKind, val |-> "string"] @@ 26 :> [kind |-> ModuleInstanceKind, \*
 * Inst(d) == INSTANCE M WITH C <- "expr(d)" name |-> "Inst", arity |-> 1,
 * params |-> <<[name |-> "d", arity |-> 0] >>, defined |-> TRUE ] @@ 27 :>
 * [kind |-> SubstInKind, body |-> 24, subst |-> "expr(d)"] @@ 28 :> [kind |->
 * UserDefinedOpKind, \* Foo(u) == "FooBody(u)" name |-> "Inst!Foo", body |->
 * 27, labels |-> << >>, arity |-> 2, params |-> << [name |-> "d", arity |-> 0],
 * [name |-> "u", arity |-> 0]>>, defined |-> TRUE, source |-> 23 ] @@ 29 :>
 * [kind |-> UserDefinedOpKind, \* Op(Arg, p) == ... name |-> "Inst!Op", body
 * |-> 30, labels |-> "lab" :> 4, arity |-> 3, params |-> <<[name |-> "d", arity
 * |-> 0], [name |-> "Arg", arity |-> 0], [name |-> "p", arity |-> 0]>>, defined
 * |-> TRUE, source |-> 1 ] @@ 30 :> [kind |-> SubstInKind, body |-> 3, subst
 * |-> "expr(d)"] @@ 31 :> [kind |-> StringKind, val |-> "Argm"] @@ 32 :> [kind
 * |-> UserDefinedOpKind, \* Bar(AOp(_)) == AOp(1) name |-> "Bar", body |-> 33,
 * labels |-> << >>, arity |-> 1, params |-> <<[name |-> "AOp", arity |-> 1]>>,
 * defined |-> TRUE, source |-> null ] @@ 33 :> [kind |-> OpApplKind, \* Arg1(1)
 * operands |-> <<14>>, operator |-> 10, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 34 :> [kind |->
 * OpArgKind, op |-> 10, arity |-> 1, name |-> "Arg1"] @@ 35 :> [kind |->
 * UserDefinedOpKind, \* Foo2 == Bar(LAMBDA m, n : <<m, n>>) name |-> "Foo2",
 * body |-> 36, labels |-> << >>, arity |-> 0, params |-> <<>>, defined |->
 * TRUE, source |-> null ] @@ 36 :> [kind |-> OpApplKind, \* Bar(LAMBDA m, n :
 * <<m, n>>) operands |-> <<41>>, operator |-> 32, unboundedBoundSymbols |->
 * <<>>, boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 37 :> [kind |->
 * UserDefinedOpKind, \* LAMBDA m, n : <<m, n>> name |-> "LAMBDA", body |-> 38,
 * labels |-> << >>, arity |-> 2, params |-> <<[name |-> "m", arity |-> 0],
 * [name |-> "n", arity |-> 0]>>, defined |-> TRUE, source |-> null ] @@ 38 :>
 * [kind |-> OpApplKind, \* <<m, n>> operands |-> << 39, 40 >>, operator |-> 8,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>] @@ 39 :> [kind |-> FormalParamKind, name |-> "m", arity |-> 0] @@ 40 :>
 * [kind |-> FormalParamKind, name |-> "n", arity |-> 0] @@ 41 :> [kind |->
 * OpArgKind, \* LAMBDA m, n : <<m, n>> op |-> 37, arity |-> 2, name |->
 * "LAMBDA"] @@ 42 :> [kind |-> UserDefinedOpKind, \* Inst!Foo2 == Bar(LAMBDA m,
 * n : <<m, n>>) name |-> "Inst!Foo2", body |-> 43, labels |-> << >>, arity |->
 * 1, params |-> <<[name |-> "d", arity |-> 0]>>, defined |-> TRUE, source |->
 * 35 ] @@ 43 :> [kind |-> SubstInKind, body |-> 36, subst |-> "expr(d)"] @@ 44
 * :> [kind |-> ThmOrAssumpDefKind, \* Thm == ASSUME Arg1(1) ... name |-> "Thm",
 * body |-> 45, labels |-> << >>, arity |-> 0, params |-> << >> , defined |->
 * TRUE, source |-> null ] @@ 45 :> [kind |-> AssumeProveKind, assumes |-> <<33,
 * 24>>, prove |-> 46 ] @@ 46 :> [kind |-> OpApplKind, \* <<c, Bar(Arg1)>>
 * operands |-> << 59, 24 >>, operator |-> 8, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 47 :> [kind |->
 * ThmOrAssumpDefKind, \* Thm == ASSUME Arg1(1) ... name |-> "Inst!Thm", body
 * |-> 48, labels |-> << >>, arity |-> 1, params |-> << [name |-> "d", arity |->
 * 0]>> , defined |-> TRUE, source |-> 44 ] @@ 48 :> [kind |-> SubstInKind, body
 * |-> 45, subst |-> "expr(d)"] @@ 49 :> [kind |-> UserDefinedOpKind, \* Foo3 ==
 * \A x : LET ... name |-> "Foo3", body |-> 51, labels |-> << >>, arity |-> 0,
 * params |-> <<>>, defined |-> TRUE, source |-> null ] @@ 50 :> [kind |->
 * LetInKind, \* Foo3 == \A x : LET Bar3 == 1 IN 2 context |-> "Bar3" :> 53,
 * body |-> 13 ] @@ 51 :> [kind |-> OpApplKind, \* \A x : LET Bar3 == 1 IN 2
 * operands |-> << 50 >>, operator |-> 52, unboundedBoundSymbols |-> <<"x">>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>] @@ 52 :> [kind |->
 * BuiltInKind, \* \A x : name |-> "$UnboundedForall", arity |-> -1] @@ 53 :>
 * [kind |-> UserDefinedOpKind, \* Bar3 == 1 name |-> "Bar3", body |-> 14,
 * labels |-> << >>, arity |-> 0, params |-> <<>>, defined |-> TRUE, source |->
 * null ] @@ 54 :> [kind |-> FormalParamKind, \* AOp name |-> "AOp", arity |->
 * 1] @@ 55 :> [kind |-> UserDefinedOpKind, \* Bar(AOp(_)) == AOp(1) name |->
 * "Inst!Bar", body |-> 56, labels |-> << >>, arity |-> 2, params |-> <<[name
 * |-> "d", arity |-> 0], [name |-> "AOp", arity |-> 1]>>, defined |-> TRUE,
 * source |-> null ] @@ 56 :> [kind |-> SubstInKind, body |-> 33, subst |->
 * "expr(d)"] @@ 57 :> [kind |-> UserDefinedOpKind, \* UU == lab:: C name |->
 * "UU", body |-> 58, labels |-> "lab":> 58, arity |-> 0, params |-> <<>>,
 * defined |-> TRUE, source |-> null ] @@ 58 :> [kind |-> LabelKind, \* lab :: C
 * name |-> "lab", body |-> 59, arity |-> 0, params |-> <<>>, labels |-> << >>]
 * 
 * @@ 59 :> [kind |-> OpApplKind, \* C operands |-> <<>>, operator |-> 18,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>] @@ 60 :> [kind |-> UserDefinedOpKind, \* UU == lab:: C name |->
 * "Inst!UU", body |-> 58, labels |-> "lab":> 58, arity |-> 1, params |->
 * <<[name |-> "d", arity |-> 0] >>, defined |-> TRUE, source |-> null ]
 * 
 * 
 * MCNodeId == 1..60
 * 
 * MCGlobalContext == "Op" :> 1 @@ "C" :> 18 @@ "UU" :> 57 @@ "Foo" :> 23 @@
 * "Inst" :> 26 @@ "Inst!Foo" :> 28 @@ "Inst!Bar" :> 55 @@ "Inst!Op" :> 29 @@
 * "Inst!UU" :> 60 @@ "Foo2" :> 35 @@ "Inst!Foo2" :> 42 @@ "Thm" :> 44 @@
 * "Inst!Thm" :> 47 @@ "Foo3" :> 49 @@ "Bar" :> 32 @@ "Arg1" :> 10 @@ "AOp" :>
 * 54 @@ "p" :> 17
 * 
 * \* Foo \* MCops == <<"Foo">> \* MCargs == << << >> >> \* MCexpectedArity == 1
 * 
 * \* Op() \* MCops == <<"Op">> \* MCargs == << <<>> >> \* MCexpectedArity == 2
 * 
 * \* Op!lab \* MCops == <<"Op", "lab">> \* MCargs == << <<>> , <<>> >> \*
 * MCexpectedArity == 5
 * 
 * \* Op!lab!<< \* MCops == <<"Op", "lab", "<<">> \* MCargs == << <<>> , <<>> ,
 * << >> >> \* MCexpectedArity == 5
 * 
 * \* Op!lab!<<!>> \* MCops == <<"Op", "lab", "<<", ">>">> \* MCargs == << << >>
 * , << >> , << >>, << >> >> \* MCexpectedArity == 5
 * 
 * \* Op!lab!label2 \* MCops == <<"Op", "lab", "label2">> \* MCargs == << << >>
 * , << >> , << >> >> \* MCexpectedArity == 5
 * 
 * \* Op!lab!label2!<< \* MCops == <<"Op", "lab", "label2", "<<">> \* MCargs ==
 * << << >> , << >> , << >>, << >> >> \* MCexpectedArity == 5
 * 
 * \* Op!lab!:!+ \* MCops == <<"Op", "lab", ":", "+" >> \* MCargs == << << >> ,
 * << >> , << >> , << >> >> \* MCexpectedArity == 7
 * 
 * \* Op!lab!:!+ \* MCops == <<"Op", "lab", ":", "+", ">>" >> \* MCargs == << <<
 * >> , << >> , << >> , << >>, << >> >> \* MCexpectedArity == 7
 * 
 * \* Op!@ \* MCops == <<"Op", "@" >> \* MCargs == << << >> , << >> >> \*
 * MCexpectedArity == 5
 * 
 * \* Op!@!>>!>>!<< \* MCops == <<"Op", "@", ">>", ">>", "<<" >> \* MCargs == <<
 * << >> , << >>, << >>, << >>, << >> >> \* MCexpectedArity == 5
 * 
 * \* Op!<<!>> \* MCops == <<"Op", "<<", ">>" >> \* MCargs == << << >>, << >>,
 * << >> >> \* MCexpectedArity == 2
 * 
 * \* Inst!Foo \* MCops == <<"Inst", "Foo">> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 2
 * 
 * \* Inst!Op \* MCops == <<"Inst", "Op">> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 3
 * 
 * \* Inst!Op!lab \* MCops == <<"Inst", "Op", "lab">> \* MCargs == << << >>, <<
 * >> , << >> >> \* MCexpectedArity == 6
 * 
 * \* Inst!Op!lab!<< \* MCops == <<"Inst", "Op", "lab", "<<">> \* MCargs == <<
 * << >>, << >> , << >> , << >> >> \* MCexpectedArity == 6
 * 
 * \* Inst!Op!lab!<<!>> \* MCops == <<"Inst", "Op", "lab", "<<", ">>">> \*
 * MCargs == << << >>, << >> , << >> , << >>, << >> >> \* MCexpectedArity == 6
 * 
 * \* Inst!Op!lab!label2 \* MCops == <<"Inst", "Op", "lab", "label2">> \* MCargs
 * == << << >>, << >> , << >> , << >> >> \* MCexpectedArity == 6
 * 
 * \* Inst!Op!lab!label2!<< \* MCops == <<"Inst", "Op", "lab", "label2", "<<">>
 * \* MCargs == << << >>, << >> , << >> , << >>, << >> >> \* MCexpectedArity ==
 * 6
 * 
 * \* Inst!Op!lab!:!+ \* MCops == <<"Inst", "Op", "lab", ":", "+" >> \* MCargs
 * == << << >>, << >> , << >> , << >> , << >> >> \* MCexpectedArity == 8
 * 
 * \* Inst!Op!lab!:!+!>> \* MCops == <<"Inst", "Op", "lab", ":", "+", ">>" >> \*
 * MCargs == << << >>, << >> , << >> , << >> , << >>, << >> >> \*
 * MCexpectedArity == 8
 * 
 * \* Inst!Op!@ \* MCops == <<"Inst", "Op", "@" >> \* MCargs == << << >>, << >>
 * , << >> >> \* MCexpectedArity == 6
 * 
 * \* Inst!Op!@!>>!>>!<< \* MCops == <<"Inst", "Op", "@", ">>", ">>", "<<" >> \*
 * MCargs == << << >>, << >> , << >>, << >>, << >>, << >> >> \* MCexpectedArity
 * == 6
 * 
 * \* Inst!Op!<<!>> \* MCops == <<"Inst", "Op", "<<", ">>" >> \* MCargs == << <<
 * >>, << >>, << >>, << >> >> \* MCexpectedArity == 3
 * 
 * \* Foo!1 \* MCops == <<"Foo", "1">> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 2
 * 
 * \* Inst!Foo!1 \* MCops == <<"Inst", "Foo", "1">> \* MCargs == << << >>, <<
 * >>, << >> >> \* MCexpectedArity == 3
 * 
 * \* Foo2!1 \* MCops == <<"Foo2", "1">> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 2
 * 
 * \* Foo2!1!(1, 2) \* MCops == <<"Foo2", "1", "null">> \* MCargs == << << >>,
 * << >>, <<14, 20>> >> \* MCexpectedArity == 0
 * 
 * \* Foo2!1!(1, 2)!2 \* MCops == <<"Foo2", "1", "null", "2">> \* MCargs == <<
 * << >>, << >>, <<14, 20>>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst!Foo2!1 \* MCops == <<"Inst", "Foo2", "1">> \* MCargs == << << >>, <<
 * >>, << >> >> \* MCexpectedArity == 3
 * 
 * \* Inst!Foo2!1 \* MCops == <<"Inst", "Foo2", "1", "@">> \* MCargs == << <<
 * >>, << >>, << >>, << >> >> \* MCexpectedArity == 3
 * 
 * \* Inst!Foo2!1!2 \* MCops == <<"Inst", "Foo2", "1", "@", "2">> \* MCargs ==
 * << << >>, << >>, << >>, << >>, << >> >> \* MCexpectedArity == 3
 * 
 * \* Inst("Argm")!Foo2!1!(1, 2) \* MCops == <<"Inst", "Foo2", "1", "null">> \*
 * MCargs == << <<31>>, << >>, << >>, <<14, 20>> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Foo2!1!(1, 2)!2 \* MCops == <<"Inst", "Foo2", "1", "null",
 * "2">> \* MCargs == << <<31>>, << >>, << >>, <<14, 20>>, << >> >> \*
 * MCexpectedArity == 0
 * 
 * \* Thm!1 \* MCops == <<"Thm", "1" >> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 0
 * 
 * \* Thm!2 \* MCops == <<"Thm", "2" >> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 0
 * 
 * \* Thm!3!<< \* MCops == <<"Thm", "3", "<<" >> \* MCargs == << << >>, << >>,
 * << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Thm!1 \* MCops == <<"Inst", "Thm", "1" >> \* MCargs == <<
 * <<31>>, << >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Thm!2 \* MCops == <<"Inst", "Thm", "2" >> \* MCargs == <<
 * <<31>>, << >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Thm!3!<< \* MCops == <<"Inst", "Thm", "3", "<<" >> \* MCargs
 * == << <<31>>, << >>, << >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!UU \* MCops == <<"Inst", "UU">> \* MCargs == << <<31>>, << >>
 * >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Bar(Arg1)!1<< \* MCops == <<"Inst", "Bar", "1" >> \* MCargs
 * == << <<31>>, <<10 >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Bar(Arg1)!1<< \* MCops == <<"Inst", "Bar", "1" >> \* MCargs
 * == << <<31>>, <<10 >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Thm \* Note: doesn't report an error because \* MCops ==
 * <<"Inst", "Thm" >> \* Inst!Thm isn't expanded \* MCargs == << <<31>>, << >>
 * >> \* MCexpectedArity == 0
 * 
 * \* Inst("Argm")!Thm!: ERROR! \* MCops == <<"Inst", "Thm", ":" >> \* MCargs ==
 * << <<31>>, << >>, << >> >> \* MCexpectedArity == 0
 * 
 * 
 * \* Foo2 \* MCops == <<"Foo2">> \* MCargs == <<<< >> >> \* MCexpectedArity ==
 * 0
 * 
 * \* Foo3!(3)!:Bar3 \* MCops == <<"Foo3", "null", "Bar3">> \* MCargs == << <<
 * >>, <<22>>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Bar(Arg1) \* \* MCops == <<"Bar">> \* \* MCargs == << <<10>> >> \* \*
 * MCexpectedArity == 0
 * 
 * \* Arg1(C) \* MCops == <<"Arg1">> \* MCargs == << <<18>> >> \*
 * MCexpectedArity == 0
 * 
 * \* AOp \* MCops == <<"AOp">> \* MCargs == << <<18 >> >> \* MCexpectedArity ==
 * 0
 * 
 * \* C \* MCops == <<"C">> \* MCargs == << << >> >> \* MCexpectedArity == 0
 * 
 * \* p \* MCops == <<"p">> \* MCargs == << << >> >> \* MCexpectedArity == 0
 * 
 * \* Foo3 \* MCops == <<"Foo3">> \* MCargs == << << >> >> \* MCexpectedArity ==
 * 0
 * 
 * \***** THIS IS A BUG--NOT HANDLED CORRECTLY ****** \* UU!lab \* MCops ==
 * <<"UU", "lab">> \* MCargs == << << >>, << >> >> \* MCexpectedArity == 0
 * 
 * \* Op(2, 2)!(2, 2, 2) \* MCops == <<"Op", "null">> \* MCargs == << <<20,
 * 20>>, <<20, 20, 20 >> >> \* MCexpectedArity == 0
 * 
 * \* Foo3!(2) \* MCops == <<"Foo3", "null">> \* MCargs == << << >>, <<20>> >>
 * \* MCexpectedArity == 0
 * 
 * \* Op(2, 2)!(2,2,2)!+(2, 2) \* MCops == <<"Op", "null", "+">> \* MCargs == <<
 * <<20,20 >>, <<20,20,20>> , <<20,20>>>> \* MCexpectedArity == 0
 * 
 * \* MCops == <<"Op">> \* MCargs == << << >> >> \* MCexpectedArity == -1
 * 
 * \* MCops == <<"Inst", "Op">> \* MCargs == << << >> , << >> >> \*
 * MCexpectedArity == -1
 * 
 * \* MCops == <<"Inst", "Thm">> \* MCargs == << << >> , << >> >> \*
 * MCexpectedArity == -1
 * 
 * \* MCops == <<"Inst", "Op", "@", "+">> \* MCargs == << << >> , << >> , << >>
 * , << >> >> \* MCexpectedArity == -1
 * 
 * \* MCops == <<"Op", "lab", ":", "+">> \* MCargs == << << >> , << >>, << >>,
 * << >> >> \* MCexpectedArity == 7
 * 
 * \* MCops == <<"Op", "lab", ":", "+">> \* MCargs == << << >> , << >>, << >>,
 * << >> >> \* MCexpectedArity == -1
 * 
 * \* MCops == <<"Foo2">> \* MCargs == << << >> >> \* MCexpectedArity == 0
 * 
 * \* MCops == <<"Foo3", ":">> \* MCargs == << << >>, << >> >> \*
 * MCexpectedArity == 0
 * 
 * \* MCops == <<"Op", "lab", ":", "+">> \* MCargs == << << >>, << >>, << >>, <<
 * >> >> \* MCexpectedArity == -1
 * 
 * \* MCops == <<"Inst", "Thm">> \* MCargs == << <<14 >>, << >> >> \*
 * MCexpectedArity == 0
 * 
 * MCops == <<"Inst", "Thm", ":">> MCargs == << <<14 >>, << >>, << >> >>
 * MCexpectedArity == 0 MCdebug == FALSE \* TRUE
 * 
 * (*********************************
 * (***************************************************************************)
 * (* Module M *) (* CONSTANT C *) (* Op(Arg(_), p) == \A x \in {1,2}, <<y, z>>
 * \in {3} : *) (* lab(x,y,z) :: LET a + b == <<Arg(a), b>> *) (* IN 1 + label2
 * :: p + C *) (* *) (* Foo(u) == "FooBody(u)" *) (* Inst(w) == INSTANCE M WITH
 * C <- <<w, CONST>> *)
 * (***************************************************************************)
 * 
 * \* MCNode == \* 1 :> [kind |-> NumeralKind, \* val |-> 1] \* @@ \* 2 :> [kind
 * |-> BuiltInKind, \* \E \* name |-> "$UnboundedExists", \* arity |-> -1] \*
 * \* @@ \* 3 :> [kind |-> OpApplKind, \* \E x : Node 1 \* operands |-> <<1>>,
 * \* operator |-> 2, \* unboundedBoundSymbols |-> <<"x">>, \*
 * boundedBoundSymbols |-> << >>, \* ranges |-> << >>] \* @@ \* 4 :> [kind |->
 * UserDefinedOpKind, \* Inst!UserOp(p1, OpP) == Node 8 \* name |->
 * "Inst!UserOp", \* body |-> 8, \* labels |-> "Label1" :> 7, \* arity |-> 2, \*
 * params |-> <<[name |-> "p1", arity |-> 0], \* [name |-> "OpP", arity |->
 * 0]>>, \* defined |-> TRUE, \* source |-> 40 ] \* @@ \* 5 :> [kind |->
 * ModuleInstanceKind, \* Inst(p1) == INSTANCE \* name |-> "Inst", \* arity |->
 * 1, \* params |-> <<[name |-> "p1", arity |-> 0] >>, \* defined |-> TRUE ]
 * \* @@ \* 6 :> [kind |-> UserDefinedOpKind, \* 1ArgOp(1OpP(_, _)) == Node 1 \*
 * name |-> "1ArgOp", \* body |-> 41, \* labels |-> << >>, \* arity |-> 1, \*
 * params |-> <<[name |-> "1OpP", arity |-> 0]>>, \* defined |-> TRUE, \* source
 * |-> null ] \* @@ \* 7 :> [kind |-> LabelKind, \* name |-> "Label1", \* body
 * |-> 14, \* arity |-> 1, \* params |-> <<[name |-> "labParam1", arity |->
 * 0]>>, \* labels |-> "Label2" :> 9 \* ] \* @@ \* 8 :> [kind |-> SubstInKind,
 * \* body |-> 11, \* subst |-> "x <- something(p1)"] \* \* @@ \* 9 :> [kind |->
 * LabelKind, \* name |-> "Label2", \* body |-> 15, \* arity |-> 1, \* params
 * |-> <<[name |-> "labParam2", arity |-> 0]>>, \* labels |-> << >> \* ] \* @@
 * \* 10 :> [kind |-> NumeralKind, \* val |-> 10] \* @@ \* 11 :> [kind |->
 * SubstInKind, \* body |-> 15, \* subst |-> "y <- something(p1)"] \* @@ \* 12
 * :> [kind |-> StringKind, \* val |-> "Body of UserOp (p1, OpP)"] \* @@ \* 13
 * :> [kind |-> StringKind, \* val |-> "Body of Label2(labParam2)"] \* @@ \* 14
 * :> [kind |-> StringKind, \* val |-> "Body of Label1(labParam1)"] \* @@ \* 15
 * :> [kind |-> LetInKind, \* context |-> "1ArgOp" :> 6, \* body |-> 16] \* @@
 * \* 16 :> [kind |-> StringKind, \* val |-> "Body of Let/In"] \* @@ \* 17 :>
 * [kind |-> UserDefinedOpKind, \* 1ArgOp("1OpP") == Node 1 \* name |-> "Foo",
 * \* body |-> 18, \* labels |-> << >>, \* arity |-> 0, \* params |-> << >> , \*
 * <<[name |-> "FooPar1", arity |-> 0]>>, \* defined |-> TRUE, \* source |->
 * null] \* @@ \* 18 :> [kind |-> OpApplKind, \* operands |-> <<42 >>, \*
 * operator |-> 21, \* unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols
 * |-> << >>, \* ranges |-> << >>] \* @@ \* 19 :> [kind |-> StringKind, \* val
 * |-> "Arg1"] \* @@ \* 20 :> [kind |-> StringKind, \* val |-> "Arg2"] \* @@ \*
 * 21 :> [kind |-> UserDefinedOpKind, \* Foo2 == [rcd-lab1 |-> rcd-comp1, \*
 * name |-> "Foo2", \* ... \* body |-> 34, \* rcd-lab3 |-> rcd-comp3] \* labels
 * |-> << >>, \* arity |-> 1, \* params |-> <<[name |-> "p1", arity |-> 1]>>, \*
 * defined |-> TRUE, \* source |-> null ] \* @@ \* 22 :> [kind |-> OpApplKind,
 * \* operands |-> <<10 (* 25 *) , 28, 31>>, \* operator |-> 23, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 23 :> [kind |-> BuiltInKind, \* name |-> "$Except", \*
 * "$Case", \* "$SetOfRcds", \* arity |-> -1 \* ] \* @@ \* 24 :> [kind |->
 * BuiltInKind, \* name |-> "$Pair", \* arity |-> 2 \* ] \* @@ \* 25 :> [kind
 * |-> OpApplKind, \* operands |-> <<26,27>>, \* operator |-> 24, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 26 :> [kind |-> StringKind, \* val |-> "rcd-lab1"] \* @@
 * \* 27 :> [kind |-> StringKind, \* val |-> "rcd-comp1"] \* \* @@ \* 28 :>
 * [kind |-> OpApplKind, \* operands |-> <<29,30>>, \* operator |-> 24, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 29 :> [kind |-> StringKind, \* val |-> "rcd-lab2"] \* @@
 * \* 30 :> [kind |-> StringKind, \* val |-> "rcd-comp2"] \* @@ \* 31 :> [kind
 * |-> OpApplKind, \* operands |-> <<32,33>>, \* operator |-> 24, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << >>, \* ranges
 * |-> << >>] \* @@ \* 32 :> [kind |-> StringKind, \* val |-> "rcd-lab3"] \* @@
 * \* 33 :> [kind |-> StringKind, \* val |-> "rcd-comp3"] \* @@ \* 34 :> [kind
 * |-> OpApplKind, \* operands |-> <<35>>, \* operator |-> 36, \*
 * unboundedBoundSymbols |-> <<>>, \* boundedBoundSymbols |-> << <<"b1", "b2">>,
 * <<"b3">> >>, \* ranges |-> <<37, 38 >>] \* @@ \* 35 :> [kind |-> StringKind,
 * \* val |-> "Fcn of b1, b2, b3"] \* @@ \* 36 :> [kind |-> BuiltInKind, \* name
 * |-> "$Pair", \* arity |-> 2 \* ] \* @@ \* 37 :> [kind |-> StringKind, \* val
 * |-> "Range 1"] \* @@ \* 38 :> [kind |-> StringKind, \* val |-> "Range 2"]
 * \* @@ \* 39 :> [kind |-> StringKind, \* val |-> "Arg3"] \* @@ \* 40 :> [kind
 * |-> UserDefinedOpKind, \* Inst!UserOp(p1, OpP) == Node 8 \* name |->
 * "UserOp", \* body |-> 8, \* labels |-> "Label1" :> 7, \* arity |-> 1, \*
 * params |-> <<[name |-> "OpP", arity |-> 1]>>, \* defined |-> TRUE, \* source
 * |-> null ] \* @@ \* 41 :> [kind |-> StringKind, \* val |-> "Body of 1ArgOp
 * may dep on (x, y)"] \* @@ \* 42 :> [kind |-> OpArgKind, \* op |-> 43, \*
 * arity |-> 1, \* name |-> "Foo3"] \* @@ \* 43 :> [kind |-> UserDefinedOpKind,
 * \* 1ArgOp("1OpP") == Node 1 \* name |-> "Foo3", \* body |-> 18, \* labels |->
 * << >>, \* arity |-> 0, \* params |-> << >>, \* <<[name |-> "FooPar1", arity
 * |-> 0]>>, \* defined |-> TRUE, \* source |-> null] \* \* MCNodeId == 1..43 \*
 * \* MCGlobalContext == \* "Inst!UserOp" :> 4 \* @@ \* "Inst" :> 5 \* @@ \*
 * "Foo" :> 17 \* @@ \* "Foo2" :> 21 \* @@ \* "Foo3" :> 43 \* \* @@ \* \*
 * "1ArgOp" :> 6 \* \* \* MCops == <<"Inst", "UserOp">> \* , "1">> \* MCargs ==
 * << <<1 >> , <<1>> >>
 * 
 * \* \* << <<1>>, <<19, 20, 33 >> >> \* <<1>>, <<10>>, << >>, <<4>> >> \* \*
 * MCexpectedArity == 0 \* -1 \* 5 )
 * 
 * -----------------------------------------------------------------------------
 * (***************************************************************************)
 * (* THE ALGORITHM *)
 * (***************************************************************************)
 * (************************************** --algorithm Subexpression variables
 * (*************************************************************************)
 * (* The input variables. *)
 * (*************************************************************************)
 * ops = MCops, args = MCargs,
 * (***********************************************************************) (*
 * The sequences op and args described above. *)
 * (***********************************************************************)
 * expectedArity = MCexpectedArity,
 * (***********************************************************************) (*
 * The arity of the operator expected, or -1 if expecting a definition *) (*
 * name. It is 0 iff an expression is expected. The result should be *) (* an
 * OpArg node if expectedArity > 0, it should be an expression node *) (* if
 * expectedArity = 0, and it should be a UserDefinedOpKind or a *) (*
 * ThmOrAssumpDefKind if expectedArity < 0. *)
 * (***********************************************************************)
 * 
 * (*************************************************************************)
 * (* The major variables of the algorithm. *)
 * (*************************************************************************)
 * substInPrefix = << >> ,
 * (***********************************************************************) (*
 * The sequence of SubstInNode or APSubstInNode sequence that will be *) (*
 * appended to body of the resulting OpApplNode *)
 * (***********************************************************************)
 * params = << >> ,
 * (***********************************************************************) (*
 * The sequence of FormalParamNode objects that are the formal *) (* parameters
 * if this produces a Lambda expression. A Lambda *) (* expression will be
 * produced iff this is non-empty *)
 * (***********************************************************************)
 * allArgs = << >> ,
 * (***********************************************************************) (*
 * The sequence of all arguments. *)
 * (***********************************************************************)
 * curNode = null,
 * (***********************************************************************) (*
 * If params = << >>, then the OpDefNode for the OpApplNode that is *) (*
 * produced. If params # << >>, then the Expr node that will form the *) (* body
 * of the Lambda expression. *) (* *) (* Note: in the Java implementation, this
 * will actually be a ref to *) (* the node--in terms of this spec, a NodeId. *)
 * (***********************************************************************)
 * subExprOf = "null",
 * (***********************************************************************) (*
 * The node UserDefinedOpDefKind or ThmOrAssumpDefKind within which *) (* this
 * subexpression is defined. *)
 * (***********************************************************************)
 * result = null,
 * (***********************************************************************) (*
 * The actual output node. *)
 * (***********************************************************************)
 * 
 * (*************************************************************************)
 * (* The local variables. *)
 * (*************************************************************************)
 * idx = 1,
 * (***********************************************************************) (*
 * The element of the arrays op and args that the algorithm is *) (* currently
 * examining. *)
 * (***********************************************************************)
 * mode = "FindingOpName",
 * (***********************************************************************) (*
 * The current mode describing what kind of selector it is expecting *) (* next.
 * Its other possible values are "FollowingLabels" and *) (* "FindingSubExpr".
 * *) (***********************************************************************)
 * prevMode = "",
 * (***********************************************************************) (*
 * The mode for the previously examined selector. *)
 * (***********************************************************************)
 * curContext = GlobalContext,
 * (***********************************************************************) (*
 * The context for looking up operator or label names. *)
 * (***********************************************************************)
 * curName = "" ,
 * (***********************************************************************) (*
 * When looking up an operator name, which may be something like *) (*
 * "Foo!Bar!Baz", this is the part that has been found so far. *)
 * (***********************************************************************)
 * opDefArityFound = 0, opDefArgs = << >>,
 * (***********************************************************************) (*
 * The total arity and the sequence of arguments found so far for the *) (*
 * current operator--for example, opDefArityFound will equal 2 if the *) (*
 * algorithm has so far processed "Foo(a, b)!Bar" *)
 * (***********************************************************************)
 * firstFindingOpName = TRUE,
 * (***********************************************************************) (*
 * True iff have entered the FindingOpName only once (initially). *)
 * (***********************************************************************)
 * opNode, newName, newNode, nodeArity, temp, tempArgs
 * 
 * 
 * (***************************************************************************)
 * (* A macro used for reporting an error and terminating the execution. *)
 * (***************************************************************************)
 * macro Error(msg) begin print msg ; if debug then
 * (**************************************) (* Force the +cal translator to *)
 * (* insert a label so the error trace *) (* shows the final state. *)
 * (**************************************) idx := idx ; idx := idx ; assert
 * FALSE else goto Done end if end macro ;
 * 
 * begin
 * 
 * (*************************************************************************)
 * (* An assertion that checks that ops and args are consistent with each *) (*
 * other and with the value of expectedArity. In an implementation, *) (* some
 * of these should be guaranteed by the context (e.g., Len(ops) = *) (*
 * Len(args) while others will be checked as part of the processing for *) (*
 * the particular value of idx. *)
 * (*************************************************************************)
 * assert /\ expectedArity \in Int /\ ops \in Seq(STRING) /\ args \in
 * Seq(Seq(NodeId)) /\ Len(ops) = Len(args) /\ \A i \in 1..Len(ops) : /\ \/
 * ops[i] \in {"<<", ">>", "@", ":"} \cup NumberOp \/ expectedArity # 0 =>
 * args[i] = << >> /\ (ops[i] = "null") => (Len(args[i]) > 0) ;
 * 
 * (*************************************************************************)
 * (* The outer "for" loop on idx. *)
 * (*************************************************************************)
 * while idx <= Len(ops) do if mode = "FindingOpName" then
 * 
 * \* The following code was modified by LL on 23 Sep 2009 to fix the following
 * \* bug. The parser produced a bogus error on a reference to an identifier \*
 * M!N that is imported by an unnamed INSTANCE of a module containing the \*
 * statement M == INSTANCE ... . The original code essentially just \* contained
 * the first iteration of the following while loop, and would \* report an error
 * if it found newNode = null. Thus, it would report \* an error in the
 * identifier M!N when it found M to be undefined. \* \* Corrected by LL on 9
 * Nov 2009 to handle arguments of those \* undefined operators. They are put
 * into tempArgs when they are \* found.
 * 
 * newNode := null ; tempArgs := << >> ;
 * (**********************************************************************) (*
 * The number of arguments found in the following loop for the *) (* undefined
 * operators *)
 * (**********************************************************************)
 * while newNode = null do if idx \geq Len(ops) then Error ("Unknown operator");
 * end if; newName := IF IsName(ops[idx]) THEN IF curName = "" THEN ops[idx]
 * ELSE curName \o "!" \o ops[idx] ELSE null ; if /\ curName = "" /\ ~
 * IsName(ops[idx]) then
 * (***************************************************************) (* I think
 * that this error can only happen for idx = 1, and *) (* should never happen in
 * the implementation because the *) (* parser should not allow a compound name
 * that doesn't begi *) (* with a name. *)
 * (***************************************************************) Error("Need
 * an operator or label name or step number here") end if; newNode := IF newName
 * # null THEN LookUp(newName, curContext) ELSE null ; if newName = null then
 * tempArgs := tempArgs \o args[idx]; idx := idx + 1; end if; end while ;
 * curNode := newNode ; curName := newName ; if curNode.kind \in
 * {UserDefinedOpKind, ThmOrAssumpDefKind, ModuleInstanceKind, ConstantDeclKind,
 * VariableDeclKind, FormalParamKind, BuiltInKind, BoundSymbolKind} then if
 * curNode.kind \in {ConstantDeclKind, VariableDeclKind, FormalParamKind,
 * BuiltInKind, BoundSymbolKind} then if idx # 1 then Error("Abort: Impossible
 * naming of declaration " \o "or built-in operator.") else if Len(ops) # 1 then
 * Error("Can't take subexpression of this"); end if end if end if ; nodeArity
 * := Arity(curNode) ; tempArgs := tempArgs \o args[idx]; if expectedArity = 0
 * then if opDefArityFound + Len(tempArgs) # nodeArity then Error("Wrong number
 * of arguments") end if ; if \E i \in 1..Len(tempArgs[idx]) :
 * Arity(Node[tempArgs[idx][i]]) # ParamArity(curNode, i + opDefArityFound) then
 * Error("Argument has wrong arity") else opDefArgs := opDefArgs \o tempArgs;
 * end if ; else if expectedArity > 0 then if \E i \in 1..Len(curNode.params) :
 * curNode.params[i].arity > 0 then Error("Higher-order operator selected " \o
 * "as operator argument") end if \* else Error( \* "Abort: Don't yet handle
 * expectedArity < 0") end if end if ; opDefArityFound := nodeArity ; if
 * curNode.kind \in {UserDefinedOpKind, ThmOrAssumpDefKind, ConstantDeclKind,
 * VariableDeclKind, FormalParamKind, BoundSymbolKind} then if /\ curNode.kind =
 * UserDefinedOpKind /\ ~ curNode.defined /\ ~ Len(ops) = 1 then Error("Can't
 * refer to subexpression of " \o "operator inside its definition") end if; if
 * /\ firstFindingOpName /\ curNode.kind \in {UserDefinedOpKind,
 * ThmOrAssumpDefKind} then subExprOf := curNode end if; if idx # Len(ops) then
 * params := params \o curNode.params ; curName := "" ; if IsName(ops[idx+1])
 * then mode := "FollowingLabels" else mode := "FindingSubExpr" ; end if ;
 * allArgs := allArgs \o opDefArgs ; opDefArityFound := 0 ; opDefArgs := << >> ;
 * newNode := Node[curNode.body] ; while newNode.kind = SubstInKind do
 * substInPrefix := substInPrefix \o <<newNode>>; newNode := Node[newNode.body];
 * end while ; while newNode.kind \in {SubstInKind, APSubstInKind}
 * (************************************************) (* Added APSubstInKind
 * test on 13 Nov 2009. *) (************************************************) do
 * substInPrefix := substInPrefix \o <<newNode>>; newNode := Node[newNode.body];
 * end while ; (********************************************) (* If the next op
 * is an OpSel, then need to *) (* skip over SubstInNodes, which are *) (*
 * invisible to the user. *) (********************************************) if
 * mode = "FindingSubExpr" then curNode := newNode end if; end if ; else \*
 * curNode.kind = ModuleInstanceKind if (idx = Len(ops)) then Error("Operator
 * name incomplete") end if end if else Error("Unexpected node kind") ; end if ;
 * prevMode := "FindingOpName" ;
 * 
 * 
 * elsif mode = "FollowingLabels" then if prevMode = "FindingOpName" then assert
 * curNode.kind \in {UserDefinedOpKind, ThmOrAssumpDefKind} ; newNode :=
 * LookUp(ops[idx], curNode.labels) ; else assert curNode.kind = LabelKind ;
 * newNode := LookUp(ops[idx], curNode.labels) ; end if ; if newNode = null then
 * Error("Label not found") end if; curNode := newNode ; if expectedArity = 0
 * then if Len(args[idx]) # curNode.arity then Error("bad arity") end if ; if \E
 * i \in 1..Len(args[idx]) : Arity(Node[args[idx][i]]) # 0 then Error("Operator
 * argument given to label") end if; allArgs := allArgs \o args[idx] ; end if;
 * params := params \o curNode.params ; if /\ idx < Len(ops) /\
 * ~IsName(ops[idx+1]) then mode := "FindingSubExpr" end if ; if \/ mode =
 * "FindingSubExpr" \/ idx = Len(ops) then curNode := Node[curNode.body] end if;
 * prevMode := "FollowingLabels";
 * 
 * 
 * elsif mode = "FindingSubExpr" then if ops[idx] = ":" then if \/ prevMode
 * \notin {"FindingOpName", "FollowingLabels"} \/ ~ \/ /\ idx = Len(ops) /\
 * prevMode = "FindingOpName" \/ /\ idx < Len(ops) /\ IsName(ops[idx+1]) then
 * Error("`!:' can be used only after a name and either at the " \o "end after
 * an operator name or before an operator name.") end if
 * 
 * elsif curNode.kind = LetInKind then if ArgNum(ops[idx], 1) = 1 then curNode
 * := Node[curNode.body] else Error("A Let/In has only a single operand") end if
 * ;
 * 
 * elsif curNode.kind = OpApplKind then opNode := Node[curNode.operator] ; if
 * opNode.kind \in {FormalParamKind, ConstantDeclKind, UserDefinedOpKind} then
 * (******************************************************************) (*
 * Selecting an argument from something of the form Op(...). *)
 * (******************************************************************) temp :=
 * ArgNum(ops[idx], opNode.arity) ; if temp = -1 then Error("Nonexistent operand
 * specified") else curNode := Node[curNode.operands[temp]] end if elsif
 * opNode.kind = BuiltInKind then \* See configuration/ConfigConstants for a
 * list of all \* BuiltInKind operators. if opNode.name \in {"$RcdConstructor",
 * "$SetOfRcds"} then
 * (*****************************************************************) (*
 * curNode represents an expression *) (* [a_1 |-> e_1, ... , a_n |-> e_n] or *)
 * (* [a_1 : e_1, ... , a_n : e_n] *) (* Its i-th argument is the $Pair node
 * (a_i, e_i) *)
 * (*****************************************************************) temp :=
 * ArgNum(ops[idx], Len(curNode.operands)) ; if temp = -1 then Error("Incorrect
 * subexpression number") end if ; curNode := Node[curNode.operands[temp]] ; if
 * \/ curNode.kind # OpApplKind \/ Node[curNode.operator].kind # BuiltInKind \/
 * Node[curNode.operator].name # "$Pair" then Error ("Expecting $Pair(...)")
 * else curNode := Node[curNode.operands[2]] end if
 * 
 * elsif opNode.name \in {"$Case"} then
 * (*****************************************************************) (* The
 * i-th clause is a $Pair node, where for the OTHER clause *) (* the 1st element
 * is null. *)
 * (*****************************************************************) if idx =
 * Len(ops) then Error( "CASE subexpression must be of form !i!j") end if ; temp
 * := ArgNum( ops[idx], Len(curNode.operands)) ; if temp = -1 then
 * Error("Incorrect subexpression name") end if ; curNode :=
 * Node[curNode.operands[temp]] ; if \/ curNode.kind # OpApplKind \/
 * Node[curNode.operator].kind # BuiltInKind \/ Node[curNode.operator].name #
 * "$Pair" then Error ("Expecting $Pair(...)") end if ; idx := idx+1 ; temp :=
 * ArgNum(ops[idx], 2); if temp = -1 then Error("Incorrect subexpression name")
 * end if ; curNode := Node[curNode.operands[temp]] ; if curNode = null then
 * Error("Selecting OTHER") end if
 * 
 * elsif opNode.name = "$Except" then
 * (****************************************************************) (* For *)
 * (* [exp_1 ELSE !... = exp_2, ... , !.. = exp_n] *) (* argument number i
 * chooses exp_i. For i > 1, exp_i is the *) (* second argument of a $Pair
 * operator. *)
 * (****************************************************************) temp :=
 * ArgNum(ops[idx], Len(curNode.operands)); if temp = -1 then Error("Bad
 * argument selector.") end if; curNode := Node[curNode.operands[temp]] ; if
 * temp > 1 then if \/ curNode.kind # OpApplKind \/ Node[curNode.operator].kind
 * # BuiltInKind \/ Node[curNode.operator].name # "$Pair" then Error("Unexpected
 * expression node found.") else curNode := Node[curNode.operands[2]] end if end
 * if
 * 
 * else (*****************************************************************) (*
 * Operator handled by standard procedure. *)
 * (*****************************************************************) if /\
 * Len(curNode.unboundedBoundSymbols) = 0 /\ Len(curNode.boundedBoundSymbols) =
 * 0 then (**********************************************************) (*
 * Current subexpression has no bound variables. *)
 * (**********************************************************) temp :=
 * ArgNum(ops[idx], Len(curNode.operands)) ; if temp = -1 then Error("Incorrect
 * subexpression selector") end if; curNode := Node[curNode.operands[temp]] ;
 * else (**********************************************************) (* Current
 * subexpression has bound variables. If *) (* selector is "@" or null, then
 * choosing body and adding *) (* parameters. Otherwise, must be selecting one
 * of the *) (* bounds. *)
 * (**********************************************************) if ops[idx] \in
 * {"null", "@"} then (***************************************************) (*
 * Set temp to the sequence of parameters. *)
 * (***************************************************) temp := IF
 * Len(curNode.unboundedBoundSymbols) > 0 THEN curNode.unboundedBoundSymbols
 * ELSE SeqSeqToSeq( curNode.boundedBoundSymbols);
 * 
 * params := params \o [i \in 1.. Len(temp) |-> [name |-> temp[i], arity |-> 0]]
 * ; allArgs := allArgs \o args[idx] ; if /\ ops[idx] = "null" /\ Len(args[idx])
 * # Len(temp) then Error("Wrong number of selector arguments"); end if; curNode
 * := Node[curNode.operands[1]]; else temp := ArgNum(ops[idx],
 * Len(curNode.ranges)) ; if temp = -1 then Error ("Selecting non-existent
 * range") ; else curNode := Node[curNode.ranges[temp]] end if end if end if end
 * if \* opNode.name = ...
 * 
 * else Error("Applying subexpression chooser to an expr" \o " with no choosable
 * subexpressions")
 * 
 * end if \* opNode.kind = ...
 * 
 * elsif curNode.kind = AssumeProveKind then temp := ArgNum(ops[idx], 1 +
 * Len(curNode.assumes)) ; if temp = -1 then Error("Illegal argument number")
 * else if temp <= Len(curNode.assumes) then curNode :=
 * Node[curNode.assumes[temp]] else curNode := Node[curNode.prove] end if end if
 * 
 * elsif curNode.kind = OpArgKind then
 * (*********************************************************************) (*
 * The only kind of OpArgNode that has a subpart is a Lambda *) (* expression.
 * *) (*********************************************************************)
 * opNode := Node[curNode.op] ; if \/ opNode.kind # UserDefinedOpKind \/
 * opNode.name # "LAMBDA" then Error("Selecting from operator argument that has
 * no sub-part") elsif ops[idx] \notin {"null", "@"} then Error("Incorrect
 * selection from LAMBDA") elsif /\ ops[idx] = "null" /\ Len(args[idx]) #
 * Len(opNode.params) then Error("Incorrect number of arguments for LAMBDA")
 * else params := params \o opNode.params ; allArgs := allArgs \o args[idx] ;
 * curNode := Node[opNode.body] ; end if
 * 
 * elsif curNode.kind \in {UserDefinedOpKind, BuiltInKind} then Error("Abort:
 * should not have been able to choose this node.")
 * 
 * elsif curNode.kind \in {AtNodeKind, DecimalKind, NumeralKind, StringKind,
 * FormalParamKind, ConstantDeclKind, VariableDeclKind, BoundSymbolKind} then
 * Error("Selected part has no subexpression")
 * 
 * elsif curNode.kind = LabelKind then
 * (*********************************************************************) (*
 * Skip over label. *)
 * (*********************************************************************)
 * curNode := Node[curNode.body] ; idx := idx - 1 ; else Error("Unexpected node
 * kind found in expression")
 * 
 * end if; \* ops[idx] = ":"
 * 
 * if idx # Len(ops) then if IsName(ops[idx+1]) then while curNode.kind =
 * LabelKind do curNode := Node[curNode.body] end while ; if curNode.kind =
 * LetInKind then curContext := curNode.context ; mode := "FindingOpName" ;
 * firstFindingOpName := FALSE; else Error("A name not following the selector of
 * a LET") end if else if ops[idx+1] = ":" then Error("!: should not follow an
 * operand selector") end if ; end if ; end if ; \* ops[idx] = ":" prevMode :=
 * "FindingSubExpr";
 * 
 * else Error("Bad value of mode")
 * 
 * end if ; \* mode = ...
 * 
 * idx := idx + 1; end while ;
 * 
 * if curNode.kind = AssumeProveKind then Error("Selecting ASSUME/PROVE instead
 * of expression") end if;
 * 
 * if expectedArity < 0 then if \/ prevMode # "FindingOpName" \/ curNode.kind
 * \notin {UserDefinedOpKind, ThmOrAssumpDefKind} then Error("Should have
 * selected a definition, but didn't.") end if; result := curNode ; goto
 * Finished end if;
 * 
 * if expectedArity > 0 then temp := Len(params) + IF \/ prevMode =
 * "FindingOpName" \/ curNode.kind = OpArgKind THEN Arity(curNode) ELSE 0 ; if
 * expectedArity # temp then Error("Expect arity = " \o ToString(expectedArity)
 * \o ", but found arity = " \o ToString(temp)) end if end if;
 * 
 * 
 * (*************************************************************************)
 * (* If found an operator def and there are parameters or substitutions, *) (*
 * then set curNode to the operator applied to new parameters, add those *) (*
 * parameters to params and add the arguments to allArgs. Note: need to *) (* do
 * this even if operator takes no parameters because we need to put *) (* the
 * operator in a LAMBDA expression whose body is an expression *)
 * (*************************************************************************)
 * if /\ prevMode = "FindingOpName" /\ Len(params) + Len(substInPrefix) > 0 then
 * temp := [i \in 1..Len(curNode.params) |-> [curNode.params[i] EXCEPT !.name =
 * "New " \o @]] ;
 * (****************************************************************) (* temp :=
 * new formal parameters for the operator, with the *) (* same arities as the
 * original parameters. *)
 * (****************************************************************)
 * 
 * curNode := [kind |-> OpApplKind, operands |-> temp, operator |-> curNode,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>] ; params := params \o temp ; allArgs := allArgs \o opDefArgs ; end if ;
 * 
 * if curNode.kind = OpArgKind then if expectedArity = 0 then Error("Selected
 * Operator Argument when expression expected.") elsif expectedArity #
 * Len(params) + curNode.arity then Error("Selected operator has wrong arity.")
 * else if Len(params) + Len(substInPrefix) > 0 then
 * (********************************************************) (* If curNode is a
 * LAMBDA, then this will eventually *) (* produce an OpArg node whose operator
 * is a LAMBDA *) (* whose body is an OpApplNode that applies the *) (*
 * curNode's LAMBDA to parameters of the outer LAMBDA. *) (* This result can be
 * simplified to a LAMBDA whose body *) (* is the body of curNode. However, that
 * *) (* simplification is what one will get by selecting the *) (* body of the
 * LAMBDA, so we keep this complicated *) (* expression in this case. *)
 * (********************************************************) temp := [i \in
 * 1..curNode.arity |-> [name |-> "NewParam" \o NumToString(i), arity |-> 0]] ;
 * curNode := [kind |-> OpApplKind, operands |-> temp, operator |->
 * Node[curNode.op], unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> <<
 * >>, ranges |-> << >>] ; params := params \o temp end if end if end if ;
 * 
 * if curNode.kind \in {UserDefinedOpKind, ConstantDeclKind, VariableDeclKind,
 * FormalParamKind, BuiltInKind, BoundSymbolKind, ThmOrAssumpDefKind} then
 * (***********************************************************************) (*
 * There are no params or substitutions, so this is an easy case. *)
 * (***********************************************************************) if
 * expectedArity > 0 then result := [kind |-> OpArgKind, name |-> curNode.name,
 * op |-> curNode, arity |-> expectedArity] elsif expectedArity = 0 then result
 * := [kind |-> OpApplKind, operands |-> opDefArgs, operator |-> curNode,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>, subExprOf |-> subExprOf] end if elsif curNode.kind = OpArgKind then
 * (***********************************************************************) (*
 * There are no params or substitutions, so this is an easy case. *)
 * (***********************************************************************)
 * result := curNode ; else
 * (******************************************************************) (*
 * curNode should be an expression node. *)
 * (******************************************************************) temp :=
 * Len(substInPrefix) ; while temp > 0 do curNode := [kind |->
 * substInPrefix[temp].kind, (********************************************) (*
 * Changed on 13 Nov 2009 from SubstInKind. *)
 * (********************************************) body |-> curNode , subst |->
 * substInPrefix[temp].subst ] ; temp := temp - 1; end while;
 * 
 * if expectedArity > 0 then if Len(params) # expectedArity then Error
 * ("Selection has wrong arity") end if ; result := [kind |-> OpArgKind, op |->
 * [kind |-> UserDefinedOpKind, name |-> "LAMBDA", body |-> curNode, params |->
 * params, arity |-> Len(params), defined |-> TRUE, source |-> null], name |->
 * "LAMBDA"] else if Len(params) # Len(allArgs) then Error("Abort: number of
 * params # num of args") end if ; if Len(params) = 0 then
 * (******************************************************) (* This is the one
 * case with expectedArity = 0 in *) (* which the result is not a
 * newly-constructed node. *) (* In this case, we construct a dummy label node
 * so *) (* we have a node to which the implementation can *) (* attach the
 * syntax node. *) (******************************************************)
 * result := [kind |-> LabelKind, name |-> "$Subexpression", arity |-> 0, params
 * |-> << >>, body |-> curNode, subExprOf |-> subExprOf]
 * 
 * else result := [kind |-> OpApplKind, operator |-> [kind |->
 * UserDefinedOpKind, name |-> "LAMBDA", body |-> curNode, params |-> params,
 * arity |-> Len(params), defined |-> TRUE, source |-> null], operands |->
 * allArgs, unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>,
 * ranges |-> << >>, subExprOf |-> subExprOf] end if end if
 * 
 * end if;
 * 
 * Finished: print "Result: " ; print result ;
 * 
 * end algorithm ) \* BEGIN TRANSLATION CONSTANT defaultInitValue VARIABLES ops,
 * args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf,
 * result, idx, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs, pc
 * 
 * vars == << ops, args, expectedArity, substInPrefix, params, allArgs, curNode,
 * subExprOf, result, idx, mode, prevMode, curContext, curName, opDefArityFound,
 * opDefArgs, firstFindingOpName, opNode, newName, newNode, nodeArity, temp,
 * tempArgs, pc >>
 * 
 * Init == (* Global variables *) /\ ops = MCops /\ args = MCargs /\
 * expectedArity = MCexpectedArity /\ substInPrefix = << >> /\ params = << >> /\
 * allArgs = << >> /\ curNode = null /\ subExprOf = "null" /\ result = null /\
 * idx = 1 /\ mode = "FindingOpName" /\ prevMode = "" /\ curContext =
 * GlobalContext /\ curName = "" /\ opDefArityFound = 0 /\ opDefArgs = << >> /\
 * firstFindingOpName = TRUE /\ opNode = defaultInitValue /\ newName =
 * defaultInitValue /\ newNode = defaultInitValue /\ nodeArity =
 * defaultInitValue /\ temp = defaultInitValue /\ tempArgs = defaultInitValue /\
 * pc = "Lbl_1"
 * 
 * Lbl_1 == /\ pc = "Lbl_1" /\ Assert(/\ expectedArity \in Int /\ ops \in
 * Seq(STRING) /\ args \in Seq(Seq(NodeId)) /\ Len(ops) = Len(args) /\ \A i \in
 * 1..Len(ops) : /\ \/ ops[i] \in {"<<", ">>", "@", ":"} \cup NumberOp \/
 * expectedArity # 0 => args[i] = << >> /\ (ops[i] = "null") => (Len(args[i]) >
 * 0), "Failure of assertion at line line 1906, column 3.") /\ pc' = "Lbl_2" /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_2 == /\ pc = "Lbl_2" /\ IF idx <= Len(ops) THEN /\ IF mode =
 * "FindingOpName" THEN /\ newNode' = null /\ tempArgs' = << >> /\ pc' = "Lbl_3"
 * /\ UNCHANGED << params, allArgs, curNode, idx, opNode, temp >> ELSE /\ IF
 * mode = "FollowingLabels" THEN /\ IF prevMode = "FindingOpName" THEN /\
 * Assert(curNode.kind \in {UserDefinedOpKind, ThmOrAssumpDefKind}, "Failure of
 * assertion at line line 2053, column 13.") /\ newNode' = LookUp(ops[idx],
 * curNode.labels) ELSE /\ Assert(curNode.kind = LabelKind, "Failure of
 * assertion at line line 2055, column 13.") /\ newNode' = LookUp(ops[idx],
 * curNode.labels) /\ IF newNode' = null THEN /\ PrintT("Label not found") /\ IF
 * debug THEN /\ idx' = idx /\ pc' = "Lbl_22" ELSE /\ pc' = "Done" /\ UNCHANGED
 * idx ELSE /\ pc' = "Lbl_23" /\ UNCHANGED idx /\ UNCHANGED << params, allArgs,
 * curNode, opNode, temp >> ELSE /\ IF mode = "FindingSubExpr" THEN /\ IF
 * ops[idx] = ":" THEN /\ IF \/ prevMode \notin {"FindingOpName",
 * "FollowingLabels"} \/ ~ \/ /\ idx = Len(ops) /\ prevMode = "FindingOpName" \/
 * /\ idx < Len(ops) /\ IsName(ops[idx+1]) THEN /\ PrintT("`!:' can be used only
 * after a name and either at the " \o "end after an operator name or before an
 * operator name.") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_29" ELSE /\ pc'
 * = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_63" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs, curNode, opNode, temp >> ELSE /\ IF
 * curNode.kind = LetInKind THEN /\ IF ArgNum(ops[idx], 1) = 1 THEN /\ curNode'
 * = Node[curNode.body] /\ pc' = "Lbl_63" /\ UNCHANGED idx ELSE /\ PrintT("A
 * Let/In has only a single operand") /\ IF debug THEN /\ idx' = idx /\ pc' =
 * "Lbl_30" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED curNode /\
 * UNCHANGED << params, allArgs, opNode, temp >> ELSE /\ IF curNode.kind =
 * OpApplKind THEN /\ opNode' = Node[curNode.operator] /\ IF opNode'.kind \in
 * {FormalParamKind, ConstantDeclKind, UserDefinedOpKind} THEN /\ temp' =
 * ArgNum(ops[idx], opNode'.arity) /\ IF temp' = -1 THEN /\ PrintT("Nonexistent
 * operand specified") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_31" ELSE /\
 * pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED curNode ELSE /\ curNode' =
 * Node[curNode.operands[temp']] /\ pc' = "Lbl_63" /\ UNCHANGED idx /\ UNCHANGED
 * << params, allArgs >> ELSE /\ IF opNode'.kind = BuiltInKind THEN /\ IF
 * opNode'.name \in {"$RcdConstructor", "$SetOfRcds"} THEN /\ temp' =
 * ArgNum(ops[idx], Len(curNode.operands)) /\ IF temp' = -1 THEN /\
 * PrintT("Incorrect subexpression number") /\ IF debug THEN /\ idx' = idx /\
 * pc' = "Lbl_32" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_33"
 * /\ UNCHANGED idx /\ UNCHANGED << params, allArgs, curNode >> ELSE /\ IF
 * opNode'.name \in {"$Case"} THEN /\ IF idx = Len(ops) THEN /\ PrintT("CASE
 * subexpression must be of form !i!j") /\ IF debug THEN /\ idx' = idx /\ pc' =
 * "Lbl_36" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_37" /\
 * UNCHANGED idx /\ UNCHANGED << params, allArgs, curNode, temp >> ELSE /\ IF
 * opNode'.name = "$Except" THEN /\ temp' = ArgNum(ops[idx],
 * Len(curNode.operands)) /\ IF temp' = -1 THEN /\ PrintT("Bad argument
 * selector.") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_46" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_47" /\ UNCHANGED idx /\ UNCHANGED
 * << params, allArgs, curNode >> ELSE /\ IF /\
 * Len(curNode.unboundedBoundSymbols) = 0 /\ Len(curNode.boundedBoundSymbols) =
 * 0 THEN /\ temp' = ArgNum(ops[idx], Len(curNode.operands)) /\ IF temp' = -1
 * THEN /\ PrintT("Incorrect subexpression selector") /\ IF debug THEN /\ idx' =
 * idx /\ pc' = "Lbl_50" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_51" /\ UNCHANGED idx /\ UNCHANGED << params, allArgs, curNode >> ELSE /\
 * IF ops[idx] \in {"null", "@"} THEN /\ temp' = (IF
 * Len(curNode.unboundedBoundSymbols) > 0 THEN curNode.unboundedBoundSymbols
 * ELSE SeqSeqToSeq( curNode.boundedBoundSymbols)) /\ params' = params \o [i \in
 * 1.. Len(temp') |-> [name |-> temp'[i], arity |-> 0]] /\ allArgs' = allArgs \o
 * args[idx] /\ IF /\ ops[idx] = "null" /\ Len(args[idx]) # Len(temp') THEN /\
 * PrintT("Wrong number of selector arguments") /\ IF debug THEN /\ idx' = idx
 * /\ pc' = "Lbl_52" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_53" /\ UNCHANGED idx /\ UNCHANGED curNode ELSE /\ temp' =
 * ArgNum(ops[idx], Len(curNode.ranges)) /\ IF temp' = -1 THEN /\
 * PrintT("Selecting non-existent range") /\ IF debug THEN /\ idx' = idx /\ pc'
 * = "Lbl_54" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED curNode ELSE /\
 * curNode' = Node[curNode.ranges[temp']] /\ pc' = "Lbl_63" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs >> ELSE /\ PrintT("Applying subexpression
 * chooser to an expr" \o " with no choosable subexpressions") /\ IF debug THEN
 * /\ idx' = idx /\ pc' = "Lbl_55" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs, curNode, temp >> ELSE /\ IF curNode.kind =
 * AssumeProveKind THEN /\ temp' = ArgNum(ops[idx], 1 + Len(curNode.assumes)) /\
 * IF temp' = -1 THEN /\ PrintT("Illegal argument number") /\ IF debug THEN /\
 * idx' = idx /\ pc' = "Lbl_56" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\
 * UNCHANGED curNode ELSE /\ IF temp' <= Len(curNode.assumes) THEN /\ curNode' =
 * Node[curNode.assumes[temp']] ELSE /\ curNode' = Node[curNode.prove] /\ pc' =
 * "Lbl_63" /\ UNCHANGED idx /\ UNCHANGED << params, allArgs, opNode >> ELSE /\
 * IF curNode.kind = OpArgKind THEN /\ opNode' = Node[curNode.op] /\ IF \/
 * opNode'.kind # UserDefinedOpKind \/ opNode'.name # "LAMBDA" THEN /\
 * PrintT("Selecting from operator argument that has no sub-part") /\ IF debug
 * THEN /\ idx' = idx /\ pc' = "Lbl_57" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs, curNode >> ELSE /\ IF ops[idx] \notin {"null",
 * "@"} THEN /\ PrintT("Incorrect selection from LAMBDA") /\ IF debug THEN /\
 * idx' = idx /\ pc' = "Lbl_58" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs, curNode >> ELSE /\ IF /\ ops[idx] = "null" /\
 * Len(args[idx]) # Len(opNode'.params) THEN /\ PrintT("Incorrect number of
 * arguments for LAMBDA") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_59" ELSE
 * /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED << params, allArgs, curNode >>
 * ELSE /\ params' = params \o opNode'.params /\ allArgs' = allArgs \o args[idx]
 * /\ curNode' = Node[opNode'.body] /\ pc' = "Lbl_63" /\ UNCHANGED idx ELSE /\
 * IF curNode.kind \in {UserDefinedOpKind, BuiltInKind} THEN /\ PrintT("Abort:
 * should not have been able to choose this node.") /\ IF debug THEN /\ idx' =
 * idx /\ pc' = "Lbl_60" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED
 * curNode ELSE /\ IF curNode.kind \in {AtNodeKind, DecimalKind, NumeralKind,
 * StringKind, FormalParamKind, ConstantDeclKind, VariableDeclKind,
 * BoundSymbolKind} THEN /\ PrintT("Selected part has no subexpression") /\ IF
 * debug THEN /\ idx' = idx /\ pc' = "Lbl_61" ELSE /\ pc' = "Done" /\ UNCHANGED
 * idx /\ UNCHANGED curNode ELSE /\ IF curNode.kind = LabelKind THEN /\ curNode'
 * = Node[curNode.body] /\ idx' = idx - 1 /\ pc' = "Lbl_63" ELSE /\
 * PrintT("Unexpected node kind found in expression") /\ IF debug THEN /\ idx' =
 * idx /\ pc' = "Lbl_62" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED
 * curNode /\ UNCHANGED << params, allArgs, opNode >> /\ UNCHANGED temp ELSE /\
 * PrintT("Bad value of mode") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_68"
 * ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED << params, allArgs,
 * curNode, opNode, temp >> /\ UNCHANGED newNode /\ UNCHANGED tempArgs ELSE /\
 * IF curNode.kind = AssumeProveKind THEN /\ PrintT("Selecting ASSUME/PROVE
 * instead of expression") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_70" ELSE
 * /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_71" /\ UNCHANGED idx /\
 * UNCHANGED << params, allArgs, curNode, opNode, newNode, temp, tempArgs >> /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, subExprOf, result,
 * mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, newName, nodeArity >>
 * 
 * Lbl_69 == /\ pc = "Lbl_69" /\ idx' = idx + 1 /\ pc' = "Lbl_2" /\ UNCHANGED <<
 * ops, args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_3 == /\ pc = "Lbl_3" /\ IF newNode = null THEN /\ IF idx \geq Len(ops)
 * THEN /\ PrintT("Unknown operator") /\ IF debug THEN /\ idx' = idx /\ pc' =
 * "Lbl_4" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_5" /\
 * UNCHANGED idx /\ UNCHANGED << curNode, curName >> ELSE /\ curNode' = newNode
 * /\ curName' = newName /\ IF curNode'.kind \in {UserDefinedOpKind,
 * ThmOrAssumpDefKind, ModuleInstanceKind, ConstantDeclKind, VariableDeclKind,
 * FormalParamKind, BuiltInKind, BoundSymbolKind} THEN /\ IF curNode'.kind \in
 * {ConstantDeclKind, VariableDeclKind, FormalParamKind, BuiltInKind,
 * BoundSymbolKind} THEN /\ IF idx # 1 THEN /\ PrintT("Abort: Impossible naming
 * of declaration " \o "or built-in operator.") /\ IF debug THEN /\ idx' = idx
 * /\ pc' = "Lbl_8" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ IF Len(ops) #
 * 1 THEN /\ PrintT("Can't take subexpression of this") /\ IF debug THEN /\ idx'
 * = idx /\ pc' = "Lbl_9" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_10" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_10" /\ UNCHANGED idx ELSE /\
 * PrintT("Unexpected node kind") /\ IF debug THEN /\ idx' = idx /\ pc' =
 * "Lbl_20" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED << ops, args,
 * expectedArity, substInPrefix, params, allArgs, subExprOf, result, mode,
 * prevMode, curContext, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_5 == /\ pc = "Lbl_5" /\ newName' = IF IsName(ops[idx]) THEN IF curName =
 * "" THEN ops[idx] ELSE curName \o "!" \o ops[idx] ELSE null /\ IF /\ curName =
 * "" /\ ~ IsName(ops[idx]) THEN /\ PrintT("Need an operator or label name or
 * step number here") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_6" ELSE /\
 * pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_7" /\ UNCHANGED idx /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newNode, nodeArity,
 * temp, tempArgs >>
 * 
 * Lbl_6 == /\ pc = "Lbl_6" /\ idx' = idx /\ Assert(FALSE, "Failure of assertion
 * at line line 1892, column 38 of macro called at line 1956, column 13.") /\
 * pc' = "Lbl_7" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, result, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_7 == /\ pc = "Lbl_7" /\ newNode' = (IF newName # null THEN
 * LookUp(newName, curContext) ELSE null) /\ IF newName = null THEN /\ tempArgs'
 * = tempArgs \o args[idx] /\ idx' = idx + 1 ELSE /\ TRUE /\ UNCHANGED << idx,
 * tempArgs >> /\ pc' = "Lbl_3" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, nodeArity, temp >>
 * 
 * Lbl_4 == /\ pc = "Lbl_4" /\ idx' = idx /\ Assert(FALSE, "Failure of assertion
 * at line line 1892, column 38 of macro called at line 1942, column 13.") /\
 * pc' = "Lbl_5" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, result, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_10 == /\ pc = "Lbl_10" /\ nodeArity' = Arity(curNode) /\ tempArgs' =
 * tempArgs \o args[idx] /\ IF expectedArity = 0 THEN /\ IF opDefArityFound +
 * Len(tempArgs') # nodeArity' THEN /\ PrintT("Wrong number of arguments") /\ IF
 * debug THEN /\ idx' = idx /\ pc' = "Lbl_11" ELSE /\ pc' = "Done" /\ UNCHANGED
 * idx ELSE /\ pc' = "Lbl_12" /\ UNCHANGED idx ELSE /\ IF expectedArity > 0 THEN
 * /\ IF \E i \in 1..Len(curNode.params) : curNode.params[i].arity > 0 THEN /\
 * PrintT("Higher-order operator selected " \o "as operator argument") /\ IF
 * debug THEN /\ idx' = idx /\ pc' = "Lbl_14" ELSE /\ pc' = "Done" /\ UNCHANGED
 * idx ELSE /\ pc' = "Lbl_15" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_15" /\
 * UNCHANGED idx /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, result, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, temp >>
 * 
 * Lbl_12 == /\ pc = "Lbl_12" /\ IF \E i \in 1..Len(tempArgs[idx]) :
 * Arity(Node[tempArgs[idx][i]]) # ParamArity(curNode, i + opDefArityFound) THEN
 * /\ PrintT("Argument has wrong arity") /\ IF debug THEN /\ idx' = idx /\ pc' =
 * "Lbl_13" ELSE /\ pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED opDefArgs ELSE /\
 * opDefArgs' = opDefArgs \o tempArgs /\ pc' = "Lbl_15" /\ UNCHANGED idx /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, mode, prevMode, curContext, curName,
 * opDefArityFound, firstFindingOpName, opNode, newName, newNode, nodeArity,
 * temp, tempArgs >>
 * 
 * Lbl_13 == /\ pc = "Lbl_13" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 1990, column
 * 26.") /\ pc' = "Lbl_15" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_11 == /\ pc = "Lbl_11" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 1985, column
 * 25.") /\ pc' = "Lbl_12" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_14 == /\ pc = "Lbl_14" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 1996, column
 * 32.") /\ pc' = "Lbl_15" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_15 == /\ pc = "Lbl_15" /\ opDefArityFound' = nodeArity /\ IF curNode.kind
 * \in {UserDefinedOpKind, ThmOrAssumpDefKind, ConstantDeclKind,
 * VariableDeclKind, FormalParamKind, BoundSymbolKind} THEN /\ IF /\
 * curNode.kind = UserDefinedOpKind /\ ~ curNode.defined /\ ~ Len(ops) = 1 THEN
 * /\ PrintT("Can't refer to subexpression of " \o "operator inside its
 * definition") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_16" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_17" /\ UNCHANGED idx ELSE /\ IF
 * (idx = Len(ops)) THEN /\ PrintT("Operator name incomplete") /\ IF debug THEN
 * /\ idx' = idx /\ pc' = "Lbl_19" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\
 * pc' = "Lbl_21" /\ UNCHANGED idx /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_17 == /\ pc = "Lbl_17" /\ IF /\ firstFindingOpName /\ curNode.kind \in
 * {UserDefinedOpKind, ThmOrAssumpDefKind} THEN /\ subExprOf' = curNode ELSE /\
 * TRUE /\ UNCHANGED subExprOf /\ IF idx # Len(ops) THEN /\ params' = params \o
 * curNode.params /\ curName' = "" /\ IF IsName(ops[idx+1]) THEN /\ mode' =
 * "FollowingLabels" ELSE /\ mode' = "FindingSubExpr" /\ allArgs' = allArgs \o
 * opDefArgs /\ opDefArityFound' = 0 /\ opDefArgs' = << >> /\ newNode' =
 * Node[curNode.body] /\ pc' = "Lbl_18" ELSE /\ pc' = "Lbl_21" /\ UNCHANGED <<
 * params, allArgs, mode, curName, opDefArityFound, opDefArgs, newNode >> /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, curNode, result, idx,
 * prevMode, curContext, firstFindingOpName, opNode, newName, nodeArity, temp,
 * tempArgs >>
 * 
 * Lbl_18 == /\ pc = "Lbl_18" /\ IF newNode.kind = SubstInKind THEN /\
 * substInPrefix' = substInPrefix \o <<newNode>> /\ newNode' =
 * Node[newNode.body] /\ pc' = "Lbl_18" /\ UNCHANGED curNode ELSE /\ IF mode =
 * "FindingSubExpr" THEN /\ curNode' = newNode ELSE /\ TRUE /\ UNCHANGED curNode
 * /\ pc' = "Lbl_21" /\ UNCHANGED << substInPrefix, newNode >> /\ UNCHANGED <<
 * ops, args, expectedArity, params, allArgs, subExprOf, result, idx, mode,
 * prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, nodeArity, temp, tempArgs >>
 * 
 * Lbl_16 == /\ pc = "Lbl_16" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2010, column
 * 25.") /\ pc' = "Lbl_17" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_19 == /\ pc = "Lbl_19" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2043, column
 * 25.") /\ pc' = "Lbl_21" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_8 == /\ pc = "Lbl_8" /\ idx' = idx /\ Assert(FALSE, "Failure of assertion
 * at line line 1892, column 38 of macro called at line 1974, column 26.") /\
 * pc' = "Lbl_10" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, result, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_9 == /\ pc = "Lbl_9" /\ idx' = idx /\ Assert(FALSE, "Failure of assertion
 * at line line 1892, column 38 of macro called at line 1977, column 33.") /\
 * pc' = "Lbl_10" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, result, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_20 == /\ pc = "Lbl_20" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2046, column
 * 9.") /\ pc' = "Lbl_21" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_21 == /\ pc = "Lbl_21" /\ prevMode' = "FindingOpName" /\ pc' = "Lbl_69"
 * /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, idx, mode, curContext, curName, opDefArityFound,
 * opDefArgs, firstFindingOpName, opNode, newName, newNode, nodeArity, temp,
 * tempArgs >>
 * 
 * Lbl_23 == /\ pc = "Lbl_23" /\ curNode' = newNode /\ IF expectedArity = 0 THEN
 * /\ IF Len(args[idx]) # curNode'.arity THEN /\ PrintT("bad arity") /\ IF debug
 * THEN /\ idx' = idx /\ pc' = "Lbl_24" ELSE /\ pc' = "Done" /\ UNCHANGED idx
 * ELSE /\ pc' = "Lbl_25" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_28" /\ UNCHANGED
 * idx /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * subExprOf, result, mode, prevMode, curContext, curName, opDefArityFound,
 * opDefArgs, firstFindingOpName, opNode, newName, newNode, nodeArity, temp,
 * tempArgs >>
 * 
 * Lbl_25 == /\ pc = "Lbl_25" /\ IF \E i \in 1..Len(args[idx]) :
 * Arity(Node[args[idx][i]]) # 0 THEN /\ PrintT("Operator argument given to
 * label") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_26" ELSE /\ pc' = "Done"
 * /\ UNCHANGED idx ELSE /\ pc' = "Lbl_27" /\ UNCHANGED idx /\ UNCHANGED << ops,
 * args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_26 == /\ pc = "Lbl_26" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2068, column
 * 20.") /\ pc' = "Lbl_27" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_27 == /\ pc = "Lbl_27" /\ allArgs' = allArgs \o args[idx] /\ pc' =
 * "Lbl_28" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * curNode, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_24 == /\ pc = "Lbl_24" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2064, column
 * 20.") /\ pc' = "Lbl_25" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_28 == /\ pc = "Lbl_28" /\ params' = params \o curNode.params /\ IF /\ idx
 * < Len(ops) /\ ~IsName(ops[idx+1]) THEN /\ mode' = "FindingSubExpr" ELSE /\
 * TRUE /\ UNCHANGED mode /\ IF \/ mode' = "FindingSubExpr" \/ idx = Len(ops)
 * THEN /\ curNode' = Node[curNode.body] ELSE /\ TRUE /\ UNCHANGED curNode /\
 * prevMode' = "FollowingLabels" /\ pc' = "Lbl_69" /\ UNCHANGED << ops, args,
 * expectedArity, substInPrefix, allArgs, subExprOf, result, idx, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_22 == /\ pc = "Lbl_22" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2059, column
 * 13.") /\ pc' = "Lbl_23" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_63 == /\ pc = "Lbl_63" /\ IF idx # Len(ops) THEN /\ IF IsName(ops[idx+1])
 * THEN /\ pc' = "Lbl_64" /\ UNCHANGED idx ELSE /\ IF ops[idx+1] = ":" THEN /\
 * PrintT("!: should not follow an operand selector") /\ IF debug THEN /\ idx' =
 * idx /\ pc' = "Lbl_66" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_67" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_67" /\ UNCHANGED idx /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_64 == /\ pc = "Lbl_64" /\ IF curNode.kind = LabelKind THEN /\ curNode' =
 * Node[curNode.body] /\ pc' = "Lbl_64" /\ UNCHANGED << idx, mode, curContext,
 * firstFindingOpName >> ELSE /\ IF curNode.kind = LetInKind THEN /\ curContext'
 * = curNode.context /\ mode' = "FindingOpName" /\ firstFindingOpName' = FALSE
 * /\ pc' = "Lbl_67" /\ UNCHANGED idx ELSE /\ PrintT("A name not following the
 * selector of a LET") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_65" ELSE /\
 * pc' = "Done" /\ UNCHANGED idx /\ UNCHANGED << mode, curContext,
 * firstFindingOpName >> /\ UNCHANGED curNode /\ UNCHANGED << ops, args,
 * expectedArity, substInPrefix, params, allArgs, subExprOf, result, prevMode,
 * curName, opDefArityFound, opDefArgs, opNode, newName, newNode, nodeArity,
 * temp, tempArgs >>
 * 
 * Lbl_65 == /\ pc = "Lbl_65" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2294, column
 * 26.") /\ pc' = "Lbl_67" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_66 == /\ pc = "Lbl_66" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2297, column
 * 26.") /\ pc' = "Lbl_67" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_67 == /\ pc = "Lbl_67" /\ prevMode' = "FindingSubExpr" /\ pc' = "Lbl_69"
 * /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, idx, mode, curContext, curName, opDefArityFound,
 * opDefArgs, firstFindingOpName, opNode, newName, newNode, nodeArity, temp,
 * tempArgs >>
 * 
 * Lbl_29 == /\ pc = "Lbl_29" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2091, column
 * 14.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_30 == /\ pc = "Lbl_30" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2098, column
 * 14.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_31 == /\ pc = "Lbl_31" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2110, column
 * 17.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_33 == /\ pc = "Lbl_33" /\ curNode' = Node[curNode.operands[temp]] /\ IF
 * \/ curNode'.kind # OpApplKind \/ Node[curNode'.operator].kind # BuiltInKind
 * \/ Node[curNode'.operator].name # "$Pair" THEN /\ PrintT("Expecting
 * $Pair(...)") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_34" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_35" /\ UNCHANGED idx /\ UNCHANGED
 * << ops, args, expectedArity, substInPrefix, params, allArgs, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_35 == /\ pc = "Lbl_35" /\ curNode' = Node[curNode.operands[2]] /\ pc' =
 * "Lbl_63" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * allArgs, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_34 == /\ pc = "Lbl_34" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2131, column
 * 18.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_32 == /\ pc = "Lbl_32" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2125, column
 * 18.") /\ pc' = "Lbl_33" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_37 == /\ pc = "Lbl_37" /\ temp' = ArgNum( ops[idx],
 * Len(curNode.operands)) /\ IF temp' = -1 THEN /\ PrintT("Incorrect
 * subexpression name") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_38" ELSE /\
 * pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_39" /\ UNCHANGED idx /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, result, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, tempArgs >>
 * 
 * Lbl_38 == /\ pc = "Lbl_38" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2145, column
 * 18.") /\ pc' = "Lbl_39" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_39 == /\ pc = "Lbl_39" /\ curNode' = Node[curNode.operands[temp]] /\ IF
 * \/ curNode'.kind # OpApplKind \/ Node[curNode'.operator].kind # BuiltInKind
 * \/ Node[curNode'.operator].name # "$Pair" THEN /\ PrintT("Expecting
 * $Pair(...)") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_40" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_41" /\ UNCHANGED idx /\ UNCHANGED
 * << ops, args, expectedArity, substInPrefix, params, allArgs, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_40 == /\ pc = "Lbl_40" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2151, column
 * 18.") /\ pc' = "Lbl_41" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_41 == /\ pc = "Lbl_41" /\ idx' = idx+1 /\ temp' = ArgNum(ops[idx'], 2) /\
 * IF temp' = -1 THEN /\ PrintT("Incorrect subexpression name") /\ IF debug THEN
 * /\ pc' = "Lbl_42" ELSE /\ pc' = "Done" ELSE /\ pc' = "Lbl_44" /\ UNCHANGED <<
 * ops, args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, tempArgs >>
 * 
 * Lbl_42 == /\ pc = "Lbl_42" /\ idx' = idx /\ pc' = "Lbl_43" /\ UNCHANGED <<
 * ops, args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_43 == /\ pc = "Lbl_43" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2156, column
 * 18.") /\ pc' = "Lbl_44" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_44 == /\ pc = "Lbl_44" /\ curNode' = Node[curNode.operands[temp]] /\ IF
 * curNode' = null THEN /\ PrintT("Selecting OTHER") /\ IF debug THEN /\ idx' =
 * idx /\ pc' = "Lbl_45" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_63" /\ UNCHANGED idx /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_45 == /\ pc = "Lbl_45" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2160, column
 * 18.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_36 == /\ pc = "Lbl_36" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2141, column
 * 18.") /\ pc' = "Lbl_37" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_47 == /\ pc = "Lbl_47" /\ curNode' = Node[curNode.operands[temp]] /\ IF
 * temp > 1 THEN /\ IF \/ curNode'.kind # OpApplKind \/
 * Node[curNode'.operator].kind # BuiltInKind \/ Node[curNode'.operator].name #
 * "$Pair" THEN /\ PrintT("Unexpected expression node found.") /\ IF debug THEN
 * /\ idx' = idx /\ pc' = "Lbl_48" ELSE /\ pc' = "Done" /\ UNCHANGED idx ELSE /\
 * pc' = "Lbl_49" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_63" /\ UNCHANGED idx /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * subExprOf, result, mode, prevMode, curContext, curName, opDefArityFound,
 * opDefArgs, firstFindingOpName, opNode, newName, newNode, nodeArity, temp,
 * tempArgs >>
 * 
 * Lbl_49 == /\ pc = "Lbl_49" /\ curNode' = Node[curNode.operands[2]] /\ pc' =
 * "Lbl_63" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * allArgs, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_48 == /\ pc = "Lbl_48" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2179, column
 * 26.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_46 == /\ pc = "Lbl_46" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2172, column
 * 19.") /\ pc' = "Lbl_47" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_51 == /\ pc = "Lbl_51" /\ curNode' = Node[curNode.operands[temp]] /\ pc'
 * = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * allArgs, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_50 == /\ pc = "Lbl_50" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2195, column
 * 25.") /\ pc' = "Lbl_51" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_53 == /\ pc = "Lbl_53" /\ curNode' = Node[curNode.operands[1]] /\ pc' =
 * "Lbl_63" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * allArgs, subExprOf, result, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_52 == /\ pc = "Lbl_52" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2220, column
 * 32.") /\ pc' = "Lbl_53" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_54 == /\ pc = "Lbl_54" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2225, column
 * 32.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_55 == /\ pc = "Lbl_55" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2232, column
 * 12.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_56 == /\ pc = "Lbl_56" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2240, column
 * 18.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_57 == /\ pc = "Lbl_57" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2255, column
 * 9.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_58 == /\ pc = "Lbl_58" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2257, column
 * 9.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_59 == /\ pc = "Lbl_59" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2260, column
 * 9.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_60 == /\ pc = "Lbl_60" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2267, column
 * 7.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_61 == /\ pc = "Lbl_61" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2272, column
 * 10.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_62 == /\ pc = "Lbl_62" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2281, column
 * 8.") /\ pc' = "Lbl_63" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_68 == /\ pc = "Lbl_68" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2303, column
 * 8.") /\ pc' = "Lbl_69" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_70 == /\ pc = "Lbl_70" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2311, column
 * 10.") /\ pc' = "Lbl_71" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_71 == /\ pc = "Lbl_71" /\ IF expectedArity < 0 THEN /\ IF \/ prevMode #
 * "FindingOpName" \/ curNode.kind \notin {UserDefinedOpKind,
 * ThmOrAssumpDefKind} THEN /\ PrintT("Should have selected a definition, but
 * didn't.") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_72" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_73" /\ UNCHANGED idx ELSE /\ pc' =
 * "Lbl_74" /\ UNCHANGED idx /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_73 == /\ pc = "Lbl_73" /\ result' = curNode /\ pc' = "Finished" /\
 * UNCHANGED << ops, args, expectedArity, substInPrefix, params, allArgs,
 * curNode, subExprOf, idx, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, temp, tempArgs >>
 * 
 * Lbl_72 == /\ pc = "Lbl_72" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2317, column
 * 17.") /\ pc' = "Lbl_73" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_74 == /\ pc = "Lbl_74" /\ IF expectedArity > 0 THEN /\ temp' =
 * (Len(params) + IF \/ prevMode = "FindingOpName" \/ curNode.kind = OpArgKind
 * THEN Arity(curNode) ELSE 0) /\ IF expectedArity # temp' THEN /\
 * PrintT("Expect arity = " \o ToString(expectedArity) \o ", but found arity = "
 * \o ToString(temp')) /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_75" ELSE /\
 * pc' = "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_76" /\ UNCHANGED idx ELSE /\
 * pc' = "Lbl_76" /\ UNCHANGED << idx, temp >> /\ UNCHANGED << ops, args,
 * expectedArity, substInPrefix, params, allArgs, curNode, subExprOf, result,
 * mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, tempArgs >>
 * 
 * Lbl_75 == /\ pc = "Lbl_75" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2329, column
 * 18.") /\ pc' = "Lbl_76" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_76 == /\ pc = "Lbl_76" /\ IF /\ prevMode = "FindingOpName" /\ Len(params)
 * + Len(substInPrefix) > 0 THEN /\ temp' = [i \in 1..Len(curNode.params) |->
 * [curNode.params[i] EXCEPT !.name = "New " \o @]] /\ curNode' = [kind |->
 * OpApplKind, operands |-> temp', operator |-> curNode, unboundedBoundSymbols
 * |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> << >>] /\ params' =
 * params \o temp' /\ allArgs' = allArgs \o opDefArgs ELSE /\ TRUE /\ UNCHANGED
 * << params, allArgs, curNode, temp >> /\ IF curNode'.kind = OpArgKind THEN /\
 * IF expectedArity = 0 THEN /\ PrintT("Selected Operator Argument when
 * expression expected.") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_77" ELSE
 * /\ pc' = "Done" /\ UNCHANGED idx ELSE /\ IF expectedArity # Len(params') +
 * curNode'.arity THEN /\ PrintT("Selected operator has wrong arity.") /\ IF
 * debug THEN /\ idx' = idx /\ pc' = "Lbl_78" ELSE /\ pc' = "Done" /\ UNCHANGED
 * idx ELSE /\ IF Len(params') + Len(substInPrefix) > 0 THEN /\ pc' = "Lbl_79"
 * ELSE /\ pc' = "Lbl_80" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_80" /\ UNCHANGED
 * idx /\ UNCHANGED << ops, args, expectedArity, substInPrefix, subExprOf,
 * result, mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, tempArgs >>
 * 
 * Lbl_77 == /\ pc = "Lbl_77" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2363, column
 * 12.") /\ pc' = "Lbl_80" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_78 == /\ pc = "Lbl_78" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2365, column
 * 12.") /\ pc' = "Lbl_80" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_79 == /\ pc = "Lbl_79" /\ temp' = [i \in 1..curNode.arity |-> [name |->
 * "NewParam" \o NumToString(i), arity |-> 0]] /\ curNode' = [kind |->
 * OpApplKind, operands |-> temp', operator |-> Node[curNode.op],
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>] /\ params' = params \o temp' /\ pc' = "Lbl_80" /\ UNCHANGED << ops, args,
 * expectedArity, substInPrefix, allArgs, subExprOf, result, idx, mode,
 * prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, tempArgs >>
 * 
 * Lbl_80 == /\ pc = "Lbl_80" /\ IF curNode.kind \in {UserDefinedOpKind,
 * ConstantDeclKind, VariableDeclKind, FormalParamKind, BuiltInKind,
 * BoundSymbolKind, ThmOrAssumpDefKind} THEN /\ IF expectedArity > 0 THEN /\
 * result' = [kind |-> OpArgKind, name |-> curNode.name, op |-> curNode, arity
 * |-> expectedArity] ELSE /\ IF expectedArity = 0 THEN /\ result' = [kind |->
 * OpApplKind, operands |-> opDefArgs, operator |-> curNode,
 * unboundedBoundSymbols |-> <<>>, boundedBoundSymbols |-> << >>, ranges |-> <<
 * >>, subExprOf |-> subExprOf] ELSE /\ TRUE /\ UNCHANGED result /\ pc' =
 * "Finished" /\ UNCHANGED temp ELSE /\ IF curNode.kind = OpArgKind THEN /\
 * result' = curNode /\ pc' = "Finished" /\ UNCHANGED temp ELSE /\ temp' =
 * Len(substInPrefix) /\ pc' = "Lbl_81" /\ UNCHANGED result /\ UNCHANGED << ops,
 * args, expectedArity, substInPrefix, params, allArgs, curNode, subExprOf, idx,
 * mode, prevMode, curContext, curName, opDefArityFound, opDefArgs,
 * firstFindingOpName, opNode, newName, newNode, nodeArity, tempArgs >>
 * 
 * Lbl_81 == /\ pc = "Lbl_81" /\ IF temp > 0 THEN /\ curNode' = [kind |->
 * SubstInKind, body |-> curNode , subst |-> substInPrefix[temp].subst ] /\
 * temp' = temp - 1 /\ pc' = "Lbl_81" /\ UNCHANGED idx ELSE /\ IF expectedArity
 * > 0 THEN /\ IF Len(params) # expectedArity THEN /\ PrintT("Selection has
 * wrong arity") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_82" ELSE /\ pc' =
 * "Done" /\ UNCHANGED idx ELSE /\ pc' = "Lbl_83" /\ UNCHANGED idx ELSE /\ IF
 * Len(params) # Len(allArgs) THEN /\ PrintT("Abort: number of params # num of
 * args") /\ IF debug THEN /\ idx' = idx /\ pc' = "Lbl_84" ELSE /\ pc' = "Done"
 * /\ UNCHANGED idx ELSE /\ pc' = "Lbl_85" /\ UNCHANGED idx /\ UNCHANGED <<
 * curNode, temp >> /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, subExprOf, result, mode, prevMode, curContext, curName,
 * opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName, newNode,
 * nodeArity, tempArgs >>
 * 
 * Lbl_83 == /\ pc = "Lbl_83" /\ result' = [kind |-> OpArgKind, op |-> [kind |->
 * UserDefinedOpKind, name |-> "LAMBDA", body |-> curNode, params |-> params,
 * arity |-> Len(params), defined |-> TRUE, source |-> null], name |-> "LAMBDA"]
 * /\ pc' = "Finished" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, idx, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_85 == /\ pc = "Lbl_85" /\ IF Len(params) = 0 THEN /\ result' = [kind |->
 * LabelKind, name |-> "$Subexpression", arity |-> 0, params |-> << >>, body |->
 * curNode, subExprOf |-> subExprOf] ELSE /\ result' = [kind |-> OpApplKind,
 * operator |-> [kind |-> UserDefinedOpKind, name |-> "LAMBDA", body |->
 * curNode, params |-> params, arity |-> Len(params), defined |-> TRUE, source
 * |-> null], operands |-> allArgs, unboundedBoundSymbols |-> <<>>,
 * boundedBoundSymbols |-> << >>, ranges |-> << >>, subExprOf |-> subExprOf] /\
 * pc' = "Finished" /\ UNCHANGED << ops, args, expectedArity, substInPrefix,
 * params, allArgs, curNode, subExprOf, idx, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_82 == /\ pc = "Lbl_82" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2431, column
 * 22.") /\ pc' = "Lbl_83" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Lbl_84 == /\ pc = "Lbl_84" /\ idx' = idx /\ Assert(FALSE, "Failure of
 * assertion at line line 1892, column 38 of macro called at line 2443, column
 * 22.") /\ pc' = "Lbl_85" /\ UNCHANGED << ops, args, expectedArity,
 * substInPrefix, params, allArgs, curNode, subExprOf, result, mode, prevMode,
 * curContext, curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode,
 * newName, newNode, nodeArity, temp, tempArgs >>
 * 
 * Finished == /\ pc = "Finished" /\ PrintT("Result: ") /\ PrintT(result) /\ pc'
 * = "Done" /\ UNCHANGED << ops, args, expectedArity, substInPrefix, params,
 * allArgs, curNode, subExprOf, result, idx, mode, prevMode, curContext,
 * curName, opDefArityFound, opDefArgs, firstFindingOpName, opNode, newName,
 * newNode, nodeArity, temp, tempArgs >>
 * 
 * Next == Lbl_1 \/ Lbl_2 \/ Lbl_69 \/ Lbl_3 \/ Lbl_5 \/ Lbl_6 \/ Lbl_7 \/ Lbl_4
 * \/ Lbl_10 \/ Lbl_12 \/ Lbl_13 \/ Lbl_11 \/ Lbl_14 \/ Lbl_15 \/ Lbl_17 \/
 * Lbl_18 \/ Lbl_16 \/ Lbl_19 \/ Lbl_8 \/ Lbl_9 \/ Lbl_20 \/ Lbl_21 \/ Lbl_23 \/
 * Lbl_25 \/ Lbl_26 \/ Lbl_27 \/ Lbl_24 \/ Lbl_28 \/ Lbl_22 \/ Lbl_63 \/ Lbl_64
 * \/ Lbl_65 \/ Lbl_66 \/ Lbl_67 \/ Lbl_29 \/ Lbl_30 \/ Lbl_31 \/ Lbl_33 \/
 * Lbl_35 \/ Lbl_34 \/ Lbl_32 \/ Lbl_37 \/ Lbl_38 \/ Lbl_39 \/ Lbl_40 \/ Lbl_41
 * \/ Lbl_42 \/ Lbl_43 \/ Lbl_44 \/ Lbl_45 \/ Lbl_36 \/ Lbl_47 \/ Lbl_49 \/
 * Lbl_48 \/ Lbl_46 \/ Lbl_51 \/ Lbl_50 \/ Lbl_53 \/ Lbl_52 \/ Lbl_54 \/ Lbl_55
 * \/ Lbl_56 \/ Lbl_57 \/ Lbl_58 \/ Lbl_59 \/ Lbl_60 \/ Lbl_61 \/ Lbl_62 \/
 * Lbl_68 \/ Lbl_70 \/ Lbl_71 \/ Lbl_73 \/ Lbl_72 \/ Lbl_74 \/ Lbl_75 \/ Lbl_76
 * \/ Lbl_77 \/ Lbl_78 \/ Lbl_79 \/ Lbl_80 \/ Lbl_81 \/ Lbl_83 \/ Lbl_85 \/
 * Lbl_82 \/ Lbl_84 \/ Finished \/ (* Disjunct to prevent deadlock on
 * termination *) (pc = "Done" /\ UNCHANGED vars)
 * 
 * Spec == Init /\ [][Next]_vars
 * 
 * Termination == <>(pc = "Done")
 * 
 * \* END TRANSLATION
 * 
 * NotDone == pc # "Done"
 * (*************************************************************************)
 * (* To print a trace of an execution that doesn't produce an error, add *) (*
 * "INVARIANT NotDone" to Subexpression.cfg . *)
 * (*************************************************************************)
 * =============================================================================
 ************************* 
 * 
 * end file Subexpression.tla
 ****************************/


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/ExSortUtils.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
/*  Notes: If imporved efficiency is needed, one place to look is at
    int to byte arrays and BigIntegers to byte arrays and back,
    because I use the built in Java routines, and it may be possible
    to optimize them. 
 */
package tlc2.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;

public class ExSortUtils
{

    /** Writes the length of the sub array and then each element of A in
        the appropriate range to out.  The subarray starts at A[start]
        and finishes at A[finish].  */
    public static void writeSizeArrayOfExternalSortable(ExternalSortable[] A, int start, int finish, OutputStream out)
            throws IOException
    {
        ByteUtils.writeInt(out, finish - start + 1);
        writeArrayOfExternalSortable(A, start, finish, out);
    }

    /** Writes each element of A in the appropriate range to out.  The
        subarray starts at A[start] and finishes at A[finish].  */
    public static void writeArrayOfExternalSortable(ExternalSortable[] A, int start, int finish, OutputStream out)
            throws IOException
    {
        for (int i = start; i <= finish; i++)
            A[i].write(out);
    }

    /** Reads an integer (len) and then len ExternalSortables and
        returns an array corresponding to the ExternalSortables.
        If the stream is empty when reading len, an IOException is
        thrown; if at any other time, an IO error occurs, a
        RuntimeException is thrown. */
    public static ExternalSortable[] readSizeArrayOfExternalSortable(InputStream in, ExternalSortable ex)
            throws IOException
    {
        int len;

        try
        {
            len = ByteUtils.readInt(in);
        } catch (IOException e)
        {
            throw new IOException("Can't read an array of ExternalSortables from the input stream; it's empty.");
        }

        ExternalSortable[] A = new ExternalSortable[len];

        try
        {
            for (int i = 0; i < len; i++)
            {
                A[i] = ex.read(in);
            }
        } catch (IOException e)
        {
            throw new IOException(
                    "Can't read an array of ExternalSortables from the input stream; not enough bytes, but not empty.");
        }
        return A;
    }

    /** Reads in as many ExternalSortables as it can and returns an
        array corresponding to the ExternalSortables.  Input: in should
        contain some sequence of ExternalSortables, otherwise a
        RuntimeException is thrown */
    public static ExternalSortable[] readArrayOfExternalSortable(InputStream in, ExternalSortable ex)
            throws IOException
    {

        Vector A = new Vector();
        int i = 0;

        try
        {
            do
            {
                A.addElement(ex.read(in));
                i++;
            } while (true);
        } catch (IOException e)
        {
        }

        ExternalSortable[] eA = new ExternalSortable[i];

        for (int j = 0; j < i; j++)
            eA[j] = (ExternalSortable) A.elementAt(j);

        return eA;
    }

    /** Reads an integer from in, and appends that integer and that many
        objects to out.  Input: If in is empty, an IOException is thrown;
        if it doesn't have enough bytes, a RuntimeException is throw. */
    public static void appendSizeExternalSortableArraySizeArray(InputStream in, OutputStream out, ExternalSortable ex)
            throws IOException
    {
        int i;
        ExternalSortable a;

        try
        {
            i = ByteUtils.readInt(in);
        } catch (IOException e)
        {
            throw new IOException("Can't append in to out; in is empty.");
        }
        ByteUtils.writeInt(out, i);
        try
        {
            for (int j = 0; j < i; j++)
            {
                a = ex.read(in);
                a.write(out);
            }
        } catch (IOException e)
        {
            throw new IOException("Can't append in to out; not enough bytes, but not empty.");
        }
    }

    /** Reads an integer from in, and appends that many objects to out.
        Input: If in is empty, an IOException is thrown; if it doesn't
        have enough bytes, a RuntimeException is throw. */
    public static void appendSizeExternalSortableArrayArray(InputStream in, OutputStream out, ExternalSortable ex)
            throws IOException
    {
        int i;
        ExternalSortable a;

        try
        {
            i = ByteUtils.readInt(in);
        } catch (IOException e)
        {
            throw new IOException("Can't append in to out; in is empty.");
        }
        try
        {
            for (int j = 0; j < i; j++)
            {
                a = ex.read(in);
                a.write(out);
            }
        } catch (IOException e)
        {
            throw new IOException("Can't append in to out; not enough bytes, but not empty.");
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test-benchmark/tlc2/value/impl/SubsetValueBenchmark.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.value.impl;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import tlc2.util.FP64;
import tlc2.value.RandomEnumerableValues;
import tlc2.value.impl.Enumerable;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.SubsetValue;

@State(Scope.Benchmark)
public class SubsetValueBenchmark {

	private static final SubsetValue subset35;
	private static final SubsetValue subset60;
	private static final SubsetValue subset100;
	private static final SubsetValue subset200;
	private static final SubsetValue subset300;
	private static final SubsetValue subset400;

	private static final int k = 80000;
	private static final double d = 0.1d;
	private static final int k2 = 160000;
	private static final double d2 = 0.2d;

	static {
		RandomEnumerableValues.setSeed(15041980L);
		RandomEnumerableValues.reset();

		FP64.Init();

		subset35 = new SubsetValue(new IntervalValue(1, 35));
		subset35.normalize();
		subset60 = new SubsetValue(new IntervalValue(1, 60));
		subset60.normalize();
		subset100 = new SubsetValue(new IntervalValue(1, 100));
		subset100.normalize();
		subset200 = new SubsetValue(new IntervalValue(1, 200));
		subset200.normalize();
		subset300 = new SubsetValue(new IntervalValue(1, 300));
		subset300.normalize();
		subset400 = new SubsetValue(new IntervalValue(1, 400));
		subset400.normalize();
	}

	@Benchmark
	public Enumerable probabilisticN035k80d01() {
		// ~49k subsets
		return subset35.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN060k80d01() {
		// ~76500 subsets
		return subset60.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN100k80d01() {
		// ~79900
		return subset100.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN200k80d01() {
		// ~80k
		return subset200.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN300k80d01() {
		// ~80k
		return subset300.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN400k80d01() {
		// ~80k
		return subset400.getRandomSetOfSubsets(k, d);
	}

	@Benchmark
	public Enumerable probabilisticN035k16d01() {
		// ~73500
		return subset35.getRandomSetOfSubsets(k2, d);
	}

	@Benchmark
	public Enumerable probabilisticN060k16d01() {
		// ~150k
		return subset60.getRandomSetOfSubsets(k2, d);
	}

	@Benchmark
	public Enumerable probabilisticN100k16d01() {
		// ~160k
		return subset100.getRandomSetOfSubsets(k2, d);
	}

	@Benchmark
	public Enumerable probabilisticN200k16d01() {
		// 160k
		return subset200.getRandomSetOfSubsets(k2, d);
	}

	@Benchmark
	public Enumerable probabilisticN300k16d01() {
		// 160k
		return subset300.getRandomSetOfSubsets(k2, d);
	}

	@Benchmark
	public Enumerable probabilisticN400k16d01() {
		// 160k
		return subset400.getRandomSetOfSubsets(k2, d);
	}
	
	/* d2 */

	@Benchmark
	public Enumerable probabilisticN035k80d02() {
		// ~77600
		return subset35.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN060k80d02() {
		// 80k
		return subset60.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN100k80d02() {
		// 80k
		return subset100.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN200k80d02() {
		// 80k
		return subset200.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN300k80d02() {
		// 80k
		return subset300.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN400k80d02() {
		// 80k
		return subset400.getRandomSetOfSubsets(k, d2);
	}

	@Benchmark
	public Enumerable probabilisticN035k16d02() {
		// ~15200
		return subset35.getRandomSetOfSubsets(k2, d2);
	}

	@Benchmark
	public Enumerable probabilisticN060k16d02() {
		// 160k
		return subset60.getRandomSetOfSubsets(k2, d2);
	}

	@Benchmark
	public Enumerable probabilisticN100k16d02() {
		// 160k
		return subset100.getRandomSetOfSubsets(k2, d2);
	}

	@Benchmark
	public Enumerable probabilisticN200k16d02() {
		// 160k
		return subset200.getRandomSetOfSubsets(k2, d2);
	}

	@Benchmark
	public Enumerable probabilisticN300k16d02() {
		// 160k
		return subset300.getRandomSetOfSubsets(k2, d2);
	}

	@Benchmark
	public Enumerable probabilisticN400k16d02() {
		// 160k
		return subset400.getRandomSetOfSubsets(k2, d2);
	}
	
	/* Exact getRandomSetOfSubsets */
	
	@Benchmark
	public Enumerable exactN035K08() {
		return subset35.getRandomSetOfSubsets(k, 8);
	}

	@Benchmark
	public Enumerable exactN035K13() {
		return subset35.getRandomSetOfSubsets(k, 13);
	}

	@Benchmark
	public Enumerable exactN060K08() {
		return subset60.getRandomSetOfSubsets(k, 8);
	}

	@Benchmark
	public Enumerable exactN100K08() {
		return subset100.getRandomSetOfSubsets(k, 8);
	}

	@Benchmark
	public Enumerable exactN100K10() {
		return subset100.getRandomSetOfSubsets(k, 10);
	}

	@Benchmark
	public Enumerable exactN200K10() {
		return subset200.getRandomSetOfSubsets(k, 10);
	}

	@Benchmark
	public Enumerable exactN300K09() {
		return subset300.getRandomSetOfSubsets(k, 9);
	}

	@Benchmark
	public Enumerable exactN400K09() {
		return subset400.getRandomSetOfSubsets(k, 9);
	}
	
	/* k2 */
	
	@Benchmark
	public Enumerable exactN035K208() {
		return subset35.getRandomSetOfSubsets(k2, 8);
	}

	@Benchmark
	public Enumerable exactN035K213() {
		return subset35.getRandomSetOfSubsets(k2, 13);
	}

	@Benchmark
	public Enumerable exactN060K208() {
		return subset60.getRandomSetOfSubsets(k2, 8);
	}

	@Benchmark
	public Enumerable exactN100K208() {
		return subset100.getRandomSetOfSubsets(k2, 8);
	}

	@Benchmark
	public Enumerable exactN100K210() {
		return subset100.getRandomSetOfSubsets(k2, 10);
	}

	@Benchmark
	public Enumerable exactN200K210() {
		return subset200.getRandomSetOfSubsets(k2, 10);
	}

	@Benchmark
	public Enumerable exactN300K209() {
		return subset300.getRandomSetOfSubsets(k2, 9);
	}

	@Benchmark
	public Enumerable exactN400K209() {
		return subset400.getRandomSetOfSubsets(k2, 9);
	}
}

/*
 * Mode.Throughput: Calculate number of operations in a time unit. (Higher score
 * better) Mode.AverageTime: Calculate an average running time. (Lower score
 * better) Mode.SampleTime: Calculate how long does it take for a method to run
 * (including percentiles). Mode.SingleShotTime: Just run a method once (useful
 * for cold-testing mode). Or more than once if you have specified a batch size
 * for your iterations (see @Measurement annotation below) - in this case JMH
 * will calculate the batch running time (total time for all invocations in a
 * batch). Any set of these modes You can specify any set of these modes - the
 * test will be run several times (depending on number of requested modes).
 * Mode.All: All these modes one after another.
 */

<|start_filename|>tlatools/org.lamport.tlatools.api/src/tlc2/IDistributedFPSet.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2;

import java.net.URI;

public interface IDistributedFPSet {

	/**
	 * Connects this {@link IDistributedFPSet} to a TLCServer/FPSetManager at the given target {@link URI} 
	 * @param uri The target {@link URI}
	 * @return true iff connected successfully
	 */
	boolean connect(URI uri);

	/**
	 * Disconnects from the remote TLCServer/FPSetManager
	 * @return true iff disconnected successfully
	 */
	boolean disconnect();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.test/src/org/lamport/tla/toolbox/spec/parser/test/ParserDependencyStorageTest.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser.test;

import java.util.Arrays;
import java.util.List;

import org.lamport.tla.toolbox.spec.parser.ParserDependencyStorage;

import junit.framework.TestCase;

/**
 * @author <NAME>
 * @version $Id$
 */
@SuppressWarnings("rawtypes")
public class ParserDependencyStorageTest extends TestCase
{

    ParserDependencyStorage store = null;

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
        store = new ParserDependencyStorage();
    }

    /**
     * module1 -> extend1, extend2
     * extend2 -> extend1
     */
    public void testStore1()
    {
        store.put("module1", Arrays.asList(new String[]{"extend1", "extend2", "extend1"}));
        
        assertTrue(store.getListOfModulesToReparse("extend1").contains("module1") && store.getListOfModulesToReparse("extend1").size() == 1);
        assertTrue(store.getListOfModulesToReparse("extend2").contains("module1") && store.getListOfModulesToReparse("extend2").size() == 1);
    }
    
    /**
     * A -> E, D 
     * D -> E
     * B -> C, D
     * C -> E
     */
	public void testStore2()
    {
        store.put("A", Arrays.asList(new String[]{"E", "D", "E"}));
        store.put("B", Arrays.asList(new String[]{"C", "E", "D", "E"}));
        
        List cModules = store.getListOfModulesToReparse("C");
        List dModules = store.getListOfModulesToReparse("D");
        List eModules = store.getListOfModulesToReparse("E");
        
        assertEquals(1, cModules.size());
        assertTrue(cModules.contains("B"));

        assertEquals(2, dModules.size());
        assertTrue(dModules.contains("A") && dModules.contains("B"));

        assertEquals(2, eModules.size());
        assertTrue(eModules.contains("B") && eModules.contains("A"));
    }

    
    /**
     * A -> E, D 
     * D -> E
     * B -> C, D
     * C -> E
     * then a parse fail of A
     * only the following should remain
     * B -> C, D
     * D -> E
     * C -> E
     */
    public void testStore2withFail()
    {
        store.put("A", Arrays.asList(new String[]{"E", "D", "E"}));
        store.put("B", Arrays.asList(new String[]{"C", "E", "D", "E"}));
        store.parseFailed("A");
        
        List cModules = store.getListOfModulesToReparse("C");
        List dModules = store.getListOfModulesToReparse("D");
        List eModules = store.getListOfModulesToReparse("E");
        
        assertEquals(1, cModules.size());
        assertTrue(cModules.contains("B"));

        assertEquals(1, dModules.size());
        assertTrue(dModules.contains("B"));

        assertEquals(1, eModules.size());
        assertTrue(eModules.contains("B"));
    }
    
    /**
     * A -> B, C 
     * A -> C, D
     * only the following should remain
     * A -> C, D
     */
    public void testStoreTwice()
    {
        List modules1 = store.put("A", Arrays.asList(new String[]{"B", "C"}));
        List modules2 = store.put("A", Arrays.asList(new String[]{"C", "D"}));
        List modulesD  = store.getListOfModulesToReparse("D");
        
        assertNull(modules1);
        
        assertNotNull(modules2);
        assertEquals(2, modules2.size());
        assertTrue(modules2.contains("C"));
        assertTrue(modules2.contains("B"));
        
        assertEquals(1, modulesD.size());
        assertTrue(modulesD.contains("A"));
    }
    
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tla2sany/RecursiveDefDeclMismatchTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tla2sany;

import java.io.File;

import org.junit.Test;

import tla2sany.drivers.SANY;
import tlc2.tool.CommonTestCase;
import util.TestPrintStream;
import util.ToolIO;

public class RecursiveDefDeclMismatchTest extends SANYTest {

	@Test
	public void test() {
		final TestPrintStream testPrintStream = new TestPrintStream();
		ToolIO.out = testPrintStream;
		
		SANY.SANYmain(new String[] { CommonTestCase.BASE_PATH + File.separator + "sany" + File.separator + "RecursiveDefDeclMismatch.tla" });

		testPrintStream.assertSubstring("Definition of CountDown has different arity than its RECURSIVE declaration.");
		testPrintStream.assertSubstring("The operator CountDown requires 2 arguments.");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/explorer/Explorer.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Fri  2 Mar 2007 at 15:51:59 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.explorer;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import tla2sany.semantic.ExternalModuleTable;
import tla2sany.semantic.FormalParamNode;
import tla2sany.semantic.Generator;
import tla2sany.semantic.OpDefOrDeclNode;
import tla2sany.semantic.SemanticNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.utilities.Vector;
import util.UniqueString;

/*
 * TL - 2014
 * Executing the SANY jar with the -d flag enters debugging mode (which is the explorer)
 * Here one can type mt to see all semantical objects parsed and one can enter the object id to see
 * a more elaborated output
 *
 */

// This class implements the explorer tool for traversing
// and examining the semantic graph and associated data structures
// of a TLA specification

public class Explorer {

	public Generator generator;

	// Next three vars used in reading commands from keyboard
	private final InputStreamReader inStream = new InputStreamReader(System.in);
	private final int inCapacity = 100;
	private StringBuffer input = new StringBuffer(inCapacity);
	private int lineLength;

	// semNodesTable contains various nodes in the semantic graph keyed
	// by their UIDs
	private final Hashtable<Integer, ExploreNode> semNodesTable = new Hashtable<>();

	// variables used in parsing commands
	private int ntokens;
	private StringTokenizer inputTokens;
	private String firstToken, secondToken;
	private Integer icmd, icmd2 = null;
	private ExploreNode obj;

	private ExternalModuleTable mt;

	// Constructor
	public Explorer(ExternalModuleTable mtarg) {

		mt = mtarg;

	}

	/*
	 * Reads one line from "inStream" into "input". Returns "false" if there is an
	 * EOF; "true" otherwise
	 */

	private boolean getLine() {
		try {
			lineLength = 0;
			input.setLength(inCapacity);
			do {
				input.setCharAt(lineLength, (char) inStream.read());
				lineLength++;
			} while (input.charAt(lineLength - 1) != '\n' & lineLength < inCapacity);
			input.setLength(lineLength);
		} catch (EOFException e) {
			return false;
		} catch (IOException e) {
			System.out.println("***I/O exception on keyboard input; " + e);
			System.exit(-1);
		}
		if (lineLength >= inCapacity) {
			System.out.println("Input line too long; line limited to " + inCapacity + " chars.  Line ignored.");
			input.setLength(0);
		}

		return true;
	}

	// Integer command
	private void printNode(int depth) {

		// See if the object requested is already in the table
		if ((obj = (ExploreNode) semNodesTable.get(icmd)) != null) {
			// Print tree to depth of icmd2
			System.out.println(((ExploreNode) obj).toString(depth));
			System.out.print("\n" + ((ExploreNode) obj).levelDataToString());
		} else {
			// object requested is not in semNodesTable
			System.out.println("No such node encountered yet");
		}
	} // end method

	private void lookUpAndPrintSyntaxTree(String symbName) {

		Vector<SymbolNode> symbolVect = new Vector<>(8); // Initial room for 8 symbols with same name

		// Collect in Vector symbols all SymbolNodes in the semNodesTable whose name ==
		// symbName

		for (Enumeration<ExploreNode> Enum = semNodesTable.elements(); Enum.hasMoreElements();) {

			ExploreNode semNode = Enum.nextElement();

			if (semNode instanceof SymbolNode
					&& ((SymbolNode) semNode).getName() == UniqueString.uniqueStringOf(symbName)) {

				symbolVect.addElement((SymbolNode) semNode);

			}
		}

		// Print them all
		for (int i = 0; i < symbolVect.size(); i++) {
			SymbolNode sym = (SymbolNode) (symbolVect.elementAt(i));
			((SemanticNode) (sym)).getTreeNode().printST(0);
			System.out.println();
		}

	}

	private void lookUpAndPrintDef(String symbName) {

		Vector<SymbolNode> symbolVect = new Vector<>(8); // Initial room for 8 symbols with same name

		// Collect in Vector symbols all SymbolNodes in the semNodesTable whose name ==
		// symbName

		for (Enumeration<ExploreNode> Enum = semNodesTable.elements(); Enum.hasMoreElements();) {

			ExploreNode semNode = Enum.nextElement();

			if (semNode instanceof SymbolNode
					&& ((SymbolNode) semNode).getName() == UniqueString.uniqueStringOf(symbName)) {

				symbolVect.addElement((SymbolNode) semNode);

			}
		}

		// Print them all
		for (int i = 0; i < symbolVect.size(); i++) {
			SymbolNode sym = (SymbolNode) (symbolVect.elementAt(i));
			if (sym instanceof OpDefOrDeclNode) {
				if (((OpDefOrDeclNode) sym).getOriginallyDefinedInModuleNode() != null) {
					System.out.print(
							"Module: " + ((OpDefOrDeclNode) sym).getOriginallyDefinedInModuleNode().getName() + "\n");
				} else {
					System.out.print("Module: " + "null" + "\n");
				}
			} else if (sym instanceof FormalParamNode) {
				System.out.print("Module: " + ((FormalParamNode) sym).getModuleNode().getName());
			}
			System.out.println(((ExploreNode) (symbolVect.elementAt(i))).toString(100));
			System.out.println();
		}

	}

	private void levelDataPrint(String symbName) {

		Vector<SymbolNode> symbolVect = new Vector<>(8); // Initial room for 8 symbols with same name

		// Collect in Vector symbols all SymbolNodes in the semNodesTable whose name ==
		// symbName

		for (Enumeration<ExploreNode> Enum = semNodesTable.elements(); Enum.hasMoreElements();) {

			ExploreNode semNode = Enum.nextElement();

			if (semNode instanceof SymbolNode
					&& ((SymbolNode) semNode).getName() == UniqueString.uniqueStringOf(symbName)) {

				symbolVect.addElement((SymbolNode) semNode);

			}
		}

		// Print them all
		for (int i = 0; i < symbolVect.size(); i++) {
			SymbolNode sym = (SymbolNode) (symbolVect.elementAt(i));
			if (sym instanceof OpDefOrDeclNode) {
				if (((OpDefOrDeclNode) sym).getOriginallyDefinedInModuleNode() != null) {
					System.out.print(
							"Module: " + ((OpDefOrDeclNode) sym).getOriginallyDefinedInModuleNode().getName() + "\n");
				} else {
					System.out.print("Module: " + "null" + "\n");
				}
			} else if (sym instanceof FormalParamNode) {
				System.out.print("Module: " + ((FormalParamNode) sym).getModuleNode().getName() + "\n");
			}
			System.out.println(((ExploreNode) (sym)).levelDataToString());
			System.out.println();
		}

	}

	private void executeCommand() throws ExplorerQuitException {

		// At this point icmd (firsToken) may be null, but icmd2
		// (second token) is always non-null

		// Integers as commands start printing at the node having icmd == UID;
		// non-integer commands do something else

		if (icmd != null) { // first token is an integer

			printNode(icmd2.intValue());

		} else { // the first token is not an integer

			// non-integer commands
			if (firstToken.toLowerCase().startsWith("qu")) {
				// "quit" command
				throw new ExplorerQuitException();

			} else if (firstToken.toLowerCase().equals("mt")) {

				// Print the semantic graph, rooted in the Module Table
				// excluding built-ins and ops defined in module Naturals
				if (icmd2 != null) {
					mt.printExternalModuleTable(icmd2.intValue(), false);
				} else {
					mt.printExternalModuleTable(2, false);
				}

			} else if (firstToken.toLowerCase().equals("mt*")) {

				// Print the semantic graph, rooted in the Module Table
				// including builtins and ops defined in Naturals
				if (icmd2 != null) {
					mt.printExternalModuleTable(icmd2.intValue(), true);
				} else {
					mt.printExternalModuleTable(2, true);
				}

			} else if (firstToken.equalsIgnoreCase("dot")) {
				dotSemanticGraph();
			} else if (firstToken.toLowerCase().startsWith("cst")) {
				printSyntaxTree();

			} else if (firstToken.toLowerCase().startsWith("s")) {
				if (secondToken != null) {
					lookUpAndPrintSyntaxTree(secondToken);
				} else {
					System.out.println("***Error: You must indicate what name you want to print the syntax tree of.");
				}

			} else if (firstToken.toLowerCase().startsWith("d")) {
				if (secondToken != null) {
					lookUpAndPrintDef(secondToken);
				} else {
					System.out.println("***Error: You must indicate what name you want to print the definition of.");
				}

			} else if (firstToken.toLowerCase().startsWith("l")) {
				if (secondToken != null) {
					levelDataPrint(secondToken);
				} else {
					System.out.println("***Error: You must indicate what name you want to print the level data of.");
				}

			} else {
				// unknown command
				System.out.println("Unknown command: " + firstToken.toString());
				return;
			}

		} // end else

	}

	private void parseAndExecuteCommand() throws ExplorerQuitException {

		icmd = null;
		icmd2 = null;
		ntokens = 0;

		// Do nothing if cmd line contains no tokens
		if (!inputTokens.hasMoreElements())
			return;

		// Process first token
		ntokens++;
		firstToken = (String) (inputTokens.nextElement());

		// Try parsing first token as an Integer
		try {
			icmd = Integer.valueOf(firstToken);
		} catch (Exception e) {
		}

		// Process second token (if present)
		if (inputTokens.hasMoreElements()) {
			ntokens++;
			secondToken = (String) (inputTokens.nextElement());

			// Try parsing second token as an Integer
			try {
				icmd2 = Integer.valueOf(secondToken);
			} catch (Exception e) {
			}
		}

		// A single token command defaults the depth to 20, except for
		// "mt" command, which defaults to 2
		if (ntokens < 2 || (icmd2 != null && icmd2.intValue() < 0)) {
			if (firstToken.toLowerCase().startsWith("mt")) {
				icmd2 = new Integer(2);
			} else {
				icmd2 = new Integer(4);
			}
		}

		if (inputTokens.hasMoreElements()) {
			System.out.println("Command has too many tokens");
			return;
		}

		executeCommand();

	} // end method
	
	public void dotSemanticGraph() {
		final DotExplorerVisitor visitor = new DotExplorerVisitor(mt.getRootModule());
		mt.getRootModule().walkGraph(visitor.getTable(), visitor);
		visitor.done();
	}

	public void printSyntaxTree() {

		int key;

		// Prepare to iterate over ExternalModuleTable entries
		Iterator<ExternalModuleTable.ExternalModuleTableEntry> modules = mt.moduleHashTable.values().iterator();
		ExternalModuleTable.ExternalModuleTableEntry mte;

		// For each entry ExternalModuleTableEntry mte in the ExternalModuleTable mt ...
		while (modules.hasNext()) {
			key = -1;

			mte = modules.next();

			// Did the module parse correctly?
			if (mte != null) {
				if (mte.getModuleNode() != null) {
					key = mte.getModuleNode().getUid();

					// Make an entry in the semNodesTable for this ModuleNode
					semNodesTable.put(key, mte.getModuleNode());

					// Print the concrete syntax tree for this ExternalModuleTableEntry
					System.out.println("\n*** Concrete Syntax Tree for Module " + key);

					tla2sany.st.TreeNode stn = mte.getModuleNode().getTreeNode();
					stn.printST(0); // Zero indentation level

					System.out.println("\n*** End of concrete syntax tree for Module " + key);
				} else {
					System.out.println("\n*** Null ExternalModuleTableEntry.  "
							+ "\n*** Next module did not parse, and cannot be printed.");
				}
			} else {
				System.out.println("*** Null SemanticNode in ExternalModuleTableEntry.  "
						+ "/n*** Next module did not parse, and cannot be printed.");
			}

		}
	}

	public void main(final String[] args) throws ExplorerQuitException {

		if (mt == null) {
			System.out.println("*** module table == null in Explorer.main() ***");
			return;
		}

		final List<String> asList = Arrays.asList(args);
		// Passing single token commands as command line parameter skips Explorer's
		// interpreter mode.
		if (asList.contains("cst")) {
			inputTokens = new StringTokenizer("cst");
			parseAndExecuteCommand();
			System.exit(0);
		} else if (asList.contains("dot")) {
			inputTokens = new StringTokenizer("dot");
			parseAndExecuteCommand();
			System.exit(0);
		} else  if (asList.contains("mt")) {
			inputTokens = new StringTokenizer("mt");
			parseAndExecuteCommand();
			System.exit(0);
		} else if (asList.contains("mt*")) {
			inputTokens = new StringTokenizer("mt*");
			parseAndExecuteCommand();
			System.exit(0);
		} else {
			// Get all semNodes in semNodeTable
			mt.walkGraph(semNodesTable);

			// Print initial user input prompt
			System.out.println("\n\n*** TLA+ semantic graph exploration tool v 1.0 (DRJ)");
			System.out.print("\n>>");
			// Main command interpreter loop
			while (getLine()) {
				
				inputTokens = new StringTokenizer(input.toString());
				
				parseAndExecuteCommand();
				
				// Print next user prompt
				System.out.print("\n>>");
				
			} // end while
		}

	} // end main() method

} // end class


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/Spec.java<|end_filename|>
package org.lamport.tla.toolbox.spec;

import java.io.File;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.texteditor.ITextEditor;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.parser.IParseConstants;
import org.lamport.tla.toolbox.tool.SpecLifecycleParticipant;
import org.lamport.tla.toolbox.util.AdapterFactory;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.lamport.tla.toolbox.util.compare.ResourceNameComparator;
import org.lamport.tla.toolbox.util.pref.PreferenceStoreHelper;

import pcal.TLAtoPCalMapping;
import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.Context;
import tla2sany.semantic.ExternalModuleTable;
import util.SimpleFilenameToStream;
import util.UniqueString;

/**
 * Represents a specification handle in the toolbox
 * 
 * In June 2010, LL added some fields by which handlers of different commands
 * could communicate with one another. I'm sure there's a more elegant way to do
 * this that involves another few levels of indirection, but I have the
 * old-fashioned belief that doing things the easy way and commenting what you
 * do is better than doing things the correct way that makes it impossible to
 * figure out what the hell is going on without learning yet another almost but
 * not quite completely undocumented Eclipse feature.
 * 
 * 
 * @version $Id$
 * @author <NAME>
 */
public class Spec implements IAdaptable {

    /**
     * specnames2mappings.get(filename) is the TLAtoPCalMapping object produced
     * by the PlusCal translator for the file named tpMappingNames[i], where the
     * file name is the module name + ".tla". (Sometimes it's easier to get the
     * file name, and sometimes the module name, and it's easier to add a ".tla"
     * than to remove it.)
     * <p>
     * There are two public procedures for manipulating these fields:
     * 
     * @see Spec#setTpMapping(TLAtoPCalMapping, String)
     * @see Spec#getTpMapping(String)
     */
    private final Map<String, TLAtoPCalMapping> spec2mappings = new HashMap<String, TLAtoPCalMapping>();

    /**
     * The following stack is used for remembering the jumping-off point for a
     * Goto Declaration or ShowDefinitions command, so we can return to it with
     * a Return from Goto Declaration command.
     */
    private final Deque<Pair> openDecls = new ArrayDeque<>();

    /**
     * The following fields are used to remember the result of a Show Uses
     * command so the Goto Next Use and Goto Previous Use commands know where to
     * go.
     * 
     * The name of the module whose instances are being shown. If there are more
     * than one, this is set by user selection from a pop-up dialog.
     */
    private String moduleToShow = null;

    /**
     * The markers to be shown, sorted by the locations in which they originally
     * appeared. I don't think that order can change, but what do I know?
     */
    private IMarker[] markersToShow = null;

    /**
     * The index of the marker in markersToShow that is currently being shown.
     */
    private int currentSelection = 0;

    /**
	 * The overall size of the spec directory with all subdirectories and files.
	 */
	private long size = 0;

    /* project handle */
    private final IProject project;

    /* root module handle */
    private IFile rootFile;

    /* status of the specification */
    private int status;

    /* the semantic tree produced by the parser */
    private SpecObj specObj;

    /**
     * Creates a Spec handle for existing project. Use the factory method
     * {@link Spec#createNewSpec(String, String, Date)} if the project reference
     * is not available
     * 
     * @param project
     *            project handle
     */
    public Spec(IProject project) {
    	Assert.isNotNull(project);
        this.project = project;
        initProjectProperties();
    }

    public Spec(IProject project, IFile rootFile) {
    	Assert.isNotNull(project);
        this.project = project;
    	Assert.isNotNull(rootFile);
    	this.rootFile = rootFile;
    }

    /**
     * Factory method Creates a new specification, the underlying IProject link
     * the root file
     * 
     * @param name
     *            the name of the specification
     * @param rootFilename
     *            the path to the root file name
     * @param importExisting
     * 
     *            Note: when importing an existing spec, the contents of the
     *            .toolbox directory needs to be fixed because it contains
     *            absolute path names, which may be incorrect if the spec was
     *            moved from someplace else. Here are the files that may need
     *            changing:
     * 
     *            .toolbox/.project : <location> entries This definitely needs
     *            to be changed. .toolbox/.setting/... .prefs : ProjectRootFile
     *            entry. This file is rewritten when the spec is created, so it
     *            may not need to be changed.
     * 
     *            Experiment shows that the rootFilename argument contains the
     *            complete path name, from which one could extract the path
     *            names of those files and then rewrite them as needed.
     * @param monitor
     * @throws CoreException 
     */
    public static Spec createNewSpec(String name, String rootFilename,
            boolean importExisting, IProgressMonitor monitor) throws CoreException {
        IProject project = ResourceHelper.getProject(name, rootFilename, true,
                importExisting, monitor);
        PreferenceStoreHelper.storeRootFilename(project, rootFilename);

        Spec spec = new Spec(project);
        spec.setLastModified();
        return spec;
    }

    /**
     * initializes the root module from the project properties
     */
    private void initProjectProperties() {
        this.rootFile = PreferenceStoreHelper.readProjectRootFile(project);
        this.specObj = null;
        this.status = IParseConstants.UNPARSED;

        // Read the current size of the spec. 
        size = ResourceHelper.getSizeOfJavaFileResource(this.project);

        // Assert.isNotNull(this.rootFile);
        // This assertion was preventing the Toolbox from starting, so LL
        // comented it out on 19 Mar 2011 and added the log message
        // on 3 Apr 2011.
        // To report this problem to the user, one can do the following:
        // - Add a failed field to the Spec object, initialized to false
        // - Set this field to true when the error occurs.
        // After the statement
        //
        // spec = new Spec(projects[i]);
        //
        // in the constructor of WorkspaceSpecManager, test this field and,
        // if true, take the appropriate action--probably popping up a warning
        // (if that's possible) or else putting the name of the spec in the
        // log, and also probably not executing the addSpec command that follows
        // this statement.
        //
        if (this.rootFile == null) {
            Activator
                    .getDefault()
                    .logError(
                            "A spec did not load correctly, probably because it was modified outside the Toolbox."
                                    + "\n Error occurred in toolbox/spec/Spec.initProjectProperties()",
                            null);
        } else {
            // Initialize TLAtoPCalMapping here for the root module to have it
            // available the moment the user needs it the first time. This is
            // just an
            // optimization because the mapping would be looked up later
            // automatically, but has the advantage that it is not done on the
            // UI thread.
            this.getTpMapping(this.rootFile.getName());
        }
    }

    /**
     * @return the lastModified
     */
    public Date getLastModified() {
        if (IResource.NULL_STAMP == project.getModificationStamp()) {
            return null;
        }
        return new Date(project.getModificationStamp());
    }

    /**
     * Touches the underlying resource
     */
    public void setLastModified() {
        try {
            project.touch(new NullProgressMonitor());
        } catch (CoreException e) {
            Activator.getDefault().logError(
                    "Error changing the timestamp of the spec", e);
        }
    }

    /**
     * Retrieves the underlying project file
     * 
     * @return the project
     */
    public IProject getProject() {
        return project;
    }

    /**
     * @return the name
     */
    public String getName() {
        return project.getName();
    }

    /**
     * Retrieves the path to the file containing the root module This is a
     * convenience method for {@link getRootFile()#getLocation()#toOSString()}
     * 
     * @return the OS representation of the root file
     */
    public String getRootFilename() {
        IPath location = rootFile.getLocation();
        return location.toOSString();
    }

    /**
     * Retrieves the handle to the root file
     * 
     * @return IFile of the root
     */
    public IFile getRootFile() {
        return this.rootFile;
    }

    /**
     * Retrieves parsing status
     * 
     * See {@link IParseConstants} for possible values of status.
     * 
     * @return the status
     */
    public int getStatus() {
        return status;
    }

    /**
     * Sets parsing status. As a side effect the
     * {@link SpecLifecycleParticipant}s get informed
     * 
     * @param status
     *            the status to set
     */
    public void setStatus(int status) {
        this.status = status;
        // informs
        Activator.getSpecManager().specParsed(this);
    }

    /**
     * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
     */
	public <T> T getAdapter(Class<T> adapter) {
        // lookup the IAdapterManager service
        final IAdapterManager manager = Platform.getAdapterManager();
        // forward the request to IAdapterManager service
        return manager.getAdapter(this, adapter);
    }

    /**
     * Retrieves the list of modules in the spec, or an empty list if no modules <br>
     * The list is sorted on the resource name
     * 
     * @return
     */
    public IResource[] getModuleResources() {
        // TODO relate this list to the list of modules, which result after
        // parse
        IResource[] modules = null;
        try {
            modules = getProject().members(IResource.NONE);
            // sort the markers
            List<IResource> moduleList = new ArrayList<IResource>(
                    Arrays.asList(modules));
            Collections.sort(moduleList, new ResourceNameComparator());
            return moduleList.toArray(new IResource[moduleList.size()]);

        } catch (CoreException e) {
            Activator.getDefault().logError(
                    "Error retrieving the the spec modules", e);
            modules = new IResource[0];
        }
        return modules;
    }

    /**
     * Returns the SpecObj
     */
    public SpecObj getRootModule() {
        return this.specObj;
    }

	/**
	 * @return The logical name of the root module. E.g. if the file is named
	 *         "DieHard.tla", the root module name is "DieHard". The root module
	 *         name reflects the name declard in the MODULE statement inside the
	 *         .tla file.
	 * @see SpecObj#getName()
	 */
    public String getRootModuleName() {
    	// Can't use this.specObj#getName because specObj can be null.

    	// ThefileExtension will be tla. 
    	final String fileExtension = this.rootFile.getFileExtension();
    	// Strip off ".tla" from the end of the string.
    	return this.rootFile.getName().replaceFirst("." + fileExtension + "$", "");
    }

    /**
     * Returns the SpecObj only on valid status
     */
    public SpecObj getValidRootModule() {
        if (AdapterFactory.isProblemStatus(this.status)) {
            return null;
        }
        return getRootModule();

    }

    /**
     * Sets the new spec object
     * 
     * @param specObj
     */
    public void setSpecObj(SpecObj specObj) {
        this.specObj = specObj;
    }

    /**
     * @param editor
     *            the ITextEditor whose current ITextSelection to remember.
     */
	public void setOpenDeclModuleName(ITextEditor editor) {
		this.setOpenDeclModuleName(editor, (ITextSelection) editor.getSelectionProvider().getSelection());
	}

    public void setOpenDeclModuleName(ITextEditor editor, ITextSelection selection) {
    	this.openDecls.push(new Pair(editor, selection));
    }
    
   /**
     * @return the openDeclModuleName
     */
    public Pair getOpenDeclModuleName() {
        return this.openDecls.poll();
    }
    
    public static class Pair {
    	public final ITextEditor editor;
    	public final ITextSelection selection;
        public Pair(ITextEditor editor, ITextSelection selection) {
			this.editor = editor;
			this.selection = selection;
		}
    }

    /**
     * @param moduleToShow
     *            the moduleToShow to set
     */
    public void setModuleToShow(String moduleToShow) {
        this.moduleToShow = moduleToShow;
    }

    /**
     * @return the moduleToShow
     */
    public String getModuleToShow() {
        return moduleToShow;
    }

    /**
     * @param markersToShow
     *            the markersToShow to set
     */
    public void setMarkersToShow(IMarker[] markersToShow) {
        this.markersToShow = markersToShow;
    }

    /**
     * @return the markersToShow
     */
    public IMarker[] getMarkersToShow() {
        return markersToShow;
    }

    /**
     * @param currentSelection
     *            the currentSelection to set
     */
    public void setCurrentSelection(int currentSelection) {
        this.currentSelection = currentSelection;
    }

    /**
     * @return the currentSelection
     */
    public int getCurrentSelection() {
        return currentSelection;
    }

	public long getSize() {
		return size;
	}
	
	/**
	 * @param size A spec size in bytes
	 */
	public void setSize(long size) {
		this.size = size;
	}

    /**
     * @see ResourceHelper#getTLALibraryPath(IProject)
     */
    public String[] getTLALibraryPath() {
    	return ResourceHelper.getTLALibraryPath(project);
    }

    /**
     * @return A {@link String} with all user defined TLA+ library path
     *         locations concatenated and as a Java VM {@link System} property.
     *         If the user has not set any library path locations, an empty
     *         {@link String} is returned, not <code>null</code>.
     * @see Spec#getTLALibraryPath()
     */
    public String getTLALibraryPathAsVMArg() {
        final String[] tlaLibraryPath = getTLALibraryPath();

        if (tlaLibraryPath.length > 0) {
            final StringBuffer buf = new StringBuffer(tlaLibraryPath.length * 2);

            buf.append("-D" + SimpleFilenameToStream.TLA_LIBRARY + "=");

            for (final String location : tlaLibraryPath) {
                buf.append(location);
                buf.append(File.pathSeparator);
            }

            final String vmArg = buf.toString();

            // remove dangling pathSeparator
            return vmArg.substring(0, vmArg.length() - 1);
        } else {
            return "";
        }
    }
    
    public String getTLALibraryPathAsClassPath() {
        final String[] tlaLibraryPath = getTLALibraryPath();

        if (tlaLibraryPath.length > 0) {
            final StringBuffer buf = new StringBuffer(tlaLibraryPath.length * 2);

            for (final String location : tlaLibraryPath) {
            	if (new File(location).isDirectory()) {
            		// For directories include everything.
            		buf.append(location + File.separator + "*") ;
            	} else {
            		buf.append(location);
            	}
                buf.append(File.pathSeparator);
            }

            final String vmArg = buf.toString();

            // remove dangling pathSeparator
            return vmArg.substring(0, vmArg.length() - 1);
        } else {
            return "";
        }
    }

    private final Lock lock = new ReentrantLock(true);

    /**
     * @param filename
     *            The filename of the {@link Spec} for which the
     *            {@link TLAtoPCalMapping} is asked for.
     * @return A {@link TLAtoPCalMapping} for the given {@link Spec}'s filename
     *         or <code>null</code> if no mapping exist.
     */
    public TLAtoPCalMapping getTpMapping(final String filename) {
        lock.lock();
        try {
            TLAtoPCalMapping mapping = spec2mappings.get(filename);
            // In-memory cache miss and thus try to read the mapping from its
            // disc
            // file. If there exists no disk file, we assume there has never
            // existed
            // a mapping.
            if (mapping == null) {
                mapping = ResourceHelper
                        .readTLAtoPCalMapping(project, filename);
                if (mapping == null) {
                    mapping = new NullTLAtoPCalMapping();
                }
                spec2mappings.put(filename, mapping);
            }

            // Always return null if the mapping maps to a NullTLAtoPCalMapping
            // as
            // our consumers expect null to indicate a non-existent mapping.
            if (mapping instanceof NullTLAtoPCalMapping) {
                return null;
            }
            return mapping;
        } finally {
            lock.unlock();
        }
    }

    /**
     * Associates the specified mapping with the specified filename (optional
     * operation). If the {@link Spec} previously contained a mapping for the
     * filename, the old mapping is replaced by the specified map.
     * 
     * @param mapping
     *            The {@link TLAtoPCalMapping} object for the given
     *            <tt>filename</tt>. <code>null</code>, will cause an
     *            {@link IllegalArgumentException}.
     * @param filename
     *            key with which the specified value is to be associated.
     *            <code>null</code>, will cause an
     *            {@link IllegalArgumentException}.
     * @param monitor
     *            A valid {@link IProgressMonitor}, <code>null</code>, will
     *            cause an {@link IllegalArgumentException}.
     * @return the previous value associated with <tt>filename</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>filename</tt>.
     * @throws NullPointerException
     *             if the specified key or value is null and this map does not
     *             permit null keys or values
     * @throws IllegalArgumentException
     *             if some property of the specified key or value prevents it
     *             from being stored in this map
     */
    public TLAtoPCalMapping setTpMapping(final TLAtoPCalMapping mapping,
            final String filename, final IProgressMonitor monitor) {

        // Safeguard against inproper use of this API
        if (mapping == null || filename == null || monitor == null) {
            throw new IllegalArgumentException();
        }

        lock.lock();
        try {
            final TLAtoPCalMapping oldMapping = spec2mappings.put(filename,
                    mapping);

            // Check if old and new mapping are identical to avoid disk flush.
            // This requires proper equals/hashcode in TLAtoPCalMapping and
            // nested.
            if (!mapping.equals(oldMapping)) {
                // Use a submonitor to show progress as well as failure
				final SubMonitor subProgressMonitor = SubMonitor.convert(monitor, 1);
                subProgressMonitor
                        .setTaskName("Writing TLA+ to PCal mapping for "
                                + filename);
                // Eagerly flush mapping to its persistent disk storage
                // (overwriting
                // any previous mapping stored on disk). This is relatively
                // cheap
                // compared to how often a mapping is re-generated, but has the
                // advantage that the mapping doesn't get lost if the Toolbox
                // decides to
                // not shut down gracefully.
                try {
                    Assert.isTrue(ResourceHelper.writeTLAtoPCalMapping(project,
                            filename, mapping, subProgressMonitor));
                } finally {
                    subProgressMonitor.done();
                }
            }

            return oldMapping;
        } finally {
            lock.unlock();
        }
    }

    @SuppressWarnings("serial")
    private static class NullTLAtoPCalMapping extends TLAtoPCalMapping {
    }

	/**
	 * @return true iff this spec is the currently active spec.
	 * 
	 * @see Activator#getSpecManager()
	 * 
	 */
	public boolean isCurrentSpec() {
		
		return Activator.getSpecManager().getSpecLoaded() == this;
	}

	public Module getModule(final String moduleName) {
		final List<Module> modules = getModules();
		for (Module module : modules) {
			if (moduleName.equals(module.getModuleName())) {
				return module;
			}
		}
		return null;
	}
	
	public List<Module> getModules() {
		final List<Module> modules = new ArrayList<Module>();
		final IResource[] moduleResources = getModuleResources();
		for (int i = 0; i < moduleResources.length; i++) {
			// skip non-modules
			if (!ResourceHelper.isModule(moduleResources[i])) {
				continue;
			}
			final Module module = new Module(moduleResources[i]);
			module.setRoot(ResourceHelper.isRoot((IFile) moduleResources[i]));
			modules.add(module);
		}
		return modules;
	}

	public boolean declares(final String str) {
		return declares(UniqueString.uniqueStringOf(str));
	}

	public boolean declares(final UniqueString us) {
		if (getRootModule() != null) {
			final ExternalModuleTable externalModuleTable = getRootModule().getExternalModuleTable();
			final Context context = externalModuleTable.getContextForRootModule();
			if (context != null) {
				return context.occurSymbol(us);
			}
		}
		return false;
	}

	/**
	 * Transitively deletes the given marker type on all modules (including the root
	 * module) of the spec.
	 */
	public void deleteMarker(final String markerType) throws CoreException {
		getRootFile().deleteMarkers(markerType, true, IResource.DEPTH_INFINITE);
		for (IResource r : getModuleResources()) {
			r.deleteMarkers(markerType, true, IResource.DEPTH_INFINITE);
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/coverage/MCoverageTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2021 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.coverage;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class MCoverageTest extends AbstractCoverageTest {

    public MCoverageTest () {
        super("M");
    }

    @Test
    public void testSpec () {
		// ModelChecker has finished and generated the expected amount of states
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "1"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "37056", "192", "0"));

		// No 'general' errors recorded
		assertFalse(recorder.recorded(EC.GENERAL));

		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
		
		assertFalse(recorder.recorded(EC.TLC_COVERAGE_MISMATCH));
		assertCoverage("<Init line 16, col 1 to line 16, col 4 of module M>: 192:192\n"
				+ "  line 17, col 17 to line 17, col 39 of module M: 1:24\n"
				+ "  |line 17, col 18 to line 17, col 27 of module M: 1\n"
				+ "  |line 17, col 32 to line 17, col 38 of module M: 1\n"
				+ "  line 18, col 16 to line 18, col 31 of module M: 8:192\n"
				+ "  |line 18, col 17 to line 18, col 21 of module M: 8\n"
				+ "  |line 18, col 26 to line 18, col 30 of module M: 8\n"
				+ "  line 19, col 6 to line 19, col 19 of module M: 64\n"
				+ "  line 20, col 6 to line 20, col 21 of module M: 192\n"
				+"<Next line 22, col 1 to line 22, col 4 of module M>: 0:36864\n"
				+ "  line 23, col 6 to line 23, col 40 of module M: 1536\n"
				+ "  |line 23, col 18 to line 23, col 40 of module M: 192:4608\n"
				+ "  ||line 23, col 19 to line 23, col 28 of module M: 192\n"
				+ "  ||line 23, col 33 to line 23, col 39 of module M: 192\n"
				+ "  line 24, col 6 to line 24, col 32 of module M: 12288\n"
				+ "  |line 24, col 17 to line 24, col 32 of module M: 1536:36864\n"
				+ "  ||line 24, col 18 to line 24, col 22 of module M: 1536\n"
				+ "  ||line 24, col 27 to line 24, col 31 of module M: 1536\n"
				+ "  line 25, col 6 to line 25, col 20 of module M: 36864\n"
				+ "  |line 25, col 16 to line 25, col 20 of module M: 12288\n"
				+ "  line 26, col 6 to line 26, col 22 of module M: 36864");

    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/management/ModelCheckerMXWrapper.java<|end_filename|>
// Copyright (c) Jan 4, 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.management;

import javax.management.NotCompliantMBeanException;

import tlc2.TLC;
import tlc2.TLCGlobals;
import tlc2.tool.ModelChecker;
import tlc2.tool.TLCState;
import tlc2.tool.distributed.management.TLCStatisticsMXBean;
import tlc2.tool.fp.DiskFPSet;

/**
 * @author <NAME>
 */
public class ModelCheckerMXWrapper extends TLCStandardMBean implements TLCStatisticsMXBean {

	public static final String OBJ_NAME = "tlc2.tool:type=ModelChecker";

	private final ModelChecker modelChecker;
	private final TLC tlc;

	public ModelCheckerMXWrapper(final ModelChecker aModelChecker, final TLC tlc)
			throws NotCompliantMBeanException {
		super(TLCStatisticsMXBean.class);
		this.modelChecker = aModelChecker;
		this.tlc = tlc;
		// register all TLCStatisticsMXBeans under the same name
		registerMBean(OBJ_NAME);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStatesGenerated()
	 */
	public long getStatesGenerated() {
		return modelChecker.getStatesGenerated();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getDistinctStatesGenerated()
	 */
	public long getDistinctStatesGenerated() {
		// if impl is DiskFPSet we don't want to add to the lock contention on
		// the RWLock in DiskFPSet and thus compromise on reading dirty values
		// (acceptable for statistics/metrics)
		if(modelChecker.theFPSet instanceof DiskFPSet) {
			DiskFPSet diskFPSet = (DiskFPSet) modelChecker.theFPSet;
			return diskFPSet.getFileCnt() + diskFPSet.getTblCnt();
		}
		return modelChecker.theFPSet.size();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStateQueueSize()
	 */
	public long getStateQueueSize() {
		return modelChecker.getStateQueueSize();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getStatesGeneratedPerMinute()
	 */
	public long getStatesGeneratedPerMinute() {
		return modelChecker.statesPerMinute;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getDistinctStatesGeneratedPerMinute()
	 */
	public long getDistinctStatesGeneratedPerMinute() {
		return modelChecker.distinctStatesPerMinute;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getProgress()
	 */
	public int getProgress() {
		return modelChecker.getProgress();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getWorkerCount()
	 */
	public int getWorkerCount() {
		return TLCGlobals.getNumWorkers();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#checkpoint()
	 */
	public void checkpoint() {
		TLCGlobals.forceChkpt();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getAverageBlockCnt()
	 */
	public long getAverageBlockCnt() {
		//TODO adapt once Workers can support units of work greater than 1 
		return 1;
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getRuntimeRatio()
	 */
	public double getRuntimeRatio() {
		return modelChecker.getRuntimeRatio();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#liveCheck()
	 */
	public void liveCheck() {
		modelChecker.forceLiveCheck();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getCurrentState()
	 */
	public String getCurrentState() {
		final TLCState state = modelChecker.theStateQueue.sPeek();
		if (state != null) {
			return state.toString();
		}
		return "N/A";
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getSpecName()
	 */
	public String getSpecName() {
		return tlc.getSpecName();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#getModelName()
	 */
	public String getModelName() {
		return tlc.getModelName();
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#stop()
	 */
	public void stop() {
		modelChecker.stop();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#suspend()
	 */
	public void suspend() {
		modelChecker.suspend();
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.distributed.management.TLCStatisticsMXBean#resume()
	 */
	public void resume() {
		modelChecker.resume();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/value/impl/MVPerms.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:42:27 PST by lamport
//      modified on Thu Nov 16 15:53:30 PST 2000 by yuanyu

package tlc2.value.impl;

import java.util.Enumeration;

import tlc2.util.Vect;
import tlc2.value.IMVPerm;
import tlc2.value.IValue;
import util.Assert;
import util.Set;

public abstract class MVPerms {
  
  public static final IMVPerm[] permutationSubgroup(final Enumerable enumerable) {
    final ValueEnumeration Enum = enumerable.elements();
	final int sz = enumerable.size() - 1;
    final Set perms = new Set(sz);
    final Vect<IMVPerm> permVec = new Vect<>(sz);
    // Compute the group generators:
    Value elem;
    while ((elem = Enum.nextElement()) != null) {
      final FcnRcdValue fcn = (FcnRcdValue) elem.toFcnRcd();
      if (fcn == null) {
	Assert.fail("The symmetry operator must specify a set of functions.");
      }
      final IMVPerm perm = new MVPerm();
      for (int i = 0; i < fcn.domain.length; i++) {
	final IValue dval = fcn.domain[i];
	final IValue rval = fcn.values[i];
	if ((dval instanceof ModelValue) && (rval instanceof ModelValue)) {
	  perm.put((ModelValue)dval, (ModelValue)rval);
	}
	else {
	  Assert.fail("Symmetry function must have model values as domain and range.");
	}
      }
      if (perm.size() > 0 && perms.put(perm) == null) {
	permVec.addElement(perm);
      }
    }
    // Compute the group generated by the generators:
    final int gsz = permVec.size();
    int sz0 = 0;
    while (true) {
      final int sz1 = permVec.size();
      for (int i = 0; i < gsz; i++) {
	final IMVPerm perm1 = (IMVPerm)permVec.elementAt(i);
	for (int j = sz0; j < sz1; j++) {
		IMVPerm perm = perm1.compose((IMVPerm)permVec.elementAt(j));
	  if (perm.size() > 0 && perms.put(perm) == null) {
	    permVec.addElement(perm);
	  }
	}
      }
      if (sz1 == permVec.size()) { break; }
      sz0 = sz1;
    }
    // Finally, put all the elements in an array ready for use:
    final IMVPerm[] res = new IMVPerm[permVec.size()];
    final Enumeration<IMVPerm> permEnum = permVec.elements();
    for (int i = 0; i < res.length; i++) {
      res[i] = permEnum.nextElement();
    }
    return res;
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/part/ValidateableSectionPart.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.part;

import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.Section;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.page.BasicFormPage;

/**
 * Section part implementing validate-able interface
 * On validation request it delegates the validation to the editor page
 * 
 * @author <NAME>
 * @version $Id$
 */
public class ValidateableSectionPart extends SectionPart implements IValidateble
{
    private BasicFormPage page;

    /**
     * Creates a wrapper around the section
     * @param section
     * @param page
     */
    public ValidateableSectionPart(Section section, BasicFormPage page, String sectionName)
    {
        super(section);
        this.page = page;
        page.getDataBindingManager().bindSection(this, sectionName, page.getId());
    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.tool.tlc.ui.editor.validator.IValidateble#validate(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
     */
    public void validate()
    {
        page.validatePage(false);
    }

    public void commit(boolean onSave)
    {
        // commit the part on save, but not on other events
        if (onSave) 
        {
            super.commit(onSave);
        }
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/LaTeXOutput.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS LaTeXOutput                                                        *
*                                                                          *
* This class defines the following static methods (aka procedures) for     *
* writing the LaTeX output.                                                *
*                                                                          *
*   WriteAlignmentFile(Token[][])                                          *
*      For tlatex.TLA, writes the LaTeX source file whose resulting        *
*      log file contains the dimensions needed to do the alignment.        *
*                                                                          *
*   WriteTeXAlignmentFile(Token[][], Vector, float)                        *
*      For tlatex.TeX, writes the LaTeX source file whose resulting        *
*      log file contains the dimensions needed to do the alignment.        *
*                                                                          *
*   RunLaTeX(fileName)                                                     *
*      Runs LaTeX on fileName.tex.                                         *
*                                                                          *
*   SetDimensions(Token[][])                                               *
*      Sets distFromMargin and preSpace for all the tokens in the spec,    *
*      using the log file produced by LaTeX'ing the alignment file.        *
*                                                                          *
*   WriteLaTeXFile(Token[][])                                              *
*      Writes the final output file for tlatex.TLA.                        *
*                                                                          *
*   WriteTLATeXEnvironment(Token[][], OutputFileWriter)                    *
*      Writes a single tlatex environment for tlatex.TeX.                  *
*                                                                          *
* Note: The methods InnerWriteAlignmentFile and InnerWriteLaTeXFile have   *
* the following bug.  If the user types something like x^2^3, the methods  *
* produce the LaTeX input x^{2}^{3}, which produces a TeX "double          *
* superscript" error.  However, since this is illegal TLA+ and TeX         *
* handles the error appropriately in \batchmode, I have not bothered to    *
* correct this.                                                            *
***************************************************************************/
package tla2tex;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Vector;

import util.ToolIO;


public final class LaTeXOutput
{   
public static void WriteAlignmentFile(Token[][] spec)
  { OutputFileWriter writer = 
         StartLaTeXOutput(Parameters.LaTeXAlignmentFile);
    InnerWriteAlignmentFile(spec, writer, true);
    return;
  }

public static void WriteTeXAlignmentFile(Token[][] spec, 
                                         Vector preamble,
                                         float  linewidth)
  /*************************************************************************
  * Called to write the alignment file for a tlatex environment, where     *
  * preamble is a vector of strings that form the preamble.  The           *
  * alignment file sets \textwidth to the linewidth value, unless          *
  * linewidth <= 0, in which case it uses whatever value the preamble      *
  * sets \textwidth to.                                                    *
  *************************************************************************/
 {OutputFileWriter writer = 
    new OutputFileWriter(Parameters.LaTeXAlignmentFile + ".tex");

  /*************************************************************************
  * Write the \batchmode command to suppress most terminal output.         *
  *************************************************************************/
  writer.putLine("\\batchmode");
  int i = 0 ;
  while (i < preamble.size())
   { writer.putLine((String) preamble.elementAt(i)) ;
     i = i + 1;
   } ;
  if (linewidth >= 0)
   { writer.putLine("\\setlength{\\textwidth}{" 
                     + Misc.floatToString(linewidth, 2) + "pt}");
     // see below for why this is commented out.
     //writer.putLine("\\makeatletter") ;   // added by LL on 7 Aug 2012
   } ;
  writer.putLine("\\begin{document}");
  // We need to put the \makeatletter command after the \begin{document}
  // because it appears that the beamer style and probably others cause
  // the \begin{document} command to reset the catcoding of @ to "other".
  // I don't know why I added the \makeatletter command only if linewidth >=0,
  // which seems to be the case only if the number of environments is different
  // this time than the last time tlatex was run.  However, it seems like 
  // there's no reason not to write the \makeatletter command in that case.
  // Hence the following statement was added by LL on 21 Feb 2013.
  writer.putLine("\\makeatletter"); 

  /*************************************************************************
  * Define \% to have its usual meaning, in case it is redefined by the    *
  * preamble.                                                              *
  *************************************************************************/
  writer.putLine("\\chardef\\%=`\\%");
  InnerWriteAlignmentFile(spec, writer, false) ;
 }

private static void InnerWriteAlignmentFile(Token[][] spec, 
                                            OutputFileWriter writer,
                                            boolean tlaMode)
  /*************************************************************************
  * Writes the body of the file (everything between the \begin{document}   *
  * and \end{document}), plus the \end{document}, for the                  *
  * WriteAlignmentFile method.  Also used to write the body of a tlatex    *
  * environment for the WriteTeXAlignmentFile method.  It is called with   *
  * the tlaMode flag true by WriteLaTeXFile and with it false by           *
  * WriteTLATeXEnvironment.                                                *
  *************************************************************************/
  { int line = 0 ;
      /*********************************************************************
      * line is the current line of the spec being ouput.                  *
      *********************************************************************/

    /***********************************************************************
    * Skip over prolog lines.                                              *
    ***********************************************************************/
    boolean inProlog = true ;
    while (inProlog && (line < spec.length))
       { if (    (spec[line].length > 0)
              && (spec[line][0].type != Token.PROLOG))
           { inProlog = false;}
         else
           { line = line + 1;}
       };

    /***********************************************************************
    * If shading is specified, then we typeset the alignment file with     *
    * LaTeX's shading flag set true--just in case that affects the width   *
    * of comments used in alignments.                                      *
    ***********************************************************************/
    if (Parameters.CommentShading)
     {writer.putLine("\\setboolean{shading}{true}") ;}

    boolean inBeginModule = false ;
      /*********************************************************************
      * True iff we have output the first "----" of                        *
      * "---- MODULE foo ----" but not the second.                         *
      *********************************************************************/

    boolean inSub = false;
         /******************************************************************
         * True while putting out sub/superscript tokens.                  *
         ******************************************************************/
      
    while (line < spec.length)
     { int item = 0 ;
         /******************************************************************
         * item is the current item of the current line.                   *
         ******************************************************************/
         
       String outLine = Parameters.LaTeXStartAlignLine + "{"; ;

       while (item < spec[line].length)
        /*******************************************************************
        * There's no need to produce output for blank lines, so we just    *
        * skip them.                                                       *
        *******************************************************************/
        { 
          Token tok = spec[line][item] ;
            /***************************************************************
            * The current token.                                           *
            ***************************************************************/

          if (inSub && (! tok.subscript))
            { /*************************************************************
              * The current subcript has ended; close the command's "}".   *
              *************************************************************/
              inSub = false ;
              outLine = outLine + "}";
            } ;
               
           if (tok.isAlignmentPoint)
              { outLine = outLine + "}" + Parameters.LaTeXAlignPoint + "{"
                            + line + "}{" + item + "}{" ; 
              };
          switch (tok.type)
           { case Token.BUILTIN :
               int symType = BuiltInSymbols.GetBuiltInSymbol(
                                       spec[line][item].string, true).symbolType ;
                 /**********************************************************
                 * Check if we should start a sub/superscript.             *
                 **********************************************************/
                 if (   (! inSub)
                     && (   (symType == Symbol.SUBSCRIPTED)
                         || tok.string.equals("^"))
                     && (item + 1 < spec[line].length)
                     && spec[line][item+1].subscript )
                        /***************************************************
                        * A subscripted/superscrip symbol (like "]_" or    *
                        * "^") begins a sub/superscript iff it is          *
                        * followed by a subscript token on the same line.  *
                        ***************************************************/
                  { /*******************************************************
                    * This starts a sub or superscript.                    *
                    *******************************************************/
                    inSub = true ;
                    if (symType == Symbol.SUBSCRIPTED)
                     { /****************************************************
                       * It's a subscript.                                 *
                       ****************************************************/
                       outLine = outLine + " " +  
                          BuiltInSymbols.GetBuiltInSymbol(
                                                   tok.string, true).TeXString
                          + "_{";
                     }    
                    else
                     { /****************************************************
                       * It's a superscript.                               *
                       ****************************************************/
                       outLine = outLine + " " + "^{";
                     }    
                  } // END then OF if if (   (! inSub) ... )
                 else
                  { /*******************************************************
                    * Not a sub/superscript.  Output a space followed by   *
                    * the symbol.  (It's always safe to put a space in a   *
                    * specification line, since it's typeset in math       *
                    * mode.                                                *
                    *******************************************************/
                    outLine = outLine + " " +  
                     BuiltInSymbols.GetBuiltInSymbol(tok.string, true).TeXString;
                  }; // END else OF if if (   (! inSub) ... )
               break ;

             case Token.NUMBER :
             case Token.IDENT :
               outLine = outLine + " " + Misc.TeXify(tok.string) ; 
                 /**********************************************************
                 * We TeXify the string to typeset a "\" from a number or  *
                 * a "_" from an identifier.                               *
                 **********************************************************/
               break ;
               
             case Token.PCAL_LABEL :
               outLine = outLine + " " + Misc.TeXifyPcalLabel(tok.string) ;
               break ;

             case Token.STRING :
               outLine = outLine + Parameters.LaTeXStringCommand + "{"  
                           + FixString(tok.string) + "}";
               break ;

             case Token.PF_STEP :
               outLine = outLine + PfStepString(tok.string) ;
               if ( ((Token.PfStepToken) tok).needsSpace )
                 {outLine = outLine + "\\ "; } ;
               break ;

             case Token.COMMENT :
               CommentToken ctok = (CommentToken) tok ;
               switch (ctok.subtype)
                { case CommentToken.ONE_LINE :
                    if (item != 0)
                      /*****************************************************
                      * If the first item is a comment, then it is either  *
                      * a left-comment or else the only token on the       *
                      * line.  If it's a left-comment token, it's going    *
                      * to be typeset with width zero, so we can omit it   *
                      * in the alignment file.  If it's the only token on  *
                      * the line, we don't need to output it in the        *
                      * alignment file.                                    *
                      *****************************************************/
                      { outLine = outLine + "%";
                        Misc.WriteIfNonNull(writer, outLine);
                        outLine = "" ;
                        Vector vec = new Vector(2);
                        vec.addElement(tok.string) ;
                        FormatComments.WriteComment
                         (writer, vec, FormatComments.ONE_LINE, 0, tlaMode) ;
                      };
                    break ;

                  case CommentToken.BEGIN_MULTI :
                  case CommentToken.NULL :
                  case CommentToken.MULTI :
                  case CommentToken.PAR :
                    /*******************************************************
                    * No alignment output is needed for a multi-line       *
                    * comment, which must be at the end of the line.       *
                    *******************************************************/
                    break ;

                  default :
                  Debug.ReportBug(
                     "Bad comment token subtype at position (" 
                         + line + ", " + item + ")\n"
                    + "    in LaTeXOutput.WriteAlignmentFile");

                } ; // END switch (ctok.subtype)
               break ;

             case Token.DASHES :
               if (inBeginModule)
                { /*********************************************************
                  * Ending a "--- MODULE foo ---".                         *
                  *********************************************************/
                  outLine = outLine + "}" + Parameters.LaTeXAlignRightDash 
                              + "{" ;
                  inBeginModule = false ;
                }  // END THEN if (inBeginModule)
               else
                { if (   (item + 1 < spec[line].length)
                       && (spec[line][item+1].string.equals("MODULE")))
                   { /******************************************************
                     * Starting a "--- MODULE foo ---".                    *
                     ******************************************************/
                     outLine = outLine + "}" + 
                                Parameters.LaTeXAlignLeftDash + "{" ;
                     inBeginModule = true ;
                   } // END THEN of if ( (item + 1 < ... ))
                  else
                   { /******************************************************
                     * This is a mid-module dash.                          *
                     ******************************************************/
                     outLine = outLine + "}" + Parameters.LaTeXAlignDash 
                                 + "{" ;
                   } // END ELSE of if ( (item + 1 < ... ))

                } ; // END ELSE if (inBeginModule)
               break ;

             case Token.END_MODULE :
               outLine = outLine + "}" + Parameters.LaTeXAlignEndModule 
                           + "{";
               break ;

             case Token.EPILOG :
               /************************************************************
               * No output needed for an epilog token.                     *
               ************************************************************/
               break ;

             default :
               Debug.ReportBug(
                    "Bad token type at position (" + line + ", " 
                         + item + ")\n"
                  + "    in LaTeXOutput.WriteAlignmentFile");

           };  // END switch (tok.type)

          item = item + 1;
        }; // END while (item < spec[line].length)

       /********************************************************************
       * End the current line.                                             *
       ********************************************************************/
       if (inSub) 
        { /*****************************************************************
          * If inside a sub/superscript, have to close the "^{" or "_{".   *
          *****************************************************************/
          outLine = outLine + "}";
          inSub = false ;
        };         
       outLine = outLine + "}";
       Misc.BreakStringOut(writer, outLine);
       line = line + 1;
     }; // END while (line < spec.length)

    /***********************************************************************
    * End of the specification; end the output file.                       *
    ***********************************************************************/
    writer.putLine("\\end{document}");
    writer.close(); 
  } ;


/* ----------------------------------------------------------------------- */


  private static OutputFileWriter StartLaTeXOutput(String fileName)
  /*************************************************************************
  * Opens writer on the file fileName.tex and writes the beginning of the  *
  * file, through the \begin{document}.                                    *
  *************************************************************************/
  { 
    /***********************************************************************
    * Open the OutputFileWriter.                                           *
    ***********************************************************************/
    OutputFileWriter writer = 
        new OutputFileWriter(prependMetaDirToFileName(fileName) + ".tex");

    /***********************************************************************
    * Write \batchmode and \documentclass commands.  (We use \batchmode    *
    * because (a) we don't want to generate much terminal output, and (b)  *
    * we want TeX to carry on in the face of an error--which should be     *
    * minor.  (In additionb to the problem mentioned at the beginning of   *
    * this file, bad `^...^' input in a comment can produce a LaTeX file   *
    * that generates a TeX error.)                                         *
    ***********************************************************************/
    writer.putLine("\\batchmode %% Suppresses most terminal output.");
    if (Parameters.LaTeXptSize == 10)
      {writer.putLine("\\documentclass{article}");}
    else
      {writer.putLine("\\documentclass[" + Parameters.LaTeXptSize
                                        + "pt]{article}");};
    /***********************************************************************
    * Add commands for making shaded comments only if shading requested.   *
    ***********************************************************************/
    if (Parameters.CommentShading)
      { writer.putLine("\\usepackage{color}") ;
        writer.putLine("\\definecolor{boxshade}{gray}{" + 
                       Parameters.PSGrayLevel + "}") ;
      }

    /***********************************************************************
    * Write commands for setting \textwidth, \textheight, \hoffset, and    *
    * \voffset.                                                            *
    ***********************************************************************/
    writer.putLine(
        "\\setlength{\\textwidth}{" + Parameters.LaTeXtextwidth + "pt}");
    writer.putLine(
        "\\setlength{\\textheight}{" + Parameters.LaTeXtextheight + "pt}");
    if (Parameters.LaTeXhoffset != 0)
      { writer.putLine(
        "\\addtolength{\\hoffset}{" + Parameters.LaTeXhoffset + "pt}");
      } ;
    if (Parameters.LaTeXvoffset != 0)
      { writer.putLine(
        "\\addtolength{\\voffset}{" + Parameters.LaTeXvoffset + "pt}");
      } ;


    /***********************************************************************
    * Either add the LaTeXStyleFile to the beginning of the output, or     *
    * else add a usepackage command to read the user-specified -style      *
    * package.                                                             *
    ***********************************************************************/
    if (Parameters.UserStyleFile.equals(""))
      { ResourceFileReader latexStyleReader 
                     = new ResourceFileReader(Parameters.LaTeXStyleFile);
        CopyResourceFile(latexStyleReader, writer);
      }
    else
      { writer.putLine("\\usepackage{" + Parameters.UserStyleFile + "}");
      } ;

    writer.putLine("\\begin{document}");
    writer.putLine("\\tlatex");
      /*********************************************************************
      * Add a \tlatex command, which causes TeX to do the following:       *
      *   - Make "@" a letter, since some special commands                 *
      *     use "@" in their name.                                         *
      *   - Define \% to its standard meaning.                             *
      *   - Set \parindent to 0.                                           *
      *********************************************************************/
    return writer ;
  }


  private static void CopyResourceFile(ResourceFileReader input, 
                                OutputFileWriter output)
  /*************************************************************************
  * Copies the complete input file to the output file, but does not close  *
  * the output file.                                                       *
  *************************************************************************/
  { 
    String line = input.getLine();
    while (line != null)
      { output.putLine(line) ;
        line = input.getLine() ;
      } ;
    input.close();
  }  


/* ----------------------------------------------------------------------- */


  public static void RunLaTeX(String fileName)
    /***********************************************************************
    * Runs LaTeX on the file fileName.tex.                                 *
    * Modified on 11 November 2001 to call ExecuteCommand.                 *
    ***********************************************************************/
    { String latexCmd = Parameters.LaTeXCommand + " " + fileName + ".tex";
      ExecuteCommand.executeCommand(latexCmd);
    }    


/* ----------------------------------------------------------------------- */


  public static void SetDimensions(Token[][] spec)
  { /***********************************************************************
    * Read the log file and set the distFromMargin fields.                 *
    *                                                                      *
    * First, open log file.                                                *
    ***********************************************************************/
    BufferedReader bufferedReader = null ;
    try 
     { bufferedReader = 
         new BufferedReader(new InputStreamReader(
           new FileInputStream(prependMetaDirToFileName(Parameters.LaTeXAlignmentFile + ".log")))) ;
     }
    catch (FileNotFoundException e)
     { /**************************************************************
       * File fileName could not be found.                           *
       **************************************************************/
       Debug.ReportError(
          "Could not read file " + Parameters.LaTeXAlignmentFile + ".log\n"
        + "    written by LaTeX");
     } ;

   /************************************************************************
   * Next, read log file.                                                  *
   ************************************************************************/
   try 
    { String inputLine = bufferedReader.readLine();

      while (inputLine != null)
       { if (   (inputLine.length() > 2)
             && (inputLine.substring(0,3).equals("\\%{")))
          { int start = 3 ;
            int after = inputLine.indexOf("}",start) ;
            int line  = Integer.parseInt(inputLine.substring(start, after));
            start = after + 2;
            after = inputLine.indexOf("}",start) ;
            int item = Integer.parseInt(inputLine.substring(start, after));
            start = after + 2;
            after = inputLine.indexOf("p",start) ;
            float dist = Misc.stringToFloat(inputLine.substring(start, after));
            spec[line][item].distFromMargin = dist;
          }; // END if (   (inputLine.length() > 2) ... )
         inputLine = bufferedReader.readLine();
       } // END while (inputLine != null)
    }
   catch (IOException e)
    { Debug.ReportError(
         "Error reading file: "  + Parameters.LaTeXAlignmentFile + ".log\n"
       + "    written by LaTeX");
          };

   /************************************************************************
   * Now, set posCols to be a sorted array of all the PosAndCol objects       *
   * corresponding to tokens in the spec.                                  *
   *                                                                       *
   * First compute the dimension of the array.                             *
   ************************************************************************/
   int line = 0 ;
   int arrayLen = 0 ;
   while (line < spec.length)
    { arrayLen = arrayLen + spec[line].length ;
      line = line + 1;
    };
   
   /************************************************************************
   * Next add all PosAndCol objects to the array and sort it.              *
   ************************************************************************/
   PosAndCol[] posCols = new PosAndCol[arrayLen] ;
   int arrayItem = 0 ;
   line = 0 ;
   while (line < spec.length)
    { int item = 0 ;
      while (item < spec[line].length)
       { posCols[arrayItem] = 
             new PosAndCol(line, item, spec[line][item].column) ;
         item = item + 1;
         arrayItem = arrayItem + 1;
       } ;
      line = line + 1;
    } ;   

   Arrays.sort(posCols);

   /************************************************************************
   * Compute preSpace fields for tokens in the order they appear in the    *
   * posCols array.                                                        *
   ************************************************************************/
   /*
    * On 1 Aug 2012, LL made the following observation and change.  The
    * code ignored tok.belowAlign if tok.aboveAlign was specified.  It was
    * possible for both to be specified, so this caused a mis-alignment in
    * rare cases--in particular, if the above alignment didn't move the
    * token far enough to the right to be above or to the right of the token
    * below it that was aligning itself with it.  Therefore, I changed the code 
    * to set preSpace to the maximum of the values computed for an aboveAlignment 
    * and a belowAlignment.
    */
   int nextPos = 0 ;
   while (nextPos < posCols.length)
    { PosAndCol pc = posCols[nextPos] ;
      Token tok = pc.toToken(spec) ;
      Debug.Assert(tok.preSpace == 0,
           "preSpace already computed when it shouldn't have been");
      if (tok.belowAlign.line != -1)
           { /**************************************************************
             * tok begins an inner-alignment.                              *
             **************************************************************/

             /**************************************************************
             * Set maxIndent to the maximum of the current indentation of  *
             * all tokens in the alignment.                                *
             **************************************************************/
             float tokIndent = 
                  TotalIndent(spec, new Position(pc.line, pc.item));
             float maxIndent = tokIndent ;
             Position alPos = tok.belowAlign ;
             while (alPos.line != -1)
              { float f = TotalIndent(spec, alPos);
                if (f > maxIndent) { maxIndent = f; } ;
                alPos = alPos.toToken(spec).belowAlign ;
              } ;

             /**************************************************************
             * Set preSpace to the difference between maxIndent and the    *
             * token's own current indentation.                            *
             **************************************************************/
             tok.preSpace = maxIndent - tokIndent ;

             /**************************************************************
             * Add extra space according to the minimum of the number of   *
             * extra spaces between each token in the alignment and the    *
             * non-left-comment token to its left (if there is one).       *
             * 
               Why is this minimum and not maximum??
               I suspect it's because TotalIndent was set to the maximum
               indent without taking into account the blank columns to
               the left of the token.  Therefore, the token with maximum 
               TotalIndent should have the minimum number of spaces to
               its left--in most cases.
               
             **************************************************************/
             Token ltok = null ;
             int extraSpace = Integer.MAX_VALUE;

             if (   (pc.item > 1)
                 || (   (pc.item == 1)
                     && (spec[pc.line][0].type != Token.COMMENT)))
               { ltok = spec[pc.line][pc.item - 1] ;
                 extraSpace = tok.column - (ltok.column + ltok.getWidth());
               };
             alPos = tok.belowAlign ;
             while (alPos.line != -1)
              { if (   (alPos.item > 1)
                    || (   (alPos.item == 1)
                        && (spec[alPos.line][0].type != Token.COMMENT)))
                  { ltok = spec[alPos.line][alPos.item - 1] ;
                    int sp = alPos.toToken(spec).column 
                                   - (ltok.column + ltok.getWidth());
                    if (sp <  extraSpace) { extraSpace = sp ;};
                  };
                alPos = alPos.toToken(spec).belowAlign ;
              } ;
             if (extraSpace == Integer.MAX_VALUE) {
                 extraSpace = 0 ;
             }
             extraSpace = extraSpace - 1 ;
                     if (extraSpace > 0)
                      { tok.preSpace = tok.preSpace + 
                           Parameters.LaTeXLeftSpace(extraSpace) ; };

           }  // END then OF if (tok.belowAlign != -1)
      if (tok.aboveAlign.line == -1)
           { /**************************************************************
             * tok not aligned.                                            *
             **************************************************************/
             float savedPreSpace = tok.preSpace;
             if (pc.item == 0)
               { /**********************************************************
                 * Left-most token on the line.                            *
                 **********************************************************/
                 tok.preSpace = Parameters.LaTeXLeftSpace(tok.column);
               }
             else
               { if (   (pc.item == 1)
                     && (spec[pc.line][0].type == Token.COMMENT))
                   { /******************************************************
                     * Left-most non-left-comment token on the line.       *
                     ******************************************************/
                     tok.preSpace = Parameters.LaTeXLeftSpace(tok.column)
                                      - spec[pc.line][0].preSpace;
                   }
                 else
                   { /******************************************************
                     * Add extra space for each extra space between this   *
                     * token and the one to its left.                      *
                     ******************************************************/
                     Token ltok = spec[pc.line][pc.item - 1] ;
                     int extraSpace = 
                          tok.column - (ltok.column + ltok.getWidth()) - 1;
                     if (extraSpace > 0)
                      { tok.preSpace = 
                           Parameters.LaTeXLeftSpace(extraSpace) ; };
                   }
               }
              if (tok.preSpace < savedPreSpace) {
                 tok.preSpace = savedPreSpace ;
              }
           }  // END  OF if (tok.belowAlign == -1)
       else
       { /******************************************************************
         * tok aligned with a previous token.                              *
         ******************************************************************/
         float savedPreSpace = tok.preSpace;
               tok.preSpace = 0;  // needed to keep TotalIndent from getting confused
         tok.preSpace =  
                TotalIndent(spec, tok.aboveAlign)
              - TotalIndent(spec, pc)
              + Parameters.LaTeXLeftSpace(
                 tok.column - tok.aboveAlign.toToken(spec).column) ;

         if (tok.preSpace < savedPreSpace) {
             tok.preSpace = savedPreSpace ;
         }
         /**************************************************************
         * If prespace is negative, then something funny has           *
         * happened.  So, we set it to zero.                           *
         **************************************************************/
         if (tok.preSpace < 0) { tok.preSpace = 0;};                  

       } // END else OF if (tok.aboveAlign == -1)
      nextPos = nextPos + 1;
    }; // END while (nextPos < posCols.length)
   
  }; // END public static void SetDimensions


  private static int findInt(String str, int start)
   /************************************************************************
   * Finds the Natural number represented by the string starting at        *
   * str.charAt(start).                                                    *
   ************************************************************************/
   { int nextChar = start;
     while (('0' <= str.charAt(nextChar) ) && (str.charAt(nextChar) <= '9'))
      { nextChar = nextChar + 1; };
     return Integer.parseInt(str.substring(start,nextChar));
   } ;

 
  private static float findFloat(String str, int start)
   /************************************************************************
   * Finds the float represented by the string starting at                 *
   * str.charAt(start).                                                    *
   ************************************************************************/
   { int nextChar = start;
     while (   (('0' <= str.charAt(nextChar) ) && (str.charAt(nextChar) <= '9'))
            || (str.charAt(nextChar) == '.'))
      { nextChar = nextChar + 1; };
     return Misc.stringToFloat(str.substring(start,nextChar));
   } ;

  private static float TotalIndent(Token[][] spec, Position pos)
    /***********************************************************************
    * The total indentation of the token tok at pos, according to the      *
    * current values of the preSpace and distFromMargin fields.  That      *
    * value equals tok.distFromMargin plus the sum of t.preSpace for all   *
    * tokens t to the left of or equal to tok.                             *
    ***********************************************************************/
    { float val = 0 ;
      int item = 0 ;
      while (item <= pos.item)
       { val = val + spec[pos.line][item].preSpace;
         item = item + 1;
       } ;
      return val + pos.toToken(spec).distFromMargin;
    }

  /**
   * Equals TotalIndent(spec, pos) plus the extra space added because of
   * spaces to the left of the token at pos
   * 
   * @param spec
   * @param pos
   * @return
   */
  private static float TotalIndentWithSpace(Token[][] spec, Position pos) {
      int posOfFirstSpaceToLeft = 0;
      if (pos.item > 0) {
          Token tokToLeft = spec[pos.line][pos.item-1] ;
          posOfFirstSpaceToLeft = tokToLeft.column + tokToLeft.getWidth();          
      }
      float spaceToLeft = Parameters.LaTeXLeftSpace(
                           pos.toToken(spec).column - posOfFirstSpaceToLeft - 1) ;
      return spaceToLeft + TotalIndent(spec, pos) ;
  }
  
  private static String FixString(String inputStr)
    /***********************************************************************
    * Result is Misc.TeXify(str) with spaces replaced by "\ " and "-"      *
    * replaced by {-}.                                                     *
    ***********************************************************************/
    { String result = "" ;
      String str = Misc.TeXify(inputStr);
      int pos = 0 ;
      while (pos < str.length())
       { char ch = str.charAt(pos) ;
         if (ch == ' ')
           { result = result + "\\ " ; }
         else 
           { if (ch == '-')
               { result = result + "{-}" ; }
             else
               { result = result + ch ; }
           } ;
         pos = pos + 1 ;
       } ;
      return result ;
    }    

  static String PfStepString(String str) 
    /***********************************************************************
    * Converts the string "<42>ab." to "\@pfstepnum{42}{ab.}"              *
    ***********************************************************************/
    { int leftAnglePos = str.indexOf('>') ;
      return Parameters.LaTeXPfStepNumCommand + "{" +
             str.substring(1, leftAnglePos) + "}{" +
             str.substring(leftAnglePos+1) + "}" ;
    }


/* ----------------------------------------------------------------------- */


public static void WriteLaTeXFile(Token[][] spec)
 { // BEGIN  WriteLaTeXFile(Token[][] spec)
  OutputFileWriter writer = 
         StartLaTeXOutput(Parameters.LaTeXOutputFile);
  InnerWriteLaTeXFile(spec, writer, true);
  writer.putLine("\\end{document}");
  writer.close(); 
  return ;
 }

public static void WriteTLATeXEnvironment(Token[][] spec, 
                                          OutputFileWriter writer)
 { writer.putLine("\\begin{tlatex}");
   InnerWriteLaTeXFile(spec, writer, false);
   writer.putLine("\\end{tlatex}");
 }

private static void InnerWriteLaTeXFile(Token[][] spec, 
                                        OutputFileWriter writer,
                                        boolean tlaMode)
  /*************************************************************************
  * Writes the body of the file (everything between the \begin{document}   *
  * and \end{document} for the WriteLaTeXFile method.  Also used to write  *
  * the body of a tlatex environment for the WriteTLATeXEnvironment        *
  * method.  It is called with the tlaMode flag true by WriteLaTeXFile     *
  * and with it false by WriteTLATeXEnvironment.                           *
  *************************************************************************/
 { // BEGIN  InnerWriteLaTeXFile(Token[][] spec)
  Vector commentVec = new Vector(150);
    /***********************************************************************
    * Used to hold the vector argument to FormatComments.WriteComment.     *
    ***********************************************************************/
  int line = 0 ;
      /*********************************************************************
      * line is the current line of the spec being ouput.                  *
      *********************************************************************/

// Debug.print2DArray(spec, "spec") ;

  /*************************************************************************
  * Skip leading blank lines.                                              *
  *************************************************************************/
  while (   (line < spec.length)
         && (   (spec[line] == null)
             || (spec[line].length == 0)))
   { line = line+1 ;}

  /*************************************************************************
  * Output the prolog, if there is one, and set line, item to the first    *
  * non-prolog token.                                                      *
  *************************************************************************/
  int item = 0 ;
  if (  (line < spec.length)
        && (spec[line][item].type == Token.PROLOG))
   {/***********************************************************************
    * Write the prolog as an unindented PAR comment.                       *
    *                                                                      *
    * First, set commentVec to the vector of prolog lines.                 *
    ***********************************************************************/
    boolean endProlog = false ;
    while (   ! endProlog 
              && (line < spec.length))
     {if  (   (spec[line] == null)
           || (spec[line].length == 0))
       { commentVec.addElement("");
         line = line + 1;
       } 
      else
       {if (spec[line][0].type != Token.PROLOG)
         {endProlog = true ;}
        else
         {commentVec.addElement(spec[line][0].string);
          if (spec[line].length > 1)
           /*********************************************************
           * If a prolog token is followed by a token on the same   *
           * line, then that token is not a prolog token.           *
           *********************************************************/
           {item = 1;
            endProlog = true ;
           }
          else
           {line = line + 1;
           } ;
         };
       };
     } ;                  // END while

    /***********************************************************************
    * Having accumulated the prolog in commentVec, we actually print it    *
    * (as a PAR comment) if the user hasn't specified the -noprolog        *
    * option.                                                              *
    ***********************************************************************/
    if (Parameters.PrintProlog)
      { FormatComments.WriteComment
              (writer, commentVec, FormatComments.PAR, 0, tlaMode);
      } ; 

   };                    // END if ((line < spec.length) ...)
  /***********************************************************************
  * End output prolog lines.                                             *
  ***********************************************************************/

  /***********************************************************************
  * If shading, then set LaTeX's shading flag.                           *
  ***********************************************************************/
  if (Parameters.CommentShading)
    {writer.putLine("\\setboolean{shading}{true}") ;}

  boolean inBeginModule = false ;
    /***********************************************************************
    * True iff we have output the first "----" of "---- MODULE foo ----"   *
    * but not the second.                                                  *
    ***********************************************************************/

  boolean done = false ;

  boolean inSub = false;
    /***********************************************************************
    * True while putting out sub/superscript tokens.                       *
    ***********************************************************************/
 
  boolean hasPcal = TokenizeSpec.hasPcal ;
  int pcalStartLine ;
  int pcalEndLine ;
  if (TokenizeSpec.hasPcal) {
    pcalStartLine = TokenizeSpec.pcalStart.line;
    pcalEndLine   = TokenizeSpec.pcalEnd.line;
  }
  else {
      pcalStartLine = Integer.MAX_VALUE ;
      pcalEndLine   = Integer.MAX_VALUE - 1;
  }
  /***********************************************************************
  * Write out the body and epilog of the specification.                  *
  ***********************************************************************/
  /*
   * pcalLine equals true during the processing of each line of the
   * PlusCalCode iff we are shading comments and hence PlusCal code.
   */
  boolean pcalLine = false;
  while (line < spec.length)
   { // BEGIN while (line < spec.length)

    if (tlaMode && TokenizeSpec.hasPcal) {
      boolean pcalLineNext = ( pcalStartLine <= line && line <= pcalEndLine) ;
      if (pcalLineNext && !pcalLine) {
          writer.putLine("\\pcalsymbolstrue") ;
          if (Parameters.CommentShading && ! Parameters.NoPlusCalShading) {
              writer.putLine("\\pcalshadingtrue") ;
          }
          if (TokenizeSpec.isCSyntax) {
              writer.putLine("\\csyntaxtrue") ;
          }
          else {
              writer.putLine("\\csyntaxfalse") ; 
          }
      }
      if (pcalLine && !pcalLineNext) {
          writer.putLine("\\pcalshadingfalse \\pcalsymbolsfalse") ;
      }
      pcalLine = pcalLineNext ;
    }
        
    if (spec[line].length == 0)
     {                   //  BEGIN then OF if (spec[line].length == 0)
       /********************************************************************
       * Skip over blank lines and write an appropriate \vspace command.   *
       ********************************************************************/
       int blankLines = 0 ;
       while (   (line < spec.length)
              && (spec[line].length == 0))
         { blankLines = blankLines + 1;
           line = line + 1;
         }
//       if (pcalLine) {
//           writer.putLine("\\begin{ppar}%") ;
//       }
       writer.putLine(
         //(  pcalLine2 ? "\\setlength{\\pcalvspace}{" :
        // "\\par\\vspace{" )
         "\\@pvspace{"
         + Misc.floatToString(Parameters.LaTeXVSpace(blankLines), 2) 
         + "pt}%" );
//       if (pcalLine) {
//           writer.putLine("\\end{ppar}%") ;
//       }


     }                   //  END then OF if (spec[line].length == 0)
       
    else
     {                   //  BEGIN else OF if (spec[line].length == 0)

      /*
       * Write "\begin{ppar}%" if this is a PlusCal Line.
       */
//      if (pcalLine) {
//          writer.putLine("\\begin{ppar}%") ;
//      }
      
      /********************************************************************
      * Write out the current line.                                       *
      ********************************************************************/
       Debug.Assert(spec[line].length != 0,
         "LaTeXOutput.WriteLaTeXFile: Unprocessed or unskipped blank line.");
      String outLine = "" ;
  
      boolean openLine = false ;
        /*******************************************************************
        * True iff there is an open LaTeXStartLine or LaTeXContinueLine    *
        * command.                                                         *
        *******************************************************************/
  
  
      boolean issueVSpace = false ;
         /********************************************************************
         * Will be set true if this line and perhaps some following ones     *
         * should be replaced by a LaTeXEndMultiLineVSpace command.          *
         ********************************************************************/
         
      if (   (spec[line][0].type == Token.COMMENT)
          && (   ( ((CommentToken) spec[line][0]).subtype 
                      == CommentToken.MULTI               )
              || ( ((CommentToken) spec[line][0]).subtype 
                      == CommentToken.NULL)               ) )
  
       { // BEGIN if ( (spec[line][0].type == Token.COMMENT) ... )
        /***************************************************************
        * Inside a multi-line comment that starts the line.  If all    *
        * the remaining tokens of the comment start their lines, then  *
        * we must issue a LaTeXEndMultiLineVSpace command.  Note that  *
        * the tokens forming a multi-line comment are doubly-linked    *
        * by belowAlign and aboveAlign pointers.                       *
        ***************************************************************/
        issueVSpace = true ;
        int i = line ;
        boolean endSearch = false ;
        while (   issueVSpace 
               && ( ! endSearch)
               && ( i < spec.length))
         /**************************************************************
         * Invariant: All lines from line through i begin with the     *
         * same multi-line comment.                                    *
         **************************************************************/
         {
          Token bATok = null;
          if (spec[i][0].belowAlign.line != -1)
            { bATok = spec[i][0].belowAlign.toToken(spec) ; } ;
          if (   (spec[i][0].belowAlign.line == -1)
              || (bATok.type != Token.COMMENT)
                   /****************************************************
                   * I think this disjunct should never be true.       *
                   ****************************************************/
              || (   (((CommentToken) bATok).subtype != CommentToken.MULTI)
                  && (((CommentToken) bATok).subtype != CommentToken.NULL)))
           { endSearch = true ;
           }
          else
           { if (spec[i][0].belowAlign.item != 0)
              { issueVSpace = false ;
                endSearch = true ;
              } 
            else
             { i = i + 1;
             };
            } ;
         }; // END while ( issueVSpace ... )
  
       if (issueVSpace)
        { // BEGIN if (issueVSpace)
          /*****************************************************************
          * Have to replace lines line through i by a                      *
          * LaTeXEndMultiLineVSpace command whose argument is the number   *
          * of lines above line in the same comment.                       *
          *****************************************************************/
          int count = line - spec[line][0].aboveAlign.line ;
          writer.putLine(Parameters.LaTeXEndMultiLineVSpace + "{" 
                      + count + "}%");
          line = i ;
          outLine = "";
          openLine = false ;
        }; // END if (issueVSpace)
  
       }; // END if ( (spec[line][0].type == Token.COMMENT) ... )
      if (! issueVSpace)
       { // BEGIN if (! issueVSpace)
  
        /*********************************************************************
        * Start the output line with a LaTeXStartLine command.               *
        *********************************************************************/
        outLine = Parameters.LaTeXStartLine + "{" ; 
//        if (pcalLine2) {
//            outLine = "\\xtest{" ;
//        }
        openLine = true ;

        /*******************************************************************
        * If numbering, then write the line number.                        *
        *******************************************************************/
        if (Parameters.PrintLineNumbers)
          { outLine = outLine 
                      + "\\makebox[0pt][r]{\\scriptsize "
                      + (line + 1) + "\\hspace{1em}}";
          };

        /********************************************************************
        * Append to outLine the output for the tokens on the line.          *
        ********************************************************************/
        while (  (! done) 
              && (item < spec[line].length) )
         { // BEGIN while (   (! done) && (item < spec[line].length)  )
          /*******************************************************************
          * Assertion: outLine has an open LaTeXStartLine or                 *
          * LaTeXContinueLine command.                                       *
          *******************************************************************/
          Debug.Assert(openLine,
               "LaTeXOutput.WriteLaTeXFile: prematurely closed line");
  
          /*****************************************************************
          * Process the current item.                                      *
          *****************************************************************/
          Token tok = spec[line][item] ;
          Position pos = new Position(line, item);
            /***************************************************************
            * The current token and its position.                          *
            ***************************************************************/
  
          if (inSub && (! tok.subscript))
            { /*************************************************************
              * The current subcript has ended; close the command's "}".   *
              *************************************************************/
              inSub = false ;
              outLine = outLine + "}";
            } ;
               
          /*****************************************************************
          * Write the command to produce the preSpace space.               *
          *****************************************************************/
          if (tok.preSpace >= Misc.stringToFloat("0.01"))
            { outLine = outLine + Parameters.LaTeXSpaceCommand + "{"
                          + Misc.floatToString(tok.preSpace,2) + "}";
            } ;
  
          switch (tok.type)
           { // BEGIN switch (tok.type)
             case Token.BUILTIN :
               int symType = BuiltInSymbols.GetBuiltInSymbol(
                                       spec[line][item].string, true).symbolType ;
                 if (   (! inSub)
                     && (   (symType == Symbol.SUBSCRIPTED)
                         || tok.string.equals("^"))
                     && (item + 1 < spec[line].length)
                     && spec[line][item+1].subscript )
                  { /*******************************************************
                    * This starts a sub or superscript.                    *
                    *******************************************************/
                    inSub = true ;
                    if (symType == Symbol.SUBSCRIPTED)
                     { /****************************************************
                       * It's a subscript.                                 *
                       ****************************************************/
                       outLine = outLine + " " +  
                          BuiltInSymbols.GetBuiltInSymbol(
                                                   tok.string, true).TeXString
                          + "_{";
                     }    
                    else
                     { /****************************************************
                       * It's a superscript.                               *
                       ****************************************************/
                       outLine = outLine + " " + "^{";
                     }    
                  } // END then OF if (   (! inSub) ... )
                 else
                  { outLine = outLine + " " +  
                     BuiltInSymbols.GetBuiltInSymbol(tok.string, true).TeXString;
                  }; // END else OF if (   (! inSub) ... )
               break ;
  
             case Token.NUMBER :
               /**************************************************************
               * A number can begin with a '\'.  Won't bother optimizing     *
               * for this special case of TeXify'ing.                        *
               **************************************************************/
               outLine = outLine + " " + Misc.TeXify(tok.string) ; 
               break ;
  
             case Token.IDENT :
               outLine = outLine + " " + Misc.TeXifyIdent(tok.string) ; 
               break ;

             case Token.PCAL_LABEL :
               outLine = outLine + " " + Misc.TeXifyPcalLabel(tok.string) ;
               break ;
               
             case Token.STRING :
               outLine = outLine + Parameters.LaTeXStringCommand + "{"  
                          + FixString(tok.string) + "}";
               break ;
  
             case Token.PF_STEP :
               outLine = outLine + PfStepString(tok.string) ;
               if ( ((Token.PfStepToken) tok).needsSpace )
                 {outLine = outLine + "\\ "; } ;
               break ;

             case Token.COMMENT :
               CommentToken ctok = (CommentToken) tok ;
  
               switch (ctok.subtype)
                { case CommentToken.ONE_LINE :
                    /*********************************************************
                    * Write out the line so far, closing the open            *
                    * LaTeXStartLine or LaTeXContinueLine command, and set   *
                    * outLine to the beginning of a LaTeXContinueLine        *
                    * command.                                               *
                    *********************************************************/

                    /*******************************************************
                    * We're going to call FormatComments.WriteComment to   *
                    * write out the comment, so we have to close the       *
                    * current LaTeXStartLine or LaTeXContinueLine command  *
                    * and write it out, setting outLine to "".             *
                    *******************************************************/
                    Misc.BreakStringOut(writer, outLine + "}%" ) ;
  
  
                    Vector vec = new Vector(2);
                    vec.addElement(tok.string) ;
                    if (   (item == 0)
                        && (spec[line].length > 1))
                      /*****************************************************
                      * If this is a left-comment, then typeset it with    *
                      * width zero.  Otherwise, format it as a one-line    *
                      * comment.  We need to format it as a one-line       *
                      * comment even if it's the only token on the line    *
                      * so the following case will align properly:         *
                      *                                                    *
                      *    xxx (* yyy *)                                   *
                      *        (* yyy *)                                   *
                      *****************************************************/
                      { FormatComments.WriteComment(writer, vec, 
                             FormatComments.ZERO_WIDTH, 0, tlaMode) ;
                      }
                    else
                      { FormatComments.WriteComment(writer, vec, 
                                FormatComments.ONE_LINE, 0, tlaMode) ;
                      }
  
                    /*********************************************************
                    * There may be more to come on the line, so open a       *
                    * LaTeXContinueLine command.                             *
                    *********************************************************/
                    outLine = Parameters.LaTeXContinueLine + "{" ;
                    break ;
  
                  case CommentToken.BEGIN_MULTI :
  
                    /*********************************************************
                    * The comment is going to be typeset so it goes to the   *
                    * right margin.  Set commentWidth to its width, in       *
                    * points.                                                *
                    *********************************************************/
                    float commentWidth = Parameters.LaTeXtextwidth  
                                           - TotalIndent(spec, pos); 
  
                    /*******************************************************
                    * Set mlineVector to the vector of non-NULL lines in   *
                    * the multi-line comment, and set lastLine to the      *
                    * last line of the comment, which may be the NULL      *
                    * line.  (A multi-line need not be ended by a NULL     *
                    * line.)                                               *
                    *******************************************************/
                    Vector mlineVector = new Vector();
                    Position nextPos = ctok.belowAlign;
                    boolean more = true;
                    Token ntok = null;
                    int lastLine = pos.line;
                    while (more && (nextPos.line != -1))
                     { ntok = nextPos.toToken(spec) ;
                       /****************************************************
                       * Change made 10 Nov 2001                           *
                       * I originally had                                  *
                       *                                                   *
                       *   Debug.Assert(ntok.type == Token.COMMENT,        *
                       *       "Non-comment part of multi-line comment."); *
                       *                                                   *
                       * here.  However, if the last line of a multi-line  *
                       * comment isn't a line of *'s, then it could be     *
                       * below-aligned with a non-comment.  So, I added    *
                       * the ntok.type==Token.COMMENT test to the          *
                       * following IF.                                     *
                       ****************************************************/
                       if (   (ntok.type == Token.COMMENT)
                           && (((CommentToken) ntok).subtype == 
                                   CommentToken.MULTI))
                         { mlineVector.addElement(ntok.string) ;
                           lastLine = nextPos.line ;
                           nextPos = ntok.belowAlign;
                         } 
                       else
                         { more = false;
                         } ;
                     } ;
                    if (   (nextPos.line != -1)
                        && (ntok.type == Token.COMMENT)
                        && (((CommentToken) ntok).subtype == CommentToken.NULL))
                      { lastLine = nextPos.line; 
                      } ;
  
                    /*******************************************************
                    * Set parMulti true iff there is no token to the left  *
                    * of any line in the multi-line comment.               *
                    *******************************************************/
                    boolean parMulti = true ;
                    Position cPos = pos ;
                    while ( parMulti && (cPos.line < lastLine) )
                     { parMulti = (cPos.item == 0) ;
                       cPos = cPos.toToken(spec).belowAlign ;
                     } ;
                    parMulti = parMulti && (cPos.item == 0) ;
  
                    /*******************************************************
                    * Write out the comment.                               *
                    *******************************************************/
                    if (parMulti)
                      { /***************************************************
                        * There's nothing to the left of this comment.     *
                        * Just delete the current LaTeXStartLine command   *
                        * and write out the comment as a PAR comment.      *
                        ***************************************************/
                       outLine = "" ;
                       openLine = false ;
                       FormatComments.WriteComment(writer, mlineVector,
                            FormatComments.PAR, TotalIndent(spec, pos), 
                            tlaMode);
                       line = lastLine ;
                      }
                    else
                      { /***************************************************
                        * There's something to the left of the comment.    *
                        * Write out the beginning of the line and then     *
                        * write the comment.                               *
                        ***************************************************/
                        Misc.BreakStringOut(writer, outLine + "}%" ) ;
                        outLine = "" ;
                        openLine = false ;
                        FormatComments.WriteComment(writer, mlineVector,
                             FormatComments.RIGHT_MULTI, commentWidth, 
                             tlaMode) ;
                      } ;
  
                    break ;
  
                  case CommentToken.NULL :
                  case CommentToken.MULTI :
                    /*******************************************************
                    * All subsequent lines of a multi-line comment were      *
                    * output with the BEGIN_MULTI line.  This is the last    *
                    * token on the line, so there's no need to open a        *
                    * LaTeXContinueLine command.                             *
                    *******************************************************/
                    break ;
  
                  case CommentToken.PAR :
                    /*******************************************************
                    * This is the only token on the line, so we can        *
                    * delete the LaTeXStartLine command.                   *
                    *******************************************************/
                    outLine = "" ;
                    openLine = false ;
                    
                    /*******************************************************
                    * Set lineVector to the vector of lines in the         *
                    * multi-line comment, and skip over all its lines.     *
                    *******************************************************/
                    Debug.Assert(outLine.equals(""),
                      "Non-empty outLine at beginning of PAR comment");
  
                    Vector lineVector = new Vector();

                    /*******************************************************
                    * Add tok.column + 2 spaces to beginning of first      *
                    * line.                                                *
                    *******************************************************/
                    String spaces = "  ";
                    int j = 0 ;
                    while (j < tok.column)
                      { spaces = spaces + " ";
                        j = j + 1;
                      } ;
                    
                    lineVector.addElement(spaces + tok.string) ;
                    while (   (line + 1 < spec.length)
                           && (   (spec[line + 1].length == 0)
                               || (   (spec[line + 1][0].type == 
                                          Token.COMMENT)
                                   && (((CommentToken) 
                                              spec[line + 1][0]).subtype 
                                         == CommentToken.PAR))))
  
                     { if (spec[line + 1].length == 0)
                         { lineVector.add("");}
                       else 
                         { lineVector.add(spec[line + 1][0].string);};
                       line = line + 1;
                     } ;
                    

                    /*******************************************************
                    * Write out lineVector.                                *
                    *******************************************************/
                    FormatComments.WriteComment
                       (writer, lineVector, FormatComments.PAR, -2, tlaMode) ;
  
                    break ;
  
                  default :
                  Debug.ReportBug(
                     "Bad comment token subtype at position (" 
                         + line + ", " + item + ")\n"
                    + "    in LaTeXOutput.WriteAlignmentFile");
  
                } ; // END switch (ctok.subtype)
               break ;
  
             case Token.DASHES :
               if (inBeginModule)
                { /*********************************************************
                  * Ending a "--- MODULE foo ---".                         *
                  *********************************************************/
                  outLine = outLine + "}" + Parameters.LaTeXRightDash 
                              + "{" ;
                  inBeginModule = false ;
                }  // END THEN if (inBeginModule)
               else
                { if (   (item + 1 < spec[line].length)
                       && (spec[line][item+1].string.equals("MODULE")))
                   { /******************************************************
                     * Starting a "--- MODULE foo ---".                    *
                     ******************************************************/
                     outLine = outLine + "}" + 
                                 Parameters.LaTeXLeftDash + "{" ;
                     inBeginModule = true ;
                   } // END THEN of if ( (item + 1 < ... ))
                  else
                   { /******************************************************
                     * This is a mid-module dash.                          *
                     ******************************************************/
                     outLine = outLine + "}" + Parameters.LaTeXDash 
                                   + "{" ;
                   } // END ELSE of if ( (item + 1 < ... ))
  
                } ; // END ELSE if (inBeginModule)
               break ;
  
             case Token.END_MODULE :
               outLine = outLine + "}" + Parameters.LaTeXEndModule 
                           + "{" ;
               break ;
  
             case Token.EPILOG :
               /************************************************************
               * The epilog is written as an unshaded PAR comment.         *
               ************************************************************/

               /************************************************************
               * If there has been other output for this line, we must     *
               * close the LaTeXStartLine or LaTeXContinueLine command     *
               * and write out the line.  Otherwise, we just delete the    *
               * LaTeXStartLine command.                                   *
               ************************************************************/
               if (item != 0)
                { Misc.BreakStringOut(writer, outLine + "}%");
                  line = line + 1;
                    /*******************************************************
                    * We throw away an EPILOG token to the right of the    *
                    * "======" that ends the module.  It doesn't seem to   *
                    * be worth the effort of figuring out what to do with  *
                    * it, and it's highly unlikely that someone            *
                    * intentionally typed something on the same line as    *
                    * the "=====".  The extra token probably consists      *
                    * only of spaces.                                      *
                    *******************************************************/
                } ;
               outLine = null ;
               openLine = false;

               if (Parameters.PrintEpilog)
                 { writer.putLine("\\setboolean{shading}{false}");
                     /******************************************************
                     * Turn off shading for the epilog.                    *
                     ******************************************************/
  
                   /********************************************************
                   * Print the epilog like a PAR comment.                  *
                   ********************************************************/
                   Vector lineVector = new Vector() ;
                   while (line < spec.length)
                    { if (spec[line].length == 0)
                       { lineVector.addElement(""); }
                      else
                       { lineVector.addElement(spec[line][0].string);};
                      line = line + 1;
                    } ;
  
                   FormatComments.WriteComment
                     (writer, lineVector, FormatComments.PAR, 0, tlaMode);
                 }
               done = true ;
               break ;
  
             default :
               Debug.ReportBug(
                    "Bad token type at position (" + line + ", " 
                         + item + ")\n"
                  + "    in LaTeXOutput.WriteLaTeXFile");
           };  // END switch (tok.type)
  
          item = item + 1 ;
         };                // END while ((! done) && (item < spec[line].length))
       };                 // END if (! issueVSpace)
  
      if (inSub) 
       { /*****************************************************************
         * If inside a sub/superscript, have to close the "^{" or "_{".   *
         *****************************************************************/
         Debug.Assert(outLine != null,
                         "Unclosed sub/superscript command at end of line") ;
         outLine = outLine + "}";
         inSub = false ;
       };         
  
      if (openLine)
       /******************************************************************
       * openLine has been set to false if the line has already been     *
       * written out.                                                    *
       ******************************************************************/
       { Misc.BreakStringOut(writer, outLine + "}%");
       } ;
      
       /*
        * Write "\end{ppar}%" if this is a PlusCal Line.
        */
//       if (pcalLine) {
//           writer.putLine("\\end{ppar}%") ;
//       }

      outLine = "" ;
      item = 0 ;
      line = line + 1;
     }                 // END else OF if (spec[line].length == 0)
    
   };                // END while (line < spec.length)
} ;

protected static String prependMetaDirToFileName(String fileName) {
    String outputFileName = fileName;
    if (! Parameters.MetaDir.equals("")) {
        outputFileName = Parameters.MetaDir + File.separator + outputFileName;
    }
ToolIO.out.println("looking for file: " + outputFileName);
    return outputFileName;
}
	
}

/* last modified on Wed 19 Sep 2007 at  6:15:07 PST by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/compare/ResourceNameComparator.java<|end_filename|>
package org.lamport.tla.toolbox.util.compare;

import java.util.Comparator;

import org.eclipse.core.resources.IResource;

/**
 * Compare resources based on the name, ignoring the case
 * @author <NAME>
 * @version $Id$
 */
public class ResourceNameComparator implements Comparator<IResource>
{

	/* (non-Javadoc)
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 */
	public int compare(IResource o1, IResource o2) {
		return o1.getName().compareToIgnoreCase(o2.getName());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/module/Integers.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Sat 23 February 2008 at  9:52:48 PST by lamport
//      modified on Thu Jan  4 21:06:47 PST 2001 by yuanyu

package tlc2.module;

import tlc2.output.EC;
import tlc2.tool.EvalException;
import tlc2.tool.impl.TLARegistry;
import tlc2.value.IBoolValue;
import tlc2.value.ValueConstants;
import tlc2.value.Values;
import tlc2.value.impl.BoolValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.ModelValue;
import tlc2.value.impl.UserObj;
import tlc2.value.impl.UserValue;
import tlc2.value.impl.Value;

public class Integers extends UserObj implements ValueConstants
{
	public static final long serialVersionUID = 20160822L;

    static
    {
		// The following entries in TLARegistry each define a mapping from a TLA+ infix
		// operator to a Java method, e.g. the TLA+ infix operator "+" is mapped to and
		// thus implemented by the Java method tlc2.module.Integers.Plus(IntValue,
		// IntValue) below.
    	//TODO Why does tlc2.module.Naturals define identical mappings?
        TLARegistry.put("Plus", "+");
        TLARegistry.put("Minus", "-");
        TLARegistry.put("Times", "*");
        TLARegistry.put("LT", "<");
        TLARegistry.put("LE", "\\leq");
        TLARegistry.put("GT", ">");
        TLARegistry.put("GEQ", "\\geq");
        TLARegistry.put("DotDot", "..");
        TLARegistry.put("Neg", "-.");
        TLARegistry.put("Divide", "\\div");
        TLARegistry.put("Mod", "%");
        TLARegistry.put("Expt", "^");
    }

    private static final Value SetInt = new UserValue(new Integers());

    public static Value Int()
    {
        return SetInt;
    }

    public static Value Nat()
    {
        return Naturals.Nat();
    }

    public static IntValue Plus(IntValue x, IntValue y)
    {
        return Naturals.Plus(x, y);
    }

    public static IntValue Minus(IntValue x, IntValue y)
    {
        return Naturals.Minus(x, y);
    }

    public static IntValue Times(IntValue x, IntValue y)
    {
        return Naturals.Times(x, y);
    }

    public static IBoolValue LT(Value x, Value y)
    {
        if (!(x instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "first", "<", "integer",
                    Values.ppr(x.toString()) });
        }
        if (!(y instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "second", "<", "integer",
                    Values.ppr(y.toString()) });
        }

        return (((IntValue) x).val < ((IntValue) y).val) ? BoolValue.ValTrue : BoolValue.ValFalse;
    }

    public static IBoolValue LE(Value x, Value y)
    {
        if (!(x instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "first", "<=", "integer",
                    Values.ppr(x.toString()) });
        }
        if (!(y instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "second", "<=", "integer",
                    Values.ppr(y.toString()) });
        }

        return (((IntValue) x).val <= ((IntValue) y).val) ? BoolValue.ValTrue : BoolValue.ValFalse;
    }

    public static BoolValue GT(Value x, Value y)
    {
        if (!(x instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "first", ">", "integer",
                    Values.ppr(x.toString()) });
        }
        if (!(y instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "second", ">", "integer",
                    Values.ppr(y.toString()) });
        }

        return (((IntValue) x).val > ((IntValue) y).val) ? BoolValue.ValTrue : BoolValue.ValFalse;
    }

    public static IBoolValue GEQ(Value x, Value y)
    {
        if (!(x instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "first", ">=", "integer",
                    Values.ppr(x.toString()) });
        }
        if (!(y instanceof IntValue))
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR_AN, new String[] { "second", ">=", "integer",
                    Values.ppr(y.toString()) });
        }

        return (((IntValue) x).val >= ((IntValue) y).val) ? BoolValue.ValTrue : BoolValue.ValFalse;
    }

    public static IntervalValue DotDot(IntValue x, IntValue y)
    {
        return new IntervalValue(x.val, y.val);
    }

    public static IntValue Neg(IntValue x)
    {
        int n = x.val;
        if (n == -2147483648)
        {
            throw new EvalException(EC.TLC_MODULE_OVERFLOW, "--2147483648");
        }
        return IntValue.gen(0 - n);
    }

    public static IntValue Divide(IntValue x, IntValue y)
    {
        if (y.val == 0)
        {
            throw new EvalException(EC.TLC_MODULE_DIVISION_BY_ZERO);
        }
        if (x.val == -2147483648 && y.val == -1)
        {
            throw new EvalException(EC.TLC_MODULE_OVERFLOW, "-2147483648 \\div -1");
        }
        int n1 = x.val;
        int n2 = y.val;
        int q = n1 / n2;
        if ((((n1 < 0) && (n2 > 0)) || ((n1 > 0) && (n2 < 0))) && (q * y.val != x.val))
        {
            q--;
        }
        return IntValue.gen(q);
    }

    public static IntValue Mod(IntValue x, IntValue y)
    {
        if (y.val <= 0)
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "%", "positive number",
                    y.toString() });
        }
        int r = x.val % y.val;
        return IntValue.gen(r < 0 ? (r + y.val) : r);
    }

    public static IntValue Expt(IntValue x, IntValue y)
    {
        if (y.val < 0)
        {
            throw new EvalException(EC.TLC_MODULE_ARGUMENT_ERROR, new String[] { "second", "^", "natural number",
                    y.toString() });
        }
        if (y.val == 0)
        {
            if (x.val == 0)
            {
                throw new EvalException(EC.TLC_MODULE_NULL_POWER_NULL);
            }
            return IntValue.ValOne;
        }
        long res = x.val;
        for (int i = 1; i < y.val; i++)
        {
            res *= x.val;
            if (res < -2147483648 || res > 2147483647)
            {

                throw new EvalException(EC.TLC_MODULE_OVERFLOW, x.val + "^" + y.val);
            }
        }
        return IntValue.gen((int) res);
    }

    @Override
    public final int compareTo(Value val)
    {
        if (val instanceof UserValue)
        {
            if (((UserValue) val).userObj instanceof Integers)
            {
                return 0;
            }
            if (((UserValue) val).userObj instanceof Naturals)
            {
                return 1;
            }
        }
        if (val instanceof ModelValue)
            return 1;
        throw new EvalException(EC.TLC_MODULE_COMPARE_VALUE, new String[] { "Int", Values.ppr(val.toString()) });
    }

    @Override
    public final boolean member(Value val)
    {
        if (val instanceof IntValue)
            return true;
        if (val instanceof ModelValue)
        {
            return ((ModelValue) val).modelValueMember(this);
        }
        throw new EvalException(EC.TLC_MODULE_CHECK_MEMBER_OF, new String[] { Values.ppr(val.toString()), "Int" });
    }

    @Override
    public final boolean isFinite()
    {
        return false;
    }

    @Override
    public final StringBuffer toString(StringBuffer sb, int offset, boolean swallow)
    {
        return sb.append("Int");
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/property/GenericSelectionProvider.java<|end_filename|>
package org.lamport.tla.toolbox.ui.property;

import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;

/**
 * Generic implementation of the ISelectionProvider
 * @author <NAME>
 * @version $Id$
 */
public class GenericSelectionProvider implements ISelectionProvider
{
    private ListenerList selectionChangedListeners = new ListenerList();
    private ISelection selection = null;
    

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
     */
    public ISelection getSelection()
    {
        return this.selection;
    }


    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
     */
    public void setSelection(ISelection selection)
    {
        this.selection = selection;
        fireSelectionChanged(new SelectionChangedEvent(this, selection));
    }

    
    /**
     * Notifies any selection changed listeners that the viewer's selection has changed.
     * Only listeners registered at the time this method is called are notified.
     *
     * @param event a selection changed event
     *
     * @see ISelectionChangedListener#selectionChanged
     */
    protected void fireSelectionChanged(final SelectionChangedEvent event) {
        Object[] listeners = selectionChangedListeners.getListeners();
        for (int i = 0; i < listeners.length; ++i) {
            final ISelectionChangedListener listener = (ISelectionChangedListener) listeners[i];
            SafeRunnable.run(new SafeRunnable() {
                public void run() {
                    listener.selectionChanged(event);
                }
            });
        }
    }
    
    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void addSelectionChangedListener(ISelectionChangedListener listener)
    {
        selectionChangedListeners.add(listener);
    }
    
    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    public void removeSelectionChangedListener(ISelectionChangedListener listener)
    {
        selectionChangedListeners.remove(listener);
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2tex/Position.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.

/***************************************************************************
* CLASS Position                                                           *
*                                                                          *
* A Position object has two fields, line and item, that identify a token   *
* in a tokenized spec object.  That is, the object                         *
*                                                                          *
*    [line |-> ln, item -> it]                                             *
*                                                                          *
* identifies item number it on line number ln.  (All numbering is from 0,  *
* a la Java.)  The Position                                                *
*                                                                          *
*    [line |-> -1, item -> 0]                                              *
*                                                                          *
* denotes a mythical token on the line preceding the spec.                 *
*                                                                          *
* A Position object has the method toToken(spec), which returns the        *
* token at that position in the tokenized spec.                            *
*                                                                          *
* Note: The toToken method causes an error if called with the token with   *
* line = -1.  It would simplify the program if, instead, it returned a     *
* dummy token with special type NOT_A_TOKEN.  This would eliminate a       *
* number of "line != -1" tests before calling this method.                 *
***************************************************************************/
package tla2tex;

public class Position
  { public int line = -1 ;
    public int item = 0  ;

    Position() { } ;

    Position(int line, int item) 
      {this.line = line ;
       this.item = item ;
      };

    public Token toToken(Token[][] spec)
      { Debug.Assert(   (line < spec.length) 
                     && (line >= 0) 
                     && (item < spec[line].length),
                     "toToken method of Position called with bad object");
        return spec[line][item];
      };

    public boolean equals(Position pos) {
          return (this.line == pos.line) && (this.item == pos.item) ; 
      }


    public String toString()     
      /*********************************************************************
      * Represents a Position as a (line, item) pair.                      *
      *********************************************************************/
      { if (line == -1) 
          { return "nil" ;}
        return "(" + line + ", " + item +")" ;
      } ;
  }

/* last modified on Thu 18 Aug 2005 at 22:12:43 UT by lamport */


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tla2tex/src/org/lamport/tla/toolbox/tool/tla2tex/TLA2TeXActivator.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tla2tex;

import java.io.File;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.lamport.tla.toolbox.AbstractTLCActivator;
import org.lamport.tla.toolbox.tool.tla2tex.preference.ITLA2TeXPreferenceConstants;
import org.osgi.framework.BundleContext;

import com.abstratt.graphviz.GraphVizActivator;
import com.abstratt.graphviz.GraphVizActivator.DotMethod;

/**
 * The activator class controls the plug-in life cycle
 */
public class TLA2TeXActivator extends AbstractTLCActivator {
    // The plug-in ID
    public static final String PLUGIN_ID = "org.lamport.tla.toolbox.tool.tlatex";

    private static final boolean IS_WINDOWS = Platform.OS_WIN32.equals(Platform.getOS());
    private static final String USR_LOCAL_BIN_PATH = "/usr/local/bin/dot";
    
    // The shared instance
    private static TLA2TeXActivator plugin;

	// Listen to preference changes in the TLA2TexPreferencePage. If the value for
	// dot command changes, we send the update to the GraphViz preference store.
	// GraphViz reads the value from its own store instead of ours.
    // Alternatively, we could instantiate GraphViz's own preference page, which
    // writes to GraphViz's preference store. However, we don't want to clutter
    // the Toolbox's preference with a dedicate GraphViz page.
    //  <page
    //    category="toolbox.ui.preferences.GeneralPreferencePage"
    //    class="com.abstratt.graphviz.ui.GraphVizPreferencePage"
    //    id="toolbox.ui.preferences.StateGraphPreferences"
    //    name="State Graph">
    // </page>
	private IPropertyChangeListener listener = new IPropertyChangeListener() {
		public void propertyChange(PropertyChangeEvent event) {
			if (ITLA2TeXPreferenceConstants.DOT_COMMAND.equals(event.getProperty())) {
				configureGraphViz((String)event.getNewValue());
			}
		}
	};

    /**
     * The constructor
     */
    public TLA2TeXActivator() {
    	super(PLUGIN_ID);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
        
		final IPreferenceStore preferenceStore = getPreferenceStore();
		preferenceStore.addPropertyChangeListener(listener);
		configureGraphViz(preferenceStore.getString(ITLA2TeXPreferenceConstants.DOT_COMMAND));
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext context) throws Exception
    {
        plugin = null;
        super.stop(context);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static TLA2TeXActivator getDefault()
    {
        return plugin;
    }
    
    private void configureGraphViz(final String dotLocationPreferenceValue) {
    	// This will be blank if the user has never entered a value in the preference panel
		String dotCommand = dotLocationPreferenceValue;
		
		// Per GitHub #412
		if (!IS_WINDOWS
					&& ((dotCommand == null)
							|| (dotCommand.trim().length() == 0)
							|| "dot".equals(dotCommand))) {
			final File f = new File(USR_LOCAL_BIN_PATH);
			
			if (f.exists() && f.canExecute()) {
				dotCommand = USR_LOCAL_BIN_PATH;
			}
		}
		
		if ("dot".equals(dotCommand)) {
			// Setting it to "dot" implies auto lookup.
			logInfo("dot command set to automatic lookup.");
			GraphVizActivator.getInstance().setDotSearchMethod(DotMethod.AUTO);
		} else {
			// Explicit path is given.
			logInfo("dot command set to: " + dotCommand);
			GraphVizActivator.getInstance().setDotSearchMethod(DotMethod.MANUAL);
			GraphVizActivator.getInstance().setManualDotPath(dotCommand);
		}
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TLCSequenceVariableValue.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.List;

public class TLCSequenceVariableValue extends TLCVariableValue implements TLCMultiVariableValue {

    private static final String[] DELIMETERS = { "<<", ",", ">>" };

    /*
     * Need to keep the following two values as arrays of objects 
     * rather than computing them afresh because those objects
     * can be stored in the HashSets that determine highlighting of an
     * error trace.  
     */
    /**
     * The list of sequence values represented as function elements
     * 1 :> v1, 2 :> v2, ... .  We return these as the sequence's children 
     * because that allows them to be displayed in the error trace in a 
     * more useful way.
     */
    private TLCFcnElementVariableValue[] elements;

    /**  
     * The list of values of the sequence elements.
     */
    private TLCVariableValue[] elementValues;
    
    TLCSequenceVariableValue(List values)
    {
        this.value = values;
        this.elements = this.innerGetElements();
        elementValues = new TLCVariableValue[elements.length];
        for (int i = 0; i < elements.length; i++) {
            elementValues[i] = (TLCVariableValue) elements[i].getValue();
        }
    }

    public Object getValue()
    {
        return getElements();
    }

    public TLCFcnElementVariableValue[] getElements() {
        return elements;
    }
 
 
    private TLCFcnElementVariableValue[] innerGetElements() {
        List list = (List) value;

        TLCFcnElementVariableValue[] result = new TLCFcnElementVariableValue[list.size()];
        for (int i = 0; i < result.length; i++)
        {
            result[i] = new TLCFcnElementVariableValue(new TLCSimpleVariableValue("" + (i + 1)),
                    (TLCVariableValue) list.get(i));
        }
        return result;
    }


    public String toSimpleString()
    {
        // Changed from using elements to using elementValues on 26 Oct 2009
        // so we don't print the "1:>", "2:>", ...
        return arrayToSimpleStringBuffer(elementValues, DELIMETERS).toString();
    }

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCMultiVariableValue#asList()
	 */
	public List<TLCVariableValue> asList() {
		return (List<TLCVariableValue>) this.value;
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue#innerDiff(org.lamport.tla.toolbox.tool.tlc.output.data.TLCVariableValue)
	 */
	protected void innerDiff(TLCVariableValue other) {
		/*
		 * SEQUENCES In general, it's not clear how differences between two
		 * sequences should be highlighted. We adopt the following
		 * preliminary approach: If one sequence is a proper initial prefix
		 * or suffix of the other, then the difference is interpreted as
		 * adding or deleting the appropriate sequence elements. Otherwise,
		 * the sequences are treated as functions.
		 * 
		 * Note: If one sequence is both an initial prefix and a suffix of
		 * the other then we give preference to interpreting the operation
		 * as adding to the end or removing from the front.
		 */
		if (!(other instanceof TLCSequenceVariableValue)) {
			return;
		}
		TLCFcnElementVariableValue[] firstElts = this.getElements();
		TLCFcnElementVariableValue[] secondElts = ((TLCSequenceVariableValue) other).getElements();
		if (firstElts.length == secondElts.length) {
			setFcnElementArrayDiffInfo(firstElts, secondElts);
			return;
		}

		TLCFcnElementVariableValue[] shorter = firstElts;
		TLCFcnElementVariableValue[] longer = secondElts;
		boolean firstShorter = true;
		if (firstElts.length > secondElts.length) {
			longer = firstElts;
			shorter = secondElts;
			firstShorter = false;
		}
		boolean isPrefix = true;
		for (int i = 0; i < shorter.length; i++) {
			if (!((TLCVariableValue) shorter[i].getValue()).toSimpleString()
					.equals(((TLCVariableValue) longer[i].getValue()).toSimpleString())) {
				isPrefix = false;
				break;
			}
		}
		boolean isSuffix = true;
		for (int i = 0; i < shorter.length; i++) {
			if (!((TLCVariableValue) shorter[i].getValue()).toSimpleString().equals(
					((TLCVariableValue) longer[i + longer.length - shorter.length].getValue()).toSimpleString())) {

				isSuffix = false;
				break;
			}
		}
		/*
		 * If it's both a prefix and a suffix, we interpret the change as
		 * either adding to the end or deleting from the front. If it's
		 * neither, we treat the sequences as functions.
		 */
		if (isPrefix && isSuffix) {
			if (firstShorter) {
				isSuffix = false;
			} else {
				isPrefix = false;
			}
		} else if (!(isPrefix || isSuffix)) {
			setFcnElementArrayDiffInfo(firstElts, secondElts);
			return;
		}
		
        /*
         * There are four cases: isPrefix and firstShorter : we mark end of
         * longer (= second) as added. isPrefix and !firstShorter : we mark
         * end of longer (= first) as deleted. isSuffix and firstShorter :
         * we mark beginning of longer (=second) as added. isSuffix and
         * !firstShorter : we mark beginning of longer (=first) as deleted.
         */
		final int firstEltToMark = (isPrefix) ? shorter.length : 0;

		for (int i = 0; i < longer.length - shorter.length; i++) {
			final TLCVariableValue value = (TLCVariableValue) longer[i + firstEltToMark].value;
			if (firstShorter) {
				value.setAdded();
			} else {
				value.setDeleted();
			}
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalDebug.java<|end_filename|>
package pcal;

import java.util.Vector;

import pcal.exception.UnrecoverableException;
import pcal.exception.UnrecoverablePositionedException;
import util.ToolIO;

/***************************************************************************
* This class provides methods called when an error is encountered,         
* methods for printing debugging output, and methods for measuring and     
* reporting elapsed time.                                                  
* @author <NAME>
* @version $Id$
***************************************************************************/
public class PcalDebug
{
    public static final String UNRECOVERABLE_ERROR = "\nUnrecoverable error:\n -- ";
    public static final String WARNING = "Warning: ";
    public static final String ERROR_POSTFIX = ".\n";

    /**
     * Printer for the exceptions
     * @param exception containing the message to print
     */
    public static void reportError(UnrecoverableException e)
    {
        if (e instanceof UnrecoverablePositionedException)
        {
            reportError(e.getMessage(), ((UnrecoverablePositionedException) e).getPosition());
        } else
        {
            reportError(e.getMessage());
        }
    };

    /**
     * Reports a warning 
     * @param warningText text to be reported
     */
    public static void reportWarning(String warningText)
    {
        ToolIO.out.println(new StringBuffer(WARNING).append(warningText));
    }

    /**
     * Reports a information for the user
     * @param infoText text to be reported
     */
    public static void reportInfo(String infoText)
    {
        ToolIO.out.println(infoText);
    }

    /**
     * Report error message 
     * @param message message to report
     */
    public static void reportError(String message)
    {
        ToolIO.out.println(new StringBuffer(UNRECOVERABLE_ERROR).append(message).append(ERROR_POSTFIX).toString());
    }

    /**
     * Reports an error
     * @param message message to report
     * @param ast the AST-object identifying the error location
     */
    public static void reportError(String message, AST ast)
    {
        if (ast == null || ast.line == 0)
        {
            reportError(message);
        } else {
            reportError(message + "\n    at " + ast.location());
        }
    }

    public static void Assert(boolean val)
    /*********************************************************************
    * Why doesn't java provide an Assert statement?                      *
    *********************************************************************/
    {
        if (!val)
        {
            ReportBug("Assertion failure");
        }
        ;
    };

    public static void Assert(boolean val, String msg)
    /*********************************************************************
    * An Assert with an error message.                                   *
    *********************************************************************/
    {
        if (!val)
        {
            ReportBug("Failure of assertion: " + msg);
        }
        ;
    };

    public static void ReportBug(String msg)
    /*********************************************************************
    * This method is called to report a bug in the program and abort.    *
    *********************************************************************/
    {
    	final StringBuilder sb = new StringBuilder("You have discovered a bug in pcal.trans.\n");
        sb.append("Send the following information and the\ninput file to the current maintainer(s).\n\n -- ");
        sb.append(msg).append(".");
    	
        ToolIO.out.println("");
        ToolIO.out.println(sb.toString());
        ToolIO.out.println("");
        
        throw new Error(sb.toString());
    };

    public static void printObjectArray(Object[] array, String name)
    /*********************************************************************
    * This method prints to standard output the contents of the array    *
    * argument, where name is the name of the array.                     *
    *********************************************************************/
    {
        if (array == null)
        {
            ToolIO.out.println(name + " == null");
            return;
        }
        ;
        int i = 0;
        while (i < array.length)
        {
            if (array[i] == null)
            {
                ToolIO.out.println(name + "[" + i + "] = null");
            } else
            {
                ToolIO.out.println(name + "[" + i + "] = " + array[i].toString());
            }
            i = i + 1;
        }
        ;
        if (array.length == 0)
        {
            ToolIO.out.println(name + " = zero-length array");
        }
        ;
    };

    public static void printIntArray(int[] array, String name)
    /*********************************************************************
    * This method prints to standard output the contents of the array    *
    * argument, where name is the name of the array.                     *
    *********************************************************************/
    {
        if (array == null)
        {
            ToolIO.out.println(name + " == null");
            return;
        }
        ;
        int i = 0;
        while (i < array.length)
        {
            ToolIO.out.println(name + "[" + i + "] = " + array[i]);
            i = i + 1;
        }
        ;
        if (array.length == 0)
        {
            ToolIO.out.println(name + " = zero-length array");
        }
        ;
    };

    public static void print2DArray(Object[][] array, String name)
    /*********************************************************************
    * This method prints to standard output the contents of the array    *
    * argument, where name is the name of the array.                     *
    *********************************************************************/
    {
        if (array == null)
        {
            ToolIO.out.println(name + " == null");
            return;
        }
        ;
        int i = 0;
        while (i < array.length)
        {
            int j = 0;
            while (j < array[i].length)
            {
                ToolIO.out.println(name + "[" + i + "][" + j + "] = " + array[i][j].toString());
                j = j + 1;
            }
            ;
            if (array[i].length == 0)
            {
                ToolIO.out.println(name + "[" + i + "] = null");
            }
            ;
            i = i + 1;
        }
        ;
        if (array.length == 0)
        {
            ToolIO.out.println(name + " = zero-length array");
        }
        ;
    };

    public static void printVector(Vector vec, String name)
    /*********************************************************************
    * This method prints to standard output the contents of the vector   *
    * argument, where name is the name of the vector.                    *
    *********************************************************************/
    {
        if (vec == null)
        {
            ToolIO.out.println(name + " == null");
            return;
        }
        ;
        int i = 0;
        while (i < vec.size())
        {
            if (vec.elementAt(i) == null)
            {
                ToolIO.out.println(name + "[" + i + "] = null");
            } else
            {
                ToolIO.out.println(name + "[" + i + "] = " + vec.elementAt(i).toString());
            }
            i = i + 1;
        }
        ;
        if (vec.size() == 0)
        {
            ToolIO.out.println(name + " = zero-length vec");
        }
        ;
    };

    public static void print2DVector(Vector vec, String name)
    /*********************************************************************
    * This method prints to standard output the contents of its vector   *
    * argument, which is a vector of vectors, where name is the name of  *
    * the vector.                                                        *
    *********************************************************************/
    {
        if (vec == null)
        {
            ToolIO.out.println(name + " == null");
            return;
        }
        ;
        int i = 0;
        while (i < vec.size())
        {
            if (vec.elementAt(i) == null)
            {
                ToolIO.out.println(name + "[" + i + "] = null");
            } else
            {
                printVector((Vector) vec.elementAt(i), name + "[" + i + "]");
            }
            ;
            i = i + 1;
        }
        ;
        if (vec.size() == 0)
        {
            ToolIO.out.println(name + " = zero-length vec");
        }
        ;
    };

    public static String pair(int i, int j)
    /*********************************************************************
    * Just a convenient little function.                                 *
    *********************************************************************/
    {
        return "(" + i + ", " + j + ")";
    };

    public static void printPair(int i, int j)
    /*********************************************************************
    * Just prints "(i, j)".                                              *
    *********************************************************************/
    {
        ToolIO.out.println(pair(i, j));
    }

}
/* last modified on Sat  4 Mar 2006 at 10:15:03 PST by lamport */


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/ContextTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.AbortException;
import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.xml.SymbolContext;
import util.UniqueString;

public class ContextTest {

	@Test
	public void testLookupEmpty() {
		assertNull(Context.Empty.lookup(new DummySymbolNode()));
		assertNull(Context.Empty.lookup(new DummySymbolNode(), true));
		assertNull(Context.Empty.lookup(new DummySymbolNode(), false));
		assertNull(Context.Empty.lookup((SymbolNode)null));
		assertNull(Context.Empty.lookup(null, true));
		assertNull(Context.Empty.lookup(null, false));
	}

	@Test
	public void testLookupBranch() {
		// BranchCtx -> Empty
		final Context ctx = Context.branch(Context.Empty);
		assertNull(ctx.lookup(new DummySymbolNode()));
		assertNull(ctx.lookup(new DummySymbolNode(), true));
		assertNull(ctx.lookup(new DummySymbolNode(), false));
		assertNull(ctx.lookup((SymbolNode)null));
		assertNull(ctx.lookup(null, false));
		assertNull(ctx.lookup(null, true));
	}
	
	@Test
	public void testLookupSymbolNodeNull() {
		final Context ctx = Context.branch(Context.Empty);
		assertNull(ctx.lookup((SymbolNode)null));
	}
	
	@Test
	public void testLookup() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx 3 -> Ctx 2 -> Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		final Context ctx2 = branch.cons(new DummySymbolNode("ctx2"), "value2");
		final Context ctx3 = ctx2.cons(new DummySymbolNode("ctx3"), "value3");
		
		assertEquals(value, ctx3.lookup(name));
	}
	
	@Test
	public void testLookupCutOffFalse() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx 3 -> Ctx 2 -> Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		final Context ctx2 = branch.cons(new DummySymbolNode("ctx2"), "value2");
		final Context ctx3 = ctx2.cons(new DummySymbolNode("ctx3"), "value3");
		
		assertEquals(value, ctx3.lookup(name, false));
	}
	
	// Cutoff causes lookup to stop at branching context
	@Test
	public void testLookupCutOffTrue() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx 3 -> Ctx 2 -> Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		final Context ctx2 = branch.cons(new DummySymbolNode("ctx2"), "value2");
		final Context ctx3 = ctx2.cons(new DummySymbolNode("ctx3"), "value3");
		
		assertNull(ctx3.lookup(name, true));
	}
	
	@Test
	public void testLookupWithAtBranching() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		
		assertEquals(value, branch.lookup(name));
	}
	
	@Test
	public void testLookupWithCutOffFalseAtBranching() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		
		assertEquals(value, branch.lookup(name, false));
	}

	@Test
	public void testLookupWithCutOffTrueAtBranching() {
		final DummySymbolNode name = new DummySymbolNode("ctx1");
		final Object value = "value1";
		
		// Ctx Branch -> Ctx 1 -> Ctx Empty
		final Context ctx1 = Context.Empty.cons(name, value);
		final Context branch = Context.branch(ctx1);
		
		assertNull(branch.lookup(name, true));
	}
	
	/**
	 * Test method for {@link tlc2.util.Context#lookup(tla2sany.semantic.SymbolNode)}.
	 */
	@Test
	public void testLookupSymbolNode() {
		final DummySymbolNode name = new DummySymbolNode();
		final Object value = new Object();

		final Context ctx = Context.branch(Context.Empty);
		Context cons = ctx.cons(name, value);
		
		Object lookup = cons.lookup(name);
		assertEquals(value, lookup);
	}
	
	// Need a dummy for the instance identity checks in Context 
	private static class DummySymbolNode extends SymbolNode {

		DummySymbolNode() {
			this("Dummy");
		}
		
		DummySymbolNode(String name) {
			super(-1, new SyntaxTreeNode(), UniqueString.uniqueStringOf(name));
		}

		public int getArity() {
			return 0;
		}

		public boolean isLocal() {
			return false;
		}
		
		public boolean match(OpApplNode test, ModuleNode mn) throws AbortException {
			return false;
		}

		protected Element getSymbolElement(Document doc, SymbolContext context) {
			return null;
		}

		protected String getNodeRef() {
			return null;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/ParamAndPosition.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

/** 
 * This class represents a combination of a parameter (OpArgNode) and
 * an argument position for that parameter.  It is wrapped as an
 * object so it can act as a key for Map objects.
 */
class ParamAndPosition {

  SymbolNode param;  
  int        position;

  ParamAndPosition(SymbolNode param, int pos) {
    this.param = param;
    this.position = pos;
  }

  public final int hashCode() {
    return this.param.hashCode() + this.position;
  }

  public final boolean equals(Object obj) {
    if (obj instanceof ParamAndPosition) {
      ParamAndPosition pap = (ParamAndPosition)obj;
      return (this.param == pap.param) && (this.position == pap.position);
    }
    return false;
  }

  public final String toString() {
    return "<" + this.param + ", " + this.position + ">";
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/pcal/PCalCompletionProcessor.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic.pcal;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.lamport.tla.toolbox.editor.basic.ToolboxCompletionProcessor;

public class PCalCompletionProcessor extends ToolboxCompletionProcessor implements IContentAssistProcessor {

	public PCalCompletionProcessor() {
		// No sense to add "--algorithm" because the 'PCalCompletionProcessor is only
		// hot when cursor/caret inside a PCal algorithm. Thus "--algorithm" is part of
		// TLACompletionProcessor.
//    	proposals.put(IPCalReservedWords.ALGORITHM, "--algorithm AName {\n}");
    	
		List<CompletionProposalTemplate> templates = new ArrayList<CompletionProposalTemplate>();
		templates.add(new CompletionProposalTemplate("process (ProcName \\in S) {\n     label: skip;\n}", 
				IPCalReservedWords.PROCESS, IPCalReservedWords.PROCESS_HELP));
		templates.add(new CompletionProposalTemplate("process (ProcName = Id) {\n    label: skip;\n}",
				IPCalReservedWords.PROCESS, IPCalReservedWords.PROCESS_HELP));
		proposals.put(IPCalReservedWords.PROCESS, templates);

		templates = new ArrayList<ToolboxCompletionProcessor.CompletionProposalTemplate>();
		templates.add(
				new CompletionProposalTemplate("if (TRUE) {\n   skip;\n};", "if-then", IPCalReservedWords.IFTHENELSE_HELP));
		templates.add(new CompletionProposalTemplate("if (TRUE) {\n   skip;\n} else {\n   skip;\n};", "if-then-else",
				IPCalReservedWords.IFTHENELSE_HELP));
		templates.add(new CompletionProposalTemplate("if (TRUE) {\n   skip;\n} else if (FALSE) {\n   skip;\n} else {\n   skip;\n};", "if-then-elseif",
				IPCalReservedWords.IFTHENELSE_HELP));
		proposals.put(IPCalReservedWords.IF, templates);

		proposals.put(IPCalReservedWords.VARIABLE,
				getSingleProposal("variable x = TRUE;", IPCalReservedWords.VARIABLE, IPCalReservedWords.VARIABLE_HELP));
		proposals.put(IPCalReservedWords.VARIABLES, getSingleProposal("variables x = TRUE;\n          y \\in {1,2,3};\n          z;",
				IPCalReservedWords.VARIABLES, IPCalReservedWords.VARIABLE_HELP));
		proposals.put(IPCalReservedWords.PROCEDURE,
				getSingleProposal("procedure PName (param1, ..., paramN) {\n  label: skip;\n}", IPCalReservedWords.PROCEDURE,
						IPCalReservedWords.PROCEDURE_HELP));
		proposals.put(IPCalReservedWords.CALL, getSingleProposal("call PName (expr1, ..., exprN)",
				IPCalReservedWords.CALL, IPCalReservedWords.PROCEDURE_HELP));
		proposals.put(IPCalReservedWords.WHILE, getSingleProposal("label: while (TRUE) {\n         skip;\n};",
				IPCalReservedWords.WHILE, IPCalReservedWords.WHILE_HELP));
		proposals.put(IPCalReservedWords.EITHER, getSingleProposal("either { skip; } or { skip; } or { skip; };",
				IPCalReservedWords.EITHER, IPCalReservedWords.EITHEROR_HELP));
		proposals.put(IPCalReservedWords.ASSERT,
				getSingleProposal("assert TRUE;", IPCalReservedWords.ASSERT, IPCalReservedWords.ASSERT_HELP));
		proposals.put(IPCalReservedWords.GOTO,
				getSingleProposal("goto label;", IPCalReservedWords.GOTO, IPCalReservedWords.GOTO_HELP));
		proposals.put(IPCalReservedWords.PRINT,
				getSingleProposal("print \"msg\";", IPCalReservedWords.PRINT, IPCalReservedWords.PRINT_HELP));
		proposals.put(IPCalReservedWords.WITH, getSingleProposal("with ( i \\in S ) {\n  skip;\n}",
				IPCalReservedWords.WITH, IPCalReservedWords.WITH_HELP));
		proposals.put(IPCalReservedWords.MACRO, getSingleProposal("macro P(param1, ... , paramN) {\n     skip;\n}",
				IPCalReservedWords.MACRO, IPCalReservedWords.MACRO_HELP));
		proposals.put(IPCalReservedWords.DEFINE,
				getSingleProposal("define {\n    Op1(param1, ... , paramN) == TRUE\n    Op2(...) == TRUE\n}",
						IPCalReservedWords.DEFINE, IPCalReservedWords.DEFINE_HELP));
	}
	
	private static List<CompletionProposalTemplate> getSingleProposal(String replacementString, String displayString, String additionalInformation) {
		final List<CompletionProposalTemplate> proposal = new ArrayList<CompletionProposalTemplate>();
		proposal.add(new CompletionProposalTemplate(replacementString, displayString, additionalInformation));
		return proposal;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.test/src/org/lamport/tla/toolbox/tool/tlc/util/OutputRegexTest.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.util;

import java.util.regex.Matcher;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IRegion;

import junit.framework.TestCase;
import tla2sany.st.Location;
import tlc2.output.SpecWriterUtilities;
import util.TLAConstants;

/**
 * Tests the regex matcher for generated ids
 * @author <NAME>
 */
public class OutputRegexTest extends TestCase {
    private String id;
    private final String random = " ksj fhksd hfskd hfsdk hsdk hj ";
    private final String random2 = " lksjfh ksfh ksdhf sdkhf sdk hj ";
    private final String location = "line 11, col 8 to line 14, col 26 of module MTest3";
    private final String ulocation = "In module MTest3";

    protected void setUp() throws Exception
    {
        super.setUp();
        id = SpecWriterUtilities.getValidIdentifier(TLAConstants.Schemes.CONSTANT_SCHEME);
    }

    public void testRegexMatchId()
    {
        // exact match
        assertTrue(SpecWriterUtilities.ID_MATCHER.matcher(id).matches());
    }

    public void testRegexFindId()
    {
        Matcher matcher = SpecWriterUtilities.ID_MATCHER.matcher(random + id + random2);
        // find the id inside of the text
        assertTrue(matcher.find());
        // start points to the beginning
        assertEquals(random.length(), matcher.start());
        // end to the end
        assertEquals(id.length(), matcher.end() - matcher.start());
        // here is how the content can be extracted
        assertEquals(id, (random + id + random2).substring(matcher.start(), matcher.end()));
        // not a false positive
        assertFalse(SpecWriterUtilities.ID_MATCHER.matcher(random + random2).find());
    }

    public void testRegexFindManyIds()
    {
        Matcher matcher = SpecWriterUtilities.ID_MATCHER.matcher(random + id + random2 + id + random);
        // find the id inside of the text
        assertTrue(matcher.find());
        // start points to the beginning
        assertEquals(random.length(), matcher.start());
        // find the id inside of the text
        assertTrue(matcher.find());
        // start points to the beginning
        assertEquals(random.length() + id.length() + random2.length(), matcher.start());
    }

    /**
     * Method test
     */
    public void testFindIds()
    {
        IRegion[] regions = ModelHelper.findIds(random + id + random2 + id + random);
        assertEquals(2, regions.length);
        // start points to the beginning
        assertEquals(random.length(), regions[0].getOffset());

        // make sure the id has correct length 
        assertEquals(id.length(), regions[0].getLength());
        
        // start points to the beginning
        assertEquals(random.length() + id.length() + random2.length(), regions[1].getOffset());
    }
    
    public void testFindIds2()
    {
        IRegion[] regions = ModelHelper.findIds(random + id + random2 + id + random);
        Document doc = new Document(random + id + random2 + id + random);
        
        try
        {
            assertEquals(id, doc.get(regions[0].getOffset(), regions[0].getLength()));
        } catch (BadLocationException e)
        {
            fail("Error reading document");
        }
    }
    
    

    public void testRegexMatchLocation()
    {
        Matcher matcher = Location.LOCATION_MATCHER.matcher(location);
        assertTrue(matcher.matches());
    }

    public void testRegexFindLocation()
    {
        Matcher matcher = Location.LOCATION_MATCHER.matcher(random + location + random2 + location + random);
        // find the id inside of the text
        assertTrue(matcher.find());
        // start points to the beginning
        assertEquals(random.length(), matcher.start());
        // find the id inside of the text
        assertTrue(matcher.find());
        // start points to the beginning
        assertEquals(random.length() + location.length() + random2.length(), matcher.start());

        // get the groups
        assertEquals(5, matcher.groupCount());
        // bl
        assertEquals(11, Integer.parseInt(matcher.group(1)));
        // bc
        assertEquals(8, Integer.parseInt(matcher.group(2)));
        // el
        assertEquals(14, Integer.parseInt(matcher.group(3)));
        // ec
        assertEquals(26, Integer.parseInt(matcher.group(4)));
        // module
        assertEquals("MTest3", matcher.group(5));
    }

    public void testRegex2FindLocation()
    {
        Matcher matcher = Location.LOCATION_MATCHER2.matcher(random + ulocation + random);
        // find the id inside of the text
        assertTrue(matcher.find());

        // get the groups
        assertEquals(1, matcher.groupCount());
        // module
        assertEquals("MTest3", matcher.group(1));
    }

    /**
     * Method test
     */
    public void testFindLocations()
    {
        IRegion[] regions = ModelHelper.findLocations(random + location + random2 + location + random);
        assertEquals(2, regions.length);
        // start points to the beginning
        assertEquals(random.length(), regions[0].getOffset());
        // start points to the beginning
        assertEquals(random.length() + location.length() + random2.length(), regions[1].getOffset());
    }

    public void testLocationParsing()
    {
        String inputString = random + location + random2 + location + random;
        IRegion[] regions = ModelHelper.findLocations(inputString);
        assertEquals(2, regions.length);

        String loc1 = inputString.substring(regions[0].getOffset(), regions[0].getOffset() + regions[0].getLength());
        String loc2 = inputString.substring(regions[1].getOffset(), regions[1].getOffset() + regions[1].getLength());

        assertEquals("MTest3", Location.parseLocation(loc1).source());
        assertEquals("MTest3", Location.parseLocation(loc2).source());
    }

    public void testLocationParsing2()
    {
        String inputString = random + location + random2 + location + random;
        Matcher matcher = Location.LOCATION_MATCHER.matcher(inputString);
        if (matcher.find())
        {
            String locationString = matcher.group();
            Location location = Location.parseLocation(locationString);
            assertEquals("MTest3", location.source());
        } else
        {
            fail();
        }
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/page/results/CoverageViewerComparator.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of c1 software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and c1 permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR c2 LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR c2WISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR c2 DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.editor.page.results;

import java.util.Comparator;

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.lamport.tla.toolbox.tool.tlc.output.data.ActionInformationItem;

public class CoverageViewerComparator extends ViewerComparator {

	@Override
	public int compare(final Viewer viewer, final Object e1, final Object e2) {
		final ActionInformationItem a1 = (ActionInformationItem) e1;
		final ActionInformationItem a2 = (ActionInformationItem) e2;

		final Table table = (Table) viewer.getControl();
		final TableColumn sortColumn = table.getSortColumn();
		if (sortColumn == null) {
			// a) Compare by distinct states first (we want actions with zero distinct states
			// to appear at the top).
			if (Long.compare(a1.getUnseen(), a2.getUnseen()) == 0L) {
				// b) Compare by location
				return a1.getModuleLocation().compareTo(a2.getModuleLocation());
			} else {
				return Long.compare(a1.getUnseen(), a2.getUnseen());
			}
		} else {
			// User requested to sort a specific column up or down.
			@SuppressWarnings("unchecked")
			final Comparator<ActionInformationItem> comp = (Comparator<ActionInformationItem>) sortColumn
					.getData(CoverageLabelProvider.COVERAGE_COMPARATOR);
			if (table.getSortDirection() == SWT.UP) {
				return comp.compare(a2, a1);
			} else {
				return comp.compare(a1, a2);
			}
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/TLAMarkerInformationHolder.java<|end_filename|>
package org.lamport.tla.toolbox.util;

import org.eclipse.core.resources.IResource;

/**
 * Holds information for marker creation
 * Helper class to ease the methods
 * @author <NAME>
 * @version $Id$
 */
public class TLAMarkerInformationHolder
{
    final IResource resource;
    final String moduleName;
    final int severityError;
    final int[] coordinates;
    final String message; 
    final String type = TLAMarkerHelper.TOOLBOX_MARKERS_TLAPARSER_MARKER_ID;
    /**
     * @param resource resource to install marker on
     * @param moduleName name of the module
     * @param severityError severity of the error
     * @param coordinates coordinates in the file
     * @param message string message
     * @param type MarkerType (as defined in plugin.xml)
     */
    public TLAMarkerInformationHolder(IResource resource, String moduleName, int severityError, int[] coordinates,
            String message)
    {
        this.resource = resource;
        this.moduleName = moduleName;
        this.severityError = severityError;
        this.coordinates = coordinates;
        this.message = message;
    }
    public final IResource getResource()
    {
        return resource;
    }
    public final String getModuleName()
    {
        return moduleName;
    }
    public final int getSeverityError()
    {
        return severityError;
    }
    public final int[] getCoordinates()
    {
        return coordinates;
    }
    public final String getMessage()
    {
        return message;
    }
    public final String getType()
    {
        return type;
    }
    
    
}

<|start_filename|>tlatools/org.lamport.tlatools/src/org/eclipse/xtext/xbase/lib/util/ToStringBuilder.java<|end_filename|>
package org.eclipse.xtext.xbase.lib.util;

public class ToStringBuilder {
	
	public ToStringBuilder(Object instance) {
	}
	
	public ToStringBuilder add(Object value) {
		return this;
	}

	public ToStringBuilder add(String fieldName, Object value) {
		return this;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/trouble/trouble.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/trouble/trouble.html  -->

 
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

<title>In Case of Trouble</title>
</head>
<!-- a comment here -->

<body>
<h1>In Case of Trouble</h1>

<pre>
Contents
  <a href="#trouble">Getting Out of Trouble</a>
  <a href="#reporting">Reporting Problems</a>
</pre>
 <P> 
The Toolbox is far from perfect.&nbsp;  Below are some hints for getting out of
trouble if it misbehaves, and instructions for reporting bugs.&nbsp;
Please be patient, we're doing the best we can.&nbsp;  We and our other users would greatly
appreciate any help you can give us.&nbsp;  <a href="../help-us/help-us.html">Click
here</a> to find out how you can help.
 </P>

<h2><a name="trouble">Getting Out of Trouble</a></h2>
<p>
Errors in the Toolbox can cause it to get into a bad state.&nbsp;  The best thing to 
do if this happens is to back out of what you were doing and try again.&nbsp;  You should try to back
out only as far as necessary. 
</p>

<h3>Backing Out of a Model</h3>

<p>
If you try running TLC and nothing seems to be happening, 
see <a href="../model/executing-tlc.html#crash">If Something Crashes</a>.&nbsp;
Looking at <a href="../model/executing-tlc.html#console">The TLC Console View</a> can help you figure out
what state TLC is in.&nbsp;  It's possible that the problem is with the model.&nbsp;
A problem with a model can also be caused by editing the model, or by
editing and re-parsing the spec.
</p>

<p>
Closing the model (by clicking on the&nbsp; <samp>X</samp>&nbsp; in the model editor's tab) and re-opening it
(with the&nbsp; <samp>TLC Model Checker/Open Model</samp>&nbsp; menu item) may solve the problem.&nbsp;
If not, try cloning the model and deleting the original.&nbsp; 
(See the <a href="../model/about-models.html"><em>Models</em></a>
help page.)&nbsp;  If the problem persists in the cloned model, try creating a new model.&nbsp;  If that
too has problems, try backing out of the spec.
</p>

<h3>Backing Out of a Spec</h3>
<p>

If the Toolbox gets into a bad state when you're editing a module, or
when you have a problem with a TLC model that can't be solved by backing
out of the model, you should try backing out of the spec.&nbsp; 

The first thing to try is closing the spec,
refresh the spec by right-clicking on its entry 
in the <a href="#spec-explorer">Spec Explorer</a>,
and re-opening the spec.&nbsp; 
(See the <a href="../spec/opening-closing.html"><em>Manipulating
Specs</em></a> help page.)&nbsp; 

If that doesn't work, try exiting from and then restarting the
Toolbox.&nbsp; 

If that fails, delete the original spec.&nbsp; 

However, if you have models that you don't want to lose, first make a
copy of the <code>.toolbox</code> directory under some other name.&nbsp;

If that works, try creating a new spec with the same root
module.&nbsp;  

If you have saved a copy of the old <code>.toolbox</code> directory,
you can first restore that directory and see if you can open it with
the <code>Import existing models</code> option.&nbsp;  

If not, you will have to try creating a new spec with the same modules
but without your saved models.&nbsp;

If you can't restore the spec, see if the problem exists with other
specs.&nbsp;

If it does, you will probably have to back out of the Toolbox.&nbsp;

If not, see if you can figure out what it is about that particular
spec that is causing the problem.

</p>

<h3><a name="backing-out">Backing Out of the Toolbox</a></h3>

<p>
If all else fails, you will have to re-initialize the Toolbox.&nbsp;  This is done by exiting the Toolbox
and deleting all its state information from the disk.&nbsp;  However, before doing this, save the relevant
part of the Toolbox's&nbsp; <code>.log</code>&nbsp; file as described in <a href="#reporting">Reporting Problems</a> below.
</p>
<p>
The Toolbox keeps its state in a folder named &nbsp;<code>workspace</code>&nbsp; that it creates in the
folder from which you run the Toolbox.&nbsp;  Deleting (or renaming) the &nbsp;<code>workspace</code>&nbsp; folder (when the Toolbox
is not running) causes the Toolbox
to start in its initial state the next time you execute it.&nbsp;  It will then show no existing specs.&nbsp;
However, the information about the individual specs that existed when you deleted 
the&nbsp; <code>workspace</code>&nbsp; folder is still there.&nbsp;
If you had a spec named&nbsp; <samp>SName</samp>&nbsp;, 
the state of that spec was saved in a folder named&nbsp; <samp>SName.toolbox</samp>&nbsp;.&nbsp;
If you open a spec with that name having the same root module, the Toolbox will give you
the option of reloading that state, which includes the state of all its models.&nbsp;
If you're lucky, that spec will work fine.&nbsp;  If not, you'll have to delete the spec 
(which deletes the&nbsp; <code>.toolbox</code>&nbsp; folder) and re-create
it from scratch.&nbsp;  Of course, the module files will still be there.
</p>

<h2><a name="reporting">Reporting Problems</a></h2>
<p>

We can't fix a problem with the Toolbox if we don't know about
it.&nbsp; 

Please report any problem you encounter--be it a bug or something you
found confusing or poorly explained.&nbsp;  

You can enter a bug report in
 <A href="https://github.com/tlaplus/tlaplus/issues", target="_blank">our 
GitHub bug database</A>.&nbsp; 

However, please search the database first to make sure that we don't
already know about it.&nbsp; 

</p>

<p>
When reporting a bug, please include all details.&nbsp; 

It will be helpful if you can include the relevant part of the
Toolbox's log, which is the file named&nbsp; <samp>.log</samp>.&nbsp;

The &nbsp; <samp>.log</samp>&nbsp; file is in the 
&nbsp; <samp>.tlaplus/.metadata/</samp> folder in your home 
directory.&nbsp; 

On Windows, you can find out where your home directory is located, by 
entering the command <code>echo %SYSTEMDRIVE%%HOMEPATH%</code> in 
Command Prompt.&nbsp; On Linux and Mac, check the $HOME variable.&nbsp;

(The log contains enough timestamped entries for you to figure out
what part of it relates to the problem you are reporting.)&nbsp;
</p>


<hr>
<a href = "../contents.html">&uarr; TLA+ Toolbox User's Guide</a>
</hr>
<!-- 
<hr> 
 delete rest of line to comment out 
<dl>
<dt><b><font color=#0000c0>Subtopics</font></b></dt>
<dd> <A href=""> TOPIC </A></dd>
<dd> <A href=""> TOPIC </A></dd>
</dl>
<!-- 
<!-- delete rest of line to comment out 
<a href = ".html">&uarr; HIGHER_LEVEL_TOPIC</a>
<!-- 
</hr>
--> 
</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/part/IAttributeBinding.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.part;

/**
 * Provides the interface for binding of attributes to the fields
 * @author <NAME>
 * @version $Id$
 */
public interface IAttributeBinding
{
    /**
     * Binds a control to the attribute
     * @param attributeName name of the attribute
     * @param control the control taking care of its display and editing
     */
    public void bindAttribute(String attributeName, Object control);

    /**
     * Retrieves the control handling the current attribute name of the attribute 
     */
    public Object getAttributeControl(String attributeName);

    /**
     * Retrieves the id of the binding 
     * @return String index representing the binding
     */
    public String getBindingId();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/tool/IParseResult.java<|end_filename|>
package org.lamport.tla.toolbox.tool;

import java.util.Vector;

import org.lamport.tla.toolbox.util.TLAMarkerInformationHolder;

/**
 * Representation of the parse result for the tools
 * @author <NAME>
 * @version $Id$
 */
public interface IParseResult
{
    /**
     * Retrieves the parse status
     * @return
     */
    public int getStatus();
    
    /**
     * Retrieves the list of {@link TLAMarkerInformationHolder} or an empty list
     */
    public Vector<TLAMarkerInformationHolder> getDetectedErrors();
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/LNStateAST.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 15:30:15 PST by lamport
//      modified on Sat Jul 28 00:37:08 PDT 2001 by yuanyu

package tlc2.tool.liveness;

import tla2sany.parser.SyntaxTreeNode;
import tla2sany.semantic.ExprNode;
import tla2sany.semantic.OpApplNode;
import tla2sany.st.TreeNode;
import tlc2.output.EC;
import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.util.Context;
import tlc2.value.IBoolValue;
import tlc2.value.IValue;
import util.Assert;

/**
 * Handles states
 *
 * @author <NAME>, <NAME>, <NAME>
 * @version $Id$
 */
class LNStateAST extends LNState {
	private final ExprNode body;

	public LNStateAST(ExprNode body, Context con) {
		super(con);
		this.body = body;
	}

	public final ExprNode getBody() {
		return this.body;
	}

	public final boolean eval(ITool tool, TLCState s1, TLCState s2) {
		IValue val = tool.eval(this.body, getContext(), s1);
		if (!(val instanceof IBoolValue)) {
			Assert.fail(EC.TLC_LIVE_STATE_PREDICATE_NON_BOOL);
		}
		return ((IBoolValue) val).getVal();
	}

	public final void toString(StringBuffer sb, String padding) {
		sb.append(this.body);
	}
	
	/* (non-Javadoc)
	 * @see tlc2.tool.liveness.LiveExprNode#toDotViz()
	 */
	public String toDotViz() {
		final StringBuffer sb = new StringBuffer();
		if (this.body instanceof OpApplNode) {
			final OpApplNode oan = (OpApplNode) this.body;
			sb.append("(");
			// Zeros
			final TreeNode[] zero = oan.getTreeNode().zero();
			for (TreeNode treeNode : zero) {
				// TreeNode is interface with only STN being impl => unchecked
				// cast is safe.
				SyntaxTreeNode stn = (SyntaxTreeNode) treeNode;
				sb.append(stn.getHumanReadableImage());
			}
			// Ones
			final TreeNode[] one = oan.getTreeNode().one();
			if (one != null) {
				for (TreeNode treeNode : one) {
					SyntaxTreeNode stn = (SyntaxTreeNode) treeNode;
					sb.append(stn.getHumanReadableImage());
				}
			}
			sb.append(")");
		} else {
			toString(sb, "");
		}
		return sb.toString();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/st/ParseTree.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.st;

// Implemented only by parser.TLAPlusParser

// Outside of the parser package this is used only by 
//   drivers.ParseUnit and drivers.SyntaxTreePrinter

public  interface ParseTree {
  public String[] dependencies();
  public TreeNode rootNode();
  public String   moduleName();
  public boolean  parse();
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/handlers/PCalTranslateAutomaticallyHandler.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.editor.basic.handlers;

import java.lang.reflect.InvocationTargetException;

import javax.inject.Inject;

import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.State;
import org.eclipse.core.runtime.Assert;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.handlers.RegistryToggleState;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.pcal.PCalTranslator;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

public class PCalTranslateAutomaticallyHandler extends PCalTranslator implements EventHandler {

	@Inject
	public void initializeAtStartup(final IWorkbench workbench, final ICommandService commandService) {
		/*
		 * Check the UI state of the IHandler/Command which indicates if the user
		 * enabled automatic PlusCal conversion.
		 */
		final Command command = commandService.getCommand("toolbox.command.module.translate.automatially");
		final State state = command.getState(RegistryToggleState.STATE_ID);
		if (!((Boolean) state.getValue()).booleanValue()) {
			return;
		}
		// This IHander is stateful even across Toolbox restarts. In other words, if the
		// user enables automatic PlusCal translation, it will remain enabled even after
		// a Toolbox restart. This means we have to register this EventHandler at the
		// IEventBroker during Toolbox startup.
		// It is vital that we use the Workbench's IEventBroker instance. If e.g. we
		// would use an IEventBroker from higher up the IEclipseContext hierarchy, the
		// broker would be disposed when a new spec gets opened while the IHandler's state
		// remains enabled.
		workbench.getService(IEventBroker.class).unsubscribe(this);
		Assert.isTrue(workbench.getService(IEventBroker.class).subscribe(TLAEditor.PRE_SAVE_EVENT, this));
	}
	
	@Execute
	public void execute(final ExecutionEvent event, final IWorkbench workbench) throws ExecutionException {
		// Toggle the IHandler's state at the UI level (check mark on/off) and
		// unsubscribe/subscribe the EventHandler.
		final IEventBroker eventBroker = workbench.getService(IEventBroker.class);
		if (HandlerUtil.toggleCommandState(event.getCommand())) {
			eventBroker.unsubscribe(this);
		} else {
			eventBroker.unsubscribe(this);
			Assert.isTrue(eventBroker.subscribe(TLAEditor.PRE_SAVE_EVENT, this));
		}
	}
	
	/* (non-Javadoc)
	 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
	 */
	@Override
	public void handleEvent(final Event event) {
		try {
			final TLAEditor editor = (TLAEditor) event.getProperty(IEventBroker.DATA);
			translate(editor, editor.getSite().getShell(), false);
		} catch (InvocationTargetException | InterruptedException e) {
			throw new RuntimeException(e);
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/BlockSelectorFactory.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.distributed.TLCServer;

public class BlockSelectorFactory {
	
	/**
	 * Delegate to a custom factory if set
	 */
	private static final String FACTORY_NAME = System.getProperty("tlc2.tool.distributed.selector.factory");

	/**
	 * {@link StaticBlockSelector} system property
	 */
	private static final String STATIC_SELECTOR = System.getProperty("tlc2.tool.distributed.selector.bsf.staticselector");
	/**
	 * {@link BlockSelector} system property
	 */
	private static final String UNLIMITING_SELECTOR = System.getProperty("tlc2.tool.distributed.selector.bsf.unlimitingselector");
	/**
	 * {@link LimitingBlockSelector} system property
	 */
	private static final String LIMITING_SELECTOR = System.getProperty("tlc2.tool.distributed.selector.bsf.limitingselector");
	
	/**
	 * Creates an {@link IBlockSelector} for the given {@link TLCServer}.
	 * @see {@link IBlockSelector}
	 * @param aTLCServer
	 * @return An {@link IBlockSelector} for the given {@link TLCServer}
	 */
	public static IBlockSelector getBlockSelector(final TLCServer aTLCServer) {
		BlockSelectorFactory bsf = new BlockSelectorFactory();
		if(FACTORY_NAME != null) {
			bsf = loadCustomFactory(FACTORY_NAME, bsf);
		}
		return bsf.getSelector(aTLCServer);
	}

	/**
	 * @param clazz Class string to load
	 * @param bsf Default BlockSelectorFactory when loading from String fails
	 * @return A BSF
	 */
	private static BlockSelectorFactory loadCustomFactory(final String clazz, BlockSelectorFactory bsf) {
		try {
			// poor mans version of modularity, booh!
			final ClassLoader classLoader = BlockSelectorFactory.class.getClassLoader();
			final Class<?> factoryClass = classLoader.loadClass(clazz);
			final Object instance = factoryClass.newInstance();
			// sanity check if given class from string implements bsf
			if (instance instanceof BlockSelectorFactory) {
				bsf = (BlockSelectorFactory) instance;
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return bsf;
	}
	
	/**
	 * @param aTLCServer
	 * @return An instance of the requested selector type
	 */
	protected IBlockSelector getSelector(final TLCServer aTLCServer) {
		if(Boolean.parseBoolean(STATIC_SELECTOR)) {
			return new StaticBlockSelector(aTLCServer);
		} else if (Boolean.parseBoolean(UNLIMITING_SELECTOR)) {
			return new BlockSelector(aTLCServer);
		} else if (Boolean.parseBoolean(LIMITING_SELECTOR)) {
			return new LimitingBlockSelector(aTLCServer);
		}
		// always return the default BlockSelector by default
		return new StatisticalBlockSelector(aTLCServer);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools.consumer.distributed/src/org/lamport/tla/distributed/consumer/DistributedFPSetConsumer.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.
package org.lamport.tla.distributed.consumer;

import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import tlc2.IDistributedFPSet;

public class DistributedFPSetConsumer {
	
	/**
	 * TLCServer address to connect to.
	 * 
	 * //TODO refactor to read/obtain URI from ECF discovery
	 * //TODO port number currently hard coded in TLCServer/TLCWorker 
	 */
	private final URI uri = URI
			.create(System.getProperty(DistributedFPSetConsumer.class.getName()
					+ ".uri", "rmi://localhost:10997"));

	/**
	 * Instructs this instance that the {@link IDistributedFPSet} service is
	 * available in the OSGi lifecycle model.
	 * 
	 * @param anIDistributedFPSet
	 *            An {@link IDistributedFPSet} passed by OSGi Declarative
	 *            Services
	 */
	public void setIDistributedFPSet(final IDistributedFPSet anIDistributedFPSet) {
		// Fork out to a separate thread to not block DeclarativeService forever
		final ExecutorService executor = Executors.newSingleThreadExecutor();
		executor.execute(new Runnable() {
			/* (non-Javadoc)
			 * @see java.lang.Runnable#run()
			 */
			public void run() {
				anIDistributedFPSet.connect(uri);
			}
		});
	}

	/**
	 * Instructs this instance that the {@link IDistributedFPSet} service is
	 * gone in the OSGi lifecycle model.
	 * 
	 * @param anIDistributedFPSet
	 *            An {@link IDistributedFPSet} passed by OSGi Declarative
	 *            Services
	 */
	public void unsetIDistributedFPSet(final IDistributedFPSet anIDistributedFPSet) {
		anIDistributedFPSet.disconnect();
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/PcalTranslate.java<|end_filename|>
/***************************************************************************
* CLASS PcalTranslate                                                      *
* last modified on Mon 20 Mar 2006 at  9:04:28 PST by lamport              *
*      modified on Fri  9 Sep 2005 at 20:58:27 UT by keith                 *
*                                                                          *
* Given an AST, "explode" it: generate a new AST that has all Call,        *
*   Return, CallReturn, GoTo and While replaced by variable, stack and     *
*   pc manipulation; add explicit pc testing and pc setting for control    *
*   flow; replace LabelIf with LabeledStmt and control flow                *
*   implementation. The exploded AST maintains the structure except        *
*   that once down to the LabeledStmt level, it is flat. The only depth    *
*   is introduced by the If statement (since this depth is reflected in    *
*   the generated TLA+ code).                                              *
*                                                                          *
* LL comment added 25 Jan 2006.  I don't understand what the preceding     *
* sentence means.  I presume that Either should be added as a              *
* "depth-introducing" statement.  But what about a With, since Withs can   *
* also be nested?                                                          *
*                                                                          *
*      AST Explode (AST ast, PcalSymTab symtab)                            *
*                                                                          *
*   There are a few other public methods that can be used to generate      *
*   snippets of TLAExpr. I only use them here.                             *
****************************************************************************/

package pcal;
import java.util.Vector;

import pcal.exception.PcalTranslateException;

public class PcalTranslate {

    private static PcalSymTab st = null;  /* Set by invocation of Explode */
    
    /**
     *  The following field added by LL on 7 June 2010 to allow return statements
     *  to be used in macros.  It is initialized to null by Explode and is
     *  set and reset by ExplodeProcedure so it equals the name of the current
     *  procedure iff Exploding statements within a procedure.
     *  
     *  See the comments for ExplodeReturn for more details.
     *  
     */
    private static String currentProcedure;  


    /*************************************************************************
     * Routines for constructing snippets of +cal code                       *
     *************************************************************************/

    public static Vector DiscardLastElement(Vector v) {
        if (v.size() > 0) v.remove(v.size() - 1);
        return v;
    }

    public static Vector Singleton(Object obj) {
        /*********************************************************************
         * If we think of a vector as a sequence, then this returns <<obj>>. *
         *********************************************************************/
        Vector result = new Vector() ;
        result.addElement(obj) ;
        return result; 
    }
 
    public static Vector Pair(Object obj1, Object obj2) {
        /*********************************************************************
         * If we think of a vector as a sequence, then this returns          *
         * << obj1,  obj2 >>.                                                *
         *********************************************************************/
        Vector result = new Vector() ;
        result.addElement(obj1) ;
        result.addElement(obj2) ;
        return result; 
    }

    public static Vector Triple(Object obj1, Object obj2, Object obj3) {
        /*********************************************************************
         * If we think of a vector as a sequence, then this returns          *
         * << obj1,  obj2, obj3 >>.                                          *
         *********************************************************************/
        Vector result = new Vector() ;
        result.addElement(obj1) ;
        result.addElement(obj2) ;
        result.addElement(obj3) ;
        return result; 
    }

    public static Vector Singleton2(Object obj) {
        /*********************************************************************
         * If we think of a vector as a sequence, then this returns          *
         * << <<obj>> >>.                                                    *
         *********************************************************************/
        return Singleton(Singleton(obj));
    } 

    public static class BoolObj {
      /*********************************************************************
      * We need to pass a boolean as an element of a triple.  But the      *
      * brain-damaged Java language makes that impossible.  While we can   *
      * put booleans in a vector, there's no way to get them out.  We can  *
      * only extract objects from a vector.  So we define an class         *
      * BoolObj of objects containing a boolean val field.  The default    *
      * object has val field equal to true.                                *
      *********************************************************************/
      boolean val = true ; }

    public static BoolObj BO(boolean v) {
      /*********************************************************************
      * What I want to do is define a constructor for the BoolObj class    *
      * with an argument that is the value of the val field.  But I don't  *
      * remember how to do that and don't have access to any Java          *
      * documentation, so I'm defining BO to be that constructor.          *
      *********************************************************************/
      BoolObj res = new BoolObj() ;
      res.val = v ;
      return res ;
     }

    public static TLAToken StringToken(String str) {
        /*********************************************************************
         * Returns a new STRING token with string str.                       *
         *********************************************************************/
        TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.STRING ;
        return result ;
      }

    public static TLAToken AddedToken(String str) {
        /*********************************************************************
         * Returns a new ADDED token with string str.                       *
         *********************************************************************/
        TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.ADDED ;
        return result ;
      }

    public static TLAToken BuiltInToken(String str)
      /*********************************************************************
      * Returns a new BUILTIN token with string str.  (A token like "="    *
      * has type BUILTIN, though in the translation phase, there will      *
      * probably be no difference in how BUILTIN and IDENT tokens are      *
      * handled.)                                                          *
      *********************************************************************/
      { TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.BUILTIN ;
        return result ;
      }

    public static TLAToken IdentToken(String str) {
        /*********************************************************************
         * Returns a new IDENT token for identifier str.                     *
         *********************************************************************/
        TLAToken result = new TLAToken() ;
        result.string = str ;
        result.type   = TLAToken.IDENT ;
        return result ;
    }

    public static TLAExpr MakeExpr(Vector vec) {
      /*********************************************************************
      * Makes a normalized expression exp with exp.tokens = vec.           *
      *********************************************************************/
        TLAExpr result = new TLAExpr(vec) ;
        result.normalize() ;
        return result ;
    }

    public static TLAExpr TokVectorToExpr(Vector vec, int spaces)
      /*********************************************************************
      * If vec is a vector of TLAToken objects, then this method returns   *
      * a TLAExpr describing a one-line expression composed of clones of   *
      * the tokens in vec separated by `spaces' spaces.                    *
      * Called only by PcalTranslate.CheckPC.                              *
      *********************************************************************/
      { Vector firstLine = new Vector() ;
        int nextCol = 0 ;
        int i = 0 ;
        while (i < vec.size())
          { TLAToken tok = ((TLAToken) vec.elementAt(i)).Clone() ;
            tok.column = nextCol ;
            firstLine.addElement(tok) ;
            nextCol = nextCol + tok.getWidth() + spaces ;
            i = i + 1 ;
          } ;
        
        return MakeExpr(Singleton(firstLine)) ;
      } ;

    public static void MakeNewStackTopExprPretty(TLAExpr expr) {
        /*********************************************************************
         * Sets columns so this expr looks nice.                             *
         * Assumes exprs that this module generates for Call and CallReturn. *
         * Lines up the |-> tokens with the one for [ << procedure |-> ...   *
         * (that is, at column 16) when it can. The record names all appear  *
         * in column 6.                                                      *
         *********************************************************************/
        Vector line; /* Vector of TLAToken */
        int nextCol = 0;
        for (int i = 0; i < expr.tokens.size(); i++) {
            line = (Vector) expr.tokens.elementAt(i);
            if (i == 0 || i == expr.tokens.size() - 1) nextCol = 1;
            else nextCol = 6;
            for (int j = 0; j < line.size(); j++) {
                TLAToken tok = ((TLAToken) line.elementAt(j));
                tok.column = nextCol;
                nextCol = nextCol + tok.getWidth();
                if (tok.type == TLAToken.BUILTIN && tok.string == "|->") {
                    tok.column = tok.column + 1;
                    if (tok.column < 16) tok.column = 16;
                    nextCol = tok.column + 5;
                }
                else if (tok.type == TLAToken.BUILTIN && tok.string == "[") {
                    nextCol = nextCol + 1;
                }
                else if (tok.type == TLAToken.BUILTIN && tok.string == "]") {
                    tok.column = tok.column + 1;
                    nextCol = nextCol + 1;
                }
                else if (tok.type == TLAToken.BUILTIN && tok.string == "<<") {
                    nextCol = nextCol + 1;
                }
                else if (tok.type == TLAToken.BUILTIN && tok.string == ">>") {
                    tok.column = tok.column + 1;
                    nextCol = nextCol + 1;
                }
                else if (tok.type == TLAToken.BUILTIN && tok.string == "\\o") {
                    tok.column = tok.column + 1;
                    nextCol = nextCol + 2;
                }

            }
        }
    }

    public static AST.Assign MakeAssign(String id, TLAExpr exp) {
        /*********************************************************************
         * Makes the assignment statement id := exp.                         *
         *                                                                   *
         * It is called only by UpdatePC, with id = "pc".                    *
         *********************************************************************/
        AST.SingleAssign sAss = new AST.SingleAssign() ;
        sAss.lhs.var = id ;
        sAss.lhs.sub = MakeExpr(new Vector()) ;
        sAss.rhs = exp ;
        AST.Assign result = new AST.Assign() ;
        result.ass = Singleton(sAss) ;
        return result ;
      }

        /*********************************************************************
        * true if expr is TRUE or ( TRUE )                                   *
        *********************************************************************/
    public static boolean IsTRUE(TLAExpr expr) {
        Vector tokens = expr.tokens;
        if (tokens.size() > 1) return false;
        Vector line = (Vector) tokens.elementAt(0);
        if (line.size() == 1) {
            TLAToken tok = (TLAToken) line.elementAt(0);
            return (tok.string.equals("TRUE")) ? true : false;
        }
        else if (line.size() == 3) {
            TLAToken tok1 = (TLAToken) line.elementAt(0);
            TLAToken tok2 = (TLAToken) line.elementAt(1);
            TLAToken tok3 = (TLAToken) line.elementAt(2);
            return (tok1.string.equals("(")
                    && tok2.string.equals("TRUE")
                    && tok3.string.equals(")")) ? true : false;
        }
        else return false;
    }

    private static AST.When CheckPC (String label) {
        /*********************************************************************
        * Generate when pc = label ;                                         *
        *********************************************************************/
        AST.When checkPC = new AST.When();
        Vector toks = new Vector();
        toks.addElement(AddedToken("pc"));
        toks.addElement(BuiltInToken("="));
        toks.addElement(StringToken(label));
        checkPC.exp = TokVectorToExpr(toks, 1);
        return checkPC;
    }

    private static AST.Assign UpdatePC (String next) {
        /*********************************************************************
        * Generate pc := next ;                                              *
        *********************************************************************/
        return MakeAssign("pc", MakeExpr(Singleton2(StringToken(next))));
    }

    /**
     * @deprecated method not used
     */
    private static AST.If IfForLabelIf (TLAExpr test,
                                        Vector unlabThen,
                                        String nextThen,
                                        Vector unlabElse,
                                        String nextElse) {
        /*********************************************************************
        * Generate  if test then unlabThen; pc := nextThen ;                 *
        *           else unlabElse; pc := nextElse ;                         *
        *********************************************************************/
        AST.If ifForLabelIf = new AST.If();
        ifForLabelIf.test = test;
        ifForLabelIf.Then = unlabThen;
        ifForLabelIf.Then.addElement(UpdatePC(nextThen));
        ifForLabelIf.Else = unlabElse;
        ifForLabelIf.Else.addElement(UpdatePC(nextElse));
        return ifForLabelIf;
    }

    /*************************************************************************
     * Explode                                                               
     **
     *************************************************************************/

    public static AST Explode (AST ast, PcalSymTab symtab) throws PcalTranslateException {
        /*********************************************************************
        * Expand while, labeled if, and nexted labeled with a sequence of    *
        * of flat labeled statements. Control flow is added via assignments  *
        * to pc. This expansion produces a new AST.                          *
        *********************************************************************/
        st = symtab;
        currentProcedure = null;  // added by LL on 7 June 2010
        if (ast.getClass().equals(AST.UniprocessObj.getClass()))
            return ExplodeUniprocess((AST.Uniprocess) ast);
        else if (ast.getClass().equals(AST.MultiprocessObj.getClass()))
            return ExplodeMultiprocess((AST.Multiprocess) ast);
        else {
            PcalDebug.ReportBug("Unexpected AST type.");
            return null;
        }
    }

    private static AST.Uniprocess ExplodeUniprocess (AST.Uniprocess ast) throws PcalTranslateException {
        /*********************************************************************
        * Generate new AST.Uniprocess that has exploded labeled statements.  *
        *********************************************************************/
        int i = 0;
        AST.Uniprocess newast = new AST.Uniprocess();
        newast.col = ast.col;
        newast.line = ast.line;
        newast.name = ast.name;
        newast.decls = ast.decls;
        newast.prcds = new Vector(ast.prcds.size(), 10);
        newast.defs = ast.defs ;  // added 25 Jan 2006 by LL
        newast.setOrigin(ast.getOrigin()) ;
        i = 0;
        while (i < ast.prcds.size()) {
            newast.prcds.addElement(
                                    ExplodeProcedure((AST.Procedure)
                                                     ast.prcds.elementAt(i)));
            i = i + 1;
        }
        i = 0;
        newast.body = new Vector(ast.body.size(), 10);
        AST.LabeledStmt thisLS = (ast.body.size() > 0)
            ? (AST.LabeledStmt) ast.body.elementAt(0) : null;
        AST.LabeledStmt nextLS = (ast.body.size() > 1)
            ? (AST.LabeledStmt) ast.body.elementAt(1) : null;
        while (i < ast.body.size()) {
            String next = (nextLS == null)
// Replacement of following line by LL on 3 Feb 2006, since
// label "Done" never has to be renamed, since "Done" is not
// a legal user label.
//                ? st.UseThis(PcalSymTab.LABEL, "Done", "")
                ? "Done"
                : nextLS.label;
            newast.body.addAll(ExplodeLabeledStmt(thisLS, next));
            i = i + 1;
            thisLS = nextLS;
            nextLS = (ast.body.size() > i + 1)
                ? (AST.LabeledStmt) ast.body.elementAt(i + 1) : null;
        }
        return newast;
    }
        
    private static AST.Multiprocess ExplodeMultiprocess (AST.Multiprocess ast) throws PcalTranslateException {
        /*********************************************************************
        * Generate new AST.Multiprocess with exploded labeled statements.    *
        *********************************************************************/
        int i = 0;
        AST.Multiprocess newast = new AST.Multiprocess();
        newast.col = ast.col;
        newast.line = ast.line;
        newast.name = ast.name;
        newast.decls = ast.decls;
        newast.prcds = new Vector(ast.prcds.size(), 10);
        newast.defs = ast.defs ;  // added 25 Jan 2006 by LL
        newast.setOrigin(ast.getOrigin()) ;
        while (i < ast.prcds.size()) {
            newast.prcds.addElement(ExplodeProcedure((AST.Procedure)
                                                     ast.prcds.elementAt(i)));
            i = i + 1;
        }
        i = 0;
        newast.procs = new Vector(ast.procs.size(), 10);
        while (i < ast.procs.size()) {
            newast.procs.addElement( ExplodeProcess((AST.Process)
                                                   ast.procs.elementAt(i)));
            i = i + 1;
        }
        return newast;
    }

    private static AST ExplodeProcedure (AST.Procedure ast) throws PcalTranslateException {
        /*********************************************************************
        * Generate new AST.Procedure with exploded labeled statements.       *
        *********************************************************************/
        int i = 0;
        AST.Procedure newast = new AST.Procedure();
        newast.setOrigin(ast.getOrigin()) ;
        newast.col = ast.col;
        newast.line = ast.line;
        newast.name = ast.name;
        currentProcedure = ast.name;  // Added by LL on 7 June 2010
        newast.params = ast.params;
        newast.decls = ast.decls;
        newast.body = new Vector(ast.body.size(), 10);
        AST.LabeledStmt thisLS = (ast.body.size() > 0)
            ? (AST.LabeledStmt) ast.body.elementAt(0) : null;
        AST.LabeledStmt nextLS = (ast.body.size() > 1)
            ? (AST.LabeledStmt) ast.body.elementAt(1) : null;
        while (i < ast.body.size()) {
            String next = (nextLS == null)
                ? st.UseThis(PcalSymTab.LABEL, "Error", "")
                : nextLS.label;
            newast.body.addAll(ExplodeLabeledStmt(thisLS, next));
            i = i + 1;
            thisLS = nextLS;
            nextLS = (ast.body.size() > i + 1)
                ? (AST.LabeledStmt) ast.body.elementAt(i + 1) : null;
        }
        currentProcedure = null;  // Added by LL on 7 June 2010
        return newast;
    }
        
    private static AST ExplodeProcess(AST.Process ast) throws PcalTranslateException {
        /*********************************************************************
        * Generate new AST.Process with exploded labeled statements.         *
        *********************************************************************/
        int i = 0;
        AST.Process newast = new AST.Process();
        newast.setOrigin(ast.getOrigin()) ;
        newast.col = ast.col;
        newast.line = ast.line;
        newast.name = ast.name;
        newast.isEq = ast.isEq;
        newast.id = ast.id;
        newast.decls = ast.decls;
        newast.body = new Vector();
        AST.LabeledStmt thisLS = (ast.body.size() > 0)
            ? (AST.LabeledStmt) ast.body.elementAt(0) : null;
        AST.LabeledStmt nextLS = (ast.body.size() > 1)
            ? (AST.LabeledStmt) ast.body.elementAt(1) : null;
        while (i < ast.body.size()) {
            String next = (nextLS == null)
// Replacement of following line by LL on 3 Feb 2006, since
// label "Done" never has to be renamed, since "Done" is not
// a legal user label.
//                ? st.UseThis(PcalSymTab.LABEL, "Done", "")
                ? "Done"
                : nextLS.label;
            newast.body.addAll(ExplodeLabeledStmt(thisLS, next));
            i = i + 1;
            thisLS = nextLS;
            nextLS = (ast.body.size() > i + 1)
                ? (AST.LabeledStmt) ast.body.elementAt(i + 1) : null;
        }
        return newast;
    }

    private static Vector CopyAndExplodeLastStmt(Vector stmts, String next) throws PcalTranslateException {
        /**************************************************************
        * The arguments are:                                               *
        *                                                                  *
        *    stmts : a (perhaps null) Vector of statements                 *
        *    next  : the label of the next control point following stmts.  *
        *                                                                  *
        * It returns a triple <<result1, result2, needsGoto>>, where       *
        *                                                                  *
        *   result1 : A vector equal to stmts with the last statement      *
        *             replaced if necessary by the exploded version--      *
        *             namely, if it is a goto, call, return, or            *
        *             callreturn, or if it is a statement with one of      *
        *             these statements or a labeled statement nested       *
        *             within it.                                           *
        *                                                                  *
        *   result2 : A (possibly empty) vector that is the sequence of    *
        *             labeled statements generated by exploding the last   *
        *             statement of stmts.                                  *
        *                                                                  *
        *   needsGoto : A boolean that equals true iff the sequence        *
        *               result1 of statements needs a goto at the end to   *
        *               transfer control to `next'.  In other words, it    *
        *               equals false if result1 contains the necessary     *
        *               goto statements and no goto must be added.         *
        *                                                                  *
        * Modified by LL on 25 Jan 2006 to handle the `either' statement   *
        * and to correct the following bug.  If a labeled statement ended  *
        * with an `if' statement, then gotos were added to both the then   *
        * and else clause, even if there was no transfer of control        *
        * within those clauses, so a single goto after the `if' would      *
        * work.  Similarly, if the statement ended with a `with', the      *
        * goto at the end would always be placed inside the `with' when    *
        * it logically belonged outside.                                   *
         **************************************************************/
        Vector result1 = new Vector(); /* a vector of statements */
        Vector result2 = new Vector(); /* a vector of labeled statements */
        boolean needsGoto = false ;
        if (stmts != null && stmts.size() > 0) {
            AST last = (AST) stmts.elementAt(stmts.size() - 1);
            result1 = stmts;
            if (last.getClass().equals(AST.LabelIfObj.getClass())) {
                Vector pair = ExplodeLabelIf((AST.LabelIf) last, next);
                  /*********************************************************
                  * Because a LabelIf has a label in the `then' or `else'  *
                  * clause, ExplodeLabelIf always has to add the           *
                  * necessary gotos.                                       *
                  *********************************************************/
                result1.removeElementAt(result1.size()-1);
                result1.addAll((Vector) pair.elementAt(0));
                result2 = (Vector) pair.elementAt(1);
            }
            // LabelEither added by LL on 25 Jan 2006
            else if (last.getClass().equals(AST.LabelEitherObj.getClass())) {
                Vector pair = ExplodeLabelEither((AST.LabelEither) last, next);
                  /*********************************************************
                  * Because a LabelEither has a label in some clause,      *
                  * ExplodeLabelEither always has to add the necessary     *
                  * gotos.                                                 *
                  *********************************************************/
                result1.removeElementAt(result1.size()-1);
                result1.addAll((Vector) pair.elementAt(0));
                result2 = (Vector) pair.elementAt(1);
            }
            else if (last.getClass().equals(AST.GotoObj.getClass())) {
                AST.Goto g = (AST.Goto) last;
                result1.removeElementAt(result1.size()-1);
                // Note: if there's a GotoObj, then omitPC should be false.
                result1.addElement(UpdatePC(g.to));
            }
            else if (last.getClass().equals(AST.CallObj.getClass())) {
                result1.removeElementAt(result1.size()-1);
                result1.addAll(ExplodeCall((AST.Call) last, next));
            }
            else if (last.getClass().equals(AST.ReturnObj.getClass())) {
                result1.removeElementAt(result1.size()-1);
                result1.addAll(ExplodeReturn((AST.Return) last, next));
            }
            else if (last.getClass().equals(AST.CallReturnObj.getClass())) {
                result1.removeElementAt(result1.size()-1);
                result1.addAll(ExplodeCallReturn((AST.CallReturn) last, next));
            }
            else if (last.getClass().equals(AST.CallGotoObj.getClass())) {
                result1.removeElementAt(result1.size()-1);
                result1.addAll(ExplodeCallGoto((AST.CallGoto) last, next));
            }
            else if (last.getClass().equals(AST.IfObj.getClass())) {
                AST.If If = (AST.If) last;
                Vector p1 = CopyAndExplodeLastStmt(If.Then, next);
                Vector p2 = CopyAndExplodeLastStmt(If.Else, next);
                result2.addAll((Vector) p1.elementAt(1));
                result2.addAll((Vector) p2.elementAt(1));
                If.Then = (Vector) p1.elementAt(0);
                If.Else = (Vector) p2.elementAt(0);
                if (! ParseAlgorithm.omitPC) {
                  boolean thenNeedsGoto = ((BoolObj) p1.elementAt(2)).val ;
                  boolean elseNeedsGoto = ((BoolObj) p2.elementAt(2)).val ;
                  needsGoto = thenNeedsGoto && elseNeedsGoto ;
                  if (! needsGoto){
                    if (thenNeedsGoto) {
                       If.Then.addElement(UpdatePC(next));
                      } ;                
                    if (elseNeedsGoto) {
                       If.Else.addElement(UpdatePC(next));
                     } ;                
                  }
                }
            }
            // EitherObj added by LL on 25 Jan 2006
            else if (last.getClass().equals(AST.EitherObj.getClass())) {
                needsGoto = true ;
                Vector needsGotoVec = new Vector() ;
                AST.Either Either = (AST.Either) last;
                for (int i = 0; i < Either.ors.size(); i++) {
                  Vector thisP = CopyAndExplodeLastStmt( 
                             (Vector) Either.ors.elementAt(i), next);
                  
                  Either.ors.setElementAt(thisP.elementAt(0), i) ;
                  result2.addAll((Vector) thisP.elementAt(1));
                  needsGoto = needsGoto && ((BoolObj) thisP.elementAt(2)).val ;
                  needsGotoVec.addElement(thisP.elementAt(2)) ;
                } ;
                if (! ParseAlgorithm.omitPC) {
                  if (! needsGoto) {
                    /* Each `or' clause needs a goto. */
                    for (int i = 0; i < Either.ors.size(); i++) {
                      if ( ((BoolObj) needsGotoVec.elementAt(i)).val ) {
                        ((Vector) 
                           Either.ors.elementAt(i)).addElement(
                                UpdatePC(next));  
                      }
                     }
                  }
                };
            }
            else if (last.getClass().equals(AST.WithObj.getClass())) {
                AST.With with = (AST.With) last;
                Vector p = CopyAndExplodeLastStmt(with.Do, next);
                with.Do = (Vector) p.elementAt(0);
                result2.addAll((Vector) p.elementAt(1));
                  /*********************************************************
                  * This statement should be a no-op because a `with'      *
                  * should have no labels inside it.  Perhaps we should    *
                  * add a test for this.  (LL comment)                     *
                  *********************************************************/
                needsGoto = ((BoolObj) p.elementAt(2)).val ;
            }
            else needsGoto = true ; // result1.addElement(UpdatePC(next));
        }
        else { 
          /* This is an empty sequence of statements.  */
          needsGoto = true ;
        }  ;
//        else  result1.addElement(UpdatePC(next));
        if (ParseAlgorithm.omitPC) {
            needsGoto = false;
        }
        return Triple(result1, result2, BO(needsGoto));
    }


    private static Vector 
          CopyAndExplodeLastStmtWithGoto(Vector stmts, String next) throws PcalTranslateException {
      /*********************************************************************
      * Added by LL on 5 Feb 2011: The following comment seems to be       *
      * wrong, and the method adds a goto iff the 3rd element of the       *
      * value returned by CopyAndExplodeLastStmt equals true.              *
      *                                                                    *
      * Like CopyAndExplodeLastStmt, but it always adds a goto and         *
      * returns only a pair consisting of the first two elements of the    *
      * triple returned by CopyAndExplodeLastStmt.                         *
      *********************************************************************/
      Vector res = CopyAndExplodeLastStmt(stmts, next) ;
        if (((BoolObj) res.elementAt(2)).val) {
          ((Vector) res.elementAt(0)).addElement(UpdatePC(next)); } ;    
      return Pair(res.elementAt(0), res.elementAt(1)) ;
    }


    private static Vector ExplodeLabeledStmt (AST.LabeledStmt ast,
                                              String next) throws PcalTranslateException {
         /******************************************************************
         * label SL -->                                                    *
         * label when pc = "label" ;                                       *
         *       SL                                                        *
         *       pc := next;                                               *
         *                                                                 *
         * Comment added by LL on 30 Jan 2006.                             *
         * I have no idea what the comment above is supposed to mean, but  *
         * this seems to return a sequence of labeled statements,          *
         * consisting of the exploded version of the labeled stmt ast      *
         * followed by the exploded labeled statements contained within    *
         * it.                                                             *
         ******************************************************************/
        /* Handle case of initial while separately */
        if (ast.stmts.size() > 0 && 
            ast.stmts.elementAt(0).getClass().equals(AST.WhileObj.getClass())) {
            return ExplodeWhile(ast, next);
        }
        AST.LabeledStmt newast = new AST.LabeledStmt();
        Vector pair = 
                CopyAndExplodeLastStmtWithGoto((Vector) ast.stmts.clone(), 
                                               next);
        Vector result = new Vector();
        newast.setOrigin(ast.getOrigin()) ;
        newast.col = ast.col;
        newast.line = ast.line;
        newast.label = ast.label;
        /* add the statements with last exploded */
        newast.stmts = (Vector) pair.elementAt(0);
        if (! ParseAlgorithm.omitPC) {
           /* prepend pc check */
           newast.stmts.insertElementAt(CheckPC(newast.label), 0);
           result.addElement(newast);
        }
        /* add recursively generated labeled statements */
        result.addAll((Vector) pair.elementAt(1));
        return result;
    }

    private static Vector ExplodeLabeledStmtSeq (Vector seq,
                                                 String next) throws PcalTranslateException {
     /**********************************************************************
     * seq is a sequence of LabeledStmts, and `next' is the label that     *
     * follows them.  Returns the sequence of LabeledStmts obtained by     *
     * iteratively calling ExplodeLabeledStmt to explode the statements    *
     * in seq.                                                             *
     *                                                                     *
     * Added by LL on 30 Jan 2006.  I don't know why this method did not   *
     * already exist, since it must have been written in-line about 5      *
     * times in various other methods.                                     *
     **********************************************************************/
     Vector result = new Vector() ;     
     for (int i = 0; i < seq.size(); i++) {
       AST.LabeledStmt stmt = (AST.LabeledStmt) seq.elementAt(i) ;
       String nxt = (i < seq.size() - 1) ?
                      ((AST.LabeledStmt) seq.elementAt(i+1)).label : next ;
       result.addAll(ExplodeLabeledStmt(stmt, nxt)) ;
      };
     return result ;
     }

    /*
     * Experimentation shows that the following method is called with ast
     * equal to a LabeledStmt such that the first elementof ast.stmts 
     * is an AST.While node, and the remaining elements are the unlabeled
     * statements following the source `while' statement.
     */
    private static Vector ExplodeWhile(AST.LabeledStmt ast,
                                       String next) throws PcalTranslateException {
        /*******************************************************************
        * label test unlabDo labDo next -->                                *
        * label when pc = "label" ;                                        *
        *       if test then unlabDo; pc := ld1;                           *
        *       else rest of statements                                    *
        *            pc := next                                            *
        * ld1   ...                                                        *
        * ldk   ...                                                        *
        *       pc := "label";                                             *
        *                                                                  *
        * Returns a pair that's like the first two elements of the         *
        * triple returned by CopyAndExplodeLastStmt.  (It always adds      *
        * the necessary goto to transfer control.)                         *
        *                                                                  *
        * If the test is TRUE or (TRUE) then the exploded code is          *
        * simplified to eliminate the if statement.  Any code that would   *
        * be executed in the "else" clause is discarded.  A warning        *
        * message is generated when the exploded code is simplified.       *
        *******************************************************************/
        Vector result = new Vector();
        AST.While w = (AST.While) ast.stmts.elementAt(0);

        AST.LabeledStmt newast = new AST.LabeledStmt();
        /*
         * We set the origin of the new LabeledStatement to that of
         * ast, if there is a statement that follows the While.  Otherwise,
         * it goes from the label to the end of the If constructed from the while.
         * 
         * We set the origin of the If constructed from the while to the end 
         * its unLabDo if there is a non-empty labDo, otherwise to the end
         * of the While. 
         */
        PCalLocation newastBeginLoc = ast.getOrigin().getBegin() ;
        PCalLocation whileBeginLoc = w.getOrigin().getBegin() ;
        PCalLocation whileBeginUnlabDoLoc = 
          (w.unlabDo.size() != 0) ? 
           ((AST) w.unlabDo.elementAt(0)).getOrigin().getBegin() :
            w.test.getOrigin().getEnd();
        PCalLocation whileEndUnlabDoLoc =
          (w.unlabDo.size() != 0) ? 
            ((AST) w.unlabDo.elementAt(w.unlabDo.size()-1)).getOrigin().getEnd() :
            w.test.getOrigin().getEnd();
        PCalLocation whileEndLoc = 
           // The original code contained
           //
           //     (w.labDo.size() != 0) ? w.getOrigin().getEnd() : whileEndUnlabDoLoc ; 
           //
           // which does not implement the comment above.
                (ast.stmts.size() != 1) ? ast.getOrigin().getEnd() : whileEndUnlabDoLoc ;
        newast.setOrigin(new Region(newastBeginLoc, whileEndLoc)) ;
        newast.col = ast.col;
        newast.line = ast.line;
        newast.label = ast.label;
        newast.stmts = new Vector();

        if (! ParseAlgorithm.omitPC) {
           newast.stmts.addElement(CheckPC(ast.label));   // pc test
        }

        /* determine where control goes after unlabDo is executed */
        AST.LabeledStmt firstLS = (w.labDo.size() == 0)
            ? null : (AST.LabeledStmt) w.labDo.elementAt(0);
        /* explode unlabDo */
        String unlabDoNext = (firstLS == null) ? ast.label : firstLS.label ;
        Vector pair1 = 
                CopyAndExplodeLastStmtWithGoto((Vector) w.unlabDo.clone(),
                                                unlabDoNext);
        /* explode the rest of the statements */
        Vector rest = (Vector) ast.stmts.clone();
           // Note: experimentation shows that clone() does a shallow copy, so
           // the elements of rest are == to the elements of ast.stmts.
        rest.remove(0);
        Vector pair2 = CopyAndExplodeLastStmtWithGoto(rest, next);

        if (IsTRUE(w.test)) // Optimized translation of while TRUE do
            newast.stmts.addAll((Vector) pair1.elementAt(0));
        else {
            AST.If ifS = new AST.If();
            ifS.test = w.test;
            ifS.Then = (Vector) pair1.elementAt(0);
            ifS.Else = (Vector) pair2.elementAt(0);
            ifS.setOrigin(new Region(whileBeginLoc, whileEndLoc)) ;
            newast.stmts.addElement(ifS);
        }
        result.addElement(newast);

        /* explode the enclosed labeled statements and add to the result */
        for (int i = 0; i < w.labDo.size(); i++) {
            AST.LabeledStmt nextLS = (w.labDo.size() > i + 1)
            ? (AST.LabeledStmt) w.labDo.elementAt(i + 1) : null;
            String nextLSL = (nextLS == null) ? ast.label : nextLS.label;
            result.addAll(ExplodeLabeledStmt(firstLS, nextLSL));
            firstLS = nextLS;
        }

        result.addAll((Vector) pair1.elementAt(1));
        
        // If IsTRUE(w.test) is true and pair2.elementAt(1) is not an empty
        // list, then there are unreachable statements after the While and
        // we should probably report an error.
        if (! IsTRUE(w.test)) 
            result.addAll((Vector) pair2.elementAt(1));

        return result;
    }

    private static Vector ExplodeLabelIf(AST.LabelIf ast, String next) throws PcalTranslateException {
        /***************************************************************
         *       test unlabThen labThen unlabElse labElse next -->     *
         *       if test then                                          *
         *          unlabThen                                          *
         *          pc := lt1                                          *
         *       else                                                  *
         *          unlabElse                                          *
         *          pc := le1                                          *
         * lt1   ...                                                   *
         * ltk   ...                                                   *
         *       pc := next;                                           *
         * le1   ...                                                   *
         * lek   ...                                                   *
         *       pc := next;                                           *
         *                                                             *
         * The result is a pair: the first is a vector of statements   *
         * corresponding to the block before lt1, and the second is    *
         * is a vector of the remaining labeled statements.            *
         ***************************************************************/
        int i = 0;
        Vector result1 = new Vector(); /* If for unlabeled statements */
        Vector result2 = new Vector(); /* the labeled statements */
        AST.If newif = new AST.If();
        AST.LabeledStmt firstThen = (ast.labThen.size() > 0)
            ? (AST.LabeledStmt) ast.labThen.elementAt(0) : null;
        AST.LabeledStmt firstElse = (ast.labElse.size() > 0)
            ? (AST.LabeledStmt) ast.labElse.elementAt(0) : null;
        Vector explodedThen = 
                 CopyAndExplodeLastStmtWithGoto(ast.unlabThen,
                                                (firstThen == null)
                                                ? next : firstThen.label);
        Vector explodedElse = 
                  CopyAndExplodeLastStmtWithGoto(ast.unlabElse,
                                                 (firstElse == null)
                                                 ? next : firstElse.label);
        /* Construct if statement */
        newif.test = ast.test;
        newif.col = ast.col;
        newif.line = ast.line;
        newif.Then = (Vector) explodedThen.elementAt(0);
        newif.Else =  (Vector) explodedElse.elementAt(0);
        newif.setOrigin(ast.getOrigin()) ;
        /*
         * The LabelIf object ast has a labeled statement in its then clause iff
         * ast.labThen or explodedThen.elementAt(1) has non-zero length.
         * It has a labeled statement in its else clause iff
         * ast.labElse or explodedElse.elementAt(1) has non-zero length.
         */
        newif.setSource(
            ((ast.labThen.size() != 0 || 
            ((Vector) explodedThen.elementAt(1)).size() != 0 ) 
               ? AST.IfObj.BROKEN_THEN : 0)      
            +
            ((ast.labElse.size() != 0 || 
            ((Vector) explodedElse.elementAt(1)).size() != 0 ) 
               ? AST.IfObj.BROKEN_ELSE : 0)
          ) ;
        result1.addElement(newif);

        /* Explode the labeled then statements */
        AST.LabeledStmt nextThen = (ast.labThen.size() > 1)
            ? (AST.LabeledStmt) ast.labThen.elementAt(1) : null;
        i = 0;
        while (i < ast.labThen.size()) {
            String nextThenLabel = (nextThen == null) ? next : nextThen.label;
            result2.addAll(ExplodeLabeledStmt(firstThen, nextThenLabel));
            i = i + 1;
            firstThen = nextThen;
            nextThen = (ast.labThen.size() > i + 1)
                ? (AST.LabeledStmt) ast.labThen.elementAt(i + 1) : null;
        }
        /* Explode the labeled else statements */
        AST.LabeledStmt nextElse = (ast.labElse.size() > 1)
            ? (AST.LabeledStmt) ast.labElse.elementAt(1) : null;
        i = 0;
        while (i < ast.labElse.size()) {
            String nextElseLabel = (nextElse == null) ? next : nextElse.label;
            result2.addAll(ExplodeLabeledStmt(firstElse, nextElseLabel));
            i = i + 1;
            firstElse = nextElse;
            nextElse = (ast.labElse.size() > i + 1)
                ? (AST.LabeledStmt) ast.labElse.elementAt(i + 1) : null;
        }
        
        
        /* Add labeled statements from exploding unlabThen and unlabElse */
        result2.addAll((Vector) explodedThen.elementAt(1));
        result2.addAll((Vector) explodedElse.elementAt(1));
        return Pair(result1, result2);
    }

    private static Vector ExplodeLabelEither(AST.LabelEither ast, 
                                             String next) throws PcalTranslateException {
        /*******************************************************************
        * Analogous to ExplodeLabelIf, except it hasa sequence of clauses  *
        * rather than just the then and else clauses.                      *
        *                                                                  *
        * The result is a pair: the first is a vector of statements        *
        * corresponding to the block before lt1, and the second is         *
        * is a vector of the remaining labeled statements.                 *
        *******************************************************************/
        Vector result1 = new Vector(); /* For the Either object.           */
        Vector result2 = new Vector(); /* The internal labeled statements. */
        AST.Either newEither = new AST.Either();

        /* Construct Either object */
        newEither.col = ast.col;
        newEither.line = ast.line;
        newEither.setOrigin(ast.getOrigin()) ;
        newEither.ors = new Vector() ;
        for (int i = 0; i < ast.clauses.size(); i++) {
          AST.Clause clause = (AST.Clause) ast.clauses.elementAt(i) ;
          Vector res = 
             CopyAndExplodeLastStmtWithGoto(
               clause.unlabOr,
               (clause.labOr.size() > 0) ?
                  ((AST.LabeledStmt) clause.labOr.elementAt(0)).label : next
               ) ;
          /**
           * Set clause.broken, which should be true iff clause.labOr or
           * res.elementAt(1) is non-empty.
           */
         if (clause.labOr.size() != 0 || ((Vector) res.elementAt(1)).size() != 0) {
             clause.setBroken(true) ;
         }         
         newEither.ors.addElement((Vector) res.elementAt(0)) ;
         result2.addAll((Vector) res.elementAt(1)) ;
         result2.addAll(ExplodeLabeledStmtSeq(clause.labOr, next)) ;
        } ;
        result1.addElement(newEither);
        return Pair(result1, result2);
    }

    /***********************************************************************
    * Generate sequence of statements corresponding to call                *
    *                                                                      *
    * Modified 1 Feb 2006 by LL to put the initialization of the           *
    * procedure's local variables as a sequence of separate assignment     *
    * statements, executed after the initialization of the formal          *
    * parameters.                                                          *
    *                                                                      *
    * Modified by LL on 2 Feb 2006 to add line and column numbers to the   *
    * newly created statements for error reporting.                        
     **
    ***********************************************************************/
    private static Vector ExplodeCall(AST.Call ast, String next) throws PcalTranslateException {
        Vector result = new Vector();
        int to = st.FindProc(ast.to);
        /*******************************************************************
        * Error check added by LL on 30 Jan 2006 to fix bug_05_12_10.      *
        *******************************************************************/
        if (to == st.procs.size())
          { throw new PcalTranslateException("Call of non-existent procedure " + ast.to,
                                    ast);  } ;
        PcalSymTab.ProcedureEntry pe =
            (PcalSymTab.ProcedureEntry) st.procs.elementAt(to);
        /*******************************************************************
        * Set ass to a multiple assignment that pushes the call record on  *
        * the stack, sets the called procedure's parameters.               *
        *                                                                  *
        * The call record put on the stack is:                             *
        *   procedure |-> ast.to                                           *
        *   pc |-> next                                                    *
        *   for each procedure variable v of ast.to v |-> v                *
        *   for each parameter p of ast.to p |-> p                         *
        *******************************************************************/
        AST.Assign ass = new AST.Assign();
        ass.ass = new Vector();
        ass.line = ast.line ;
        ass.col  = ast.col ;
        AST.SingleAssign sass = new AST.SingleAssign();
        sass.line = ast.line ;
        sass.col  = ast.col ;
        sass.lhs.var = "stack";
        sass.lhs.sub = MakeExpr(new Vector());
        TLAExpr expr = new TLAExpr();
        expr.addLine();
        expr.addToken(BuiltInToken("<<"));
        expr.addToken(BuiltInToken("["));
        expr.addToken(IdentToken("procedure"));
        expr.addToken(BuiltInToken("|->"));
        expr.addToken(StringToken(ast.to));
        expr.addToken(BuiltInToken(","));
        expr.addLine();
        expr.addToken(IdentToken("pc"));
        expr.addToken(BuiltInToken("|->"));
        expr.addToken(StringToken(next));       
        for (int i = 0; i < pe.decls.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.decls.elementAt(i);
            expr.addToken(BuiltInToken(","));
            expr.addLine();
            expr.addToken(IdentToken(decl.var));
            expr.addToken(BuiltInToken("|->"));
            expr.addToken(IdentToken(decl.var));
        }
        for (int i = 0; i < pe.params.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.params.elementAt(i);
            expr.addToken(BuiltInToken(","));
            expr.addLine();
            expr.addToken(IdentToken(decl.var));
            expr.addToken(BuiltInToken("|->"));
            expr.addToken(IdentToken(decl.var));
        }
        expr.addToken(BuiltInToken("]"));
        expr.addToken(BuiltInToken(">>"));
        expr.addLine();
        expr.addToken(BuiltInToken("\\o"));
        expr.addToken(AddedToken("stack"));
        MakeNewStackTopExprPretty(expr);
        expr.normalize();
        sass.rhs = expr;
        ass.ass.addElement(sass);
        /*********************************************************
         * for each parameter p of ast.to                        *
         *   p := matching expr in ast.arg                       *
         *********************************************************/
        /*******************************************************************
        * Assert changed to ReportErrorAt by LL on 30 Jan 2006.            *
        *******************************************************************/
        if (pe.params.size() != ast.args.size())
            throw new PcalTranslateException(
                  "Procedure " + ast.to +
                       " called with wrong number of arguments",
                  ast) ;
        /**
         * Set the origin of the AST.Assign object ass.origin to the region occupied
         * by the parameter declarations, and set the origin of each of its SingleAssign 
         * subobjects that set the parameters to that parameter's declaration as a parameter
         * of the procedure.  (This code assumes that  the declarations appear in the params
         * list of an AST.Procedure in the order in which they appear in the PCal code.)
         * Since we're setting the origin to the entire declaration, if the declaration
         * specifies an initial value, then this will set the origin to the entire
         * declaration, rather than just the variable name.  This could be fixed easily,
         * but it's not worth the effort.
         */
        PCalLocation beginLoc = null ;
        PCalLocation endLoc = null ;
        for (int i = 0; i < pe.params.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.params.elementAt(i);
            if (i == 0) {
                beginLoc = decl.getOrigin().getBegin();
            }
            if (i == pe.params.size() - 1) {
                endLoc = decl.getOrigin().getEnd();
            }
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            sass.setOrigin(decl.getOrigin()) ;
            sass.lhs.var = decl.var;
            sass.lhs.sub = MakeExpr(new Vector());
            sass.rhs = (TLAExpr) ast.args.elementAt(i);
            ass.ass.addElement(sass);
        }
        if (beginLoc != null) {
            ass.setOrigin(new Region(beginLoc, endLoc)) ;
        }
        result.addElement(ass);
        /*******************************************************************
        * Add a sequence of assignment statements to initialize each       *
        * procedure variable v of ast.to with                              *
        *   v := initial value                                             *
        *******************************************************************/
        for (int i = 0; i < pe.decls.size(); i++) {
            ass = new AST.Assign();
            ass.ass = new Vector() ;
            ass.line = ast.line ;
            ass.col  = ast.col ;
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.decls.elementAt(i);
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            sass.setOrigin(decl.getOrigin()) ;
            sass.lhs.var = decl.var;
            sass.lhs.sub = MakeExpr(new Vector());
            sass.rhs = (TLAExpr) decl.val;
            ass.setOrigin(decl.getOrigin()) ;
            ass.ass.addElement(sass);
            result.addElement(ass) ;
        }
        
        /*******************************************************************
        * Add assignment to set pc:                                        *
        *   pc := entry point of ast.to                                    *
        *******************************************************************/
        // Note: omitPC must be false if there's a call statement (and hence
        // a procedure being called).
        result.addElement(UpdatePC(pe.iPC));
        return result;
    }

    /***********************************************************************
    * Modified by LL on 2 Feb 2006 to add line and column numbers to the   *
    * newly created statements for error reporting.                        
     **
    ***********************************************************************/
    private static Vector ExplodeReturn(AST.Return ast, String next) throws PcalTranslateException {
        Vector result = new Vector();
        /*******************************************************************
        * On 30 Mar 2006, added code to throw a PcalTranslateException     *
        * when ast.from equals null to raise an error if a return          *
        * statement appears outside a procedure.  That error was not       *
        * caught by the parsing phase for reasons explained in the         *
        * comments for ParseAlgorithm.GetReturn.                           *
        *                                                                  *
        * Unfortunately, that test raised an error if the return actually  *
        * was inside a procedure but was generated by macro expansion.     *
        * To allow that case, on 7 June 2010 LL added the                  *
        * currentProcedure field (see comments for that field) and         *
        * modified the test accordingly.  (This was after an incorrect     *
        * attempt to fix the problem on 6 June 2010.)                      *
        *******************************************************************/
        if (ast.from == null)
        {
            ast.from = currentProcedure;
        }
        if (ast.from == null)
        {
            throw new PcalTranslateException("`return' statement not in procedure", ast);
        }
        ;

        int from = st.FindProc(ast.from);
        // The following added by LL on 13 Jan 2011.
        if (!(from < st.procs.size())) {
        	throw new PcalTranslateException("Error in procedure (perhaps name used elsewhere)", ast);
        }
        PcalSymTab.ProcedureEntry pe =
            (PcalSymTab.ProcedureEntry) st.procs.elementAt(from);
        /*********************************************************
         * With h being the head of stack                        *
         *   pc := h.pc                                          *
         *   for each procedure variable v of ast.from v := h.v  *
         *   for each parameter p of ast.from p := h.p           *
         *********************************************************/
        AST.Assign ass = new AST.Assign();
        ass.line = ast.line ;
        ass.col  = ast.col ;
        AST.SingleAssign sass = new AST.SingleAssign();
        sass.line = ast.line ;
        sass.col  = ast.col ;
        TLAExpr expr = new TLAExpr();
        sass.lhs.var = "pc";
        sass.lhs.sub = new TLAExpr();
        expr.addLine();
        expr.addToken(IdentToken("Head"));
        expr.addToken(BuiltInToken("("));
        expr.addToken(AddedToken("stack"));
        expr.addToken(BuiltInToken(")"));
        expr.addToken(BuiltInToken("."));
        expr.addToken(IdentToken("pc"));
        expr.normalize();
        sass.rhs = expr;
        ass.ass = Singleton(sass);
        result.addElement(ass);
        for (int i = 0; i < pe.decls.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.decls.elementAt(i);
            ass = new AST.Assign();
            ass.line = ast.line ;
            ass.col  = ast.col ;
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            expr = new TLAExpr();
            sass.lhs.var = decl.var;
            sass.lhs.sub = new TLAExpr();
            expr.addLine();
            expr.addToken(IdentToken("Head"));
            expr.addToken(BuiltInToken("("));
            expr.addToken(AddedToken("stack"));
            expr.addToken(BuiltInToken(")"));
            expr.addToken(BuiltInToken("."));
            expr.addToken(IdentToken(decl.var));
            expr.normalize();
            sass.rhs = expr;
            /**
             * For assignments that restore procedure variables, there's no
             * good origin.  I decided to set them to the origin of the return statement.
             */
            sass.setOrigin(ast.getOrigin()) ;
            ass.setOrigin(ast.getOrigin()) ;
            ass.ass = Singleton(sass);
            result.addElement(ass);
        }
        for (int i = 0; i < pe.params.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) pe.params.elementAt(i);
            ass = new AST.Assign();
            ass.line = ast.line ;
            ass.col  = ast.col ;
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            /** For assignments that restore procedure parameter values, there's no
             * good origin.  I decided to set them to the origin of the return statement.
             */
            sass.setOrigin(ast.getOrigin()) ;
            ass.setOrigin(ast.getOrigin()) ;
            expr = new TLAExpr();
            sass.lhs.var = decl.var;
            sass.lhs.sub = new TLAExpr();
            expr.addLine();
            expr.addToken(IdentToken("Head"));
            expr.addToken(BuiltInToken("("));
            expr.addToken(AddedToken("stack"));
            expr.addToken(BuiltInToken(")"));
            expr.addToken(BuiltInToken("."));
            expr.addToken(IdentToken(decl.var));
            expr.normalize();
            sass.rhs = expr;
            ass.ass = Singleton(sass);
            result.addElement(ass);
        }

        /*********************************************************
         * stack := Tail(stack)                                  *
         *********************************************************/
        ass = new AST.Assign();
        ass.line = ast.line ;
        ass.col  = ast.col ;
        sass = new AST.SingleAssign();
        sass.setOrigin(ast.getOrigin()) ;
        ass.setOrigin(ast.getOrigin()) ;
        sass.line = ast.line ;
        sass.col  = ast.col ;
        expr = new TLAExpr();
        sass.lhs.var = "stack";
        sass.lhs.sub = new TLAExpr();
        expr.addLine();
        expr.addToken(IdentToken("Tail"));
        expr.addToken(BuiltInToken("("));
        expr.addToken(AddedToken("stack"));
        expr.addToken(BuiltInToken(")"));
        expr.normalize();
        sass.rhs = expr;
        ass.ass = Singleton(sass);
        result.addElement(ass);
        return result;
    }

    /***********************************************************************
    * Generate sequence of statements corresponding to call followed by a  *
    * returen.                                                             *
    *                                                                      *
    * Modified 1 Feb 2006 by LL for the case of the calling and called     *
    * procedures being different to put the initialization of the          *
    * procedure's local variables as a sequence of separate assignment     *
    * statements, executed after the initialization of the formal          *
    * parameters.                                                          *
    *                                                                      *
    * Modified by LL on 2 Feb 2006 to add line and column numbers to the   *
    * newly created statements for error reporting.                        
     **
    ***********************************************************************/
    private static Vector ExplodeCallReturn(AST.CallReturn ast, String next) throws PcalTranslateException {
        Vector result = new Vector();
        /*******************************************************************
        * The following test for a return not in a procedure was added by  *
        * LL on 30 Mar 2006.  This error isn't caught by the parsing       *
        * phase for reasons explained in the comments for                  *
        * ParseAlgorithm.GetReturn.                                        *
        *******************************************************************/
        if (ast.from == null)
          { throw new PcalTranslateException(
              "`return' statement following `call' at " +
               ast.location() + " not in a procedure");
          } ;
        int from = st.FindProc(ast.from);
        PcalSymTab.ProcedureEntry peFrom =
            (PcalSymTab.ProcedureEntry) st.procs.elementAt(from);
        int to = st.FindProc(ast.to);
        /*******************************************************************
        * Assert changed to ReportErrorAt by LL on 30 Jan 2006, and moved  *
        * to where it belongs.                                             *
        *******************************************************************/
        if (to == st.procs.size())
          { throw new PcalTranslateException("Call of non-existent procedure " + ast.to,
                                    ast);  } ;
        PcalSymTab.ProcedureEntry peTo =
            (PcalSymTab.ProcedureEntry) st.procs.elementAt(to);
        PcalDebug.Assert(from < st.procs.size());
        AST.Assign ass = new AST.Assign();
        ass.ass = new Vector();
        ass.line = ast.line ;
        ass.col  = ast.col ;
        AST.SingleAssign sass = null;
        TLAExpr expr = null;
        /*******************************************************************
        * Add a single multiple assignment statement that                  *
        *   - restores the local variables of ast.from from the head of    *
        *     the stack.                                                   *
        *   - replaces the head of the stack with a record used to reset   *
        *     the local variables.                                         *
        *   - sets the parameters of ast.to.                               *
        *                                                                  *
        * First, with h being the head of the stack, restore each local    *
        * variable v of ast.from with v := h.v .                           *
        *******************************************************************/
        if (! ast.from.equals(ast.to)) {
            for (int i = 0; i < peFrom.decls.size(); i++) {
                AST.PVarDecl decl =
                    (AST.PVarDecl) peFrom.decls.elementAt(i);
                sass = new AST.SingleAssign();
                sass.line = ast.line ;
                sass.col  = ast.col ;
                expr = new TLAExpr();
                sass.lhs.var = decl.var;
                sass.lhs.sub = new TLAExpr();
                expr.addLine();
                expr.addToken(IdentToken("Head"));
                expr.addToken(BuiltInToken("("));
                expr.addToken(AddedToken("stack"));
                expr.addToken(BuiltInToken(")"));
                expr.addToken(BuiltInToken("."));
                expr.addToken(IdentToken(decl.var));
                expr.normalize();
                sass.rhs = expr;
                ass.ass.addElement(sass);
            }
            /********************************************************
             * Replace head of stack with record                    *
             *   procedure |-> ast.to                               *
             *   pc |-> h.pc (for current head h)                   *
             *   for each procedure variable v of ast.to v |-> v    *
             *   for each parameter variable p of ast.to p |-> p    *
             ********************************************************/
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            sass.lhs.var = "stack";
            sass.lhs.sub = MakeExpr(new Vector());
            expr = new TLAExpr();
            expr.addLine();
            expr.addToken(BuiltInToken("<<"));
            expr.addToken(BuiltInToken("["));
            expr.addToken(IdentToken("procedure"));
            expr.addToken(BuiltInToken("|->"));
            expr.addToken(StringToken(ast.to));
            expr.addToken(BuiltInToken(","));
            expr.addLine();
            expr.addToken(IdentToken("pc"));
            expr.addToken(BuiltInToken("|->"));
            expr.addToken(IdentToken("Head"));
            expr.addToken(BuiltInToken("("));
            expr.addToken(AddedToken("stack"));
            expr.addToken(BuiltInToken(")"));
            expr.addToken(BuiltInToken("."));
            expr.addToken(IdentToken("pc"));
            for (int i = 0; i < peTo.decls.size(); i++) {
                AST.PVarDecl decl =
                    (AST.PVarDecl) peTo.decls.elementAt(i);
                expr.addToken(BuiltInToken(","));
                expr.addLine();
                expr.addToken(IdentToken(decl.var));
                expr.addToken(BuiltInToken("|->"));
                expr.addToken(IdentToken(decl.var));
            }
            for (int i = 0; i < peTo.params.size(); i++) {
                AST.PVarDecl decl =
                    (AST.PVarDecl) peTo.params.elementAt(i);
                expr.addToken(BuiltInToken(","));
                expr.addLine();
                expr.addToken(IdentToken(decl.var));
                expr.addToken(BuiltInToken("|->"));
                expr.addToken(IdentToken(decl.var));
            }
            expr.addToken(BuiltInToken("]"));
            expr.addToken(BuiltInToken(">>"));
            expr.addLine();
            expr.addToken(BuiltInToken("\\o"));
            expr.addToken(IdentToken("Tail"));
            expr.addToken(BuiltInToken("("));
            expr.addToken(AddedToken("stack"));
            expr.addToken(BuiltInToken(")"));
            MakeNewStackTopExprPretty(expr);
            expr.normalize();
            sass.rhs = expr;
            ass.ass.addElement(sass);
        }
        /*********************************************************
         * for each parameter p of ast.to                        *
         *   p := matching expr in ast.arg                       *
         *********************************************************/
        /*******************************************************************
        * Assert changed to ReportErrorAt by LL on 30 Jan 2006.            *
        *******************************************************************/
        if (peTo.params.size() != ast.args.size())
            throw new PcalTranslateException(
                  "Procedure " + ast.to +
                       " called with wrong number of arguments",
                  ast) ;
        /**
         * Setting of origins of created AST.Assign and AST.SingleAssign objects
         * essentialy the same as in ExplodeCall.
         */
        PCalLocation beginLoc = null ;
        PCalLocation endLoc = null ;
        for (int i = 0; i < peTo.params.size(); i++) {
            AST.PVarDecl decl =
                (AST.PVarDecl) peTo.params.elementAt(i);
            if (i == 0) {
                beginLoc = decl.getOrigin().getBegin();
            }
            if (i == peTo.params.size() - 1) {
                endLoc = decl.getOrigin().getEnd();
            }
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            sass.lhs.var = decl.var;
            sass.lhs.sub = MakeExpr(new Vector());
            sass.rhs = (TLAExpr) ast.args.elementAt(i);
            ass.ass.addElement(sass);
        }
        if (beginLoc != null) {
            ass.setOrigin(new Region(beginLoc, endLoc)) ;
        }
        result.addElement(ass);
        /*******************************************************************
        * Add a sequence of assignment statements to initialize each       *
        * procedure variable v of ast.to with                              *
        *   v := initial value                                             *
        *******************************************************************/
        for (int i = 0; i < peTo.decls.size(); i++) {
            ass = new AST.Assign();
            ass.line = ast.line ;
            ass.col  = ast.col ;
            ass.ass = new Vector() ;
            AST.PVarDecl decl =
                (AST.PVarDecl) peTo.decls.elementAt(i);
            sass = new AST.SingleAssign();
            sass.line = ast.line ;
            sass.col  = ast.col ;
            sass.setOrigin(decl.getOrigin()) ;
            sass.lhs.var = decl.var;
            sass.lhs.sub = MakeExpr(new Vector());
            sass.rhs = (TLAExpr) decl.val;
            ass.setOrigin(decl.getOrigin()) ;
            ass.ass.addElement(sass);
            result.addElement(ass) ;
        }
        /*********************************************************
         * pc := entry point of ast.to                           *
         *********************************************************/
        result.addElement(UpdatePC(peTo.iPC));
        return result;
    }

    /***********************************************************************
    * Generate sequence of statements corresponding to call followed by a  *
    * goto.                                                                *
    ***********************************************************************/
    private static Vector ExplodeCallGoto(AST.CallGoto ast, String next) throws PcalTranslateException {
      AST.Call call = new AST.Call();
      call.to = ast.to;
      call.args = ast.args;
      call.line = ast.line;
      call.col = ast.col;
      call.setOrigin(ast.getOrigin());
      return ExplodeCall(call, ast.after);
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/PcalTLAGenException.java<|end_filename|>
package pcal.exception;

import pcal.AST;

/**
 * @author <NAME>
 * @version $Id$
 */
public class PcalTLAGenException extends UnrecoverablePositionedException
{

    /**
     * @param message
     */
    public PcalTLAGenException(String message)
    {
        super(message);
    }

    /**
     * @param message
     * @param elementAt2
     */
    public PcalTLAGenException(String message, AST elementAt2)
    {
        super(message, elementAt2);
    }
    
    

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/RootCoverageInformationItem.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.List;

public class RootCoverageInformationItem extends CoverageInformationItem {

	public static final int rootLayer = -2;
	
	public RootCoverageInformationItem() {
		layer = rootLayer;
	}
	
	@Override
	protected boolean isRoot() {
		return true;
	}

	@Override
	CoverageInformationItem setRoot(ActionInformationItem root) {
		throw new RuntimeException("Root must not have siblings.");
	}

	@Override
	CoverageInformationItem setSiblings(List<CoverageInformationItem> siblings) {
		throw new RuntimeException("Root must not have siblings.");
	}

	@Override
	boolean hasSiblings() {
		return false;
	}

	@Override
	CoverageInformationItem addChild(CoverageInformationItem child) {
		if (child instanceof ActionInformationItem) {
			return super.addChild(child);
		}
		throw new IllegalArgumentException("Only ActionInformationItem allowed for root.");
	}

	@Override
	CoverageInformationItem setLayer(int i) {
		throw new RuntimeException("Root has fixed layer.");
	}

	@Override
	public CoverageInformationItem getParent() {
		throw new RuntimeException("Root has no parent.");
	}

	@Override
	public ActionInformationItem getRoot() {
		throw new RuntimeException("Root has no ActionInformationItem.");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ParseUnitsTable.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.modanalyzer;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Each instance of this class basically is a map from ParseUnit objects to
 * ParseUnitRelatives objects.
 *
 * It is just a wrapper for a Hashtable, with the added benefit of type checking
 */

class ParseUnitsTable {

  // Maps ParseUnit string names to their respective ParseUnit objects
  Hashtable parseUnitTable = new Hashtable();

  ParseUnit get(String parseUnitName) { 
    return (ParseUnit)parseUnitTable.get(parseUnitName); 
  }

  void put (ParseUnit parseUnitName, ParseUnit parseUnit) {
    parseUnitTable.put(parseUnitName, parseUnit);
  }

  Enumeration getKeys() { return parseUnitTable.keys(); }  

  public String toString() {
    String ret = "";

    Enumeration e = parseUnitTable.keys();
    while ( e.hasMoreElements()) {
      ret += "[ ParseUnit: " + ((ParseUnit)e.nextElement()).getName() + " ] ";
    }
    return ret;
  }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/tasks/test.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
	<title>See how this works</title>
</head>

<body>
<h1>Open existing specification</h1>
Some description how this can;t be done.
<a href="open_spec.html">open spec</a>

</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/ConsoleProcessOutputSink.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output;

import java.io.IOException;

import org.eclipse.ui.console.IOConsoleOutputStream;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.console.ConsoleFactory;

import tlc2.output.MP;

/**
 * A sink writing to a console. In plain English, this causes the Toolbox's
 * console to show TLC's output (stdout/stderr).
 * 
 * @author <NAME>
 */
public class ConsoleProcessOutputSink implements IProcessOutputSink {

	private final IOConsoleOutputStream outputStream;

	public ConsoleProcessOutputSink() {
		this.outputStream = ConsoleFactory.getTLCConsole().newOutputStream();
	}

	@Override
	public synchronized void appendText(final String text) {
		try {
			// Remove TLC's "-tool" markers for better readability by a human.
			if (Boolean.getBoolean(ConsoleProcessOutputSink.class.getName() + ".tool")) {
				this.outputStream.write(text.getBytes());
			} else {
				final String[] lines = text.split(MP.CR);
				for (String line : lines) {
					if (!line.startsWith(MP.DELIM) && !line.trim().isEmpty()) {
						line += MP.CR;
						this.outputStream.write(line.getBytes());
					}
				}
			}
		} catch (IOException e) {
			TLCUIActivator.getDefault().logError("Error printing a console message: >" + text + "<", e);
		}
	}

	@Override
	public void initializeSink(Model model, int sinkType) {
		// No-op (The why has been lost in time).
	}

	@Override
	public void processFinished() {
		// No-op (The why has been lost in time).
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ModuleContext.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.

// Last modified onFri  2 Mar 2007 at 15:40:00 PST by lamport
/***************************************************************************
* 2 Mar 2007: enum <- Enum                                                 *
***************************************************************************/

package tla2sany.modanalyzer;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * An instance of this class is the ModuleContext for a module, i.e. the mapping between
 * module String names and other ModulePointers elsewhere in the specification that they 
 * are bound to.
 * 
 * There is no distinction made between a String that is not the name of a module known
 * in this context, and an as-yet unbound name that is known.  In both cases resolve()
 * returns null.
 */
public class ModuleContext {

  Hashtable context = new Hashtable();

  /** 
   * Find the ModulePointer that the String modName resolves to;
   * Return null if either modName is not found in the context or
   * if it is found and resolves to null, i.e. is not yet resolved.
   */

  ModulePointer resolve( String modName ) {
    return (ModulePointer)context.get(modName);
  }

  /**
   * Bind a module name to a particular ModulePointer, replacing any binding
   * that is already there to the same modName.
   */
  void bind( String modName, ModulePointer modPointer) {
    context.put(modName,modPointer);
  }

 /**
   * Bind a module name to a particular ModulePointer iff that name is not
   * already bound; otherwise no-op.
   */
  void bindIfNotBound( String modName, ModulePointer modPointer) {
    if (context.get(modName) == null) context.put(modName,modPointer);
  }

  /**
   * Add elements of unionee ModuleContext to THIS ModuleContext,
   * without overwriting in cases where keys overlap between THIS and unionee
   */
  void union (ModuleContext unionee) {

    Enumeration Enum = unionee.context.keys();
    while ( Enum.hasMoreElements() ) {
      String key = (String)Enum.nextElement();
      this.bindIfNotBound(key,unionee.resolve(key));
    }

  }

  public String toString() {
    String ret = "Context:\n";
    Enumeration Enum = context.keys();

    while (Enum.hasMoreElements()) {
      String key = (String)Enum.nextElement();
      ModulePointer modPointer = (ModulePointer)context.get(key);

      ret = ret + "  " + key + "-->" + (modPointer != null ? modPointer.toStringAbbrev() : "null");
    }

    return ret;

  } // end toString()
    

} // end class


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/util/pref/PreferenceStoreHelper.java<|end_filename|>
package org.lamport.tla.toolbox.util.pref;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.util.ResourceHelper;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

/**
 * Utils for accessing persistence storage
 * @author zambrovski
 */
public class PreferenceStoreHelper
{
	/**
     * Stores root file name in project preferences
     * @param project
     * @param rootFilename
     */
	public static void storeRootFilename(IProject project, String rootFilename) {
		// If this condition does not hold, the subsequent code but also
		// AddModuleHandler will not work. The claim is that spec files are
		// always in the parent folder of the IProject.
		final IPath path = new Path(rootFilename);
		Assert.isTrue(ResourceHelper.isProjectParent(path.removeLastSegments(1), project),
				project.getLocation().toOSString() + " is *not* a subdirectory of " + rootFilename
						+ ". This is commonly caused by a symlink contained in the latter path.");
		// Store the filename *without* any path information, but prepend the
		// magical PARENT-1-PROJECT-LOC. It indicates that the file can be found
		// *one* level up (hence the "1") from the project location.
		// readProjectRootFile can later easily deduce the relative location of
		// the file.
		rootFilename = ResourceHelper.PARENT_ONE_PROJECT_LOC + path.lastSegment();
        IEclipsePreferences projectPrefs = getProjectPreferences(project);
        projectPrefs.put(IPreferenceConstants.P_PROJECT_ROOT_FILE, rootFilename);
        storePreferences(projectPrefs);        
    }

    /**
     * Retrieves project root file name
     * @param project
     * @return
     */
	public static IFile readProjectRootFile(IProject project) {
		final IEclipsePreferences projectPrefs = getProjectPreferences(project);
		if (projectPrefs != null) {
			String rootFileName = projectPrefs.get(IPreferenceConstants.P_PROJECT_ROOT_FILE,
					IPreferenceConstants.DEFAULT_NOT_SET);
			if (!IPreferenceConstants.DEFAULT_NOT_SET.equals(rootFileName)) {
				final IPath path = new Path(rootFileName);
				if (path.isAbsolute()) {
					// Convert a legacy (absolute) path to the new relative one
					// with the magic PARENT_PROJECT_LOC prefix.
					rootFileName = ResourceHelper.PARENT_ONE_PROJECT_LOC + path.lastSegment(); 
					convertAbsoluteToRelative(projectPrefs, rootFileName);
				}
				return ResourceHelper.getLinkedFile(project, rootFileName);
			}
		} else {
			Activator.getDefault().logInfo("projectPrefs is null");
		}
		return null;
	}

	private static void convertAbsoluteToRelative(final IEclipsePreferences projectPrefs, final String path) {
		projectPrefs.remove(IPreferenceConstants.P_PROJECT_ROOT_FILE);
		projectPrefs.put(IPreferenceConstants.P_PROJECT_ROOT_FILE, path);
		try {
			projectPrefs.flush();
			projectPrefs.sync();
		} catch (BackingStoreException notExpectedToHappen) {
			Activator.getDefault().logError(
					"Failed to store rewritten absolute to relative root file name: " + path,
					notExpectedToHappen);
		}
	}

    /**
     * Retrieves project preference node
     * @param project 
     * @return
     */
	private static IEclipsePreferences getProjectPreferences(IProject project)
    {
        if (project == null ) 
        {
            return null;
        }
        ProjectScope scope = new ProjectScope(project);
        
        
        //store.get
        
        IEclipsePreferences projectNode = scope.getNode(Activator.PLUGIN_ID);
        return projectNode;
    }
    /**
     * Stores the preferences to disk
     * @param preferences
     */
    private static void storePreferences(Preferences preferences)
    {
        try
        {
            preferences.flush();
        } catch (BackingStoreException e)
        {
            Activator.getDefault().logError("Error storing the preference node", e);
        }
    }

    /**
     * Retrieves preference store with the project scope
     * @return a store instance
     */
    public static IPreferenceStore getProjectPreferenceStore(IProject project)
    {
        ProjectScope scope = new ProjectScope(project);
        ScopedPreferenceStore store = new ScopedPreferenceStore(scope, Activator.PLUGIN_ID /*Activator.getDefault().getBundle().getSymbolicName()*/);
        return store;
    }
    
    public static IPreferenceStore getProjectPreferenceStore(Spec spec) {
    	return getProjectPreferenceStore(spec.getProject());
    }

    /**
     * Retrieves preference store with the workspace scope
     * @return a store instance
     */
    public static IPreferenceStore getInstancePreferenceStore()
    {
        IPreferenceStore store = Activator.getDefault().getPreferenceStore();
        return store;
    }
    
    public static String[] getStringArray(Spec spec, String key, String[] def) {
    	final IPreferenceStore projectPreferences = getProjectPreferenceStore(spec);
    	final String string = projectPreferences.getString(key);
    	if (string == null) {
    		return def;
    	}
    	return string.split(" ");
    }
}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/TreeBarrierTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class TreeBarrierTest extends PCalModelCheckerTestCase {

	public TreeBarrierTest() {
		super("TreeBarrier", "pcal", new String[] {"-wfNext"});
	}

	@Test
	public void testSpec() {
		assertTrue(recorder.recordedWithStringValue(EC.TLC_INIT_GENERATED1, "1"));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_CHECKING_TEMPORAL_PROPS, "complete", "12570", "6 branches of ")); // 6 * 2095 = 12570 
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertFalse(recorder.recorded(EC.GENERAL));
		assertTrue(recorder.recordedWithStringValues(EC.TLC_STATS, "5414", "2095", "0"));
		assertTrue(recorder.recordedWithStringValue(EC.TLC_SEARCH_DEPTH, "106"));

		assertUncovered("line 120, col 19 to line 120, col 32 of module TreeBarrier: 0");
	}
}
/*
C:\lamport\tla\pluscal>java -mx1000m -cp "c:/lamport/tla/newtools/tla2-inria-workspace/tla2-inria/tlatools/class" tlc2.TLC -cleanup TreeBarrier.tla         
TLC2 Version 2.05 of 18 May 2012
Running in Model-Checking mode.
Parsing file TreeBarrier.tla
Parsing file C:\lamport\tla\newtools\tla2-inria-workspace\tla2-inria\tlatools\class\tla2sany\StandardModules\Naturals.tla
Parsing file C:\lamport\tla\newtools\tla2-inria-workspace\tla2-inria\tlatools\class\tla2sany\StandardModules\Sequences.tla
Semantic processing of module Naturals
Semantic processing of module Sequences
Semantic processing of module TreeBarrier
Starting... (2012-08-10 17:39:50)
Implied-temporal checking--satisfiability problem has 6 branches.
Computing initial states...
Finished computing initial states: 1 distinct state generated.
Checking temporal properties for the complete state space...
Model checking completed. No error has been found.
  Estimates of the probability that TLC did not check all reachable states
  because two distinct states had the same fingerprint:
  calculated (optimistic):  val = 3.8E-13
  based on the actual fingerprints:  val = 6.4E-14
5414 states generated, 2095 distinct states found, 0 states left on queue.
The depth of the complete state graph search is 106.
Finished. (2012-08-10 17:39:53)
*/

<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/BufferedRandomAccessFile.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:26 PST by lamport
//      modified on Mon Jun 19 14:28:04 PDT 2000 by yuanyu
package tlc2.util;

/**
 * A <code>BufferedRandomAccessFile</code> is like a
 * <code>RandomAccessFile</code>, but it uses a private buffer
 * so that most operations do not require a disk access.<P>
 * 
 * Note: The operations on this class are unmonitored.
 * The code was written by <NAME>
 */

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;

public final class BufferedRandomAccessFile extends java.io.RandomAccessFile {
	// Increase 8k buffer to match modern day hardware? No!!! The implementation
	// discards the whole buffer each time it seeks to a position outside the
	// current buffer. It then creates a new buffer, which takes proportionally
	// longer with larger buffer sizes.
	static final int LogBuffSz = 13; // 8K buffer
    public static final int BuffSz = (1 << LogBuffSz);
    static final int BuffMask = ~(BuffSz - 1);

    /* This implementation is based on the buffer implementation in
       Modula-3's "Rd", "Wr", "RdClass", and "WrClass" interfaces. */
    private boolean dirty;  // true iff unflushed bytes exist
    // SZ Feb 24, 2009: never read
    // private boolean closed; // true iff the file is closed
    private long curr;      // current position in file
    private long lo, hi;    // bounds on characters in "buff"
    private byte[] buff;    // local buffer
    private long maxHi;     // this.lo + this.buff.length
    private boolean hitEOF; // buffer contains last file block?
    private long diskPos;   // disk position
	private long mark;
    
    private static final Object mu = new Object(); // protects the following fields
    private static byte[][] availBuffs = new byte[100][];
    private static int numAvailBuffs = 0;

    /* To describe the above fields, we introduce the following
       abstractions for the file "f":

          len(f)  the length of the file
         curr(f)  the current position in the file
            c(f)  the abstract contents of the file
         disk(f)  the contents of f's backing disk file
       closed(f)  true iff the file is closed

       "curr(f)" is an index in the closed interval [0, len(f)].
       "c(f)" is a character sequence of length "len(f)". "c(f)"
       and "disk(f)" may differ if "c(f)" contains unflushed
       writes not reflected in "disk(f)". The flush operation has
       the effect of making "disk(f)" identical to "c(f)".

       A file is said to be *valid* if the following conditions
       hold:

       V1. The "closed" and "curr" fields are correct:

           f.closed == closed(f)
           f.curr == curr(f)

       V2. The current position is either contained in the buffer,
           or just past the buffer:

           f.lo <= f.curr <= f.hi

       V3. Any (possibly) unflushed characters are stored
           in "f.buff":

           (forall i in [f.lo, f.curr):
             c(f)[i] == f.buff[i - f.lo])

       V4. For all characters not covered by V3, c(f) and
           disk(f) agree:

           (forall i in [f.lo, len(f)):
             i not in [f.lo, f.curr) => c(f)[i] == disk(f)[i])

       V5. "f.dirty" is true iff the buffer contains bytes that
           should be flushed to the file; by V3 and V4, only part
           of the buffer can be dirty.

           f.dirty ==
           (exists i in [f.lo, f.curr):
             c(f)[i] != f.buff[i - f.lo])

       V6. this.maxHi == this.lo + this.buff.length
       
       Note that "f.buff" can be "null" in a valid file, since the
       range of characters in V3 is empty when "f.lo == f.curr".
       
       A file is said to be *ready* if the buffer contains the
       current position, i.e., when:
       
       R1. !f.closed && f.buff != null
           && f.lo <= f.curr && f.curr < f.hi
           
       When a file is ready, reading or writing a single byte
       can be performed by reading or writing the in-memory
       buffer without performing a disk operation.
    */

    /** Open a new <code>BufferedRandomAccessFile</code> on
        <code>file</code> in mode <code>mode</code>, which
        should be "r" for reading only, or "rw" for reading
        and writing. */
    public BufferedRandomAccessFile(File file, String mode)
    throws IOException {
      super(file, mode);
      this.init();
    }

    /** 
     * Open a new <code>BufferedRandomAccessFile</code> on the
     * file named <code>name</code> in mode <code>mode</code>, 
     * which should be "r" for reading only, or "rw" for reading
     * and writing.
     */
    public BufferedRandomAccessFile(String name, String mode)
    throws IOException 
    {
        // <NAME>. replaced the original:
        //    super(name, mode);
        //    this.init();
        // with this.
        this(new File (name), mode);
    }
    
    /* Initialize the private fields of the file so as to
       make it valid. */
    private void init() {
      this.dirty = false;
      // SZ Feb 24, 2009: never read locally
      // this.closed = false;
      this.lo = this.curr = this.hi = 0;
      synchronized (mu) {
	this.buff =
	  (numAvailBuffs > 0) ? availBuffs[--numAvailBuffs] : new byte[BuffSz];
      }
      this.maxHi = BuffSz;
      this.hitEOF = false;
      this.diskPos = 0L;
    }
    
    /* overrides RandomAccessFile.close() */
    public void close() throws IOException {
        // Assert.check(!this.closed);
        this.flush();
        // SZ Feb 24, 2009: never read locally
        // this.closed = true;
        synchronized (mu) {
            // grow "availBuffs" array if necessary
            if (numAvailBuffs >= availBuffs.length) {
                byte[][] newBuffs = new byte[numAvailBuffs + 10][];
                System.arraycopy(availBuffs, 0, newBuffs, 0, numAvailBuffs);
                availBuffs = newBuffs;
            }
            availBuffs[numAvailBuffs++] = this.buff;
        }
        super.close();
    }
    
    /** Flush any bytes in the file's buffer that have not
        yet been written to disk. If the file was created
        read-only, this method is a no-op. */
    public void flush() throws IOException {
        // Assert.check(!this.closed);
        this.flushBuffer();
    }
    
    /* Flush any dirty bytes in the buffer to disk. */
    private boolean flushBuffer() throws IOException {
        if (this.dirty) {
            // Assert.check(this.curr > this.lo);
            if (this.diskPos != this.lo) super.seek(this.lo);
            int len = (int)(this.curr - this.lo);
            super.write(this.buff, 0, len); 
            this.diskPos = this.curr;
            this.dirty = false;
            return true;
        }
        return false;
    }
    
    /* Read at most "this.buff.length" bytes into "this.buff",
       returning the number of bytes read. If the return result
       is less than "this.buff.length", then EOF was read. */
    private int fillBuffer() throws IOException {
        int cnt = 0;
        int rem = this.buff.length;
        while (rem > 0) {
            int n = super.read(this.buff, cnt, rem); 
            if (n < 0) break;
            cnt += n;
            rem -= n;
        }
        this.hitEOF = (cnt < this.buff.length);
        this.diskPos += cnt;
        return cnt;
    }

    /* overrides RandomAccessFile.seek(long) */
    public void seek(long pos) throws IOException {
        // Assert.check(!this.closed);
        if (pos >= this.hi || pos < this.lo) {
            // seeking outside of current buffer -- flush and read
            this.flushBuffer();
            this.lo = pos & BuffMask; // start at BuffSz boundary
            this.maxHi = this.lo + this.buff.length;
            if (this.diskPos != this.lo) {
                super.seek(this.lo); 
                this.diskPos = this.lo;
            }
            int n = this.fillBuffer();
            this.hi = this.lo + n;
        }
	else {
            // seeking inside current buffer -- no read required
            if (pos < this.curr) {
                // if seeking backwards, we must flush to maintain V4
                this.flushBuffer();
            }
        }
        this.curr = pos;
    }
    
    /* extends this.seek(long) by return if a page has been read (used for statistics) */
    //TODO come up with better name for seeek %)
    public boolean seeek(long pos) throws IOException {
		boolean pageReadNeeded = true;
		// Assert.check(!this.closed);
		if (pos >= this.hi || pos < this.lo) {
			// seeking outside of current buffer -- flush and read
			this.flushBuffer();
			this.lo = pos & BuffMask; // start at BuffSz boundary
			this.maxHi = this.lo + this.buff.length;
			if (this.diskPos != this.lo) {
				super.seek(this.lo);
				this.diskPos = this.lo;
			}
			int n = this.fillBuffer();
			this.hi = this.lo + n;
		} else {
			// seeking inside current buffer -- no read required
			if (pos < this.curr) {
				// if seeking backwards, we must flush to maintain V4
				pageReadNeeded = this.flushBuffer();
			} else {
				pageReadNeeded = false;
			}
		}
		this.curr = pos;
		return pageReadNeeded;
	}

    /* overrides RandomAccessFile.getFilePointer() */
    public long getFilePointer() {
        // Assert.check(!this.closed);
        return this.curr;
    }
    
    /* overrides RandomAccessFile.length() */
    public long length() throws IOException {
        // Assert.check(!this.closed);
        return Math.max(this.curr, super.length());
    }
    
    /* overrides RandomAccessFile.read() */
    public int read() throws IOException {
        // Assert.check(!this.closed);
        if (this.curr == this.hi) {
            // test for EOF
            // if (this.hi < this.maxHi) return -1;
            if (this.hitEOF) return -1;
                
            // slow path -- read another buffer
            this.seek(this.curr);
            if (this.curr == this.hi) return -1;
        }
        // Assert.check(this.curr < this.hi);
        try {
        	byte res = this.buff[(int)(this.curr - this.lo)];
        	this.curr++;
        	return ((int)res) & 0xFF; // convert byte -> int
        } catch (ArrayIndexOutOfBoundsException e) {
        	throw new IOException("Read past end of file (increase with setLength)?", e);
        }
    }
    
    /* overrides RandomAccessFile.read(byte[]) */
    public int read(byte[] b) throws IOException {
        return this.read(b, 0, b.length);
    }
    
    /* overrides RandomAccessFile.read(byte[], int, int) */
    public int read(byte[] b, int off, int len) throws IOException {
        // Assert.check(!this.closed);
        if (this.curr == this.hi) {
            // test for EOF
            // if (this.hi < this.maxHi) return -1;
            if (this.hitEOF) return -1;
                
            // slow path -- read another buffer
            this.seek(this.curr);
            if (this.curr == this.hi) return -1;
        }
        // Assert.check(this.curr < this.hi);
        len = Math.min(len, (int)(this.hi - this.curr));
        int buffOff = (int)(this.curr - this.lo);
        System.arraycopy(this.buff, buffOff, b, off, len);
        this.curr += len;        
        return len;
    }

    public BigInteger readBigInteger(int size) throws IOException {
      byte[] b = new byte[size];
      // Assert.check(this.read(b) == size);
      return new BigInteger(b);
    }
    
    public final int readShortNat() throws IOException {
        int res = this.readByte();
        if (res >= 0) return res;
        res = (res << 16) | (this.readByte() & 0xff);
        return -res;
    }

  public final int readNat() throws IOException {
    int res = this.readShort();
    if (res >= 0) return res;
    res = (res << 16) | (this.readShort() & 0xffff);
    return -res;
  }

  public final long readLongNat() throws IOException {
    long res = this.readInt();
    if (res >= 0) return res;
    res = (res << 32) | ((long)this.readInt() & 0xffffffffL);
    return -res;
  }

    /* overrides RandomAccessFile.write(int) */
    public void write(int b) throws IOException {
        // Assert.check(!this.closed);
        if (this.curr == this.hi) {
            if (this.hitEOF && this.hi < this.maxHi) {
                // at EOF -- bump "hi"
                this.hi++;
            }
	    else {
                // slow path -- write current buffer; read next one
                this.seek(this.curr);
                if (this.curr == this.hi) {
                    // appending to EOF -- bump "hi"
                    // Assert.check(this.hitEOF);
                    this.hi++;
                }
            }
        }
        // Assert.check(this.curr < this.hi);
        try {
        	this.buff[(int)(this.curr - this.lo)] = (byte)b;
        	this.curr++;
        	this.dirty = true;
        } catch (ArrayIndexOutOfBoundsException e) {
        	throw new IOException("Wrote past end of file (increase with setLength)?", e);
        }
    }
    
    /* overrides RandomAccessFile.write(byte[]) */
    public void write(byte[] b) throws IOException {
        this.write(b, 0, b.length);
    }
    
    /* overrides RandomAccessFile.write(byte[], int, int) */
    public void write(byte[] b, int off, int len) throws IOException {
        // Assert.check(!this.closed);
        while (len > 0) {
            int n = this.writeAtMost(b, off, len);
            off += n;
            len -= n;
        }
        this.dirty = true;
    }

    public void writeBigInteger(BigInteger bi, int size) throws IOException {
      byte[] b = bi.toByteArray();
      // Assert.check(b.length <= size);
      this.write(b, 0, size);
    }
    
    /* Precondition: x is a non-negative short. */
    public final void writeShortNat(int x) throws IOException {
      if (x <= 0x7f) {
        this.writeByte((short)x);
      }
      else {
        this.writeShort(-x);
      }
    }

  /* Precondition: x is a non-negative int. */
  public final void writeNat(int x) throws IOException {
    if (x <= 0x7fff) {
      this.writeShort((short)x);
    }
    else {
      this.writeInt(-x);
    }
  }

  /* Precondition: x is a non-negative long. */
  public final void writeLongNat(long x) throws IOException {
    if (x <= 0x7fffffff) {
      this.writeInt((int)x);
    }
    else {
      this.writeLong(-x);
    }
  }

    /* Write at most "len" bytes to "b" starting at position "off",
       and return the number of bytes written. */
    private int writeAtMost(byte[] b, int off, int len)
      throws IOException {
        if (this.curr == this.hi) {
            if (this.hitEOF && this.hi < this.maxHi) {
                // at EOF -- bump "hi"
                this.hi = this.maxHi;
            } else {
                // slow path -- write current buffer; read next one
                this.seek(this.curr);
                if (this.curr == this.hi) {
                    // appending to EOF -- bump "hi"
                    // Assert.check(this.hitEOF);
                    this.hi = this.maxHi;
                }
            }
        }
        // Assert.check(this.curr < this.hi);
        len = Math.min(len, (int)(this.hi - this.curr));
        int buffOff = (int)(this.curr - this.lo);
        System.arraycopy(b, off, this.buff, buffOff, len);
        this.curr += len;
        return len;
    }
    
    /**
	 * Resets the BufferedRandomAccessFile so it appears to be a pristine file.
	 * The previous content of the underlying disk file will be overwritten.
	 * 
	 * @throws IOException
	 */
    public void reset() throws IOException {
    	setLength(0);
    	this.init();
    }
    
    public long getMark() {
    	return this.mark;
    }
    
    public long mark() {
    	final long oldMark = this.mark; 
    	this.mark = getFilePointer();
    	return oldMark;
    }
    
    public void seekAndMark(long pos) throws IOException {
    	this.mark = pos;
    	this.seek(pos);
    }

  public static void main(String[] args) throws IOException {
    String name = "xxx";
    String mode = "rw";
    BufferedRandomAccessFile braf = new BufferedRandomAccessFile(name, mode);
    int x = 100;
    braf.writeLong(x); braf.writeLong(x); braf.writeLong(x);
    System.err.println("len = " + braf.length() + ", pos = " + braf.getFilePointer());
    braf.close();
    braf = new BufferedRandomAccessFile(name, mode);
    System.err.println("len = " + braf.length() + ", pos = " + braf.getFilePointer());
    braf.seek(braf.length());
    System.err.println("len = " + braf.length() + ", pos = " + braf.getFilePointer());
    braf.writeLong(x); braf.writeLong(x); braf.writeLong(x);
    System.err.println("len = " + braf.length() + ", pos = " + braf.getFilePointer());
    braf.close();
  }
  
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/editor/part/IValidateble.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.editor.part;

/**
 * Interface of validateble parts
 * @author <NAME>
 * @version $Id$
 */
public interface IValidateble
{

    /**
     * @param oldInput
     * @param newInput
     */
    public void validate();

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TBGraphNode.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:50 PST by lamport
//      modified on Sun Aug  5 00:16:15 PDT 2001 by yuanyu

package tlc2.tool.liveness;

import tla2sany.semantic.LevelConstants;
import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.util.SetOfLong;
import tlc2.util.Vect;

public class TBGraphNode {
	/**
	 * TBGraphNode represents a node in the tableau graph. Read MP for what a
	 * particle tableau graph is. We give each node in the tableau-graph an
	 * index because it might be useful for hashing. statePreds are deduced from
	 * the particle at the moment of creation. They are later used in checking
	 * if a state-node is consistent with a tableau-node.
	 */
	private final TBPar par; // particle
	public final Vect<TBGraphNode> nexts; // outlinks
	private int index; // unique id for this node
	private final LiveExprNode[] statePreds; // state predicates in the particle

	public static TBGraphNode dummyNode = new TBGraphNode();

	private TBGraphNode() {
		this.par = null;
		this.nexts = null;
		this.index = -1;
		this.statePreds = null;
	}

	public TBGraphNode(TBPar par) {
		this.par = par;
		this.index = 0;
		this.nexts = new Vect<>();
		TBPar preds = new TBPar(par.size());
		for (int i = 0; i < par.size(); i++) {
			LiveExprNode ln = par.exprAt(i);
			// MAK 04/15/2021: See MAK 04/15/2021 notes in comment of
			// tlc2.tool.liveness.LiveExprNode.simplify().
			// The conditional below has been changed in two dimension:
			// a) Instead of checking the concrete ln's type with instanceof, we check the
			// ln's level.
			// b) The check has been changed to accept ConstantLevel *and* VariableLevel,
			// which used to be just VariableLevel.
			// Obviously, constant-level expressions may appear in places where
			// VariableLevel (state-level) expressions are allowed. Ignoring a
			// constant-level expression here, causes bogus counterexamples reported for
			// properties such as `<>TRUE` or `FALSE ~> x#x` (see Github604.tla/java for
			// more details). Widening the check below to include constant-level expressions
			// causes additional state predicates to be created. If one of more of those
			// state predicates evaluate to false for a given state in
			// tlc2.tool.liveness.TBGraphNode.isConsistent(TLCState, ITool), the state gets
			// excluded from the behavior graph.
			// The assertion with msg "Found LNAction(s) in temporal formulae." in
			// Liveness.java implies that the LiveExprNode sub-types that we can encounter
			// here won't include LNActions. The comment of
			// tlc2.tool.liveness.TBPar.positiveClosure() confirms it too.
			// However, ln.getLevel might still be action or temporal because of e.g. formulae
			// such as `[]~someStatePredicate` as negation of `<>someStatePredicate`, or
			// `()[]~(someStatePredicate)` as a particle of `[]-someStatePredicate` with `()`
			// denoting LNNext/LTL's next operator.
			if (ln.getLevel() <= LevelConstants.VariableLevel) {
				preds.addElement(ln);
			}
		}
		this.statePreds = new LiveExprNode[preds.size()];
		for (int i = 0; i < preds.size(); i++) {
			this.statePreds[i] = preds.exprAt(i);
		}
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(final int i) {
		this.index = i;
	}

	public final TBPar getPar() {
		return this.par;
	}

	public int nextSize() {
		return this.nexts.size();
	}

	public TBGraphNode nextAt(int i) {
		return (TBGraphNode) this.nexts.elementAt(i);
	}

	public final boolean hasLink(TBGraphNode target) {
		int sz = this.nexts.size();
		for (int i = 0; i < sz; i++) {
			if (this.nexts.elementAt(i) == target) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Checks if this particle node is consistent with the given
	 * {@link TLCState}. In other words, it checks if {@link TLCState}'s truth
	 * values according to all state predicates of the tableau node. The state
	 * predicates are deduced from the particles during tableau construction.
	 */
	public boolean isConsistent(TLCState state, ITool tool) {
		for (int j = 0; j < this.statePreds.length; j++) {
			if (!this.statePreds[j].eval(tool, state, null)) {
				return false;
			}
		}
		return true;
	}

	public final String toString() {
		StringBuffer buf = new StringBuffer();
		SetOfLong visited = new SetOfLong(16);
		this.toString(buf, visited);
		return buf.toString();
	}

	private final void toString(StringBuffer buf, SetOfLong visited) {
		if (!visited.put(this.index)) {
			buf.append(this.par.toString());
			for (int i = 0; i < this.nexts.size(); i++) {
				buf.append(this.nextAt(i).index + " ");
			}
			buf.append("\n");
			for (int i = 0; i < this.nexts.size(); i++) {
				this.nextAt(i).toString(buf, visited);
			}
		}
	}

	/**
	 * @see TBGraph#toDotViz()
	 */
	public String toDotViz(final boolean isInitNode) {
		final String label = "\"Id: " + this.index + "\n" + par.toDotViz() + "\"";
		
		final StringBuffer buf = new StringBuffer(nextSize());
		buf.append(this.index + " [label=" + label + "]\n"); // nodes label
		if (isInitNode) {
			buf.append("[style = filled]\n");
		}
		for (int i = 0; i < nextSize(); i++) {
			final TBGraphNode successor = nextAt(i);
			buf.append(this.index + " -> " + successor.index);
			buf.append("\n");
		}
		return buf.toString();
	}
}



<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/view/PDFBrowser.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package org.lamport.tla.toolbox.ui.view;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class PDFBrowser extends ViewPart {

	public static final String ID = "org.lamport.tla.toolbox.PDFBrowser";
	
	private Browser browser;

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
	 */
	public void createPartControl(Composite parent) {
		final Composite body = new Composite(parent, SWT.NONE);
        body.setLayout(new FillLayout());
        this.browser = new Browser(body, SWT.NONE);
        setBlank();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
	 */
	public void setFocus() {
		this.browser.setFocus();
	}

	public void setBlank() {
		this.browser.setText("<html><body></body></html>");
	}
	
	public void setInput(String title, String url) {
		this.setPartName(title);
		this.browser.setUrl(url);
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/ui/property/ModulePropertyPage.java<|end_filename|>
package org.lamport.tla.toolbox.ui.property;

import org.eclipse.core.resources.IResource;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.lamport.tla.toolbox.util.pref.IPreferenceConstants;
import org.lamport.tla.toolbox.util.pref.ResourceBasedPreferenceStore;

/**
 * @author <NAME>
 * @version $Id$
 * @deprecated Not used 
 */
public class ModulePropertyPage extends GenericFieldEditorPropertyPage
{
    StringFieldEditor pcalParamEditor;
    
    /** (non-Javadoc)
     * Method declared on PreferencePage
     */
    public Control createContents(Composite parent)
    {
        Control contents = super.createContents(parent);
        // ensure the page has no special buttons
        noDefaultAndApplyButton();
        // setup help
        // UIHelper.setHelp(contents, IHelpConstants.MODULE_PROPERTY_PAGE);
        return contents;
    }

    /* (non-Javadoc)
     * @see org.lamport.tla.toolbox.ui.property.GenericFieldEditorPropertyPage#createFieldEditors(org.eclipse.swt.widgets.Composite)
     */
    public void createFieldEditors(Composite composite)
    {
        pcalParamEditor = new StringFieldEditor(IPreferenceConstants.PCAL_CAL_PARAMS, "PlusCal call arguments", composite);
        addEditor(pcalParamEditor);
    }

    public IPreferenceStore getPreferenceStore()
    {
        IResource resource = (IResource) getElement();
        return new ResourceBasedPreferenceStore(resource);
    }
    
    
    
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/value/impl/TupleValueTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved.
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ******************************************************************************/
package tlc2.value.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.TLCGlobals;
import tlc2.value.impl.IntervalValue;
import tlc2.value.impl.SetOfTuplesValue;
import tlc2.value.impl.TupleValue;
import tlc2.value.impl.IntValue;
import tlc2.value.impl.StringValue;
import tlc2.value.impl.Value;
import util.Assert;


public class TupleValueTest {

    @Test
    public void testErrorMessages() {
        Value elems[] = {new StringValue("A")};
        final TupleValue tupVal = new TupleValue(elems);

        try{
            tupVal.apply(IntValue.gen(2), 0);
        } catch(Assert.TLCRuntimeException ex){
            assertTrue(ex.getMessage().contains("Attempted to access index 2 of tuple\n<<\"A\">>\nwhich is out of bounds"));
        }

        try{
            tupVal.apply(new StringValue("a"), 0);
        } catch(Assert.TLCRuntimeException ex){
            assertTrue(ex.getMessage().contains("Attempted to access tuple at a non integral index: \"a\""));
        }

        try{
            tupVal.select(new StringValue("a"));
        } catch(Assert.TLCRuntimeException ex){
            assertTrue(ex.getMessage().contains("Attempted to access tuple at a non integral index: \"a\""));
        }

        try{
            Value args[] = {new StringValue("arg1"), new StringValue("arg2")};
            tupVal.apply(args, 0);
        } catch(Assert.TLCRuntimeException ex){
            assertTrue(ex.getMessage().contains("Attempted to access tuple with 2 arguments when it expects 1."));
        }
    }
}


<|start_filename|>general/bugzilla/css/global.css<|end_filename|>
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This Source Code Form is "Incompatible With Secondary Licenses", as
 * defined by the Mozilla Public License, v. 2.0.
 */

/* global (begin) */
    body {
        font-family: sans-serif;
        color: #000;
        background: #fff url("global/body-back.gif") repeat-x;
    }
    body, td, th, input {
        font-family: Verdana, sans-serif;
        font-size: small;
    }
    /* monospace is much smaller than Verdana by default, so we make it a bit bigger. */
    pre, code, kbd {
        font-size: medium;
    }
/* global (end) */

/* header (begin) */
    #header {
        margin-bottom: 1em;
    }

    #header form, #header form input,
    #footer form, #footer form input
    {
        font-size: 95%;
        display: inline;
    }

    #header .links {
        border-left: 1px solid #747E93;
        border-right: 1px solid #747E93;
        border-bottom: 1px solid #747E93;
        border-bottom-left-radius: 5px;
        border-bottom-right-radius: 5px;
        padding: 0.5em;
    }

    #lang_links_container {
        float: right;
    }
    #lang_links_container .links {
        border: none;
        padding: .5em;
    }

    .lang_current {
        font-weight: bold;
    }

    #message {
        border: 1px solid red;
        margin: 0.3em 0em;
        padding: 0.3em;
        color: green;
    }

    form.mini_login input.bz_login  {
        width: 10em;
    }
    form.mini_login input.bz_password {
        width: 6em;
    }
    form.mini_login input.bz_remember {
        margin: 0;
    }
    .bz_mini_login_help {
        color: #777;
    }

/* header (end)   */

/* banner (begin) */
    #banner {
    }

/* banner (end) */

/* titles (begin) */
    #titles {
        width: 100%;
        background-color: #404D6C;
        color: #fff;
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
        font-size: 110%;
        margin: 0;
        padding: 0.5em;
        vertical-align: bottom;
    }

    #titles a {
        color: #fff;
    }

    #titles p {
        margin: 0;
        padding: 0;
    }

    #titles #title {
        font-weight: bold;
        white-space: nowrap;
    }

    #titles #subtitle {
        font-weight: normal;
        width: 100%;
        text-align: center;
    }

    #titles #information {
        font-weight: normal;
        text-align: right;
        font-size: 90%;
        white-space: nowrap;
    }

/* titles (end) */

/* footer (begin)
 * See also the "header" section for styles that apply
 * to both the header and footer. 
 */
    #footer {
        clear: both;
        margin-top: 1em;
        width: 100%;
        background: #edf2f2;
        border-top: 1px solid #ddd;
        border-bottom: 1px solid #ddd;
    }

    #footer #useful-links {
        padding-left: 1ex;
        padding-right: 1ex;
    }

    #footer ul {
        list-style-type: none;
    }
    #links-saved ul {
        display: inline;
    }
    #links-saved th {
        vertical-align: top;
    }

    #footer .label {
        white-space: nowrap;
        vertical-align: top;
    }

    #footer .links {
        vertical-align: top;
    }
/* footer (end) */

/* link lists (begin) */
    ul.links {
        margin: 0;
        padding: 0;
        list-style-type: none;
    }

    ul.links li {
        display: inline;
        white-space: nowrap;
    }
/* link lists (end) */

/* tabs (begin) */
    .tabs td {
        background: #eee;
        text-align: center;
        border-style: solid;
        border-color: black;
        border-width: 0px 0px 2px 0px;
    }
        
    .tabs td.selected {
        background: white;
        border-width: 2px 2px 0px 2px;
    }

    .tabs td.spacer {
        background: white;
    }
/* tabs (end) */

/* generic (begin) */
    a {
        color: #039;
    }

    a:visited {
        color: #636;
    }

    a:hover {
        color: #333;
    }

    a:active {
        color: #000;
    }

    .clickable_area {
        cursor: pointer;
    }

    textarea {
        font-family: monospace;
    }
/* generic (end) */

/* Links that control whether or not something is visible. */
a.controller {
    font-size: 115%;
}

div#docslinks {
    float: right;
    border: 1px solid black;
    padding: 1ex;
    font-size: 80%;
}

#docslinks h2 {
    margin: 0;
}

/**************************/
/* Bug links and statuses */
/**************************/

.bz_bug_link {
    /* Catch-all if you want common styles for all bug links */
}

.bz_bug_link .bz_status_UNCONFIRMED {
    font-style: italic;
}

.bz_obsolete {
    text-decoration: line-through;
}
.bz_inactive {
    text-decoration: line-through;
}
.bz_closed,
.bz_CLOSED td {
    text-decoration: line-through;
}
.bz_private {
    color: darkred;
    background: #f3eeee;
}
.bz_disabled {
    color: #a0a0a0;
}

/************/
/* Comments */
/************/

.bz_comment_table td {
    vertical-align: top;
}

.bz_comment {
    margin-bottom: 2em;
}

/* tbody.file pre is for the Diff view of attachments. */
.bz_comment_text, .uneditable_textarea, tbody.file pre {
     font-family: monospace;
     white-space: pre-wrap;
}

.bz_comment_text {
     width: 50em;
}

.bz_comment_user, .bz_comment_time, .bz_comment_number, 
.bz_private_checkbox, .bz_comment_actions
{
    margin: 0 .5em;
}

.bz_comment_actions, .bz_comment_number, .bz_private_checkbox {
    float: right;
}

.bz_collapse_expand_comments {
    padding: 0;
    margin: 0 0 0 1em;
    list-style-type: none;
}
.bz_collapse_expand_comments li {
    margin-bottom: .5em;
}
.bz_collapse_comment {
    text-decoration: none;
}

.bz_private_checkbox input { 
    margin: 0;
    vertical-align: middle;
}

.bz_comment_head, .bz_first_comment_head {
    padding-top: .1em;
    padding-bottom: .1em;
    padding-left: .5em;
    background-color: #e0e0e0;
}

.bz_comment_user_images img {
    vertical-align: bottom;
}

.bz_comment_hilite pre {
    background-color: lightgreen;
    margin: 0;
    padding: 1em 0;
}

/** End Comments **/

.bz_default_hidden, .bz_tui_hidden, .bz_hidden_field, .bz_hidden_option {
    /* We have !important because we want elements with these classes to always
     * be hidden, even if there is some CSS that overrides it (we use these
     * classes inside JavaScript to hide things). */
    display: none !important;
}

.bz_comment_text span.quote {
    color: #65379c;
    /* Make quoted text not wrap. */
    white-space: pre;
}

table#flags th,
table#flags td {
    vertical-align: middle;
    text-align: left;
}

.flag_select {
    min-width: 3em;
}

input.requestee {
    width: 15em;
}

#error_msg {
    font-size: x-large;
}

.warning {
  color: red;
}

.throw_error {
    background-color: #ff0000;
    color: black;
    font-size: 120%;
    margin: 1em;
    padding: 0.5em 1em;
}

dt {
    font-weight: bold;
}
body > dl > dt {
    border-top: dotted gray thin;
}
dl dl > dt {
    border-top: none;
}

#admin_table th {
    white-space: normal !important;
}

/* Arrow buttons are buttons with only &uarr;, &darr;, &larr; or &rarr; on
 * them. We want these to look a little less spidery. */
.arrow_button {
    font-size: 150%;
}

/* Style of the attachment table and time tracking table */
#attachment_table {
    border-collapse: collapse;
    border: 1px solid #333333;
}

#attachment_table th, .bz_attach_footer, .bz_time_tracking_table th {
    background-color: #E0E0E0;
    color: black;
}

#attachment_table td, .bz_time_tracking_table th, .bz_time_tracking_table td {
    border: 1px solid #333333;
}

.bz_attach_extra_info {
    font-size: smaller;
}

.bz_attach_flags, .bz_attach_footer {
    white-space: nowrap;
}

.bz_attach_view_hide {
    float: right;
    padding-left: 1em;
}

div.user_match {
    margin-bottom: 1em;
}

.box {
    border: 1px solid black;
    color: black;
    background-color: #ffc;
    margin: 1em;
    padding: 0.5em 1em;
}

.collapsed {
    display: none;
}

/* Rules specific for printing */
@media print {
    #header, #footer {
        display: none;
    }

    div.bz_query_buttons {
        display: none;
    }

    body {
        background-image: none;
        background-color: #fff;
    }
}

/**************/
/* Bug Fields */
/**************/

.field_label {
    text-align: right;
    vertical-align: top;
    font-weight: bold;
}
.field_help_link {
    cursor: help;
}
.field_value, form#Create th, form#Create td {
    vertical-align: top;
}
.field_value .text_input {
  width: 100%;
  min-width: 25em;
}

.uneditable_textarea {
    width: 30em;
    font-size: medium;
}

th.required:before {
    content: "* ";
}
th.required:before, span.required_star {
    color: red;
}
input.required, select.required, span.required_explanation {
    background-color: #fff7cd;
    color: #000;
}

.calendar_button {
    background: transparent url("global/calendar.png") no-repeat;
    width: 20px;
    height: 20px;
    vertical-align: middle;
}
.calendar_button span { display: none }
/* These classes are set by YUI. */
.yui-calcontainer {
    display: none; 
    background-color: white; 
    padding: 10px;
    border: 1px solid #404D6C;
}

.bug_urls {
    margin: 0 0 1em 0;
    padding: 0;
    list-style-type: none;
}

/* custom styles for inline instances of autocomplete input fields */
.yui-skin-sam .yui-ac-input { position:static !important; 
                              vertical-align:middle !important; }
.yui-skin-sam .yui-ac-container { left:0px !important; }
.yui-skin-sam .yui-ac { display: inline-block; }
#bugzilla-body .yui-ac-content {
    max-height: 19em;
    overflow: auto;
    overflow-x: hidden;
}

#keywords_container {
    padding-top: .2em;
}


#keywords_container .yui-ac-content {
    margin-left: -1px;
}

/*******************/
/* Form Validation */
/*******************/

.validation_error_text {
    font-size: 120%;
    color: #B70000;
    font-weight: bold;
}

.validation_error_field, input.validation_error_field {
    border: 2px solid #B70000;
    background-color: #FFEBEB;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/fp/dfid/MultiFPIntSet.java<|end_filename|>
// Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:15:53 PST by lamport
//      modified on Tue May 15 11:44:57 PDT 2001 by yuanyu

package tlc2.tool.fp.dfid;

import java.io.IOException;
import java.rmi.RemoteException;

/**
 * An <code>MultiFPInt</code> is a set of 64-bit fingerprints.
 */
public class MultiFPIntSet extends FPIntSet {

  private FPIntSet[] sets;
  private int fpbits;

  public MultiFPIntSet(int bits) throws RemoteException {
    int len = 1 << bits;
    this.sets = new FPIntSet[len];
    for (int i = 0; i < len; i++) {
      this.sets[i] = new MemFPIntSet();
    }
    this.fpbits = 64 - bits;
  }

  public final void init(int numThreads, String metadir, String filename)
  throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].init(numThreads, metadir, filename+"_"+i);
    }
  }
  
  /**
   * Returns the number of fingerprints in this set.
   * Warning: The size is only accurate in single-threaded mode.
   */
  public final long size() {
    int sum = 0;
    for (int i = 0; i < this.sets.length; i++) {
      sum += this.sets[i].size();
    }
    return sum;
  }

  public final void setLeveled(long fp) {
    int idx = (int)(fp >>> this.fpbits);
    this.sets[idx].setLeveled(fp);
  }
  
  public final int setStatus(long fp, int status) {
    int idx = (int)(fp >>> this.fpbits);
    return this.sets[idx].setStatus(fp, status);
  }

  /* Returns the status of fp. */
  public final int getStatus(long fp) {
    int idx = (int)(fp >>> this.fpbits);
    return this.sets[idx].getStatus(fp);
  }

  public final boolean allLeveled() {
    for (int i = 0; i < this.sets.length; i++) {
      if (!this.sets[i].allLeveled()) return false;
    }
    return true;
  }

  public final void close() {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].close();
    }
  }

  /* This is not quite correct. */
  public final long checkFPs() throws IOException {
    long res = Long.MIN_VALUE;
    for (int i = 0; i < this.sets.length; i++) {
      res = Math.max(res, this.sets[i].checkFPs());
    }
    return res;
  }

  public final void exit(boolean cleanup) throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].exit(cleanup);
    }
  }
  
  public final void beginChkpt() throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].beginChkpt();
    }
  }
  
  public final void commitChkpt() throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].commitChkpt();
    }
  }
       
  public final void recover() throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].recover();
    }
  }

  public final void beginChkpt(String filename) throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].beginChkpt(filename);
    }
  }
  
  public final void commitChkpt(String filename) throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].commitChkpt(filename);
    }
  }
  
  public final void recover(String filename) throws IOException {
    for (int i = 0; i < this.sets.length; i++) {
      this.sets[i].recover(filename);
    }
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/exception/PcalFixIDException.java<|end_filename|>
package pcal.exception;

/**
 * @author <NAME>
 * @version $Id$
 */
public class PcalFixIDException extends UnrecoverableException
{

    /**
     * @param message
     */
    public PcalFixIDException(String message)
    {
        super(message);
    }

}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/TLAEditorActionContributor.java<|end_filename|>
package org.lamport.tla.toolbox.editor.basic;

import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.editors.text.TextEditorActionContributor;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.RetargetTextEditorAction;

/**
 * Content assist actions
 * @author <NAME>
 * @version $Id$
 */
public class TLAEditorActionContributor extends TextEditorActionContributor
{

    protected RetargetTextEditorAction fContentAssistProposal;
    protected RetargetTextEditorAction fContentAssistTip;

    /**
     * Default constructor.
     */
    public TLAEditorActionContributor()
    {
        super();
        fContentAssistProposal = new RetargetTextEditorAction(TLAEditorMessages.getResourceBundle(),
                "ContentAssistProposal."); //$NON-NLS-1$
        fContentAssistProposal.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
        fContentAssistTip = new RetargetTextEditorAction(TLAEditorMessages.getResourceBundle(), "ContentAssistTip."); //$NON-NLS-1$
        fContentAssistTip.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
    }

    /*
     * @see IEditorActionBarContributor#init(IActionBars)
     */
    public void init(IActionBars bars)
    {
        super.init(bars);

        IMenuManager menuManager = bars.getMenuManager();
        IMenuManager editMenu = menuManager.findMenuUsingPath("toolbox.edit.menu");
        if (editMenu != null)
        {
            editMenu.add(new Separator());
            editMenu.add(fContentAssistProposal);
            editMenu.add(fContentAssistTip);
        }
    }

    /*
     * @see IEditorActionBarContributor#setActiveEditor(IEditorPart)
     */
    public void setActiveEditor(IEditorPart part)
    {
        super.setActiveEditor(part);
        ITextEditor editor = null;
        if (part instanceof ITextEditor) 
        {
            editor = (ITextEditor) part;
        }
        fContentAssistProposal.setAction(getAction(editor, "ContentAssistProposal")); //$NON-NLS-1$
        fContentAssistTip.setAction(getAction(editor, "ContentAssistTip")); //$NON-NLS-1$

    }

    /*
     * @see IEditorActionBarContributor#dispose()
     */
    public void dispose()
    {
        setActiveEditor(null);
        super.dispose();
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/AbstractTableLabelProvider.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

/**
 * An abstract superclass for label providers.
 */
public abstract class AbstractTableLabelProvider
		extends LabelProvider
		implements ITableLabelProvider, ITableColorProvider {
	private final int m_minimumWidth;
	private final String[] m_columnTitles;
	private final double[] m_columnWidthPercentages;
	
	protected AbstractTableLabelProvider(final int minWidth, final String[] titles, final double[] percentages) {
		m_minimumWidth = minWidth;
		m_columnTitles = titles;
		m_columnWidthPercentages = percentages;
	}
	
	/**
	 * @return the minimum required width of all columns provided
	 */
	public int getMinimumTotalWidth() {
		return m_minimumWidth;
	}

	/**
	 * @param columnIndex the index of the column for which the title is desired
	 * @return the title for the column at the specified index, or null if the index is out of bounds
	 */
	public String getColumnTitle(final int columnIndex) {
		if ((columnIndex >= 0) && (columnIndex < m_columnTitles.length)) {
			return m_columnTitles[columnIndex];
		}
		
		return null;
	}
	
	/**
	 * This method will be invoked when the table's size is changing; the provider should size the columns
	 * 	appropriately.
	 * 
	 * @param newTableWidth the new size for the table
	 */
	public void resizeColumns(final int newTableWidth, final Table table) {
		double tableWidth = (double)newTableWidth;
		int currentWidthSum = 0;
		
		for (int i = 0; i < (m_columnWidthPercentages.length - 1); i++) {
			final TableColumn column = table.getColumn(i);
			final int newWidth = (int)(m_columnWidthPercentages[i] * tableWidth);
			
			column.setWidth(newWidth);
			currentWidthSum += newWidth;
		}
		
		final TableColumn column = table.getColumn(m_columnWidthPercentages.length - 1);
		column.setWidth(newTableWidth - currentWidthSum);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/liveness/TBPar.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:33:50 PST by lamport
//      modified on Thu Sep 21 22:20:35 PDT 2000 by yuanyu

package tlc2.tool.liveness;

import tlc2.output.EC;
import tlc2.util.Vect;
import util.Assert;

/**
 * See Section 5.5 "Particle Tableaux" in Temporal Verification of Reactive
 * Systems *Safety* by <NAME> and <NAME>.
 * <p>
 * A {@link TBPar} means Tableau Particle. A particle is an incomplete atom
 * because it only adheres to a relaxed version of atoms. Due to its
 * incompleteness, it results in a more efficient tableau since its size is less
 * than that with complete atoms. However, it does not loose generality.
 * <p>
 * The formulas are in positive form, meaning negation
 * is only applied to state formulas. The state formulas are not keep in
 * {@link TBPar}, but in {@link TBGraphNode#statePreds} instead. There is also where the
 * successors of the particle are held.
 * <p>
 * TLA+ supports only future formulas and no past temporal operators (compare
 * with p. 43 fig. 0.15), thus it uses the PART-TAB algorithm (p. 456) for the
 * tableau construction.
 */
@SuppressWarnings("serial")
public class TBPar extends Vect<LiveExprNode> {

	TBPar() {
		super(0);
	}

	public TBPar(int i) {
		super(i);
	}

	public final LiveExprNode exprAt(int i) {
		return (LiveExprNode) elementAt(i);
	}

	/* This method returns true iff this particle is equal to another particle */
	public final boolean equals(TBPar par) {
		return (this.contains(par) && par.contains(this));
	}

	/**
	 * This method tests whether or not an expression is in a list of
	 * expressions.
	 */
	final boolean member(LiveExprNode e) {
		for (int i = 0; i < this.size(); i++) {
			if (e.equals(this.exprAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * This method tests whether a particle par is a subset of this particle.
	 */
	private final boolean contains(TBPar par) {
		for (int i = 0; i < par.size(); i++) {
			if (!this.member(par.exprAt(i))) {
				return false;
			}
		}
		return true;
	}

	/* This method returns the unions of two particles. */
	@SuppressWarnings("unused")
	private final TBPar union(TBPar par) {
		TBPar res = new TBPar(this.size() + par.size());
		for (int i = 0; i < this.size(); i++) {
			if (!par.member(this.exprAt(i))) {
				res.addElement(this.exprAt(i));
			}
		}
		for (int i = 0; i < par.size(); i++) {
			res.addElement(par.exprAt(i));
		}
		return res;
	}

	/* This method appends an expression to the tail of Par. */
	private final TBPar append(LiveExprNode ln) {
		TBPar res = new TBPar(this.size() + 1);
		for (int i = 0; i < this.size(); i++) {
			res.addElement(this.exprAt(i));
		}
		res.addElement(ln);
		return res;
	}

	/* This method appends two expressions to the tail of Par. */
	private final TBPar append(LiveExprNode ln1, LiveExprNode ln2) {
		TBPar res = new TBPar(this.size() + 2);
		for (int i = 0; i < this.size(); i++) {
			res.addElement(this.exprAt(i));
		}
		res.addElement(ln1);
		res.addElement(ln2);
		return res;
	}

	/**
	 * The method particleClosure, given a list of terms (initially just a
	 * single term), returns a list of all particles containing those terms.
	 * It's a recursive tree search.
	 */
	public TBParVec particleClosure() {
		TBPar positive_closure = this.positiveClosure();
		Vect<TBTriple> alphas = positive_closure.alphaTriples();
		Vect<TBTriple> betas = positive_closure.betaTriples();
		return particleClosure(this, alphas, betas);
	}

	private TBParVec particleClosure(final TBPar terms, final Vect<TBTriple> alphas, final Vect<TBTriple> betas) {
		// if terms is not locally consistent, then terminate .
		if (!terms.isLocallyConsistent()) {
			// TODO: The calling code does not seem to terminate if the term is
			// inconsistent.
			return new TBParVec(0);
		}
		// if terms is not alpha-closed, then close it.
		// first, try alpha expansion. See MP page 403 
		// figure 5.1. for alpha expansion rules.
		TBPar terms1 = terms;
		for (int i = 0; i < terms1.size(); i++) {
			LiveExprNode ln = terms1.exprAt(i);
			LiveExprNode kappa1 = null, kappa2 = null;
			if (ln instanceof LNAll) {
				// Alpha-Expansion: []p expands to p, ()[]p
				kappa1 = ((LNAll) ln).getBody();
				kappa2 = new LNNext(ln);
			} else if (ln instanceof LNConj) {
				// Alpha-Expansion: p /\ q expands to p, q
				kappa1 = ((LNConj) ln).getBody(0);
				kappa2 = ((LNConj) ln).getBody(1);
			}
			if (kappa1 != null) {
				if (terms1.member(kappa1)) {
					if (!terms1.member(kappa2)) {
						terms1 = terms1.append(kappa2);
					}
				} else if (terms1.member(kappa2)) {
					terms1 = terms1.append(kappa1);
				} else {
					terms1 = terms1.append(kappa1, kappa2);
				}
			}
		}
		// second, try alpha^-1 expansion (inverse expansion)
		boolean done;
		do {
			done = true;
			for (int i = 0; i < alphas.size(); i++) {
				TBTriple alpha = (TBTriple) alphas.elementAt(i);
				if (terms1.member(alpha.getB()) && terms1.member(alpha.getC()) && !terms1.member(alpha.getA())) {
					terms1.addElement(alpha.getA());
					done = false;
				}
			}
		} while (!done);
		// finally, recurse only when locally consistent
		if ((terms1.size() > terms.size()) && (!terms1.isLocallyConsistent())) {
			return new TBParVec(0);
		}
		return particleClosureBeta(terms1, alphas, betas);
	}

	private TBParVec particleClosureBeta(final TBPar terms, final Vect<TBTriple> alphas, final Vect<TBTriple> betas) {
		// try a beta expansion. See MP page 403 
		// figure 5.1. for beta expansion rules.
		for (int i = 0; i < terms.size(); i++) {
			LiveExprNode ln = terms.exprAt(i);
			LiveExprNode kappa1 = null, kappa2 = null;
			if (ln instanceof LNEven) {
				// Beta-Expansion: <>p expands to p, ()<>p
				kappa1 = ((LNEven) ln).getBody();
				kappa2 = new LNNext(ln);
			} else if (ln instanceof LNDisj) {
				// Beta-Expansion: p \/ expands to p, q
				kappa1 = ((LNDisj) ln).getBody(0);
				kappa2 = ((LNDisj) ln).getBody(1);
			}
			if ((kappa1 != null) && !terms.member(kappa1) && !terms.member(kappa2)) {
				TBParVec ps1 = particleClosure(terms.append(kappa1), alphas, betas);
				TBParVec ps2 = particleClosure(terms.append(kappa2), alphas, betas);
				return ps1.union(ps2);
			}
		}
		// try a beta^-1 expansion
		for (int i = 0; i < betas.size(); i++) {
			TBTriple beta = (TBTriple) betas.elementAt(i);
			if ((terms.member(beta.getB()) || terms.member(beta.getC())) && !terms.member(beta.getA())) {
				return particleClosure(terms.append(beta.getA()), alphas, betas);
			}
		}
		// if there are not any more expansions to do, return the terms
		// we've got as the only particle in a list of particles.
		TBParVec res = new TBParVec(1);
		res.addElement(terms);
		return res;
	}

	/**
	 * The methods alphaTriples and betaTriples, given a positive closure,
	 * figure out the alpha and beta triples. The way the algorithm works, by
	 * the time we extract triples, it should already have been positively
	 * closed. All junctions must have been binarified at this stage by
	 * makeBinary, otherwise it may give the wrong answer and crash.
	 */
	private final Vect<TBTriple> alphaTriples() {
		Vect<TBTriple> ts = new Vect<>();
		for (int i = 0; i < this.size(); i++) {
			LiveExprNode ln = this.exprAt(i);
			if (ln instanceof LNAll) {
				ts.addElement(new TBTriple(ln, ((LNAll) ln).getBody(), new LNNext(ln)));
			} else if (ln instanceof LNConj) {
				LNConj lnc = (LNConj) ln;
				ts.addElement(new TBTriple(lnc, lnc.getBody(0), lnc.getBody(1)));
			}
		}
		return ts;
	}

	private final Vect<TBTriple> betaTriples() {
		Vect<TBTriple> ts = new Vect<>();
		for (int i = 0; i < this.size(); i++) {
			LiveExprNode ln = this.exprAt(i);
			if (ln instanceof LNEven) {
				ts.addElement(new TBTriple(ln, ((LNEven) ln).getBody(), new LNNext(ln)));
			} else if (ln instanceof LNDisj) {
				LNDisj lnd = (LNDisj) ln;
				ts.addElement(new TBTriple(lnd, lnd.getBody(0), lnd.getBody(1)));
			}
		}
		return ts;
	}

	/**
	 * The method isLocallyConsistent determines whether a list of state predicates
	 * is locally consistent.
	 * <p>
	 * Manna &Pnueli (p.444): A set of temporal formulae B is (locally) consistent
	 * if it does *not* contain a formulae and its negation, and the conjunction of
	 * all state formulae state(B) is satisfiable.
	 * <p>
	 * Check Manna & Pnueli book page 444ff and 453 specifically for the theory of
	 * locally consistent.
	 */
	private final boolean isLocallyConsistent() {
		// Pre-conditions per Manna & Pnueli and the calling code:
		//assert !this.containsActions (no LNAction instances)
		//assert this.isPositiveForm()
		// First put the elements into positive or negative bin
		TBPar pos = new TBPar(this.size());
		TBPar neg = new TBPar(this.size());
		for (int i = 0; i < this.size(); i++) {
			LiveExprNode ln = this.exprAt(i);
			// Implementation not aligned with TBGraphNode::new because here we split into
			// pos and neg bins.
			if (ln instanceof LNState || ln instanceof LNBool) {
				pos.addElement(ln);
			} else if (ln instanceof LNNeg) {
				LiveExprNode body = ((LNNeg) ln).getBody();
				// Because tf has been brought into positive form by the nested pushNeg of
				// toDNF, the sub-terms of LNNeg can only be LNState and LNBool, but not
				// arbitrary terms such as ~[]p or []<>p.
				//assert body instanceof LNState || body instanceof LNBool;
				if (body instanceof LNState || body instanceof LNBool) {
					neg.addElement(body);
				}
			}
		}
		// If any positive is in the negative bin, that's a clash.
		for (int i = 0; i < pos.size(); i++) {
			if (neg.member(pos.exprAt(i))) {
				// This is reachable if two LNState instances have the same tag
				// (LNState#tetTag), which are set in Liveness before the liveness constraints
				// and properties are brought into disjunct normal form.  Thus, for two (or more)
				// LNState to have the same tag, LiveExprNode.toDNF() would have to duplicate
				// the LNState instance.
				// For two LNBool to be equal, their boolean values have to be the same.
				return false;
			}
		}
		return true;
	}

	/**
	 * This method, given a list of terms, returns all those terms and subterms that
	 * are positive (i.e. whose major operator is not a negation). For LNAll and
	 * LNEven, it also adds LNNext particles.
	 * <p>
	 * There can not be LNActs in the expression.
	 */
	private final TBPar positiveClosure() {
		// tps is the queue of terms to be processed.
		TBPar tps = new TBPar(this.size() * 2);
		for (int i = 0; i < this.size(); i++) {
			tps.addElement(this.elementAt(i));
		}
		TBPar result = new TBPar(this.size() * 2);
		while (tps.size() > 0) {
			LiveExprNode ln = tps.exprAt(tps.size() - 1);
			tps.removeLastElement();
			if (ln instanceof LNNeg) {
				// LNNeg is obviously not positive, but its subterms might.
				tps.addElement(((LNNeg) ln).getBody());
			} else if (ln instanceof LNNext) {
				result.addElement(ln);
				tps.addElement(((LNNext) ln).getBody());
			} else if (ln instanceof LNEven) {
				result.addElement(ln);
				// See page 452, Closure and Particles, 3. item
				result.addElement(new LNNext(ln));
				tps.addElement(((LNEven) ln).getBody());
			} else if (ln instanceof LNAll) {
				result.addElement(ln);
				// See page 452, Closure and Particles, 3. item
				result.addElement(new LNNext(ln));
				tps.addElement(((LNAll) ln).getBody());
			} else if (ln instanceof LNConj) {
				LNConj lnc = (LNConj) ln;
				for (int i = 0; i < lnc.getCount(); i++) {
					tps.addElement(lnc.getBody(i));
				}
				result.addElement(ln);
			} else if (ln instanceof LNDisj) {
				LNDisj lnd = (LNDisj) ln;
				for (int i = 0; i < lnd.getCount(); i++) {
					tps.addElement(lnd.getBody(i));
				}
				result.addElement(ln);
			} else if (ln instanceof LNState) {
				result.addElement(ln);
			} else if (ln instanceof LNBool) {
				result.addElement(ln);
			} else {
				Assert.fail(EC.TLC_LIVE_ENCOUNTERED_ACTIONS);
			}
		}
		return result;
	}

	/**
	 * This method returns a list of implied successors of a given particle.
	 * PART-TAB particle tableau construction on page 456 in Manna & Pnueli.
	 */
	final TBPar impliedSuccessors() {
		TBPar successors = new TBPar(this.size());
		for (int i = 0; i < this.size(); i++) {
			LiveExprNode ln = this.exprAt(i);
			if (ln instanceof LNNext) {
				successors.addElement(((LNNext) ln).getBody());
			}
		}
		return successors;
	}

	/**
	 * This methods returns true iff this particle (TBPar) fulfills the given
	 * promise.
	 * <p>
	 * A particle/atom A is said to fulfill formula &#966; which promises r if either:
	 * <ul>
	 * <li>&#966; \notin A</li>
	 * <li>r \in A</li>
	 * </ul>
	 */
	final boolean isFulfilling(LNEven promise) {
		return !this.member(promise) || this.member(promise.getBody());
	}

	public final void toString(StringBuffer sb, String padding) {
		sb.append("{");
		String padding1 = padding + " ";
		if (this.size() != 0) {
			((LiveExprNode) this.elementAt(0)).toString(sb, padding1);
		}
		for (int i = 1; i < this.size(); i++) {
			sb.append(",\n");
			sb.append(padding1);
			((LiveExprNode) this.elementAt(i)).toString(sb, padding1);
		}
		sb.append("}");
	}

	public final String toString() {
		StringBuffer sb = new StringBuffer();
		this.toString(sb, "");
		return sb.toString();
	}

	public String toDotViz() {
		final StringBuffer sb = new StringBuffer();
		sb.append("{");
		if (this.size() != 0) {
			LiveExprNode liveExprNode = (LiveExprNode) this.elementAt(0);
			sb.append(liveExprNode.toDotViz());
		}
		for (int i = 1; i < this.size(); i++) {
			sb.append(",\n");
			LiveExprNode liveExprNode = (LiveExprNode) this.elementAt(i);
			sb.append(liveExprNode.toDotViz());
		}
		sb.append("}");
		// properly escape the "/\" to "/\\" or "\A" to "\\A"
		return sb.toString().replace("\\", "\\\\");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/utilities/VectorEnumeration.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
package tla2sany.utilities;
import java.util.Enumeration;

final class VectorEnumeration<E> implements Enumeration<E> {
  int index = 0;
  Object data[];

  VectorEnumeration( Object info[], int size ) {
    data = new Object[ size ];
    System.arraycopy( info, 0, data, 0, size );
  }

  public final boolean hasMoreElements() {
    return index < data.length;
  }

  @SuppressWarnings("unchecked")
  public final E nextElement() {
    if (index < data.length)
      return (E)data[index++];
    else
      throw new java.util.NoSuchElementException();
  }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/handlers/CloneForeignModelHandler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.handlers;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.lamport.tla.toolbox.spec.Spec;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.launch.IConfigurationConstants;
import org.lamport.tla.toolbox.tool.tlc.launch.IModelConfigurationConstants;
import org.lamport.tla.toolbox.tool.tlc.launch.TLCModelLaunchDelegate;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;

/**
 * A handler which presents the user with a dialog through which to choose a spec and a model.
 */
public class CloneForeignModelHandler extends AbstractHandler implements IModelConfigurationConstants {
	public static final String COMMAND_ID = "toolbox.tool.tlc.commands.model.cloneforeign";

	private static final Comparator<Model> MODEL_SORTER = (m1, m2) -> {
		return m1.getName().compareTo(m2.getName());
	};
	
	
	public Object execute(final ExecutionEvent event) throws ExecutionException {
		final TreeMap<String, TreeSet<Model>> projectModelMap = buildMap();
		if (projectModelMap == null) {
			return null;
		}
		
		final Shell shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
		final ForeignModelPicker modelPicker = new ForeignModelPicker(shell, projectModelMap);
		
		if (modelPicker.open() == Dialog.OK) {
	        final Map<String, String> parameters = new HashMap<String, String>();
	        parameters.put(CloneModelHandlerDelegate.PARAM_FOREIGN_FULLY_QUALIFIED_MODEL_NAME,
	        			   modelPicker.getFullyQualifiedNameOfSelection());

			final ExecutionEvent cloneEvent = new ExecutionEvent(null, parameters, null, null);
			final CloneModelHandlerDelegate cloner = new CloneModelHandlerDelegate();
			cloner.execute(cloneEvent);
		}
        
		return null;
	}
	
	private TreeMap<String, TreeSet<Model>> buildMap() {
        final Spec currentSpec = ToolboxHandle.getCurrentSpec();
        if (currentSpec == null) {
        	return null;
        }
        
		final IProject specProject = currentSpec.getProject();
		final TreeMap<String, TreeSet<Model>> projectModelMap = new TreeMap<>();
		
		try {
			final IWorkspace iws = ResourcesPlugin.getWorkspace();
			final IWorkspaceRoot root = iws.getRoot();
			final IProject[] projects = root.getProjects();
			
			for (final IProject project : projects) {
				if (!specProject.equals(project)) {
					projectModelMap.put(project.getName(), new TreeSet<>(MODEL_SORTER));
				}
			}
			
			final String currentProjectName = specProject.getName();
			final ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
			final ILaunchConfigurationType launchConfigurationType
					= launchManager.getLaunchConfigurationType(TLCModelLaunchDelegate.LAUNCH_CONFIGURATION_TYPE);
			final ILaunchConfiguration[] launchConfigurations
					= launchManager.getLaunchConfigurations(launchConfigurationType);
			for (final ILaunchConfiguration launchConfiguration : launchConfigurations) {
				final String projectName = launchConfiguration.getAttribute(IConfigurationConstants.SPEC_NAME, "-l!D!q_-l!D!q_-l!D!q_");
				if (!projectName.equals(currentProjectName)) {
					final TreeSet<Model> models = projectModelMap.get(projectName);
					
					if (models != null) {
						final Model model = launchConfiguration.getAdapter(Model.class);
						
						if (!model.isSnapshot()) {
							models.add(model);
						}
					} else {
						TLCUIActivator.getDefault().logError("Could not generate model map for [" + projectName + "]!");
					}
				}
			}
		} catch (final CoreException e) {
			TLCUIActivator.getDefault().logError("Building foreign model map.", e);
			
			return null;
		}
		
		return projectModelMap;
	}
	
	
	private static class ForeignModelPicker extends Dialog {
		private final TreeMap<String, TreeSet<Model>> specNameModelMap;
		
		private List specList;
		private List modelList;
		
		// oh SWT, you terrible terrible thing... after the dialog closes, all of the widgets are disposed - too bad, too late... 
		private String selectedFullyQualifiedName;
		
		private ForeignModelPicker(final Shell shell, final TreeMap<String, TreeSet<Model>> projectModelMap) {
			super(shell);
			
			specNameModelMap = projectModelMap;
		}
		
		private String getFullyQualifiedNameOfSelection() {
			return selectedFullyQualifiedName;
		}
		
	    @Override
	    protected Control createDialogArea(final Composite parent) {
	        final Composite container = (Composite) super.createDialogArea(parent);
	        
	        GridLayout gl = new GridLayout(2, false);
	        container.setLayout(gl);
	        
	        
	        final Composite leftPane = new Composite(container, SWT.NONE);
	        gl = new GridLayout(1, false);
	        gl.marginHeight = 0;
	        gl.marginWidth = 0;
	        leftPane.setLayout(gl);
	        GridData gd = new GridData();
	        gd.horizontalAlignment = SWT.FILL;
	        gd.grabExcessHorizontalSpace = true;
	        gd.verticalAlignment = SWT.FILL;
	        gd.grabExcessVerticalSpace = true;
	        leftPane.setLayoutData(gd);
	        
	        final Composite rightPane = new Composite(container, SWT.NONE);
	        gl = new GridLayout(1, false);
	        gl.marginHeight = 0;
	        gl.marginWidth = 0;
	        rightPane.setLayout(gl);
	        gd = new GridData();
	        gd.horizontalAlignment = SWT.FILL;
	        gd.grabExcessHorizontalSpace = true;
	        gd.verticalAlignment = SWT.FILL;
	        gd.grabExcessVerticalSpace = true;
	        rightPane.setLayoutData(gd);
	        
	        
	        Label l = new Label(leftPane, SWT.LEFT);
	        l.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
	        l.setText("Spec:");
	        
	        specList = new List(leftPane, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
	        for (final String specName : specNameModelMap.keySet()) {
	        	specList.add(specName);
	        }
	        specList.addSelectionListener(new SelectionAdapter() {
	        	@Override
	        	public void widgetSelected(final SelectionEvent se) {
	    	        getButton(IDialogConstants.OK_ID).setEnabled(false);
	    	        selectedFullyQualifiedName = null;
	    	        
	        		modelList.removeAll();
	        		
	        		final TreeSet<Model> models = specNameModelMap.get(specList.getSelection()[0]);
	    	        for (final Model model : models) {
	    	        	modelList.add(model.getName());
	    	        }
	        	}
	        });
	        gd = new GridData();
	        gd.horizontalAlignment = SWT.FILL;
	        gd.grabExcessHorizontalSpace = true;
	        gd.verticalAlignment = SWT.FILL;
	        gd.grabExcessVerticalSpace = true;
	        specList.setLayoutData(gd);
	        
	        
	        l = new Label(rightPane, SWT.LEFT);
	        l.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
	        l.setText("Model:");
	        
	        modelList = new List(rightPane, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
	        gd = new GridData();
	        gd.horizontalAlignment = SWT.FILL;
	        gd.grabExcessHorizontalSpace = true;
	        gd.verticalAlignment = SWT.FILL;
	        gd.grabExcessVerticalSpace = true;
	        modelList.setLayoutData(gd);
	        modelList.addSelectionListener(new SelectionAdapter() {
	        	@Override
	        	public void widgetSelected(final SelectionEvent se) {
	    	        getButton(IDialogConstants.OK_ID).setEnabled(true);
	    	        
	    	        selectedFullyQualifiedName
	    	        		= Model.fullyQualifiedNameFromSpecNameAndModelName(specList.getSelection()[0],
	    	        														   modelList.getSelection()[0]);
	        	}
	        });
	        
	        return container;
	    }
	    
	    @Override
		protected Control createButtonBar(final Composite parent) {
	    	final Control buttonBar = super.createButtonBar(parent);
	    	
	        getButton(IDialogConstants.OK_ID).setEnabled(false);
	    	
	    	return buttonBar;
	    }

	    @Override
	    protected Point getInitialSize() {
	        return new Point(500, 330);
	    }

	    @Override
	    protected void configureShell(final Shell shell) {
	        super.configureShell(shell);
	        shell.setText("Please choose a spec and a model");
	    }
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/util/SynchronousDiskIntStackTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.util;

import static org.junit.Assert.assertEquals;

import java.io.File;

import org.junit.Test;

public class SynchronousDiskIntStackTest {

	@Test
	public void testPushIntNoWrite() {
		final String diskdir = System.getProperty("java.io.tmpdir") + File.separator + "SynchronousDiskIntStackTest_"
				+ System.currentTimeMillis();

		final int size = 8;
		
		final IntStack diskIntStack = new SynchronousDiskIntStack(diskdir, "SynchronousDiskIntStackTest", size);
		
		// Fill stack
		for (int i = 0; i < size; i++) {
			diskIntStack.pushInt(i);
		}

		// Check all elements still on stack
		for (int i = size - 1; i >= 0; i--) {
			assertEquals(i, diskIntStack.popInt());
		}
	}

	@Test
	public void testPushIntWrite() {
		final String diskdir = System.getProperty("java.io.tmpdir") + File.separator + "SynchronousDiskIntStackTest_"
				+ System.currentTimeMillis();
		new File(diskdir).mkdirs();

		final int size = 8;
		
		final IntStack diskIntStack = new SynchronousDiskIntStack(diskdir, "SynchronousDiskIntStackTest", size);
		
		// Fill stack trice
		for (int i = 0; i < (size * 3); i++) {
			diskIntStack.pushInt(i);
		}

		// Check all elements still on stack
		for (int i = (3*size) - 1; i >= 0; i--) {
			assertEquals(i, diskIntStack.popInt());
		}
		
		assertEquals(0, diskIntStack.size());
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/simulation/LiveCheckTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness.simulation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.io.IOException;

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;

import tlc2.tool.ITool;
import tlc2.tool.TLCState;
import tlc2.tool.liveness.AbstractDiskGraph;
import tlc2.tool.liveness.ILiveCheck;
import tlc2.tool.liveness.LiveCheck;
import tlc2.tool.liveness.LiveExprNode;
import tlc2.tool.liveness.OrderOfSolution;
import tlc2.tool.liveness.TBGraph;
import tlc2.tool.liveness.TBGraphNode;
import tlc2.tool.queue.DummyTLCState;
import tlc2.util.SetOfStates;
import tlc2.util.statistics.DummyBucketStatistics;

public class LiveCheckTest {

	private ITool tool;
	
	@Before
	public void createTool() {
		this.tool = EasyMock.createNiceMock(ITool.class);
	}

	// Add identical state twice, which can happen in simulation mode when the
	// trace is: <<100L, 200L, ..., 100L, 200L>> (as in a cycle that is
	// repeated due to the trace length). In this scenario DiskGraph should
	// *not* add/update the 100L state, because it's successors (200L) don't
	// change.
	// Note that adding/updating the state would result in a larger
	// on-disk file, but doesn't seem to invalidate the simulation validity.
	@Test
	public void testAddIdenticalNodeTwiceNoTableau() throws IOException {
		addIdenticalNodeTwice(false, -1);
	}

	@Test
	public void testAddIdenticalNodeTwiceWithTableau() throws IOException {
		addIdenticalNodeTwice(true, 0);
	}

	public void addIdenticalNodeTwice(boolean withTablue, int tableauId) throws IOException {
		final ILiveCheck liveCheck;
		if (withTablue) {
			liveCheck = getLiveCheckWithTableau();
		} else {
			liveCheck = getLiveCheck();
		}

		assertEquals(1, liveCheck.getNumChecker());
		final AbstractDiskGraph diskGraph = liveCheck.getChecker(0).getDiskGraph();
		assertNotNull(diskGraph);
		
		final TLCState state = new DummyTLCState();
		liveCheck.addInitState(tool, state, 100L);

		final SetOfStates setOfStates = new SetOfStates(1);
		setOfStates.put(200L, new DummyTLCState(200L));
		
		// Add state 100L the first time, then add its successor
		liveCheck.addNextState(tool, state, 100L, setOfStates);
		liveCheck.addNextState(tool, state, 200L, setOfStates);
		assertEquals(0, diskGraph.getPtr(100L, tableauId));

		// Add state 100L again and check that it does *not* 
		// end up in disk graph.
		liveCheck.addNextState(tool, state, 100L, setOfStates);
		assertEquals(0, diskGraph.getPtr(100L, tableauId));
	}

	private ILiveCheck getLiveCheck() throws IOException {
		final ITool tool = EasyMock.createNiceMock(ITool.class);
		// Configure OOS mock to react to the subsequent invocation. This is
		// essentially the list of calls being made on OOS during
		// LiveCheck#addInitState and LiveCheck#addNextState
		final OrderOfSolution oos = EasyMock.createNiceMock(OrderOfSolution.class);
		EasyMock.expect(oos.hasTableau()).andReturn(false);
		EasyMock.expect(oos.getCheckAction()).andReturn(new LiveExprNode[0]).anyTimes();
		EasyMock.expect(oos.checkState((ITool) EasyMock.anyObject(), (TLCState) EasyMock.anyObject())).andReturn(new boolean[0]).anyTimes();
		EasyMock.replay(oos);
		
		return new LiveCheck(tool,
				new OrderOfSolution[] { oos }, System.getProperty("java.io.tmpdir"), new DummyBucketStatistics());
	}
	
	private ILiveCheck getLiveCheckWithTableau() throws IOException {
		final TBGraphNode node = EasyMock.createMock(TBGraphNode.class);
		EasyMock.expect(node.isConsistent((TLCState) EasyMock.anyObject(), (ITool) EasyMock.anyObject())).andReturn(true)
				.anyTimes();
		EasyMock.expect(node.nextSize()).andReturn(1).anyTimes();
		EasyMock.expect(node.nextAt(0)).andReturn(node).anyTimes();
		EasyMock.expect(node.getIndex()).andReturn(0).anyTimes();
		EasyMock.replay(node);
		
		final TBGraph tbGraph = new TBGraph();
		tbGraph.addElement(node);
		tbGraph.setInitCnt(1);
		
		// Configure OOS mock to react to the subsequent invocation. This is a
		// essentially the list of calls being made on OOS during
		// LiveCheck#addInitState and LiveCheck#addNextState
		final OrderOfSolution oos = EasyMock.createNiceMock(OrderOfSolution.class);
		EasyMock.expect(oos.hasTableau()).andReturn(true);
		EasyMock.expect(oos.getTableau()).andReturn(tbGraph).anyTimes();
		EasyMock.expect(oos.getCheckAction()).andReturn(new LiveExprNode[0]).anyTimes();
		EasyMock.expect(oos.checkState((ITool) EasyMock.anyObject(), (TLCState) EasyMock.anyObject())).andReturn(new boolean[0]).anyTimes();
		EasyMock.replay(oos);
		
		return new LiveCheck(tool,
				new OrderOfSolution[] { oos }, System.getProperty("java.io.tmpdir"), new DummyBucketStatistics());
	}
}



<|start_filename|>toolbox/org.lamport.tla.toolbox/src/org/lamport/tla/toolbox/spec/parser/ParserDependencyStorage.java<|end_filename|>
package org.lamport.tla.toolbox.spec.parser;

import java.util.List;
import java.util.Vector;

/**
 * This class is responsible for the storage of the dependency information between the modules.
 * It uses the DoubleHashedTable class to store the information in a rather obscure way.  My
 * guess is that Simon originally intended for this to keep the two directed graphs with "imports" and
 * "is imported by" edges.  However, a little experimentation suggests that the implementation
 * degenerated into two trivial graphs saying only that the root module imports every other module,
 * and every other module is imported by the root module.
 * 
 * @author <NAME>
 * @version $Id$
 */
public class ParserDependencyStorage
{
    
    private DoubleHashedTable moduleStore = null;

    public ParserDependencyStorage()
    {
        initialize();
    }

    /**
     * Initializes the 
     */
    public void initialize()
    {
        moduleStore = new DoubleHashedTable(101);
    }

    /**
     * Looks up a module
     * @param moduleName
     * @return true
     */
    public boolean hasModule(String moduleName) 
    {
        return moduleStore.containsKey(moduleName) || moduleStore.containsValue(moduleName); 
    }
    
    /**
     * Saves the new module dependency list, returns the old
     * list. 
     *  
     *  
     * @param parsedModule the module on which the parse has been invoked 
     * @param listOfParsedModules a list of modules, found during the parse operation, excluding the standard modules
     */
    public List put(String parsedModule, List listOfParsedModules)
    {
        if (parsedModule == null || listOfParsedModules == null)
        {
            return new Vector(0);
        }

        // cleanup the entire information that has been stored about this module
        List oldValues = parseFailed(parsedModule);

        // store the dependencies
        moduleStore.put(parsedModule, listOfParsedModules);
        
        // return the old values
        return oldValues;
        
    }

    /**
     * Parse operation failed on the specified parse module 
     * @param parseModule the module on which the parse has been invoked 
     */
    public List parseFailed(String parseModule)
    {
        // remove the key
        return moduleStore.removeKey(parseModule);
    }

    /**
     * The following documentation by Simon seems to be almost totally incorrect.
     * A little experimentation suggests that this returns a list containing only the root module
     * if changedModule is not the root Module, and an empty list otherwise.
     * 
     * Retrieves the list of modules, that should be re-parsed, because a module has changed
     * <br><b>Note:</b> The modules on the list returned EXTEND the changed module.
     * 
     *  
     * @param changedModule the name of the changed module + ".tla"
     * @return list of modules to re-parse
     */
    public List getListOfModulesToReparse(String changedModule)
    {
        Vector dependantModules = (Vector) moduleStore.getKeys(changedModule);
        if (dependantModules == null)
        {
            dependantModules = new Vector();
        }
        return dependantModules;
    }
    
    /**
     * The following documentation by Simon seems to be almost totally incorrect.
     * A little experimentation suggests that this returns the the list of all
     * imported modules if changedModule is the root module, and an empty list otherwise.
     * By "module", of course, we mean the module name + ".tla".

     * Retrieves the list of modules that are imported (directly
     * or indirectly) by current module
     * @param rootModule, name of the module + ".tla"
     * @return list of modules it depends (EXTEND) on
     */
    public List getListOfExtendedModules(String rootModule)
    {
        Vector dependantModules = null;
        if (rootModule == null) 
        {
            dependantModules = new Vector();
            return dependantModules;
        }
        dependantModules = (Vector) moduleStore.getValues(rootModule);
        if (dependantModules == null)
        {
            dependantModules = new Vector();
        }
        return dependantModules;
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.product.standalone/src/org/lamport/tla/toolbox/lifecycle/ToolboxLifecycleParticipant.java<|end_filename|>
package org.lamport.tla.toolbox.lifecycle;

import org.eclipse.ui.IWorkbenchWindow;

/**
 * Describes a basic interface for the tool contribution
 * 
 * @author <NAME>
 */
public abstract class ToolboxLifecycleParticipant
{
    /**
     * Is called during toolbox initialization
     * The implementation is empty, subclasses may override
     */
	public void initialize() {
    	// subclasses may override
	}
    
    /**
     * Is called when the {@link IWorkbenchWindow} has been opened.
     */
    public void postWorkbenchWindowOpen() {
    	// subclasses may override
    }
    
    /**
     * Is called during termination of the toolbox. 
     * The implementation is empty, subclasses may override
     */
	public void terminate(){
    	// subclasses may override
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/Set.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Last modified on Tue Sep 12 14:46:23 PDT 2000 by yuanyu  
//      modified on Thu Jul  9 22:10:25 PDT 1998 by manolios

/**
 * This class was derived from the HashTable implementation
 * in Sun's JDK. It supports quick membership check.
 */
package util;

import java.io.IOException;
import java.util.Enumeration;
import java.util.NoSuchElementException;

class SetEntry {
  /*
   * Set collision list.
   */
  int hash;
  Object key;
  SetEntry next;

  protected Object clone() {
    SetEntry entry = new SetEntry();
    entry.hash = hash;
    entry.key = key;
    entry.next = (next != null) ? (SetEntry)next.clone() : null;
    return entry;
  }
}

/**
 * This class implements a set. Any non-<code>null</code> object can
 * be used as a key (element).
 * <p>
 * To successfully store and retrieve objects from a set, the element
 * objects used as keys must implement the <code>hashCode</code> 
 * method and the <code>equals</code> method. 
 * <p>
 * An instance of <code>Set</code> has two parameters that affect its
 * efficiency: its <i>capacity</i> and its <i>load factor</i>. The 
 * load factor should be between 0.0 and 1.0. When the number of entries
 * in the set exceeds the product of the load factor and the current
 * capacity, the capacity is increased by calling the <code>rehash</code>
 * method. Larger load factors use memory more efficiently, at the 
 * expense of larger expected time per lookup. 
 * <p>
 * If many entries are to be made into a <code>Set</code>, creating it
 * with a sufficiently large capacity may allow the entries to be 
 * inserted more efficiently than letting it perform automatic rehashing
 * as needed to grow the set.
 * <p>
 * </pre></blockquote>
 */
public class Set implements Cloneable, java.io.Serializable {
    /*
     * A set of objects.
     */
    private transient SetEntry set[];

    /* The total number of elements in the set.  */
    private transient int count;

    /* Rehashes the set when count exceeds this threshold.  */
    private int threshold;

    /* The load factor for the set.    */
    private float loadFactor;

    /* use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = 1421746759512286392L;

    /*
     * Constructs a new, empty set with the specified initial 
     * capacity and the specified load factor. 
     *
     * @param      initialCapacity   the initial capacity of the set.
     * @param      loadFactor        a number between 0.0 and 1.0.
     * @exception  IllegalArgumentException  if the initial capacity is less
     *               than or equal to zero, or if the load factor is less than
     *               or equal to zero.
     * @since      JDK1.0
     */
    public Set(int initialCapacity, float loadFactor) {
      if ((initialCapacity <= 0) || (loadFactor <= 0.0)) {
	throw new IllegalArgumentException();
      }
      this.loadFactor = loadFactor;
      set = new SetEntry[initialCapacity];
      threshold = (int)(initialCapacity * loadFactor);
    }

    /*
     * Constructs a new empty set with the specified initial capacity
     * and default load factor.
     *
     * @param   initialCapacity   the initial capacity of the set.
     */
    public Set(int initialCapacity) {
      this(initialCapacity, 0.75f);
    }

    /*
     * Constructs a new, empty set with a default capacity and load
     * factor. 
     */
    public Set() { this(101, 0.75f); }

    /*
     * Returns the number of keys in this set.
     *
     * @return  the number of keys in this set.
     */
    public int size() { return this.count; }

    /*
     * Tests if this set is empty.
     *
     * @return  <code>true</code> if this set is empty.
     *          <code>false</code> otherwise.
     * @since   JDK1.0
     */
    public boolean isEmpty() { return count == 0; }

    /*
     * Returns an enumeration of the elements in this set.
     *
     * @return  an enumeration of the elements in this set.
     * @see     java.util.Enumeration
     */
    public synchronized Enumeration elements() {
      return new SetEnumerator(set);
    }

    /*
     * Tests if the specified object is an element in this set.
     * 
     * @param   key   possible key.
     * @return  <code>true</code> if the specified object is an element
     *          in this set; <code>false</code> otherwise.
     */
    public synchronized boolean contains(Object key) {
      SetEntry tab[] = set;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;
      for (SetEntry e = tab[index] ; e != null ; e = e.next) {
	if ((e.hash == hash) && e.key.equals(key)) {
	  return true;
	}
      }
      return false;
    }

    /*
     * Rehashes the contents of the set into a set with a larger capacity.
     * This method is called automatically when the number of keys in the
     * set exceeds this set's capacity and load factor. 
     */
    protected void rehash() {
      int oldCapacity = set.length;
      SetEntry oldSet[] = set;
	
      int newCapacity = oldCapacity * 2 + 1;
      SetEntry newSet[] = new SetEntry[newCapacity];

      threshold = (int)(newCapacity * loadFactor);
      set = newSet;

      for (int i = oldCapacity ; i-- > 0 ;) {
	for (SetEntry old = oldSet[i] ; old != null ; ) {
	  SetEntry e = old;
	  old = old.next;

	  int index = (e.hash & 0x7FFFFFFF) % newCapacity;
	  e.next = newSet[index];
	  newSet[index] = e;
	}
      }
    }

    /*
     * Puts the specified <code>key</code> as an element into this set.
     * The key can not be <code>null</code>. 
     * <p>
     * @param      key     the element.
     * @return     the previous copy of the element in this set,
     *             or <code>null</code> if it did not have one.
     * @exception  NullPointerException  if the element is <code>null</code>.
     * @see     java.lang.Object#equals(java.lang.Object)
     */
    public synchronized Object put(Object key) {
      // Makes sure the key is not already in the set.
      SetEntry tab[] = set;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;
      for (SetEntry e = tab[index] ; e != null ; e = e.next) {
	if ((e.hash == hash) && e.key.equals(key)) {
	  Object old = e.key;
	  e.key = key;
	  return old;
	}
      }
      
      if (count >= threshold) {
	// Rehash the set if the threshold is exceeded
	rehash();
	return put(key);
      } 

      // Creates the new entry.
      SetEntry e = new SetEntry();
      e.hash = hash;
      e.key = key;
      e.next = tab[index];
      tab[index] = e;
      count++;
      return null;
    }

    /*
     * Removes the key (element) from this set. This method does nothing
     * if the key is not in the set.
     *
     * @param   key   the key that needs to be removed.
     * @return  the element in this set, or <code>null</code> if the key
     *          is not in the set.
     */
    public synchronized Object remove(Object key) {
      SetEntry tab[] = set;
      int hash = key.hashCode();
      int index = (hash & 0x7FFFFFFF) % tab.length;
      for (SetEntry e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
	if ((e.hash == hash) && e.key.equals(key)) {
	  if (prev != null) {
	    prev.next = e.next;
	  } else {
	    tab[index] = e.next;
	  }
	  count--;
	  return e.key;
	}
      }
      return null;
    }

    /*
     * Empty this set.
     */
    public synchronized void clear() {
      SetEntry tab[] = set;
      for (int index = tab.length; --index >= 0; )
	tab[index] = null;
      count = 0;
    }

    /*
     * Creates a shallow copy of this set. The elements themselves are
     * not cloned. 
     * This is a relatively expensive operation.
     *
     * @return  a clone of the set.
     */
    public synchronized Object clone() {
      try { 
	Set t = (Set)super.clone();
	t.set = new SetEntry[set.length];
	for (int i = set.length ; i-- > 0 ; ) {
	  t.set[i] = (set[i] != null) ? (SetEntry)set[i].clone() : null;
	}
	return t;
      } catch (CloneNotSupportedException e) { 
	// this shouldn't happen, since we are Cloneable
	throw new InternalError();
      }
    }

    /*
     * Returns a rather long string representation of this set.
     *
     * @return a string representation of this set.
     */
    public synchronized String toString() {
	int max = size() - 1;
	StringBuffer buf = new StringBuffer();
	Enumeration e = elements();
	buf.append("{");

	for (int i = 0; i <= max; i++) {
	    String s1 = e.nextElement().toString();
	    buf.append(s1);
	    if (i < max) buf.append(", ");
	}
	buf.append("}");
	return buf.toString();
    }

    /*
     * WriteObject is called to save the state of the set to a stream.
     * Only the elements are serialized since the hash values may be
     * different when the contents are restored.
     * iterate over the contents and write out the elements.
     */
    private synchronized void writeObject(java.io.ObjectOutputStream s)
    throws IOException {
      // Write out the length, threshold, loadfactor
      s.defaultWriteObject();

      // Write out length, count of elements and then the key/value objects
      s.writeInt(set.length);
      s.writeInt(count);
      for (int index = set.length-1; index >= 0; index--) {
	SetEntry entry = set[index];

	while (entry != null) {
	  s.writeObject(entry.key);
	  entry = entry.next;
	}
      }
    }

    /*
     * readObject is called to restore the state of the set from
     * a stream.  Only the elements are serialized since the
     * hash values may be different when the contents are restored.
     * Read count elements and insert into the set.
     */
    private synchronized void readObject(java.io.ObjectInputStream s)
    throws IOException, ClassNotFoundException {
	// Read in the length, threshold, and loadfactor
	s.defaultReadObject();

	// Read the original length of the array and number of elements
	int origlength = s.readInt();
	int elements = s.readInt();

	// Compute new size with a bit of room 5% to grow but
	// No larger than the original size.  Make the length
	// odd if it's large enough, this helps distribute the entries.
	// Guard against the length ending up zero, that's not valid.
	int length = (int)(elements * loadFactor) + (elements / 20) + 3;
	if (length > elements && (length & 1) == 0) length--;
	if (origlength > 0 && length > origlength) length = origlength;

	set = new SetEntry[length];
	count = 0;

	// Read the number of elements and then all the key/value objects
	for (; elements > 0; elements--) {
	    Object key = s.readObject();
	    put(key);
	}
    }

  /**
   * Checks for set containment, ie. is x in this? It is just another
   * way to write the hashtable containsKey.
   */
  public synchronized boolean in(Object x) {
    return contains(x);
  }

  /**
   * Destructively modify this so that it becomes the intersection of
   * itself with x.  We iterate over the elements in this and remove any
   * that are not also in x.
   */
  public void intersection (Set x) { 
    Enumeration elements = elements();
    Object a;
    while (elements.hasMoreElements()) {
      a = elements.nextElement();
      if (! x.in(a))
	remove(a);
    }
  }

  /**
   * Create a new set which is the intersection of x and y.  We clone
   * the smaller (set size) of x, y because that's what intersection
   * iterates on.
   */
  public static Set intersection(Set x, Set y) {
    Set result = new Set();
    if (x.size() < y.size()) {
      result = (Set) x.clone();
      result.intersection(y);
    }
    else {
      result = (Set) x.clone();
      result.intersection(y);
    }
    return result;
  }

  /**
   * Destructively modify this so that it becomes the union of itself
   * with x.  We iterate over the elements in x, adding to this any that
   * are not in x.
   */
  public void union(Set x) { 
    Enumeration elements = x.elements();
    while (elements.hasMoreElements()) 
      put(elements.nextElement());
  }

  /**
   * Create a new set which is the union of x and y.  We clone the
   * larger (set size) of x, y because union iterates on the one not
   * cloned.
   */
  public static Set union(Set x, Set y) {
    Set result = new Set();
    if (x.size() > y.size()) {
      result = (Set) x.clone();
      result.union(y);
    }
    else {
      result = (Set) x.clone();
      result.union(y);
    }
    return result;
  }

  /**
   * Destructively modify this so that all elements in x are removed.
   * If |this| > |x| we iterate over the elements in x, removing them all
   * from this.  Otherwise, we iterate over the elements in this, removing
   * any that are in x.
   */
  public void minus(Set x) { 
    if (size() > x.size()) {
      Enumeration elements = x.elements();
      while (elements.hasMoreElements()) 
	remove(elements.nextElement());
    }
    else {
      Enumeration elements = elements();
      Object a;
      while (elements.hasMoreElements()) {
	a = elements.nextElement();
	if (x.in(a))
	  remove(a);
      }
    }
  }

  /* Create a new set which equals x - y.  */
  public static Set minus(Set x, Set y) {
    Set result = (Set) x.clone();
    result.minus(y);
    return result;
  }

  /* Complementation with respect to universe u. */
  public static Set complement (Set x, Set u) { return minus(u, x); }

  /* Is this a subset of x. */  
  public boolean subset (Set x) {
    Enumeration elements = elements();
    while (elements.hasMoreElements()) 
      if (! x.in(elements.nextElement()))
	return false;
    return true;
  }
 
  /* Is x a subset of y?  */
  public static boolean subset (Set x, Set y) { return x.subset(y); }

  /* Is this equal (as a set) to x?   */
  public boolean equal (Set x) {
    return (subset(x) && x.subset(this));
  }
 
  /* Is x equal (as a set) to y? */
  public static boolean equal (Set x, Set y) { return x.equal(y); }
}

/*
 * A set enumerator class.  This class should remain opaque 
 * to the client. It will use the Enumeration interface. 
 */
class SetEnumerator implements Enumeration {
  int index;
  SetEntry set[];
  SetEntry entry;

  SetEnumerator(SetEntry set[]) {
    this.set = set;
    this.index = set.length;
  }
	
  public boolean hasMoreElements() {
    if (entry != null) {
      return true;
    }
    while (index-- > 0) {
      if ((entry = set[index]) != null) {
	return true;
      }
    }
    return false;
  }

  public Object nextElement() {
    if (entry == null) {
      while ((index-- > 0) && ((entry = set[index]) == null));
    }
    if (entry != null) {
      SetEntry e = entry;
      entry = e.next;
      return e.key;
    }
    throw new NoSuchElementException("SetEnumerator");
  }
}


<|start_filename|>tlatools/org.lamport.tlatools/src/util/TLAFlightRecorder.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package util;

// Label is only used by Mission control but not relevant for the recording itself.
public class TLAFlightRecorder {
	
    @jdk.jfr.Label("Progress")
    @jdk.jfr.Category({"TLC", "Progress"})
    @jdk.jfr.StackTrace(false)// No need to capture the stack of the reporting (main) thread when it emits the event.
	private static class ProgressEvent extends jdk.jfr.Event {
		@jdk.jfr.Label("States generated per minute")
		@jdk.jfr.Unsigned
		private long spm;
		@jdk.jfr.Label("Distinct states generated per minute")
		@jdk.jfr.Unsigned
		private long dspm;
		@jdk.jfr.Label("Unseen States")
		@jdk.jfr.Unsigned
		private long unseen;
		@jdk.jfr.Label("Diameter")
		@jdk.jfr.Unsigned
		private int diameter;
		@jdk.jfr.Label("States Generated")
		@jdk.jfr.Unsigned
		private long states;
		@jdk.jfr.Label("Distinct States Generated")
		@jdk.jfr.Unsigned
		private long distStates;
		@jdk.jfr.Label("Model Checking done")
		private boolean isFinal;
	}

	public static void progress(boolean isFinal, final int diameter, final long states, final long distinctStates, final long unseen,
			final long statesPerMinute, final long distinctStatesPerMinute) {
		try {
			final ProgressEvent e = new ProgressEvent();
			e.isFinal = isFinal;
			e.spm = statesPerMinute;
			e.dspm = distinctStatesPerMinute;
			e.diameter = diameter;
			e.unseen = unseen;
			e.states = states;
			e.distStates = distinctStates;
			e.commit();
		} catch (NoClassDefFoundError e) {
			// Java 1.8 doesn't have jdk.jfr.Event and thus this flight recording is broken.
		}
	}
	
    @jdk.jfr.Label("Message")
    @jdk.jfr.Category({"TLC"})
    @jdk.jfr.StackTrace(false)// No need to capture the stack of the reporting (main) thread when it emits the event.
	private static class MessageEvent extends jdk.jfr.Event {
		@jdk.jfr.Label("Message")
		public String message;
    }

	public static String message(final String message) {
		try {
			final MessageEvent e = new MessageEvent();
			e.message = message;
			e.commit();
		} catch (NoClassDefFoundError e) {
			// Java 1.8 doesn't have jdk.jfr.Event and thus this flight recording is broken.
		}
		return message;
	}
}

<|start_filename|>toolbox/org.lamport.tla.toolbox.doc/html/prover/reading.html<|end_filename|>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- This is file org.lamport.tla.toobox.doc/html/prover/prover.html -->
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <LINK href="../style.css" rel="stylesheet" type="text/css">

	<title>Viewing and Editing Structured Proofs</title>
</head>
<!-- a comment -->

<body>
<h1>Viewing and Editing Structured Proofs</h1>

<pre>
Contents
  <a href="#viewing">Viewing proofs</a>
  <a href="#editing">Editing proofs</a>
</pre>

<h2><a name="viewing">Viewing Proofs</a></h2>
<p> When you open in the module editor a module containing a theorem
wth a proof, you will see a &nbsp;<samp>(-)</samp>&nbsp; next to the
theorem and next to each step that has a subproof.&nbsp; To avoid
repeatedly saying <em>step or theorem</em>, we here take a
<em>step</em> to be either a theorem or a step of a theorem's
proof.&nbsp;

Clicking on the &nbsp;<samp>(-)</samp>&nbsp; next to a step hides the
step's proof and changes the &nbsp;<samp>(-)</samp>&nbsp; to a
&nbsp;<samp>(+)</samp>&nbsp;.

Clicking on the &nbsp;<samp>(+)</samp>&nbsp; undoes the effect of
clicking on the &nbsp;<samp>(-)</samp>&nbsp;.
</p>

Right-clicking on a step provides a menu with a section containing
the following commands for
hiding and revealing parts of the proof of the step at which the
cursor is positioned.&nbsp;  These commands can also be executed
with the indicated pair of keystrokes.&nbsp;

If you just type <samp>Ctl+G</samp> (the first keystroke) and wait
a second, you will see a list of all the commands telling you what
keystroke you should type next.

<p>

<dl>

<dt> <b>Show Current Subtree</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+S</samp> </dt>
<dd> Reveals the proof of the step.</dd>
<p> </p>

<dt> <b>Hide Current Subtree</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+H</samp> </dt>
<dd> Hides the proof of the step.</dd>
<p> </p>

<dt> <b>Show Children Only</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+C</samp> </dt>
<dd> Reveals the top level of the step's proof.</dd>
<p> </p>

<dt> <b>Focus on Step</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+F</samp> </dt>
<dd> Hides everything except the top level of the step's proof and
the siblings (steps at the same level as) of the step and
of every ancestor of that step in the proof.</dd>
</dl>

The following commands can be performed by right-clicking anywhere
in the module.

<dl>
<dt> <b>Show All Proofs</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+A</samp> </dt>
<dd> Reveals the complete proof of every theorem in the module.</dd>
<p> </p>

<dt> <b>Hide All Proofs</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+N</samp> </dt>
<dd> Hides the proof of every theorem in the module.</dd>
</dl>
The <em>Focus on Step</em> command performed outside a proof
is equivalent to <em>Hide All Proofs</em>

<h2><a name="editing">Editing Proofs</a></h2>

There are two commands especially for editing proofs:
<dl>
<dt><b>Decompose Proof</b> &nbsp; &nbsp; <samp>Ctl+G Ctl+D</samp> </dt>
<dd> To use this command, put the cursor in a theorem or proof step that
has either no proof or else a leaf proof (a <code>BY</code> or <code>OBVIOUS</code>
proof) that TLAPS can't verify.&nbsp;  This command raises a dialog window that allows
you to decompose the proof of the theorem or step into simpler steps.&nbsp;
The dialog contains a 
   <IMG SRC=../gettingstarted/question-mark.gif align=bottom>
button that raises <a href="decompose.html">this help page</a>, which explains
what you can do with this dialog.

</dd>

<p> </p>
<dt><b><a name="renumber-proof">Renumber Proof</a></b> &nbsp; &nbsp; <samp>Ctl+G Ctl+R</samp> </dt>
<dd>
A proof step is either <i>named</i> or <i>unnamed</i>.&nbsp;  

An unnamed step begins with just a level number, like <code><4></code>.&nbsp;

A named step begins with a level number and a name, like <code><4>7</code>
or <code><4>xy2</code> (optionally followed by a period).&nbsp;

Putting the cursor on a proof step and executing the <i>Renumber Proof</i>
command causes all the named top-level steps of its proof to be renamed with
consecutive numbers, like <code><4>1</code>, <code><4>2</code>, etc.&nbsp;

However, you might want to use some meaningful step names like <code><2>NextImpliesInv1</code>
that you don't want to be turned into numbers.&nbsp;

A <a href="../gettingstarted/module-editor-preferences.html">module editor
preference</a> provides options to control what step names don't get turned 
into numbers.&nbsp;

There is also a preference that determines whether the module should be saved 
after executing the command.

</dd>
</dl>
The Toolbox editor's 
<a href="../spec/editing-modules.html#block-selection">block-selection
mode</a> can help in formatting proofs.&nbsp;

We would like to create additional editor commands to make it easier to write
and edit proofs, but we don't know what commands would be useful.&nbsp;  

Please tell us what commands <i>you</i> would like.&nbsp;



</p>
<hr>
<a href = "prover.html">&uarr; Proofs</a>
</hr>

</body>
</html>

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc/src/org/lamport/tla/toolbox/tool/tlc/job/AbstractJob.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.job;

import java.io.File;

import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.action.Action;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.progress.IProgressConstants;

/**
 * General job
 * @author <NAME>
 * @version $Id$
 */
public abstract class AbstractJob extends Job
{
    /**
     * 
     * @param name
     */
    public AbstractJob(String name)
    {
        super(name);
    }

    /**
     * 
     * @param job
     * @return
     */
    protected static boolean isModal(Job job)
    {
        Boolean isModal = (Boolean) job.getProperty(IProgressConstants.PROPERTY_IN_DIALOG);
        if (isModal == null)
            return false;
        return isModal.booleanValue();
    }

    /**
     * Called when the job is finished.
     */
    protected void doFinish()
    {
        // setProperty(IProgressConstants.ICON_PROPERTY, image);
        if (AbstractJob.isModal(this))
        {
            Display.getDefault().asyncExec(new Runnable() {
                public void run()
                {
                    getJobCompletedAction().run();
                }
            });
        } else
        {
            setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
            setProperty(IProgressConstants.ACTION_PROPERTY, getJobCompletedAction());
        }
    }
    

	protected IVMInstall getVMInstall() {
        IVMInstall vmInstall = null;

		// Try using the very same VM the Toolbox is running with (e.g.
		// this avoids problems when the Toolbox runs with a 64bit VM, but
		// the nested VM is a 32bit one).
        final String javaHome = System.getProperty("java.home");
        if (javaHome != null) {
            final IVMInstallType installType = new StandardVMType();
            vmInstall = installType.createVMInstall("TLCModelCheckerNestedVM");
            vmInstall.setInstallLocation(new File(javaHome));
            return vmInstall;
        }

        // get OS default VM (determined by path) not necessarily the same
		// the toolbox is running with.
        return JavaRuntime.getDefaultVMInstall();
	}

    protected abstract Action getJobCompletedAction();

}


<|start_filename|>tlatools/org.lamport.tlatools/test/pcal/StackTestTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2018 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package pcal;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import tlc2.output.EC;

public class StackTestTest extends PCalModelCheckerTestCase {

	public StackTestTest() {
		super("StackTest", "pcal");
	}

	@Test
	public void testSpec() {
		assertTrue(recorder.recorded(EC.TLC_FINISHED));
		assertFalse(recorder.recorded(EC.GENERAL));
	}
}
/*
TLC2 Version 2.12 of 29 January 2018
Running breadth-first search Model-Checking with 1 worker on 4 cores with 5303MB heap and 64MB offheap memory (Linux 4.15.0-22-generic amd64, Oracle Corporation 1.8.0_171 x86_64).
Parsing file /home/markus/Desktop/LesliePCalTest/alltests/StackTest.tla
Parsing file /home/markus/src/TLA/tla/tlatools/class/tla2sany/StandardModules/Sequences.tla
Parsing file /home/markus/src/TLA/tla/tlatools/class/tla2sany/StandardModules/Naturals.tla
Parsing file /home/markus/src/TLA/tla/tlatools/class/tla2sany/StandardModules/TLC.tla
Semantic processing of module Naturals
Semantic processing of module Sequences
Semantic processing of module TLC
Semantic processing of module StackTest
Starting... (2018-05-23 12:30:31)
Computing initial states...
Finished computing initial states: 1 distinct state generated.
Warning: The EXCEPT was applied to non-existing fields of the value at
line 36, col 26 to line 36, col 30 of module StackTest
(Use the -nowarning option to disable this warning.)
Error: TLC threw an unexpected exception.
This was probably caused by an error in the spec or model.
See the User Output or TLC Console for clues to what happened.
The exception was a tlc2.tool.EvalException
: Attempted to apply the operator overridden by the Java method
public static tlc2.value.Value tlc2.module.TLC.Assert(tlc2.value.Value,tlc2.value.Value),
but it produced the following error:
The first argument of Assert evaluated to FALSE; the second argument was:
"Failure of assertion at line 13, column 17."
Error: The behavior up to this point is:
State 1: <Initial predicate>
/\ stack = (0 :> <<>> @@ 1 :> <<>> @@ 2 :> <<>>)
/\ a = (0 :> 42 @@ 1 :> 42 @@ 2 :> 42)
/\ pc = (0 :> "Q1" @@ 1 :> "Q1" @@ 2 :> "Q1")

State 2: <Q1 line 51, col 13 to line 59, col 47 of module StackTest>
/\ stack = ( 0 :> <<[pc |-> "Done", a |-> 42, procedure |-> "P"]>> @@
  1 :> <<>> @@
  2 :> <<>> )
/\ a = (0 :> 22 @@ 1 :> 42 @@ 2 :> 42)
/\ pc = (0 :> "P1" @@ 1 :> "Q1" @@ 2 :> "Q1")

Error: The error occurred when TLC was evaluating the nested
expressions at the following positions:
0. Line 35, column 13 to line 42, column 21 in StackTest
1. Line 35, column 16 to line 35, column 30 in StackTest
2. Line 36, column 16 to line 36, column 80 in StackTest
3. Line 37, column 16 to line 38, column 68 in StackTest


4 states generated, 4 distinct states found, 2 states left on queue.
The depth of the complete state graph search is 2.
The average outdegree of the complete state graph is 3 (minimum is 3, the maximum 3 and the 95th percentile is 3).
Finished in 00s at (2018-05-23 12:30:31)
*/

<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/dialog/ExtraModulesDialog.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 *   <NAME> - Rewrite of ErrorViewTraceFilterDialog 
 ******************************************************************************/
package org.lamport.tla.toolbox.tool.tlc.ui.dialog;

import java.util.Arrays;
import java.util.Set;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class ExtraModulesDialog extends Dialog {
	private CheckboxTableViewer tableViewer;
	
	private final Set<String> modules;
	private final Set<String> selection;
	
	/**
	 * @param parentShell
	 * @param modules a copy of this list will be made
	 * @param previouslySelectedModuleNames 
	 */
	public ExtraModulesDialog(final Shell parentShell, final Set<String> modules, Set<String> previouslySelectedModuleNames) {
		super(parentShell);
		
		this.modules = modules;
		this.selection = previouslySelectedModuleNames;
	}
	
	public Set<String> getSelection() {
		return selection;
	}
	
    @Override
    protected final Control createDialogArea(final Composite parent) {
    	final Composite container = (Composite) super.createDialogArea(parent);
    	GridLayout gl = new GridLayout(2, false);
    	gl.verticalSpacing = 9;
    	container.setLayout(gl);

    	
    	
    	final Label l = new Label(container, SWT.LEFT);
    	l.setText("Selected modules to be made available in trace expressions.");
    	l.setFont(JFaceResources.getFontRegistry().get(JFaceResources.DIALOG_FONT));
    	GridData gd = new GridData();
    	gd.horizontalSpan = 2;
    	l.setLayoutData(gd);
    	

    	
    	tableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE);
    	tableViewer.setContentProvider(new ArrayContentProvider());
    	tableViewer.setLabelProvider(new ColumnLabelProvider() {
    		@Override
    		public String getText(final Object element) {
    			return (String) element;
    		}
    	});
    	tableViewer.setInput(modules);
		selection.stream().forEach((element) -> tableViewer.setChecked(element, true));
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	gd.minimumWidth = 333;
    	tableViewer.getTable().setLayoutData(gd);
    	
    	
    	final Composite buttonPane = new Composite(container, SWT.NONE);
    	gl = new GridLayout(1, false);
    	buttonPane.setLayout(gl);
    	
    	Button b = new Button(buttonPane, SWT.PUSH);
    	b.setText("Select All");
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	b.setLayoutData(gd);
    	b.addSelectionListener(new SelectionAdapter() {
    		@Override
    		public void widgetSelected(final SelectionEvent se) {
    			tableViewer.setAllChecked(true);
    		}
    	});
    	
    	b = new Button(buttonPane, SWT.PUSH);
    	b.setText("Deselect All");
    	gd = new GridData();
    	gd.horizontalAlignment = SWT.FILL;
    	gd.grabExcessHorizontalSpace = true;
    	b.setLayoutData(gd);
    	b.addSelectionListener(new SelectionAdapter() {
    		@Override
    		public void widgetSelected(final SelectionEvent se) {
    			tableViewer.setAllChecked(false);
    		}
    	});
    	
    	
        return container;
    }

    @Override
    protected void okPressed() {
    	selection.clear();
    	
		Arrays.stream(tableViewer.getCheckedElements()).forEach((element) -> selection.add((String)element));
		
        super.okPressed();
    }
    
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
    }
    
	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText("Extra Modules");
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/distributed/selector/IBlockSelector.java<|end_filename|>
package tlc2.tool.distributed.selector;

import tlc2.tool.TLCState;
import tlc2.tool.distributed.TLCWorker;
import tlc2.tool.distributed.TLCWorkerRMI;
import tlc2.tool.queue.IStateQueue;
import tlc2.tool.queue.StateQueue;

public interface IBlockSelector {
	/**
	 * Calculates the number of states a worker should be assigned. This
	 * calculation is based on the current number of workers registered with the
	 * server assigning each worker 1/N of the {@link StateQueue} with N being the
	 * current amount of {@link TLCWorker}.
	 * 
	 * The block size essentially load balances the workers by deciding how much
	 * work they get assigned.
	 * 
	 * @param stateQueue Current queue of new states
	 * @param worker {@link TLCWorker} requesting work units ({@link TLCState})
	 * @return The states that will be assigned to the given remote {@link TLCWorker}
	 */
	public abstract TLCState[] getBlocks(final IStateQueue stateQueue, final TLCWorkerRMI worker);

	/**
	 * @param aMaximum
	 *            The maximum possible size that can be transfered over the
	 *            network. The {@link BlockSelector} must not exceed this value.
	 */
	public abstract void setMaxTXSize(int aMaximum);
	
	/**
	 * Statistical value intended for performance/scalability measures.
	 * @return The average block size handed out to workers
	 */
	public abstract long getAverageBlockCnt();
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/semantic/LevelConstants.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.semantic;

import java.util.HashSet;

public interface LevelConstants {

  static final int ConstantLevel = 0;
  static final int VariableLevel = 1;
  static final int ActionLevel   = 2;
  static final int TemporalLevel = 3;

  static final int MinLevel      = 0;
  static final int MaxLevel      = 3;

  static final Integer[] Levels = {new Integer(ConstantLevel),
				   new Integer(VariableLevel),
				   new Integer(ActionLevel),
				   new Integer(TemporalLevel)};
  
  static final HashSet EmptySet = new HashSet();
  static final SetOfLevelConstraints EmptyLC = new SetOfLevelConstraints();
  static final SetOfArgLevelConstraints EmptyALC = new SetOfArgLevelConstraints();
}



<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/ui/util/RecordToSourceCoupler.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.ui.util;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.lamport.tla.toolbox.tool.ToolboxHandle;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.model.TLCSpec;
import org.lamport.tla.toolbox.tool.tlc.output.data.ActionInformationItem;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCState;
import org.lamport.tla.toolbox.util.UIHelper;

import tla2sany.st.Location;

/**
 * A listener that will respond to the user double clicking or selecting an
 * action by opening the module containing that action and highlighting the
 * action; this also supports a jump to the location in a saved module editor if
 * such an editor is already open.
 * 
 * Currently, double clicking or selecting something in a viewer with this as a
 * listener will only do something if the selection is an instance of
 * {@link IModuleLocatable}.
 * {@link org.lamport.tla.toolbox.tool.tlc.output.data.TLCState} and
 * {@link org.lamport.tla.toolbox.tool.tlc.output.data.CoverageInformationItem}
 * implement that interface.
 * 
 * @author <NAME>
 */
public class RecordToSourceCoupler implements MouseListener, KeyListener {
	/**
	 * @see RecordToSourceCoupler#RecordToSourceCoupler(Viewer, Set, IWorkbenchPart, FocusRetentionPolicy)
	 */
	public enum FocusRetentionPolicy {
		/** All actions that are responded to keep focus in the defined workbench part **/
		ALWAYS,
		/** Only actions that are triggered by arrow key traversals keep focus in the defined workbench part **/
		ARROW_KEY_TRAVERSAL;
	}
	
	/**
	 * @see #setNonDefaultObservables(int)
	 */
	public static final int OBSERVE_DEFAULT = 0;
	public static final int OBSERVE_ARROW_KEY = 1 << 1;
	public static final int OBSERVE_SINGLE_CLICK = 1 << 2;
	
	
	private final Viewer viewer;
	private final Set<Class<? extends ITextEditor>> blacklist;
	private final IWorkbenchPart partToRefocus;
	
	private final AtomicBoolean observeArrowKeyEvents;
	private final AtomicBoolean observeSingleClickEvents;
	
	private final FocusRetentionPolicy focusRetentionPolicy;

	public RecordToSourceCoupler(final Viewer viewer) {
		this(viewer, new HashSet<Class<? extends ITextEditor>>());
	}

	public RecordToSourceCoupler(final Viewer variableViewer, final Set<Class<? extends ITextEditor>> editorBlacklist) {
		this(variableViewer, editorBlacklist, null, null);
	}

	/**
	 * @param workbenchPart if this is non-null, then the potential part focus change which may occur due to Location-based
	 * 			viewing will be followed with first a focus on to this, followed by a focus to the
	 * 			<code>variableViewer</code>'s control.
	 * @param focusPolicy under what conditions focus retention on the above workbench part is preserved
	 */
	public RecordToSourceCoupler(final Viewer variableViewer, final Set<Class<? extends ITextEditor>> editorBlacklist,
			final IWorkbenchPart workbenchPart, final FocusRetentionPolicy focusPolicy) {
		viewer = variableViewer;
		blacklist = editorBlacklist;
		partToRefocus = workbenchPart;
		observeArrowKeyEvents = new AtomicBoolean(false);
		observeSingleClickEvents = new AtomicBoolean(false);
		focusRetentionPolicy = focusPolicy;
	}
	
	/**
	 * @param observablesMask either OBSERVE_DEFAULT (turning off any changes in
	 *                        default behavior or a bitwise-OR'd combination of the
	 *                        OBSERVE_* constants)
	 */
	public void setNonDefaultObservables(final int observablesMask) {
		observeArrowKeyEvents.set((observablesMask & OBSERVE_ARROW_KEY) == OBSERVE_ARROW_KEY);
		observeSingleClickEvents.set((observablesMask & OBSERVE_SINGLE_CLICK) == OBSERVE_SINGLE_CLICK);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
	 */
	public void mouseDoubleClick(final MouseEvent event) {
		performSourceCoupling(viewer.getSelection(), ((event.stateMask & SWT.MOD1) != 0), false);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
	 */
	public void mouseDown(final MouseEvent event) {}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
	 */
	public void mouseUp(final MouseEvent event) {
		if (observeSingleClickEvents.get()) {
			performSourceCoupling(viewer.getSelection(), ((event.stateMask & SWT.MOD1) != 0), false);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
	 */
	public void keyPressed(final KeyEvent event) {}

	/* (non-Javadoc)
	 * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
	 */
	public void keyReleased(final KeyEvent event) {
		final int code = event.keyCode;
		
		if (code == SWT.CR) {
			performSourceCoupling(viewer.getSelection(), ((event.stateMask & SWT.MOD1) != 0), false);
		} else if ((code == SWT.KEYPAD_DIVIDE) && ((event.stateMask & SWT.ALT) != 0) && (viewer instanceof TreeViewer)) {
			((TreeViewer) viewer).collapseAll();
		} else if (observeArrowKeyEvents.get() && ((code == SWT.ARROW_UP) || (code == SWT.ARROW_DOWN))
				&& (viewer instanceof TreeViewer)) {
			performSourceCoupling(viewer.getSelection(), false, true);
		}
	}
	
	private void performSourceCoupling(final ISelection selection, final boolean jumpToPCal, final boolean dueToArrowKeys) {
		if (selection != null && !selection.isEmpty()) {
			if (selection instanceof StructuredSelection) {
				final StructuredSelection structuredSelection = (StructuredSelection) selection;
				// on a double click there should not be multiple selections,
				// so taking the first element of the structured selection
				// should work
				final Object firstElement = structuredSelection.getFirstElement();
				if (firstElement instanceof LoaderTLCState) {
					final LoaderTLCState loader = (LoaderTLCState) firstElement;
					// Loading more states can potentially block for a couple
					// seconds. Thus, give feedback to user.
					BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
						public void run() {
							loader.loadMore();
						}
					});
				} else if (firstElement instanceof IModuleLocatable) {
					final IModuleLocatable moduleLocatable = (IModuleLocatable) firstElement;
					Location location = moduleLocatable.getModuleLocation();
					if (moduleLocatable instanceof ActionInformationItem) {
						ActionInformationItem aii = (ActionInformationItem) moduleLocatable;
						if (aii.hasDefinition()) {
							// Do not jump to a sub-actions identifier but to its actual definition if a
							// sub-action has a definition. Consider this partial spec:
							// ...
							// Next == \/ /\ x = 42
							//            /\ x' = 23
							//         \/ /\ x = 23
							//            /\ x' = 4711
							// ...
						    // getModuleLocation called on the ActionInformationItem for sub-action
							// "x = 42 /\ x' = 23" returns the location of  "x = 42 /\ x' = 23" and not
							// that of "Next".
							// This relevant in the Sub-actions for next-state table of the Model Checking
							// Results page.
							location = aii.getDefinition();
						}
					}
					if (location != null) {
						/*
						 * jumpToNested will be true if the location could be
						 * shown in a nested saved module editor. If it is
						 * false, we jump to the regular TLA editor instead.
						 */
						Model model = ToolboxHandle.getCurrentSpec().getAdapter(TLCSpec.class).getModel(moduleLocatable
								.getModelName());
						if (!TLCUIHelper.jumpToSavedLocation(location, model, blacklist)) {
							final IWorkbenchPart iwp;
							if (dueToArrowKeys || FocusRetentionPolicy.ALWAYS.equals(focusRetentionPolicy)) {
								iwp = partToRefocus;
							} else {
								iwp = null;
							}
							UIHelper.jumpToLocation(location, jumpToPCal, iwp);
							
							if (iwp != null) {
								viewer.getControl().getDisplay().asyncExec(() -> {
									viewer.getControl().forceFocus();
								});
							}
						}
					}
				} else if (!Platform.getWS().equals(Platform.WS_WIN32) && viewer instanceof TreeViewer) {
					// Windows has built-in expand/collapse on double click
					TreeViewer treeViewer = (TreeViewer) viewer;
					if (treeViewer.getExpandedState(firstElement)) {
						treeViewer.collapseToLevel(firstElement, 1);
					} else {
						treeViewer.expandToLevel(firstElement, 1);
					}
				}
			}
		}
	}
    
	
    public static class LoaderTLCState extends TLCState {
		private final TLCError error;
		private final int numberOfStatesToShow;
		private final TreeViewer viewer;

		public LoaderTLCState(TreeViewer viewer, int numberOfStatesToShow, TLCError error) {
			super(-1, "Load more...");
			this.viewer = viewer;
			this.numberOfStatesToShow = numberOfStatesToShow;
			this.error = error;
			setLabel(String.format("Load %s additional states...", numberOfStatesToShow));
		}

		public void loadMore() {
			error.reduceTraceRestrictionBy(numberOfStatesToShow);
			viewer.getTree().setItemCount(error.getTraceSize() + (error.isTraceRestricted() ? 1 : 0));
			// Reset the viewer's selection to the empty selection. With empty
			// selection, the subsequent setInput call does *not* invalidate the
			// viewer content provider's lazy policy.
			// Since we know that this loadMore() method is called when the user
			// clicks the first tree item (which is the LoaderTLCState), there
			// is no point in preserving the selection anyway.
			viewer.setSelection(new ISelection() {
				public boolean isEmpty() {
					return true;
				}
			});
			viewer.setInput(error);
		}
    }
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.jclouds/src/org/lamport/tla/toolbox/jcloud/TLAAzureARMCloudTLCInstanceParameters.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2019 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package org.lamport.tla.toolbox.jcloud;

import java.util.Properties;

import org.jclouds.location.reference.LocationConstants;

public class TLAAzureARMCloudTLCInstanceParameters extends AzureARMCloudTLCInstanceParameters {

	public TLAAzureARMCloudTLCInstanceParameters(final String tlcParams, int numberOfWorkers) {
        super(tlcParams.trim(), numberOfWorkers);
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#getImageId()
	 */
	@Override
	public String getImageId() {
		// With azure-cli v2 (based on Python) extract name from 'az vm image list --all --publisher Canonical'.
		return System.getProperty("azure.image", "tlaplus/" + getRegion() + "/tlaplus-tlc-2019.12.23");
	}

	/* (non-Javadoc)
	 * @see org.lamport.tla.toolbox.jcloud.CloudTLCInstanceParameters#mungeProperties(java.util.Properties)
	 */
	@Override
	public void mungeProperties(final Properties properties) {
		super.mungeProperties(properties);
		// Receiving publisher images can take a long time if the publisher has many
		// images. We know which image we want to use (ours!!!), which is why we don't
		// want to wait. A bogus name won't have images.
        properties.setProperty("jclouds.azurecompute.arm.publishers", "APublisherThatDoesNotExist");
        properties.setProperty(LocationConstants.PROPERTY_REGIONS, getRegion());
	}

	@Override
	protected boolean isVanillaVMImage() {
		return false;
	}
	
	/*
	 * How to create a TLA+ VM image?
	 * 1. Start a regular Axure image with Cloud TLC.
	 * 2. Disable/Remove Cloud Shutdown hook
	 *    (see AzureARMCloudTLCInstanceParam#getCloudAPIShutdown NoAZDelete.txt)!!!
	 * 3. Deprovision the VM: sudo waagent -deprovision+user
	 *    https://docs.microsoft.com/en-us/azure/virtual-machines/linux/capture-image
	 * 3. Stop the Azure VM through the portal or az command-line app.
	 * 4. Trigger image creation through Azure portal and wait for Azure to do its thing.
	 * 5. Delete remnant of the actual Azure instance.
	 * 6. Subst azure.image above with name given in 4.
	 */
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/fp/OffHeapDiskFPSetTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2016 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.tool.fp;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static tlc2.tool.fp.DiskFPSet.MARK_FLUSHED;
import static tlc2.tool.fp.OffHeapDiskFPSet.EMPTY;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import util.TLCRuntime;

public class OffHeapDiskFPSetTest {
	
	protected static final String filename = "OffHeapDiskFPSetTest";
	
	@Before
	public void setup() {
		Assume.assumeTrue(TLCRuntime.getInstance().getArchitecture() == TLCRuntime.ARCH.x86_64);
	}

//	@Test
//	public void testInsertAndEvictRnd() throws Exception {
//		Random rnd = new Random();
//		for (int i = 0; i < 1000; i++) {
//			doTest(System.currentTimeMillis(), rnd.nextInt(255) + 1);
//		}
//	}
	
	@Test
	public void testInsertAndEvict1() throws Exception {
		doTest(1473793977852L, 87);
	}
	
	@Test
	public void testInsertAndEvict2() throws Exception {
		doTest(1473793976137L, 87);
	}
	
	@Test
	public void testInsertAndEvict3() throws Exception {
		doTest(1473839150698L, 46);
	}
	
	@Test
	public void testInsertAndEvict4() throws Exception {
		doTest(1473839150698L, 46);
	}
	
	@Test
	public void testInsertAndEvict5() throws Exception {
		doTest(1473839322351L, 23);
	}

	@Test
	public void testInsertAndEvict6() throws Exception {
		doTest(1473839380539L, 23);
	}

	@Test
	public void testInsertAndEvict7() throws Exception {
		doTest(1473839422899L, 11);
	}

	@Test
	public void testInsertAndEvict8() throws Exception {
		doTest(1473839543883L, 11);
	}
	
	@Test
	public void testInsertAndEvict9() throws Exception {
		doTest(1473871461079L, 64);
	}

	@Test
	public void testInsertAndEvict10() throws Exception {
		doTest(1473871462765L, 64);
	}

	@Test
	public void testInsertAndEvict11() throws Exception {
		doTest(1473871522834L, 32);
	}
	
	@Test
	public void testInsertAndEvict12() throws Exception {
		doTest(1473871526136L, 32);
	}

	@Test
	public void testInsertAndEvict13() throws Exception {
		doTest(1473873732723L, 47);
	}

	@Test
	public void testInsertAndEvict14() throws Exception {
		doTest(1473871294851L, 93);
	}

	@Test
	public void testInsertAndEvict15() throws Exception {
		doTest(1473871365625L, 93);
	}

	@Test
	public void testInsertAndEvict16() throws Exception {
		doTest(1473871209569L, 157);
	}

	private void doTest(final long rgenseed, final long length) throws RemoteException, IOException, NoSuchFieldException, IllegalAccessException {
		final DummyFPSetConfiguration fpSetConfig = new DummyFPSetConfiguration();
		fpSetConfig.setMemoryInFingerprintCnt(length);
		
		final DiskFPSet fpSet = new OffHeapDiskFPSet(fpSetConfig);
		fpSet.init(1, createTmpFile(), filename);

		// Insert n randomly choosen positive longs.
		Random random = new Random(rgenseed);
		for (int i = 0; i < length / 2; i++) {
			assertFalse(fpSet.put(getFingerprint(random)));
		}

		// Get the current content of LongArray for later comparison of special elements.
		Field field = OffHeapDiskFPSet.class.getDeclaredField("array");
		field.setAccessible(true);
		final long[] expected = LongArrays.toArray((LongArray) field.get(fpSet));
		
		// Flush/Evict the first time and assure its successful.
		assertTrue(fpSet.getGrowDiskMark() == 0);
		fpSet.forceFlush();
		fpSet.contains(1L); // contains triggers eviction
		assertTrue(fpSet.getGrowDiskMark() == 1);
		
		// Special elements (EMPTY or marked evicted) do not change positions
		// when sorted.
		final LongArray actual = (LongArray) field.get(fpSet);
		for (int i = 0; i < expected.length; i++) {
			if (expected[i] == EMPTY) {
				assertEquals(
						String.format(
								"Expected empty position with seed %sL and length %s.\n\nexpected: %s\n\nactual: %s",
								new Object[] { rgenseed, length, Arrays.toString(expected), actual.toString() }),
						EMPTY, actual.get(i));
			} else if (expected[i] < EMPTY) {
				assertEquals(
						String.format(
								"Expected negative position with seed %sL and length %s.\n\nexpected: %s\n\nactual: %s",
								new Object[] { rgenseed, length, Arrays.toString(expected), actual.toString() }),
						EMPTY, actual.get(i));
			}
		}
		
		random = new Random(rgenseed);
		for (int i = 0; i < length / 2; i++) {
			final long fp = getFingerprint(random);
			assertTrue(String.format("Failed to find fp %s/%s with seed %sL and length %s.\n\nexpected: %s\n\nactual: %s",
					new Object[] { fp, (fp | MARK_FLUSHED), rgenseed, length, Arrays.toString(expected),
							actual.toString() }),
					fpSet.contains(fp));
		}
		
		assertTrue(
				String.format("Invariant violated with seed %sL and length %s.\n\nexpected: %s\n\nactual: %s",
						new Object[] { rgenseed, length, Arrays.toString(expected), actual.toString() }),
				fpSet.checkInvariant());

		// Clear the index to secondary/disk which hides secondary from
		// DiskFPSet.
		field = DiskFPSet.class.getDeclaredField("index");
		field.setAccessible(true);
		field.set(fpSet, null);

		// Confirm that even without secondary, it's possible to lookup the
		// fingerprints.
		random = new Random(rgenseed);
		for (int i = 0; i < length / 2; i++) {
			final long fp = getFingerprint(random);
			assertTrue(String.format("Failed to find fp %s/%s with seed %sL and length %s.\n\nexpected: %s\n\nactual: %s",
					new Object[] { fp, (fp | MARK_FLUSHED), rgenseed, length, Arrays.toString(expected),
							actual.toString() }),
					fpSet.contains(fp));
		}
		
		fpSet.close();
	}
	
	@Test
	public void testOffset1Page() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		final long length = DiskFPSet.NumEntriesPerPage;
		doTestOffset(length, 1474536306841L);
	}
	
	@Test
	public void testOffset3Page() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		long length = DiskFPSet.NumEntriesPerPage * 3L;
		doTestOffset(length, 1474536306841L);
	}
	
	@Test
	public void testOffset5Page() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		long length = DiskFPSet.NumEntriesPerPage * 5L;
		doTestOffset(length, 1474536306841L);
	}
	
	@Test
	public void testOffset9Page() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		long length = DiskFPSet.NumEntriesPerPage * 9L;
		doTestOffset(length, 1474536306841L);
	}

	private void doTestOffset(long length, long rgenseed) throws RemoteException, IOException, NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		
		final DummyFPSetConfiguration fpSetConfig = new DummyFPSetConfiguration();
		fpSetConfig.setMemoryInFingerprintCnt(length);
		
		final OffHeapDiskFPSet fpSet = new OffHeapDiskFPSet(fpSetConfig);
		fpSet.init(1, createTmpFile(), filename);

		final SortedSet<Long> longs = new TreeSet<Long>();
		
		// Insert n randomly chosen positive longs.
		Random random = new Random(rgenseed);
		for (int i = 0; i < length / 2; i++) {
			long fingerprint = getFingerprint(random);
			assertFalse(fpSet.put(fingerprint));
			longs.add(fingerprint);
		}
		fpSet.forceFlush();
		assertFalse(fpSet.contains(1L)); // contains triggers flush
		
		final Method field = OffHeapDiskFPSet.class.getDeclaredMethod("getDiskOffset", new Class[] {int.class, long.class});
		field.setAccessible(true);
		
		for (long i = 0L; i < longs.size(); i++) {
			long fp = longs.first();
			assertEquals(String.format("Length: %s with seed: %s", length, rgenseed), i + 1L,
					field.invoke(fpSet, 0, fp + 1L));
			longs.remove(fp);
		}
	}
	
	private static String createTmpFile() {
		final String tmpdir = System.getProperty("java.io.tmpdir") + File.separator + "OffHeapDiskFPSetTest"
				+ System.currentTimeMillis();
		new File(tmpdir).mkdirs();
		return tmpdir;
	}

	private static long getFingerprint(Random random) {
		final long fp = (((long) random.nextInt(Integer.MAX_VALUE - 1) + 1) << 32) | (random.nextInt() & 0xffffffffL);
		return fp;
	}

	@Test
	public void testWriteIndex() throws NoSuchFieldException, SecurityException, IllegalArgumentException,
			IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
		final DummyFPSetConfiguration fpSetConfig = new DummyFPSetConfiguration();
		fpSetConfig.setMemoryInFingerprintCnt(1);

		final OffHeapDiskFPSet fpSet = new OffHeapDiskFPSet(fpSetConfig);
		final Method method = OffHeapDiskFPSet.class.getDeclaredMethod("writeIndex",
				new Class[] { long[].class, java.io.RandomAccessFile.class, long.class });
		method.setAccessible(true);

		// length of array times NumEntriesPerPage has to exceed Integer.MAX_VALUE
		final int length = 99999999;
		assertTrue(length * DiskFPSet.NumEntriesPerPage < 1);

		try {
			method.invoke(fpSet, new long[length], new DummyRandomAccessFile(File.createTempFile("foo", "bar"), "rw"),
					Integer.MAX_VALUE);
		} catch (InvocationTargetException e) {
			Throwable targetException = e.getTargetException();
			fail(targetException.getMessage());
		}
	}

	private static class DummyRandomAccessFile extends java.io.RandomAccessFile {

		public DummyRandomAccessFile(File file, String mode) throws FileNotFoundException {
			super(file, mode);
		}

		@Override
		public int read() throws IOException {
			return 0;
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/distributed/fp/FaultyFPSet.java<|end_filename|>
// Copyright (c) 2012 Microsoft Corporation.  All rights reserved.

package tlc2.tool.distributed.fp;

import java.rmi.RemoteException;

import tlc2.tool.fp.FPSetConfiguration;
import tlc2.tool.fp.MemFPSet;

@SuppressWarnings("serial")
public class FaultyFPSet extends MemFPSet implements FPSetRMI {

	private int putInvocations = 0;
	private int containsInvocations = 0;

	protected FaultyFPSet() throws RemoteException {
		super(new FPSetConfiguration());
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.MemFPSet#put(long)
	 */
	public synchronized boolean put(long fp) {
		// Simulate network error after a single successful invocation
		if (putInvocations++ > 0) {
			throw new RuntimeException("Test FPSet");
		}
		return super.put(fp);
	}

	/* (non-Javadoc)
	 * @see tlc2.tool.fp.MemFPSet#contains(long)
	 */
	public synchronized boolean contains(long fp) {
		// Simulate network error after a single successful invocation
		if (containsInvocations++ > 0) {
			throw new RuntimeException("Test FPSet");
		}
		return super.contains(fp);
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/overrides/TLAPlusCallable.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2020 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/
package tlc2.overrides;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * @see MethodValue.
 */
@Retention(RUNTIME)
@Target(METHOD)
public @interface TLAPlusCallable {

	/**
	 * @return The identifier of a TLA+ state or action predicate. 
	 */
	String definition();

	/**
	 * @return The name of the TLA+ module declaring the definition above.
	 */
	String module();

	/**
	 * @return The minimum level that will be assigned to the OpDefNode that
	 *         represents the EvaluatingValue in the semantic graph. Unless
	 *         the actual level checking in Spec.getLevelBound assigns a
	 *         greater value, the OpDefNode is a constant-level expression if
	 *         0 causing it to be eagerly evaluated in 
	 *         SpecProcessor.processConstantDefns.
	 * @see tla2sany.semantic.LevelNode.getLevel()
	 * @see tlc2.tool.impl.Spec.getLevelBound(SemanticNode, Context)
	 * @see tlc2.value.impl.EvaluatingValue
	 * @see tlc2.tool.impl.SpecProcessor.processConstantDefns()
	 */
	int minLevel() default 0;
	
	/**
	 * @return true if a warning should be printed when a EV cannot be mapped to the
	 *         given TLA+ definition in module.
	 * @see Evaluation#definition()
	 * @see Evaluation#module()
	 */
	boolean warn() default true;
}


<|start_filename|>tlatools/org.lamport.tlatools/src/tla2sany/modanalyzer/ModuleRelatives.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tla2sany.modanalyzer;

import tla2sany.utilities.Vector;

/**
 * This class contains fields representing the names of modules that are all related by EXTENDing or INSTANCEing
 * or inner definition to a ParseUnit (i.e. top level module in its own file)
 */
class ModuleRelatives {

  ParseUnit     parseUnit;                              // The ParseUnit that THIS ModuleRelatives object is associated with

  ModulePointer currentModule                   = null; // The TreeNode where the name of the current module appears in
                                                        //   in the image field; using the tree node rather than the String
                                                        //   name of the module 

  ModulePointer outerModule                     = null; // TreeNode of the immediate outer (parent) module; 
                                                        //   null currentModule is the outermost in parseUnit

  Vector        directInnerModules              = new Vector(); 
                                                        // Vector of ModulePointers for immediate inner modules 

  Vector        directlyExtendedModuleNames     = new Vector(); 
                                                        // Vector of String names for modules mentioned in EXTENDS decls by 
                                                        //   currentModule, whether or not they are resolved within the 
                                                        //   current ParseUnit

  Vector        directlyInstantiatedModuleNames = new Vector(); 
                                                        // Vector of String names for modules directly instantiated 
                                                        //   by currentModule, whether or not they are resolved within the
                                                        //   current ParseUnit

  ModuleContext context = new ModuleContext();          // The context that maps module String names known in this module 
                                                        //   (whether or not they are referenced in it) to ModulePointers


  // constructor
  public ModuleRelatives(ParseUnit pu, ModulePointer node) {
    parseUnit     = pu;
    currentModule = node;
  }

  public String toString() {
    String ret = "currentModuleName: " + currentModule.getName();

    ret += "\nouterModule: " + ( outerModule == null 
				 ? "<null>" 
				 : outerModule.getName() );

    ret += "\ndirectInnerModules: ";
    for (int i = 0; i < directInnerModules.size(); i++) {
      ret += ((ModulePointer)(directInnerModules.elementAt(i))).getName() + " ";
    }

    ret += "\ndirectlyExtendedModuleNames: ";
    for (int i = 0; i < directlyExtendedModuleNames.size(); i++) {
      ret += (String)(directlyExtendedModuleNames.elementAt(i)) + " ";
    }

    ret += "\ndirectlyInstantiatedModuleNames: ";
    for (int i = 0; i < directlyInstantiatedModuleNames.size(); i++) {
      ret += (String)(directlyInstantiatedModuleNames.elementAt(i)) + " ";
    }

    ret += "\n" + context.toString();
    return ret;
  }

} // end class


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/tool/liveness/DiskGraphTest.java<|end_filename|>
/*******************************************************************************
 * Copyright (c) 2015 Microsoft Research. All rights reserved. 
 *
 * The MIT License (MIT)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Contributors:
 *   <NAME> - initial API and implementation
 ******************************************************************************/

package tlc2.tool.liveness;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

import tlc2.util.BitVector;
import tlc2.util.LongVec;
import tlc2.util.statistics.FixedSizedBucketStatistics;
import tlc2.util.statistics.IBucketStatistics;

public class DiskGraphTest {

	private static final IBucketStatistics GRAPH_STATS = new FixedSizedBucketStatistics("Test Dummy", 16);
	private static final int NUMBER_OF_SOLUTIONS = 1;
	private static final int NO_TABLEAU = -1;
	private static final int NUMBER_OF_ACTIONS = 0;
	private static final BitVector NO_ACTIONS = null;
	
	protected AbstractDiskGraph getDiskGraph() throws IOException {
		// Have to use dedicated folder for each test. Otherwise tests interfere
		// with each other (e.g. test A reads the disk file of test B)
		return new DiskGraph(createTempDirectory().getAbsolutePath(), NUMBER_OF_SOLUTIONS, GRAPH_STATS);
	}

	protected File createTempDirectory() throws IOException {
		final File temp;
		temp = File.createTempFile("temp", Long.toString(System.nanoTime()));
		if (!(temp.delete())) {
			throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
		}
		if (!(temp.mkdir())) {
			throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
		}
		return temp;
	}
	
	// No init node makes DiskGraph#getPath never break from the while loop
	@Test
	public void testGetPathWithoutInitNoTableau() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();
		dg.addNode(new GraphNode(1L, NO_TABLEAU));
		dg.createCache();
		try {
			dg.getPath(1L, -1);
		} catch (RuntimeException e) {
			return;
		}
		fail("getPath() without init nodes has to throw a RuntimeException");
	}

	// Create a linear minimal graph (2 nodes) and check if the graph is
	// returned by getPath afterwards.
	@Test
	public void testGetMinimalPathWithoutTableau() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		final long initFP = 1L;
		final long successorFP = 2L;
		
		// Init node
		dg.addInitNode(1L, NO_TABLEAU);

		// Successor node
		dg.addNode(new GraphNode(successorFP, NO_TABLEAU));
		
		// Create relationship between init and successor
		final GraphNode node = new GraphNode(initFP, NO_TABLEAU);
		node.addTransition(successorFP, NO_TABLEAU, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS, NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);

		// Can only lookup/get a node, if there is a cache
		dg.createCache();
		final LongVec path = dg.getPath(successorFP, -1);
		dg.destroyCache();

		assertFalse("Length or path returned is too short", path.size() < 2);
		assertFalse("Length or path returned is too long", path.size() > 2);
	}
	
	/*
	 * +----------+                   
	 * |          |                   
	 * | init     |                   
	 * |          |                   
	 * |          |                   
	 * +----------+                   
	 *                                
	 * +----------+       +----------+
	 * |          |       |          |
	 * | second   +------->  final   |
	 * | init     |       |          |
	 * |          |       |          |
	 * +----------+       +----------+
	 * 
	 * The specialty here is that there are *two* init nodes and one of them has *no* successors.
	 * 
	 * @see Bug #293 in general/bugzilla/index.html
	 */
	@Test
	public void testPathWithTwoInitNodes() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		long noSuccessorInitState = 1L;

		long regularInitState = 2L;
		
		long finalState = 3L;

		// Init
		dg.addInitNode(noSuccessorInitState, NO_TABLEAU);
		
		/*
		 * Intentionally *NOT* adding the init via dg.addNode(init)
		 */
		
		// second init (this one gets added via addNode
		dg.addInitNode(regularInitState, NO_TABLEAU);
		GraphNode node = new GraphNode(regularInitState, NO_TABLEAU);
		node.addTransition(finalState, NO_TABLEAU, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		
		// final
		node = new GraphNode(finalState, NO_TABLEAU);
		dg.addNode(node);
		
		dg.createCache();
		LongVec path = dg.getPath(finalState, NO_TABLEAU);
		dg.destroyCache();
		
		assertEquals(2, path.size());
		assertEquals(finalState, path.elementAt(0));
		assertEquals(regularInitState, path.elementAt(1));

		// Make sure it also returns a path if init is searched
		dg.createCache();
		path = dg.getPath(noSuccessorInitState, NO_TABLEAU);
		dg.destroyCache();

		assertEquals(1, path.size());
		assertEquals(noSuccessorInitState, path.elementAt(0));
	}
	
	/*
	 * Make sure the same logical node isn't counted twice.
	 */
	@Test
	public void testAddSameGraphNodeTwice() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();
		dg.addNode(new GraphNode(1L, 1));
		dg.addNode(new GraphNode(1L, 1));
		assertEquals(1, dg.size());
	}
	
	
	/*
	 * Test that it is possible to "update" a GraphNode's outgoing transitions.
	 */
	@Test
	public void testLookupExistingNode() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();
		
		GraphNode node = dg.getNode(1L, -1);
		assertEquals(0, node.succSize());
		dg.addNode(node);
		
		// Cause the DiskGraph to be read from disk
		dg.makeNodePtrTbl();
		
		node = dg.getNode(1L, -1);
		dg.addNode(node);
		assertEquals(0, node.succSize());
		
		node.addTransition(2, -1, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		assertEquals(1, node.succSize());
		assertTrue(node.transExists(2, -1));
		
		dg.makeNodePtrTbl();
		
		node = dg.getNode(1L, -1);
		assertEquals(1, node.succSize());

		node.addTransition(3, -1, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);
		assertEquals(2, node.succSize());
		assertTrue(node.transExists(2, -1));
		assertTrue(node.transExists(3, -1));
		
		// commit/chkpt
		dg.beginChkpt();
		dg.commitChkpt();
		dg.recover();
		
		node = dg.getNode(1L, -1);
		assertEquals(2, node.succSize());
		assertTrue(node.transExists(2, -1));
		assertTrue(node.transExists(3, -1));
	}
	
	/*
	 * Test that adding a GraphNode twice (same fingerprint & tableau idx) but
	 * with different successors afterwards yields the union of the successors.
	 */
	@Test
	public void testAddSameGraphNodeTwiceCorrectSuccessors() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();

		// Add a graphnode to DiskGraph with a single transition
		final GraphNode graphNode = dg.getNode(1, NO_TABLEAU);
		graphNode.addTransition(2, NO_TABLEAU, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		long firstPtr = dg.addNode(graphNode);
		
		// Update the same graph node with another transition
		final GraphNode graphNodeSecondInstance = dg.getNode(1, NO_TABLEAU);
		graphNodeSecondInstance.addTransition(3, NO_TABLEAU, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		long secondPtr = dg.addNode(graphNodeSecondInstance);
		
		assertEquals(1, dg.size());
		
		assertNotSame(firstPtr, secondPtr);
		assertEquals(secondPtr, dg.getLink(1, NO_TABLEAU));

		final GraphNode node = dg.getNode(1, NO_TABLEAU);
		assertEquals(2, node.succSize());
		assertTrue(node.transExists(2, NO_TABLEAU));
		assertTrue(node.transExists(3, NO_TABLEAU));
		
		dg.makeNodePtrTbl();
		dg.createCache();
		final long ptr = dg.getLink(1, NO_TABLEAU);
		final GraphNode n = dg.getNode(1, NO_TABLEAU, ptr);
		assertEquals(2, n.succSize());
		assertTrue(n.transExists(2, NO_TABLEAU));
		assertTrue(n.transExists(3, NO_TABLEAU));
	}
	
	/*
	 * Test to verify that getPath does not throw an ArrayIndexOutOfBounds due
	 * to nextLoc being -1. This used to happen intermittently when liveness
	 * checking runs periodically on an incomplete state/behavior graph, a
	 * liveness violation is found and the path of the error trace gets explored.
	 */
	@Test
	public void testGetPathPartialGraph() throws IOException {
		final AbstractDiskGraph dg = getDiskGraph();
		
		final long initState = 2L;
		final long danglingState = 3L;

		// Init
		dg.addInitNode(initState, NO_TABLEAU);
		final GraphNode node = new GraphNode(initState, NO_TABLEAU);
		node.addTransition(danglingState, NO_TABLEAU, NUMBER_OF_SOLUTIONS, NUMBER_OF_ACTIONS, NO_ACTIONS,
				NUMBER_OF_ACTIONS, 0);
		dg.addNode(node);

		/*
		 * The dangling state does not get added on purpose to simulate a
		 * partial graph.
		 */
	
		// Now get the path to some non-existing state (to explore all states in
		// the graph)
		dg.createCache();
		try {
			dg.getPath(5L, NO_TABLEAU);
		} catch (ArrayIndexOutOfBoundsException e) {
			fail(e.getMessage());
		} catch (RuntimeException e) {
			// Make sure it is the correct RuntimeException
			assertEquals("Couldn't re-create liveness trace (path) starting at: 5 and tidx: -1", e.getMessage());
		}
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/source/TLCCharScanner.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.source;

import org.eclipse.jface.text.rules.ICharacterScanner;

public abstract class TLCCharScanner {
	   

    public static boolean isEOF(final ICharacterScanner scanner) {
    	return isChar(scanner, ICharacterScanner.EOF);
	}
    
    public static boolean isEOL(final ICharacterScanner scanner) {
    	return isChar(scanner, 10);
    }
    
    private  static boolean isChar(final ICharacterScanner scanner, int i) {
		int c = scanner.read();
		scanner.unread();
		return c == i;
    }
    
    public static boolean isTag(final ICharacterScanner scanner, final String tag) {
		final int length = tag.length();
		
		int i = 0;
		for (; i < length; i++) {
			if (tag.charAt(i) != scanner.read() ) {
				unwind(scanner, i + 1);
				return false;
			}
		}
		unwind(scanner, length);
		return true;
	}

	private static void unwind(ICharacterScanner scanner, int i) {
		for (int j = 0; j < i; j++) {
			scanner.unread();
		}
	}
}


<|start_filename|>tlatools/org.lamport.tlatools/src/pcal/MappingObject.java<|end_filename|>
/**
 *  
 */
package pcal;

import java.io.Serializable;
import java.util.Vector;

/**
 * A MappingObject is an element in the mapping field of a TLAtoPCalMapping object.
 * It describes either a region in the TLA+ translation or the start or end of a 
 * region in the PlusCal code.  See the TLAToPCal.tla module for a TLA+ specification
 * of what these objects mean.  The correspondence between MappingObject classes and
 * sets in the TLAToPCal spec is:
 * 
 * LeftParen / RightParen :
 *   Elements of Paren with type field  "begin" / "end"
 * 
 * BeginTLAToken / EndTLAToken : 
 *   Represent the beginning and end locations of elements of TLAToken with
 *   inExpr field FALSE.  The line field of the TLAToken element is implicit
 *   in the location of the BeginTLAToken or EndTLAToken object in the mapping.  
 *   Since the TLAToken's regions can span multiple lines, this requires that 
 *   its Java representation be split into these two Java objects.
 *   
 * SourceToken :
 *   Represents an element of TLAToken with inExpr field TRUE, together with
 *   the Parens that surround it.   (The region 
 *   of a TLAToken occupies a single line, so there is no need to split the
 *   Java object.)  Again, the line of the TLAToken is implict in the position
 *   of the ExprToken object in the mapping, so only the token's position and
 *   length is needed in the object
 *   
 * Break :
 *   Represents an element of Break.
 * 
 * @author lamport
 *
 */
public class MappingObject implements Serializable {
    
    /**
	 * @see TLAtoPCalMapping#serialVersionUID
	 */
	private static final long serialVersionUID = 8620480075506527787L;

	/*
     * The type field tells what subclass the MappingObject belongs to
     */
    private int type ;
    
    /*
     * The following are the types of MappingObjects.
     */
    public static final int LEFT_PAREN     = 0;
    public static final int RIGHT_PAREN    = 1;
    public static final int BEGIN_TLATOKEN = 2 ;
    public static final int END_TLATOKEN   = 3 ;
    public static final int SOURCE_TOKEN   = 4 ;
    public static final int BREAK          = 5 ;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
    
    public MappingObject(int type) {
        this.type = type ;
    }
    
    public static class LeftParen extends MappingObject {
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = 5476753619018204229L;
		//        private int column ;
        private PCalLocation location ;
        public LeftParen(PCalLocation location) {
           super(LEFT_PAREN) ;
//           this.column = column;
           this.location = location;
        }
        
        public String toString() {
            return "((-" + this.location.toString();
        }

//        public int getColumn() {
//            return column;
//        }

        public PCalLocation getLocation() {
            return location;
        }

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result
					+ ((location == null) ? 0 : location.hashCode());
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			LeftParen other = (LeftParen) obj;
			if (location == null) {
				if (other.location != null)
					return false;
			} else if (!location.equals(other.location))
				return false;
			return true;
		}
    }
    
    public static class RightParen extends MappingObject {
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = 1313886393528667584L;
		//        private int column ;
        private PCalLocation location ;
        public RightParen(PCalLocation location) {
           super(RIGHT_PAREN) ;
//           this.column = column;
           this.location = location;
        }
        
        public String toString() {
            return this.location.toString() + "-))";
        }

//        public int getColumn() {
//            return column;
//        }

        public PCalLocation getLocation() {
            return location;
        }

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result
					+ ((location == null) ? 0 : location.hashCode());
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			RightParen other = (RightParen) obj;
			if (location == null) {
				if (other.location != null)
					return false;
			} else if (!location.equals(other.location))
				return false;
			return true;
		}
    }
    
    public static class BeginTLAToken extends MappingObject {
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = 3737867780161818714L;
		private int column ;

        public int getColumn() {
            return column;
        }
        public void setColumn(int column) {
            this.column = column ;
        }
        
        public BeginTLAToken(int column) {
            super(BEGIN_TLATOKEN) ;
            this.column = column ;
        }
        
        public String toString() {
            return "[" + this.column;
        }
		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + column;
			return result;
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			BeginTLAToken other = (BeginTLAToken) obj;
			if (column != other.column)
				return false;
			return true;
		}
    }
    
    public static class EndTLAToken extends MappingObject {
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = -2173558662370032149L;
		private int column ;

        public int getColumn() {
            return column;
        }
        public void setColumn(int column) {
            this.column = column ;
        }
        
        public EndTLAToken(int column) {
            super(END_TLATOKEN) ;
            this.column = column ;
        }
        
        public String toString() {
            return this.column + "]";
        }
		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + column;
			return result;
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			EndTLAToken other = (EndTLAToken) obj;
			if (column != other.column)
				return false;
			return true;
		}
    }
    
    public static class SourceToken extends MappingObject {
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = 6438346684127312114L;
		private int beginColumn ;
        private int endColumn ;
        private Region origin ;
        
        public int getBeginColumn() {
            return beginColumn;
        }

        public void setBeginColumn(int beginColumn) {
            this.beginColumn = beginColumn;
        }

        public int getEndColumn() {
            return endColumn;
        }

        public void setEndColumn(int endColumn) {
            this.endColumn = endColumn;
        }

        public Region getOrigin() {
            return origin;
        }

//        public void setOrigin(Region origin) {
//            this.origin = origin;
//        }

        public SourceToken(int beginCol, int endCol, Region origin) {
            super(SOURCE_TOKEN) ;
            this.setBeginColumn(beginCol) ;
            this.setEndColumn(endCol) ;
            this.origin = origin ;
        }
        
        public String toString() {
            return "((-" + this.origin.getBegin().toString() +
                    "[" + this.beginColumn + "--" + this.endColumn + "]" 
                    + this.origin.getEnd().toString() + "-))";
        }

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + beginColumn;
			result = prime * result + endColumn;
			result = prime * result
					+ ((origin == null) ? 0 : origin.hashCode());
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			SourceToken other = (SourceToken) obj;
			if (beginColumn != other.beginColumn)
				return false;
			if (endColumn != other.endColumn)
				return false;
			if (origin == null) {
				if (other.origin != null)
					return false;
			} else if (!origin.equals(other.origin))
				return false;
			return true;
		}
        
    }
    public static class Break extends MappingObject{
        /**
    	 * @see TLAtoPCalMapping#serialVersionUID
    	 */
		private static final long serialVersionUID = 3197403974334483558L;
		private int depth ;

        public int getDepth() {
            return depth;
        }
        
        public Break(int depth) {
            super(BREAK) ;
            this.depth = depth;
        }

		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + depth;
			return result;
		}

		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			Break other = (Break) obj;
			if (depth != other.depth)
				return false;
			return true;
		}

    }
    
    /**
     * A mapping vector is a vector of vectors of MappingObject
     * objects.  This transforms a mapping vector obtained from a
     * TLAExpr object by a call of toMappingVector to produce the
     * mapping vector that would have resulted from that call if the
     * entire expression had been moved  to the right by `shift'
     * characters.
     *  
     * @param mvec  A mapping vector.
     * @param shift The distance to shift to the right.
     */
    public static void shiftMappingVector(Vector mvec, int shift) {
        for (int i = 0; i < mvec.size(); i++) {
            Vector line = (Vector) mvec.elementAt(i);
            for (int j = 0; j < line.size(); j++) {
                MappingObject mobj = (MappingObject) line.elementAt(j);
                if (mobj.type == BEGIN_TLATOKEN) {
                    BeginTLAToken obj = (BeginTLAToken) mobj;
                    obj.setColumn(obj.getColumn()+shift) ;
                } else if (mobj.type == END_TLATOKEN) {
                    EndTLAToken obj = (EndTLAToken) mobj;
                    obj.setColumn(obj.getColumn()+shift) ;
                } else if (mobj.type == SOURCE_TOKEN) {
                    SourceToken obj = (SourceToken) mobj;
                    obj.setBeginColumn(obj.getBeginColumn()+shift) ;
                    obj.setEndColumn(obj.getEndColumn()+shift) ;
                }
            }
        }
    }
    
    /**
     * For debugging.
     * @param mvec
     */
    public static void printMappingVector(Vector mvec) {
        for (int i = 0; i < mvec.size(); i++) {
            Vector line = (Vector) mvec.elementAt(i);
            System.out.print("line " + i + ":");
            for (int j = 0; j < line.size(); j++) {
                MappingObject mobj = (MappingObject) line.elementAt(j) ;
                System.out.print("  " + mobj.toString());
            }
            System.out.println("");
        }
    }
    
    public static void printMapping(MappingObject[][] mapping) {
        for (int i = 0; i < mapping.length; i++) {
            MappingObject[] line = mapping[i];
            System.out.print("line " + i + ":");
            for (int j = 0; j < line.length; j++) {
                MappingObject mobj = line[j] ;
                System.out.print("  " + mobj.toString());
            }
            System.out.println("");
        }
    }

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + type;
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MappingObject other = (MappingObject) obj;
		if (type != other.type)
			return false;
		return true;
	}
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.tool.tlc.ui/src/org/lamport/tla/toolbox/tool/tlc/output/data/TraceExplorerDataProvider.java<|end_filename|>
package org.lamport.tla.toolbox.tool.tlc.output.data;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.lamport.tla.toolbox.Activator;
import org.lamport.tla.toolbox.tool.tlc.model.Model;
import org.lamport.tla.toolbox.tool.tlc.output.data.TLCError.Order;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCOutputSourceRegistry;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCRegion;
import org.lamport.tla.toolbox.tool.tlc.output.source.TLCRegionContainer;
import org.lamport.tla.toolbox.tool.tlc.traceexplorer.TraceExplorerHelper;
import org.lamport.tla.toolbox.tool.tlc.ui.TLCUIActivator;
import org.lamport.tla.toolbox.tool.tlc.ui.editor.ModelEditor;
import org.lamport.tla.toolbox.tool.tlc.ui.view.TLCErrorView;
import org.lamport.tla.toolbox.util.LegacyFileDocumentProvider;
import org.lamport.tla.toolbox.util.UIHelper;

import tlc2.model.Formula;
import tlc2.model.TraceExpressionInformationHolder;
import tlc2.output.EC;
import util.TLAConstants;

/**
 * A data provider for runs of the trace explorer. This mostly uses the methods from
 * {@link TLCModelLaunchDataProvider}, but it also performs some processing
 * of an error trace, if one is produced.
 * 
 * @author <NAME>
 */
public class TraceExplorerDataProvider extends TLCModelLaunchDataProvider
{
    private static String TE_ERROR_HEADER = "Error(s) from running the Trace Explorer:\n";

    
    // a hashmap containing information about trace expressions if this
    // provider is for a run of the trace explorer
    // the key is the variable name used for the expression, the value
    // is an instance of TraceExpressionInformationHolder corresponding
    // to the expression.
    private Hashtable<String, TraceExpressionInformationHolder> traceExpressionDataTable;

    public TraceExplorerDataProvider(Model model)
    {
        super(model);
    }

    /** 
     * This is currently called by the constructor of TLCModelLaunchDataProvider
     * 
     * There are two different tlc output source registries,
     * one for trace exploration and one for model checking. This
     * connects to the one for trace exploration.
     */
	protected boolean connectToSourceRegistry() {
		return TLCOutputSourceRegistry.getTraceExploreSourceRegistry().connect(this);
    }

    public void onDone()
    {
        super.onDone();

        getTraceExpressionsInformation();

        processTraceForTraceExplorer();

        final IEditorPart activeEditor = UIHelper.getActiveEditor();
		if (activeEditor != null) {
			if (activeEditor instanceof ModelEditor) {
				final ModelEditor activeModelEditor = (ModelEditor) activeEditor;
				if (activeModelEditor.getModel() != null) {
					UIHelper.runUIAsync(() -> {
						TLCErrorView.updateErrorView(activeModelEditor);
					});
				}
			}
		}
    }

    /**
     * Collects and stores trace expression information for later use.
     */
    private void getTraceExpressionsInformation()
    {
    	if (traceExpressionDataTable == null) {
			// getTraceExpressionsInformation is called implicitly when
			// super(config) is called in the constructor. Thus, we have to
			// initialize it here.
    		traceExpressionDataTable = new Hashtable<String, TraceExpressionInformationHolder>();
    	}
        // erase existing information
        traceExpressionDataTable.clear();

        /*
         * Retrieve the TE file and create a document provider. This document
         * provider will be used to connect to the file editor input for
         * the TE file so that a Document representation of the file can
         * be created in the following try block. We disconnect the document
         * provider in the finally block for this try block in order to avoid
         * a memory leak.
         */
        IFile teFile = getModel().getTraceExplorerTLAFile();
        FileEditorInput teFileEditorInput = new FileEditorInput((IFile) teFile);
		// Use LegacyFileDocumentProvider to fix race condition which causes Trace
		// Explorer Exploration to label the expression as __trace_var_XXXXXXXX instead
		// of the actual expression. The broken label is accompanied by an exception:
        // java.lang.IllegalArgumentException: Attempted to beginRule: F/DijkstraMutex/Model_1, 
        // does not match outer scope rule: org.lamport.tla.toolbox.tool.tlc.launch.TLCModelLaunchDelegate$MutexRule@1e6cad2d
        FileDocumentProvider teFileDocumentProvider = new LegacyFileDocumentProvider();
        try
        {

            teFileDocumentProvider.connect(teFileEditorInput);

            // the document connected to the TE file
            IDocument teDocument = teFileDocumentProvider.getDocument(teFileEditorInput);

            // the search adapter on the TE file
            FindReplaceDocumentAdapter teSearcher = new FindReplaceDocumentAdapter(teDocument);

            // search for comments containing the information about trace explorer expressions
            String regularExpression = FindReplaceDocumentAdapter.escapeForRegExPattern("\\* ") + ":[0-2]:"
                    + TLAConstants.Schemes.TRACE_EXPR_VAR_SCHEME + "_[0-9]{17,}:[\\s\\S]*?"
                    + Pattern.quote(TLAConstants.CONSTANT_EXPRESSION_EVAL_IDENTIFIER) + "\n";
            IRegion region = teSearcher.find(0, regularExpression, true, true, false, true);

            while (region != null)
            {
                // found a region
                // first character should be the level of the expression
                String commentString = teDocument.get(region.getOffset(), region.getLength());
                // commentString should be of the form "\* :x:___trace_var_12321312312312:expr"$!@$!@$!@$!@$!""
                // where x is the level of the expression
                String[] stringSections = commentString.split(":", 4);
                int level = Integer.parseInt(stringSections[1]);
                String variableName = stringSections[2];
                // should be expr"$!@$!@$!@$!@$!" where "$!@$!@$!@$!@$!" is the delimiter
                String expressionAndDelimiter = stringSections[3];
                String expression = expressionAndDelimiter.substring(0, expressionAndDelimiter
                        .indexOf(TLAConstants.CONSTANT_EXPRESSION_EVAL_IDENTIFIER));

                TraceExpressionInformationHolder expressionData = new TraceExpressionInformationHolder(expression,
                        null, variableName);
                expressionData.setLevel(level);
                this.traceExpressionDataTable.put(variableName.trim(), expressionData);

                region = teSearcher.find(region.getOffset() + region.getLength(), regularExpression, true, true, false,
                        true);
            }

        } catch (CoreException e)
        {
            TLCUIActivator.getDefault().logError("Error finding trace expression information in TE.tla file.", e);
        } catch (BadLocationException e)
        {
            TLCUIActivator.getDefault().logError("Error finding trace expression information in TE.tla file.", e);
        } finally
        {
            /*
             * The document provider is not needed. Always disconnect it to avoid a memory leak.
             * 
             * Keeping it connected only seems to provide synchronization of
             * the document with file changes. That is not necessary in this context.
             */
            teFileDocumentProvider.disconnect(teFileEditorInput);
        }
    }

    /**
     * Performs processing for the error and the error trace produced after a run of the trace explorer.
     * 
     * This method (and nested ones) does the following to a trace:
     * 
     * 1.) Changes the names of the variables corresponding to trace
     * explorer expressions to the actual expressions.
     * 
     * 2.) It also shifts the values of expressions
     * of level 2. For an expressions of level 2 (expression with primed variables), the value in
     * state x becomes the original value in state x+1. The value in the final state of such
     * expressions is equal to "--".
     * 
     * 3.) Changes the state labels "<Action ... in module TE> State (num = 3)" to the state labels
     * of the original trace. The goal is to have no reference to module TE.
     * 
     * 4.) Puts the variables representing the trace explorer expressions before the actual
     * variables in each state.
     * 
     * 5.) Removes any extra states produced by the trace explorer. This can sometimes occur when
     * evaluating expressions for a looping ("Back to state") trace and for a stuttering trace. This can
     * be illustrated by an example. Consider the following trace:



    <Initial predicate> <State num 1>
    x=0

    <Action ...> <State num 2>
    x=1

    <Back to state 1>




    The user wants to evaluate the following expression:

    x' >= x

    The toolbox uses the following as init and next:

    Init ==
     /\ x=0
     /\ __trace_var_213123 = "--"

    Next ==
     \/ /\ x=0
        /\ x'=1
        /\ __trace_var_213123' = (x'>=x)
     \/ /\ x=1
        /\ x'=0
        /\ __trace_var_213123' = (x'>=x)

    We check the following property:

    prop_23432 ==
    ~([]<>(x=1)/\[]<>(x=0))

    This produces the following trace:



    <Initial predicate> <State num 1>
    x=0
    __trace_var_213123 = "--"

    <Action ...> <State num 2>
    x=1
    __trace_var_213123 = TRUE

    <Action ...> <State num 3>
    x=0
    __trace_var_213123 = FALSE

    <Back to state 2>



    Note the additional state with x=0 and __trace_var_213123 = FALSE. We shift the values for
    expressions with primed variables up by one state, so this extra state is necessary for
    producing the value for the expression "x' >= x" in the second state of the trace (In non-looping
    traces, there is no value for the expression in the final state, so we simply assign it
    the value "--".) The processing by this method eliminates this extra state but uses the value for
    __trace_var_213123, so that the following trace can be displayed to the user:



    <Initial predicate> <State num 1>
    x=0
    (x' >= x)    =     TRUE

    <Action ...> <State num 2>
    x=1
    (x' >= x)    =    FALSE

    <Back to state 1>

     * 6.) If the trace explorer ran successfully, this method changes several attributes
     * of the error trace produced by the trace explorer. It changes
     * the following three attributes:
     *  - error message
     *  - error code
     *  - cause
     * 
     * It sets these attributes equal to those attributes for
     * the error trace produced by the last run of model checking on
     * the model for which the trace explorer was run.
     * 
     * 7.) If the run of the trace explorer was successful, then we set the list
     * of errors for this data provider in the following way :
     * 
     *  - Copy the list of errors from the original run of TLC.
     *  - In the copied list, replace the original trace error with the new trace
     *    error created by the successful run of the trace explorer.
     */
    private void processTraceForTraceExplorer()
    {
        // retrieve the error with a trace for which the trace explorer was run
        final TLCError originalErrorWithTrace = TraceExplorerHelper.getErrorOfOriginalTrace(getModel());
        if (originalErrorWithTrace == null)
        {
            // the trace explorer is meaningless if the original trace cannot be recovered
            // all errors should be cleared
            getErrors().clear();
            return;
        }

        /*
         * The following will point to the error containing the trace for the
         * run of the trace explorer, iff the run of the trace explorer was successful.
         * The run was successful if TLC was able to evaluate the trace explorer
         * expressions at every possible state of the original trace.
         * 
         * The value of successfulTEError is set in the following while loop, if the
         * run was successful.
         */
        TLCError successfulTEError = null;

        final Map<String, Formula> traceExplorerExpressions = getModel().getNamedTraceExplorerExpressionsAsFormula();
  
        // iterate through the errors to find one with a trace
        Iterator<TLCError> it = getErrors().iterator();
        while (it.hasNext())
        {
            TLCError error = it.next();

            if (error.hasTrace())
            {
        		// Set the message, cause, and code of the error to the message of the original
        		// error for which the trace explorer was run if the new error
        		// message is for an invariant or property violation or deadlock. An invariant
        		// or property violation or deadlock indicates that the trace explorer ran
        		// successfully. This is item (6).
        		int errorCode = error.getErrorCode();
        		if (errorCode == EC.TLC_DEADLOCK_REACHED || errorCode == EC.TLC_TEMPORAL_PROPERTY_VIOLATED
        		        || errorCode == EC.TLC_INVARIANT_VIOLATED_BEHAVIOR
        		        || errorCode == EC.TLC_INVARIANT_VIOLATED_INITIAL)
        		{
        		    error.setErrorCode(originalErrorWithTrace.getErrorCode());
        		    error.setMessage(originalErrorWithTrace.getMessage());
        		    error.setCause(originalErrorWithTrace.getCause());

        		    successfulTEError = error;
        		} else
        		{
        		    error.setMessage(TE_ERROR_HEADER + error.getMessage());
        		}
        		
                error.applyFrom(originalErrorWithTrace, traceExplorerExpressions, traceExpressionDataTable,
						getModel().getName());

            } else
            {
                // error does not have trace
                // indicate that it is an error from the trace explorer
                error.setMessage(TE_ERROR_HEADER + error.getMessage());
            }
        }

        /*
         * The following accomplishes item 7 from the above documentation.
         */
        if (successfulTEError != null)
        {
            List<TLCError> originalErrors = TLCOutputSourceRegistry.getModelCheckSourceRegistry().getProvider(getModel())
                    .getErrors();
            List<TLCError> newErrors = new LinkedList<TLCError>();
            Iterator<TLCError> iterator = originalErrors.iterator();
            while (iterator.hasNext())
            {
                TLCError next = iterator.next();
                if (next == originalErrorWithTrace)
                {
                    newErrors.add(successfulTEError);
                } else
                {
                    newErrors.add(next);
                }
            }

            setErrors(newErrors);
        }

    }

    /**
     * Creates an error without any replacement of text from the error message reported by TLC.
     * 
     * This overrides the method in TLCModelLaunchDataProvider because that method does a lot
     * of work to search for Strings such as inv_2354234343434 in the error message and replace
     * them with the actual invariant from the MC.tla file. The user should never see anything from
     * the TE file, so this work is unnecessary for the trace explorer.
     * 
     * <br>This is a factory method
     * 
     * @param tlcRegion a region marking the error information in the document
     * @param message the message represented by the region
     * @return the TLC Error representing the error
     */
    protected TLCError createError(TLCRegion tlcRegion, String message)
    {
        // the root of the error trace
		final IDialogSettings dialogSettings = Activator.getDefault().getDialogSettings();
        final boolean stateSortOrder = dialogSettings.getBoolean(STATESORTORDER);
		final TLCError topError = new TLCError(Order.valueOf(stateSortOrder));

        if (tlcRegion instanceof TLCRegionContainer)
        {
            TLCRegionContainer container = (TLCRegionContainer) tlcRegion;
            // read out the subordinated regions
            ITypedRegion[] regions = container.getSubRegions();

            // currently, there can be at most three regions
            Assert.isTrue(regions.length < 3, "Unexpected error region structure, this is a bug.");

            // iterate over regions
            for (int i = 0; i < regions.length; i++)
            {
                // the region itself is a TLC region, detect the child error
                if (regions[i] instanceof TLCRegion)
                {
                    TLCError cause = createError((TLCRegion) regions[i], message);
                    topError.setCause(cause);
                } else
                {
                    // set error text
                    topError.setMessage(message);
                    // set error code
                    topError.setErrorCode(tlcRegion.getMessageCode());
                }
            }
        }
        return topError;

    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/tool/IWorker.java<|end_filename|>
package tlc2.tool;

import tlc2.TLCGlobals;
import tlc2.value.IValue;

/**
 * A common interface for workers
 * @author <NAME>
 */
public interface IWorker
{
	/**
	 * @return A worker's id in the range 0 to {@link TLCGlobals#getNumWorkers()} - 1
	 */
	public int myGetId();
	
    // see Thread
    
	public void start();

	public void join() throws InterruptedException;

	// see IdThread
	
	public IValue getLocalValue(int idx);

	public void setLocalValue(int idx, IValue val);
}


<|start_filename|>toolbox/org.lamport.tla.toolbox.editor.basic/src/org/lamport/tla/toolbox/editor/basic/tla/TokenSpec.java<|end_filename|>
/**
 * 
 */
package org.lamport.tla.toolbox.editor.basic.tla;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.ISourceViewer;
import org.lamport.tla.toolbox.editor.basic.TLAEditor;
import org.lamport.tla.toolbox.editor.basic.TLAEditorActivator;
import org.lamport.tla.toolbox.editor.basic.util.EditorUtil;
import org.lamport.tla.toolbox.util.ResourceHelper;

import tla2sany.semantic.ModuleNode;
import tla2sany.semantic.SymbolNode;
import tla2sany.st.Location;
import util.UniqueString;

/**
 * A TokenSpec object represents a possible TLA+ symbol name together
 * with the position of that symbol.  Note that the
 * expression Foo(a, b)!Bar(c) may be an occurrence of the symbol
 * named "Foo!Bar", whose left position is at the "F" and whose right
 * position is just after the "r" (and hence, at the following ")").
 * 
 * The main methods are the two is findCurrentTokenSpecs methods.  
 * Most of the work is done by findTokenSpecs, which was coded from 
 * a PlusCal spec that is appended to this file.
 *  
 * @author lamport
 *
 */
public class TokenSpec
{
    /*
     * The following are the fields of the object.  They are accessed
     * directly, without any of this set...() and get...() Java 
     * nonsense.
     */
    public String token;
    public int leftPos;
    public int rightPos;
    public SymbolNode resolvedSymbol = null;

    public TokenSpec(String tok, int left, int right)
    {
        this.token = tok;
        this.leftPos = left;
        this.rightPos = right;
    }

    /**
     * This method returns the TokenSpec of the symbol at the cursor position 
     * of the TLAEditor with the current focus.  If it cannot find the definition
     * or declaration of such a symbol, it returns a TokenSpec for the token
     * being pointed to with a null resolvedSymbol field.  This will be the
     * case if that token is a module name.  This method is used by
     * ShowUsesHandler.execute.
     * 
     * @return
     */
    public static TokenSpec findCurrentTokenSpec()
    {
        return findCurrentTokenSpec(null);
    }

    /**
     * This method is like findCurrentTokenSpec(), except it finds the
     * symbol at the position specified by a region, which is assumed
     * to be a region in the TLA editor with the current focus.  This method
     * is used by TLAHyperlinkDetector.detectHyperlinks.
     * 
     * @param regionInput
     * @return
     */
    public static TokenSpec findCurrentTokenSpec(IRegion regionInput)
    {
        // We first get the editor with focus and find its module and
        // its document, returning null if we get any nulls.
        // Note: Simon wrote a somewhat more baroque way of
        // getting the current editor at the beginning of
        // TLAEditor$OpenDeclarationHandler.execute. I don't know why.
        TLAEditor editor = EditorUtil.getTLAEditorWithFocus();
        if (editor == null)
        {
            return null;
        }
        String moduleName = editor.getModuleName();
        if (moduleName == null) {
        	return null;
        }
        ModuleNode moduleNode = ResourceHelper.getModuleNode(moduleName);
        if (moduleNode == null)
        {
            return null;
        }
        ISourceViewer internalSourceViewer = editor.publicGetSourceViewer();
        IDocument document = internalSourceViewer.getDocument();
        ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
        IRegion region = regionInput;
        if (regionInput == null)
        {
            region = new Region(selection.getOffset(), selection.getLength());
        }

        // Sets currentLine to the line of text of the module containing the beginning of the
        // current region, and sets currentPos to the position of the beginning of the
        // current region in that line. The Document.getLineLength method seems to include
        // the length of the line's delimeter, which should not be included in currentLine.
        String currentLine;
        int currentPos;
        int offsetOfLine;
        try
        {
            int lineNumber = document.getLineOfOffset(region.getOffset());
            int lineDelimLength = 0;
            String delim = document.getLineDelimiter(lineNumber);
            if (delim != null)
            {
                lineDelimLength = delim.length();
            }
            ;
            offsetOfLine = document.getLineOffset(lineNumber);
            currentLine = document.get(offsetOfLine, document.getLineLength(lineNumber) - lineDelimLength);
            currentPos = region.getOffset() - offsetOfLine;
        } catch (BadLocationException e)
        {
        	TLAEditorActivator.getDefault().logDebug("Exception thrown", e);
            return null;
        }

        // Call findTokenSpecs to find the array of candidate TokenSpec
        // objects. Note that this may return an array of length 0, but
        // does not return null.
        TokenSpec[] tokenSpecs = findTokenSpecs(currentLine, currentPos);

        // We update the positions to be offsets within the document,
        // and look for resolvedSymbol, setting goodIndex to the index
        // in tokenSpecs of the first element that resolves.
        int goodIndex = -1;
        SymbolNode symbol = null;
        for (int i = 0; i < tokenSpecs.length; i++)
        {

            int leftPos = tokenSpecs[i].leftPos;
            int rightPos = tokenSpecs[i].rightPos;
            tokenSpecs[i].leftPos = leftPos + offsetOfLine;
            tokenSpecs[i].rightPos = rightPos + offsetOfLine;

            String indiceAdjustedToken = tokenSpecs[i].token;
            Location location = EditorUtil.getLocationAt(document, tokenSpecs[i].leftPos, rightPos - leftPos);
            
            if ((indiceAdjustedToken != null) && (indiceAdjustedToken.length() > 1) && (indiceAdjustedToken.charAt(0) == '_')) {
                indiceAdjustedToken = indiceAdjustedToken.substring(1);
            }
            
            symbol = EditorUtil.lookupOriginalSymbol(UniqueString.uniqueStringOf(indiceAdjustedToken), moduleNode, location, null);
            if (symbol != null)
            {
                goodIndex = i;
                break;
            }
        }
        if (goodIndex == -1)
        {
            if (tokenSpecs.length == 0)
            {
                return null;
            } else
            {
                goodIndex = 0;
            }
        }
        TokenSpec result = new TokenSpec(tokenSpecs[goodIndex].token, tokenSpecs[goodIndex].leftPos,
                tokenSpecs[goodIndex].rightPos);
        result.resolvedSymbol = symbol;
        return result;
    }

    /** 
     * This method finds all possible symbol names containing the character at
     * or just before position inputPosition of line inputLine, in order of
     * decreasing length.  It returns their positions relative to the
     * beginning of the line.  There can be multiple possibilities because if
     * inputPosition is at the "a" in
     * 
     *    Foo!Bar!End
     * 
     * then the method return the array whose first element represents
     * Foo!Bar!End and whose second element represents Foo!Bar.  We don't
     * know which is correct, because End could either be a symbol defined
     * in an instantiated instantiated model, or else a label in the 
     * definition of the instantiated symbol Bar.
     * 
     * This method is the encoding of the PlusCal procedure of the same name in
     * module FindOp, which is appended as a comment to this file.
     * 
     * @param inputLine
     * @param inputPosition
     * @return
     */
    public static TokenSpec[] findTokenSpecs(String inputLine, int inputPosition)
    {
        // we pad the input line on the ends so we don't have to worry
        // about going off the end of the line.
        String line = Padding + inputLine + Padding;

        // Maintains the current position at which we are processing.
        int curPos = inputPosition + Padding.length();

        // Contains the result we've found so far.
        TokenSpec[] foundTokenSpecs = new TokenSpec[0];

        // Set true if there can be no tokens to right of first one found.
        boolean lastToken = false;

        // Set true if we find a "!" to the right of the first token found.
        boolean notLastToken = false;

        // temporary variable
        TokenSpec currentToken;

        // Try to find the current TokenSpec and put it in foundTokenSpecs,
        // leaving curPos to the left of that token. If the token is a
        // step name, we can return that single TokenSpec as the spec.
        // If it is an unnamed step, or if it is not a possible identifier
        // or operator symbol, we return << >> (a zero-length array).

        // First, we must check if we may be inside a string a possibly empty
        // sequence of spaces, a "!", and a possibly empty sequence of spaces.
        // If so, we move to its left, setting notLastToken to true.
        if (line.charAt(curPos) == ' ')
        {
            curPos = skipLeftOverSpaces(line, curPos);
            if (line.charAt(curPos - 1) == '!' && line.charAt(curPos - 2) != '!')
            {
                notLastToken = true;
                curPos = curPos - 1;
                curPos = skipLeftOverSpaces(line, curPos);
            }
        } else if ((line.charAt(curPos) == '!') && (line.charAt(curPos - 1) != '!') && (line.charAt(curPos + 1) != '!'))
        {
            notLastToken = true;
            curPos = skipLeftOverSpaces(line, curPos);
        }
        ;

        // If we're to the right of a ")", we could be inside something like
        //
        // Foo(42) ! bar
        // ^
        // so we set notLastToken true and move to the left of the parenthesized string.
        if ((notLastToken || line.charAt(curPos) == ' ') && (line.charAt(curPos - 1) == ')'))
        {
            notLastToken = true;
            int returnVal = findMatchingLeftParen(line, curPos);
            if (returnVal < 0)
            {
                return new TokenSpec[0];
            }
            curPos = returnVal;
            curPos = skipLeftOverSpaces(line, curPos);
        }
        ;
        // If notLastToken is true, then we should be just to the right
        // of the token we are expecting to find to the left of the '!' or the
        // parenthesized expression.
        if (notLastToken)
        {
            curPos = curPos - 1;
        } else
        {
            if ((!(Character.isLetterOrDigit(line.charAt(curPos)) || (line.charAt(curPos) == '_')))
                    && (findTokenIn(line, curPos, Operators) == null))
            {
                curPos = curPos - 1;
            }
        }

        if (Character.isLetterOrDigit(line.charAt(curPos)) || line.charAt(curPos) == '_')
        {
            if ((line.charAt(curPos) == 'X') && findTokenIn(line, curPos, XOperators) != null)
            {
                TokenSpec returnVal = findTokenIn(line, curPos, XOperators);
                foundTokenSpecs = new TokenSpec[] { returnVal };
                curPos = returnVal.leftPos;
                lastToken = true;
            } else
            {
                currentToken = findMaximalIdCharSeq(line, curPos);
                
                // silently prevent NPEs (hyperlinks will just not work)
                if (currentToken == null)
                {
					TLAEditorActivator
							.getDefault()
							.getLog()
							.log(new Status(IStatus.WARNING, TLAEditorActivator.PLUGIN_ID,
									"Hyperlinking failed for " + inputLine));
					return new TokenSpec[0];
                }
                // Check if token is part of step name. If it is, we set
                // First, see if currentToken could be the token after the "<...>".
                if (line.charAt(currentToken.leftPos - 1) == '>')
                {
                    TokenSpec returnVal = findMaximalIdCharSeq(line, currentToken.leftPos - 1);
                    returnVal = checkIfStepName(line, returnVal, currentToken);
                    if (returnVal != null)
                    {
                        return FixOrigin(new TokenSpec[] { returnVal });
                    }
                }
                ;
                // Next see if it's the token to the left of the '>'
                if (line.charAt(currentToken.rightPos) == '>')
                {
                    TokenSpec returnVal = findMaximalIdCharSeq(line, currentToken.rightPos + 1);
                    returnVal = checkIfStepName(line, currentToken, returnVal);
                    if (returnVal != null)
                    {
                        return FixOrigin(new TokenSpec[] { returnVal });
                    }
                }
                ;

                // Next, check if it's a number, and return if it is.
                if (IsNumber(currentToken.token))
                {
                    return new TokenSpec[0];
                }
                // Next, check if the token appears as a "\\" token, in
                // which case we adjust currentTok
                int left = currentToken.leftPos;
                int rt = currentToken.rightPos;
                if ((line.charAt(left - 1) == '\\') && (line.charAt(left - 2) != '\\')
                        && IsTeXSymbol(line.substring(left - 1, rt)))
                {
                    lastToken = true;
                    currentToken.leftPos = left - 1;
                    currentToken.token = line.substring(left - 1, rt);
                }
                ;
                foundTokenSpecs = new TokenSpec[] { currentToken };
                curPos = left;
            }
        } else
        {
            currentToken = findTokenIn(line, curPos, Operators);
            if (currentToken == null)
            {
                return new TokenSpec[0];
            }
            ;
            TokenSpec returnVal = findTokenIn(line, curPos, NonOperators);
            if (returnVal != null)
            {
                return new TokenSpec[0];
            }
            ;

            // Need to check if beginning or end of level specifier
            // of step number.
            if (currentToken.token.equals("<"))
            {
                TokenSpec temp1 = findMaximalIdCharSeq(line, currentToken.rightPos);
                if ((temp1 != null) && (line.charAt(temp1.rightPos) == '>'))
                {
                    TokenSpec temp2 = findMaximalIdCharSeq(line, temp1.rightPos + 1);
                    returnVal = checkIfStepName(line, temp1, temp2);
                    if (returnVal != null)
                    {
                        return FixOrigin(new TokenSpec[] { returnVal });
                    }
                }
            } else if (currentToken.token.equals(">"))
            {
                TokenSpec temp1 = findMaximalIdCharSeq(line, currentToken.leftPos);
                TokenSpec temp2 = findMaximalIdCharSeq(line, currentToken.rightPos);
                returnVal = checkIfStepName(line, temp1, temp2);
                if (returnVal != null)
                {
                    return FixOrigin(new TokenSpec[] { returnVal });
                }
            }

            // We check for the case of a '\\' starting a TeX token.
            if (currentToken.token.equals("\\"))
            {
                returnVal = findMaximalIdCharSeq(line, currentToken.rightPos);
                if ((returnVal != null) && IsTeXSymbol(line.substring(currentToken.leftPos, returnVal.rightPos)))
                {
                    currentToken.rightPos = returnVal.rightPos;
                    currentToken.token = line.substring(currentToken.leftPos, returnVal.rightPos);
                }
            }
            ;

            foundTokenSpecs = new TokenSpec[] { currentToken };
            curPos = currentToken.leftPos;
            lastToken = true;
        }
        ;

        // At this point, foundTokenSpecs.length = 1, and we have found the
        // base token. We now look to find extenders to the left of the form
        // idtoken '!'. These must be part of the name, so we prepend
        // them to foundTokenSpecs[0].
        curPos = foundTokenSpecs[0].leftPos;
        boolean notDone = true;
        while (notDone)
        {
            curPos = skipLeftOverSpaces(line, curPos);
            if (curPos < 0 || line.charAt(curPos - 1) == PaddingChar)
            {
                notDone = false;
            } else
            {
                if (line.charAt(curPos - 1) == '!' && (line.charAt(curPos - 2) != '!'))
                {
                    curPos = curPos - 1;
                    curPos = skipLeftOverSpaces(line, curPos);
                    curPos = findMatchingLeftParen(line, curPos);
                    if (curPos < 0)
                    {
                        notDone = false;
                    } else
                    {
                        curPos = skipLeftOverSpaces(line, curPos);
                        currentToken = findMaximalIdCharSeq(line, curPos);
                        if ((currentToken == null) || IsNumber(currentToken.token))
                        {
                            notDone = false;
                        } else
                        {
                            curPos = currentToken.leftPos;
                            foundTokenSpecs[0] = new TokenSpec(currentToken.token + "!" + foundTokenSpecs[0].token,
                                    curPos, foundTokenSpecs[0].rightPos);
                        }
                    }
                } else
                {
                    notDone = false;
                }
            }
        }

        // We have now completed the first token. If there are no more,
        // then we're done.
        if (lastToken == true)
        {
            return FixOrigin(foundTokenSpecs);
        }

        // There may be more "!" parts of the name to the right.
        curPos = foundTokenSpecs[0].rightPos;
        boolean foundBangToken = false;
        notDone = true;
        while (notDone)
        {
            curPos = skipRightOverSpaces(line, curPos);
            curPos = findMatchingRightParen(line, curPos);
            if (curPos < 0)
            {
                notDone = false;
            } else
            {
                curPos = skipRightOverSpaces(line, curPos);
                if ((line.charAt(curPos) != '!') || (line.charAt(curPos + 1) == '!'))
                {
                    notDone = false;
                } else
                {
                    curPos = curPos + 1;
                    curPos = skipRightOverSpaces(line, curPos);
                    currentToken = findMaximalIdCharSeq(line, curPos);
                    if ((currentToken == null) || IsNumber(currentToken.token))
                    {
                        notDone = false;
                    } else
                    {
                        foundBangToken = true;
                        // We now create a new TokenSpec by appending
                        // "!" + currentToken.token to the end of the
                        // first TokenSpec of foundTokenSpecs, and we prepend
                        // this TokenSpec to the beginning of foundTokenSpecs.
                        // We build the new foundTokenSpecs array in temp.
                        TokenSpec[] temp = new TokenSpec[1 + foundTokenSpecs.length];
                        temp[0] = new TokenSpec(foundTokenSpecs[0].token + "!" + currentToken.token,
                                foundTokenSpecs[0].leftPos, currentToken.rightPos);
                        for (int i = 0; i < foundTokenSpecs.length; i++)
                        {
                            temp[i + 1] = foundTokenSpecs[i];
                        }
                        foundTokenSpecs = temp;
                        curPos = currentToken.rightPos;
                    }
                }
            }
        }
        ;
        // If this wasn't the last token but we found no "!" following it,
        // then something is wrong so we return an empty result
        if (notLastToken && !foundBangToken)
        {
            return new TokenSpec[0];
        }
        ;

        return FixOrigin(foundTokenSpecs);
    }

    /**
     *  Returns the TokenSpec for the token in the array tokArray of Java
     * strings (Java array of 1-character strings) in the line containing the
     * character at position pos, or NullTokenSpec if there is none.
     * 
     * @return
     */
    private static TokenSpec findTokenIn(String line, int pos, String[] tokArray)
    {
        int tokIdx;
        for (int i = 0; i < tokArray.length; i++)
        {
            tokIdx = tokArray[i].indexOf(line.charAt(pos), 0);
            while (tokIdx != -1)
            {
                int ftlft = pos - tokIdx;
                int ftrt = pos - tokIdx + tokArray[i].length();
                if (tokArray[i].equals(line.substring(ftlft, ftrt)))
                {
                    return new TokenSpec(tokArray[i], ftlft, ftrt);
                }
                tokIdx = tokArray[i].indexOf(line.charAt(pos), tokIdx + 1);
            }
        }
        return null;
    }

    /**
     * Returns the TokenSpec of the largest token containing digits, letters,
     * and "_" characters containing position pos.  Returns null if
     * that would be an empty token.
     */
    private static TokenSpec findMaximalIdCharSeq(String line, int pos)
    {
        int left = pos;
        int rt = pos;
        left = pos;
        while (Character.isLetterOrDigit(line.charAt(left - 1)) || line.charAt(left - 1) == '_')
        {
            left--;
        }
        // The following while was
        //
        //   while (Character.isLetterOrDigit(line.charAt(rt)) || line.charAt(left - 1) == '_')
        //
        // Apparently, the previous while was copied and only half-modified.  As a
        // result, the Goto Declaration and Show Uses commands wouldn't work if
        // the cursor was inside an identifier containing a "_" to the left   of the
        // "_".  This was also a problem with Control+click. 
        // Fixed by LL on 7 May 2012
        while (Character.isLetterOrDigit(line.charAt(rt)) || line.charAt(rt) == '_')

        {
            rt++;
        }
        if (left == rt)
        {
            return null;
        } else
        {
            return new TokenSpec(line.substring(left, rt), left, rt);
        }
    }

    /**
     * Assumes that leftTok and rightTok are two TokenSpecs, possibly 
     * NullTokenSpecs, separated by a ">".  Checks if they form a step name.
     * If so, it returns the TokenSpec for that step name; otherwise it
     * returns null.
     * 
     * @param line
     * @param leftTok
     * @param rightTok
     * @return
     */
    private static TokenSpec checkIfStepName(String line, TokenSpec leftTok, TokenSpec rightTok)
    {
        if (leftTok == null || rightTok == null)
        {
            return null;
        }
        if (IsNumber(leftTok.token) && (line.charAt(leftTok.leftPos - 1) == '<')
                && (line.charAt(leftTok.leftPos - 2) != '<'))
        {
            return new TokenSpec(line.substring(leftTok.leftPos - 1, rightTok.rightPos), leftTok.leftPos - 1,
                    rightTok.rightPos);
        } else
        {
            return null;
        }
    }

    /**
     * Returns the position of the left paren matching a ")" at pos-1.  
     * If there is none, it returns -1.
     * 
     * @param line
     * @param pos
     * @return
     */
    private static int findMatchingLeftParen(String line, int pos)
    {
        if (line.charAt(pos - 1) != ')')
        {
            return pos;
        }
        ;
        return findMatchingLeftInner(line, pos, 0);
    }

    private static int findMatchingLeftInner(String line, int pos, int delim)
    {
        int ipos = pos;
        int jdelim;
        int delimLen = LeftDelimiters[delim].length();
        ipos = pos - delimLen;
        while (!line.substring(ipos - delimLen, ipos).equals(LeftDelimiters[delim]))
        {
            if (line.charAt(ipos - 1) == PaddingChar)
            {
                return -1;
            }
            ;
            ipos = ipos - 1;
            jdelim = 0;
            while (jdelim < LeftDelimiters.length)
            {
                if (line.substring(ipos - delimLen, ipos).equals(RightDelimiters[jdelim]))
                {
                    ipos = findMatchingLeftInner(line, ipos, jdelim);
                    if (ipos < 0)
                    {
                        return -1;
                    }
                    jdelim = 99999; // exit while loop
                }
                ;
                jdelim = jdelim + 1;
            }
        }
        ;
        return ipos - delimLen;
    }

    /**
     * Returns the position of the right paren matching a "(" at position pos.  
     * If there is none, it returns -1.
     * 
     * @param line
     * @param pos
     * @return
     */
    private static int findMatchingRightParen(String line, int pos)
    {
        if (line.charAt(pos) != '(')
        {
            return pos;
        }
        ;
        return findMatchingRightInner(line, pos, 0);
    }

    private static int findMatchingRightInner(String line, int pos, int delim)
    {
        int ipos = pos;
        int jdelim;
        int delimLen = RightDelimiters[delim].length();
        ipos = pos + delimLen;
        while (!line.substring(ipos, ipos + delimLen).equals(RightDelimiters[delim]))
        {
            if (line.charAt(ipos) == PaddingChar)
            {
                return -1;
            }
            ipos = ipos + 1;
            jdelim = 0;
            while (jdelim < RightDelimiters.length)
            {
                if (line.substring(ipos, ipos + delimLen).equals(LeftDelimiters[jdelim]))
                {
                    ipos = findMatchingRightInner(line, ipos, jdelim);
                    if (ipos < 0)
                    {
                        return -1;
                    }
                    jdelim = 99999; // exit while loop
                }
                ;
                jdelim = jdelim + 1;
            }
        }
        ;
        return ipos + delimLen;
    }

    private static int skipLeftOverSpaces(String line, int curPos)
    {
        int index = curPos;
        while (line.charAt(index - 1) == ' ')
        {
            index--;
        }
        return index;
    }

    private static int skipRightOverSpaces(String line, int curPos)
    {
        int index = curPos;
        while (line.charAt(index) == ' ')
        {
            index++;
        }
        return index;
    }

    private static boolean IsNumber(String str)
    {
        if (str.length() == 0)
        {
            return false;
        }
        for (int i = 0; i < str.length(); i++)
        {
            if (!Character.isDigit(str.charAt(i)))
            {
                return false;
            }
        }
        return true;
    }

    private static TokenSpec[] FixOrigin(TokenSpec[] tspec)
    {
        TokenSpec[] result = new TokenSpec[tspec.length];
        for (int i = 0; i < tspec.length; i++)
        {
            result[i] = new TokenSpec(tspec[i].token, tspec[i].leftPos - Padding.length(), tspec[i].rightPos
                    - Padding.length());
        }
        return result;
    }

    private static final char PaddingChar = '\u0000';

    private static final String Padding = "" + PaddingChar + PaddingChar + PaddingChar + PaddingChar + PaddingChar
            + PaddingChar + PaddingChar + PaddingChar + PaddingChar + PaddingChar;

    private static final String[] Operators = new String[] { "-+->", "<=>", "...", "::=", "(+)", "(-)", "(.)", "(/)",
            "(\\X)", "--", "**", "++", "<:", "<=", "<", ">=", "..", "||", "[]", "<>", "/\\", "\\/", "//", "/", "/=",
            "~>", "=>", "=<", "=|", "^^", "##", "|-", "|=", "&&", "$$", "??", "%%", "@@", "!!", ":>", ":=", "~", "=",
            "#", "^", "-", "*", ">", "<", "+", "|", "&", "$", "%", "\\" };

    /*
     * XOperators are the Operators containing an "X".  Note that "\\X" is in
     * a TeXSymbol, not in Operators.
     */
    private static final String[] XOperators = { "(\\X)" };

    // private static final String[] ParenOperators = new String[] { "(+)", "(-)", "(.)", "(/)", "(\\X)" };

    private static final String[] TeXSymbols = new String[] { "\\neg", "\\lnot", "\\approx", "\\asymp", "\\bigcirc",
            "\\bullet", "\\cap", "\\cdot", "\\circ", "\\cong", "\\cup", "\\div", "\\doteq", "\\equiv", "\\geq", "\\gg",
            "\\in", "\\intersect", "\\union", "\\land", "\\leq", "\\ll", "\\lor", "\\mod", "\\o", "\\odot", "\\ominus",
            "\\oplus", "\\oslash", "\\otimes", "\\prec", "\\preceq", "\\propto", "\\sim", "\\simeq", "\\sqcap",
            "\\sqcup", "\\sqsubset", "\\sqsupset", "\\sqsubseteq", "\\sqsupseteq", "\\star", "\\subset", "\\subseteq",
            "\\succ", "\\succeq", "\\supset", "\\supseteq", "\\uplus", "\\wr", "\\notin", "\\times", "\\X" };

    private static final String[] NonOperators = new String[] { "==", "---", "->", "<-", "***", "<<", ">>" };

    /**
     * Returns true iff str is an element of the array TeXSymbols.
     * 
     * @param str
     * @return
     */
    private static final boolean IsTeXSymbol(String str)
    {
        for (int i = 0; i < TeXSymbols.length; i++)
        {
            if (str.equals(TeXSymbols[i]))
            {
                return true;
            }
        }
        return false;
    }

    private static String[] RightDelimiters = { ")", "]", "}", ">>" };
    private static String[] LeftDelimiters = { "(", "[", "{", "<<" };

    public String toString()
    {
        String str = "[token |-> " + this.token + ", leftPos |-> " + this.leftPos +
        /*    */", rightPos |-> " + this.rightPos + ", resolvedSymbol |-> ";
        if (this.resolvedSymbol == null)
        {
            return str + "null]";
        }
        return str + this.resolvedSymbol.getName() + "]";

    }
}

/****************************  file FindOp.tla ************************
Known Bugs:
- The operator may not be found if you click on a space inside its name, as in 
   "Bar   (x)  !  y"

Known Features:
- Detects the ">" and "<" in " <3> " as operators. 

- If at a label that is also the name of an operator, then that operator 
  will be found.

- An operator appearing inside a comment or a string will be found.

------------------------------- MODULE FindOp -------------------------------
EXTENDS Integers, Sequences, TLC
-----------------------------------------------------------------------------
(***************************************************************************)
(* Operations for doing things in Java coordinates.                        *)
(***************************************************************************)
JavaSeq(seq) == [i \in 0 .. (Len(seq)-1) |-> seq[i+1]]
   \* Turns a TLA sequence into a Java array.
   
JavaSubseq(seq, b, e) == [i \in 0 .. (e-1-b) |-> seq[i+b]]
  \* Corresponds to Java's Subseq String method.
  
JavaLen(seq) == IF DOMAIN seq = {}
                  THEN 0
                  ELSE 1 + 
                         CHOOSE i \in DOMAIN seq : \A j \in DOMAIN seq : i >= j
  \* Corresponds to Java's seq.size() for strings or seq.len for
  \* arrays.  

JavaIndex(jarray, elt, fromPos) == 
  \* For jarray a Java array, it equals the smallest i >= fromPos such that
  \* jarray[i] = elt, or -1 if there is no such i
  LET Found(i) == jarray[i] = elt
      lastIdx == JavaLen(jarray) - 1
  IN  IF \E i \in fromPos .. lastIdx : Found(i)
         THEN CHOOSE i \in fromPos .. lastIdx : /\ Found(i)
                                                /\ \A j \in fromPos .. (i-1): ~Found(j)
         ELSE -1
  
JavaSeqSeq(seq) == [i \in 0 .. (Len(seq)-1) |-> JavaSeq(seq[i+1])]
  \* Converts a TLA sequence of TLA sequences to the corresponding
  \* array of Java arrays
  
JavaAppend(seq, elt) == LET len == JavaLen(seq) 
                        IN  [i \in 0..len |-> IF i = len THEN elt ELSE seq[i]]
  \* Appends an element to the end  of a Java sequence.

JavaConcatenate(seq1, seq2) == LET len1 == JavaLen(seq1)
                                   len2 == JavaLen(seq2)
                               IN  [i \in 0..(len1 + len2-1) |->
                                     IF i < len1 THEN seq1[i] 
                                                 ELSE seq2[i-len1]]
  \* Concatenates two Java arrays
  
IsJavaArray(array, S) == array \in [0..(JavaLen(array)-1) ->  S]
  \* True iff array is a Java array of elements of "type" S
  
\* NullJavaArray == (-1 :> {})
-----------------------------------------------------------------------------                      
(***************************************************************************)
(* The input.                                                              *)
(***************************************************************************)

(***************************************************************************)
(* The contents of the current line of the module.                         *)
(***************************************************************************)
lineInput == JavaSeq(<< "f", "(" , "b", ")", " ", "!", " ", "a", "!" , " ", "g" , \* , " ", " ", " ", "(", "[", "x", "]", ")", " ",
                     "(", "e", ")", " ",
                     "<", "3", "4", ">", "a", "."
 >>)  

               
(***************************************************************************)
(* The current position (in Java coordinates) of the cursor in the module. *)
(***************************************************************************)
currentPosition == 7 
-----------------------------------------------------------------------------
Padding ==  JavaSeq(<<";", ";", ";", ";", ";", ";", ";", ";", ";", ";">>)
  \* In an implementation ";" is replaced by an untypable character


GoingLeft == FALSE
  \* TRUE would mean that we continue searching for the symbol to the left if 
  \* find that we're inside a subexpression selector.

XSymbols == JavaSeqSeq(<< <<"(", "\\", "X", ")">>  >>)
  \* These are the Operators that contain "X".
  \*  Note that "\\X" is a TeXSymbol, not an Operator.

Operators == JavaSeqSeq(<<
\*   "-+->", "<=>", "...", "::=", "(+)", "(-)", "(.)", "(/)", "(\\X)",
\*   "--", "**", "++", "<:", "<=", "<", ">=", "..", "||", "[]", "<>",
\*   "/\\", "\\/", "//", "/", "/=", "~>", "=>", "=<", "=|", "^^", "##",
\*   "|-", "|=", "&&", "$$", "??", "%%", "@@", "!!", ":>", ":=", "~", "=",
\*   "#", "^", "-", "*", ">", "<", "+", "|", "&", "$", "%", "\\"
<< "(", "+", ")" >>,
<< "-", "+", "-", ">" >>,
<< "<", "=", ">" >>,
<< ".", ".", "." >>,
<< ":", ":", "=" >>,
<< "(", "-", ")" >>,
<< "(", ".", ")" >>,
<< "(", "/", ")" >>,
<< "(", "\\", "X", ")" >>,
<< "-",  "-" >>,
<< "*",  "*" >>,
<< "+",  "+" >>,
<< "<",  ":" >>,
<< "<",  "=" >>,
<< "<", " " >>,
<< ">",  "=" >>,
<< ".",  "." >>,
<< "|",  "|" >>,
<< "[",  "]" >>,
<< "<",  ">" >>,
<< "/", "\\" >>,
<< "\\", "/" >>,
<< "/",  "/" >>,
<< "/",  "=" >>,
<< "~",  ">" >>,
<< "=",  ">" >>,
<< "=",  "<" >>,
<< "=",  "|" >>,
<< "^",  "^" >>,
<< "#",  "#" >>,
<< "|",  "-" >>,
<< "|",  "=" >>,
<< "&",  "&" >>,
<< "$",  "$" >>,
<< "?",  "?" >>,
<< "%",  "%" >>,
<< "@",  "@" >>,
<< "!",  "!" >>,
<< ":",  ">" >>,
<< ":",  "=" >>,
<<"^", "+">>,
<<"^", "*">>,
<<"^", "#">>,
<<"~">>,
<<"=">>,
<<"#">>,
<<"^">>,
<<"-">>,
<<"*">>,
<<">">>,
<<"<">>,
<<"+">>,
<<"|">>,
<<"&">>,
<<"$">>,
<<"%">>,
<<"\\">>,
<<"'">>
>>)

NonOperators == JavaSeqSeq( <<
<<"=", "=">>, 
<<"-", "-", "-">>,
<<"-", ">">>,
<<"<", "-">>,
<<"*", "*", "*">>,
<<"<", "<">>,
<<">", ">">>
>> )

\* ParenOperators == JavaSeqSeq( <<
\* << "(", "+", ")" >>,
\* << "(", "-", ")" >>,
\* << "(", ".", ")" >>,
\* << "(", "/", ")" >>,
\* << "(", "\\", "X", ")" >>
\* >> )

TeXSymbols == JavaSeqSeq(<<
\*   "\\neg", "\\lnot", "\\approx",
\*   "\\asymp", "\\bigcirc", "\\bullet", "\\cap", "\\cdot", "\\circ",
\*   "\\cong", "\\cup", "\\div", "\\doteq", "\\equiv", "\\geq", "\\gg",
\*   "\\in", "\\intersect", "\\union", "\\land", "\\leq", "\\ll", "\\lor",
\*   "\\mod", "\\o", "\\odot", "\\ominus", "\\oplus", "\\oslash",
\*   "\\otimes", "\\prec", "\\preceq", "\\propto", "\\sim", "\\simeq",
\*   "\\sqcap", "\\sqcup", "\\sqsubset", "\\sqsupset", "\\sqsubseteq",
\*   "\\sqsupseteq", "\\star", "\\subset", "\\subseteq", "\\succ",
\*   "\\succeq", "\\supset", "\\supseteq", "\\uplus", "\\wr", "\\notin",
\*   "\\times", "\\X" 
<<"\\", "n", "e", "g">>,
<<"\\", "l", "n", "o", "t">>,
<<"\\", "a", "p", "p", "r", "o", "x">>,
<<"\\", "a", "s", "y", "m", "p">>,
<<"\\", "b", "i", "g", "c", "i", "r", "c">>,
<<"\\", "b", "u", "l", "l", "e", "t">>,
<<"\\", "c", "a", "p">>,
<<"\\", "c", "d", "o", "t">>,
<<"\\", "c", "i", "r", "c">>,
<<"\\", "c", "o", "n", "g">>,
<<"\\", "c", "u", "p">>,
<<"\\", "d", "i", "v">>,
<<"\\", "d", "o", "t", "e", "q">>,
<<"\\", "e", "q", "u", "i", "v">>,
<<"\\", "g", "e", "q">>,
<<"\\", "g", "g">>,
<<"\\", "i", "n", "t", "e", "r", "s", "e", "c", "t">>,
<<"\\", "u", "n", "i", "o", "n">>,
<<"\\", "l", "a", "n", "d">>,
<<"\\", "l", "e", "q">>,
<<"\\", "l", "l">>,
<<"\\", "l", "o", "r">>,
<<"\\", "m", "o", "d">>,
<<"\\", "o", "d", "o", "t">>,
<<"\\", "o", "m", "i", "n", "u", "s">>,
<<"\\", "o", "p", "l", "u", "s">>,
<<"\\", "o", "s", "l", "a", "s", "h">>,
<<"\\", "o", "t", "i", "m", "e", "s">>,
<<"\\", "p", "r", "e", "c">>,
<<"\\", "p", "r", "e", "c", "e", "q", "">>,
<<"\\", "p", "r", "o", "p", "t", "o">>,
<<"\\", "s", "i", "m">>,
<<"\\", "s", "i", "m", "e", "q">>,
<<"\\", "s", "q", "c", "a", "p">>,
<<"\\", "s", "q", "c", "u", "p">>,
<<"\\", "s", "q", "s", "u", "b", "s", "e", "t">>,
<<"\\", "s", "q", "s", "u", "p", "s", "e", "t">>,
<<"\\", "s", "q", "s", "u", "b", "s", "e", "t", "e", "q">>,
<<"\\", "s", "q", "s", "u", "p", "s", "e", "t", "e", "q">>,
<<"\\", "s", "t", "a", "r">>,
<<"\\", "s", "u", "b", "s", "e", "t", "">>,
<<"\\", "s", "u", "b", "s", "e", "t", "e", "q">>,
<<"\\", "s", "u", "c", "c">>,
<<"\\", "s", "u", "c", "c", "e", "q">>,
<<"\\", "s", "u", "p", "s", "e", "t", "">>,
<<"\\", "s", "u", "p", "s", "e", "t", "e", "q">>,
<<"\\", "u", "p", "l", "u", "s">>,
<<"\\", "w", "r">>,
<<"\\", "n", "o", "t", "i", "n">>,
<<"\\", "t", "i", "m", "e", "s">>,
<<"\\", "o">>,
<<"\\", "i", "n">>,
<<"\\", "X">>
>>)

IsNumber(seq) == /\ \A i \in DOMAIN seq : 
                       seq[i] \in {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
                 /\ (DOMAIN seq) # {}
IdChar == {"a", "b", "c", "d", "e", "f", "g", "h", "i", "n", (* ... *) "X", "Y", "Z",  
           "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "_"}

RightDelimiters == JavaSeqSeq(<< <<")">>, <<"]">>, <<"}">>, <<">", ">">> >>)
LeftDelimiters == JavaSeqSeq(<< <<"(">>, <<"[">>, <<"{">>, <<"<", "<">> >>)
-----------------------------------------------------------------------------
TokenSpec == [token : STRING, leftPos : Nat, rightPos : Nat]
NullTokenSpec == [null |-> "null"]
(****************************************************************************
 
--algorithm FindOp {
variables 
  line = JavaConcatenate (Padding, JavaConcatenate(lineInput, Padding));
  foundTokenSpecs = << >>  ; 
   \* Array records of form [token   |-> string of a token,
   \*                        leftPos |-> location in line of left of token,
   \*                        rightPos   |-> location in line of just to the 
   \*                                    right of token]
  lastToken = FALSE; \* true if there can be no tokens to right of first
                     \* one found
  notLastToken = FALSE;  \* true if we found a "!" to the right of the
                         \* first token found.
  curPos = currentPosition  + JavaLen(Padding) ;
  returnVal; \* Use for returning values from a procedure call.
  tempVar1 ;
  tempVar2 ;
  tempVar3 ;
  
define 
{ 
  FixOrigin(tokarray) ==
  [i \in DOMAIN tokarray |->
           [token |->tokarray[i].token, rightPos |-> tokarray[i].rightPos - JavaLen(Padding), 
            leftPos |-> tokarray[i].leftPos - JavaLen(Padding)]]

};

macro vreturn(val)
{ returnVal := val;
  return;
}

\* Returns the TokenSpec for the token in the array tokArray of
\* Java strings (Java array of 1-character strings) in the line
\* containing the character at position pos, or NullTokenSpec
\* if there is none.
procedure findTokenIn(pos, tokArray) 
  variables i ; tokIdx ;
    { i := 0;
      while (i < JavaLen(tokArray)) 
       { tokIdx := JavaIndex(tokArray[i], line[pos], 0);
         while (tokIdx # -1) 
           { with (ftlft = pos - tokIdx,
                   ftrt = pos - tokIdx + JavaLen(tokArray[i]))
               { if (tokArray[i] = JavaSubseq(line, ftlft, ftrt))
                  { vreturn([token |-> tokArray[i],
                                  leftPos |-> ftlft, rightPos |-> ftrt])
                  };
               };
             tokIdx := JavaIndex(tokArray[i], line[pos], tokIdx+1);
           };
           i := i+1; 
        };
      vreturn(NullTokenSpec);
    }


\* Returns the TokenSpec of the largest token containing digits,
\* letters, and "_" characters containing position pos.  Returns
\* NullTokenSpec if that would be an empty token.
procedure findMaximalIdCharSeq(pos) 
  variables token = << >>; left = pos; rt = pos;
  { \* token := << >>;
    \* left := pos;
    while (line[left-1] \in IdChar)
      { left := left-1; 
      };
    while (line[rt] \in IdChar)
     { rt := rt+1
     };
   if (left = rt)
     { vreturn(NullTokenSpec) }
   else
     { vreturn([token |-> JavaSubseq(line, left, rt), 
                leftPos |-> left, rightPos |-> rt])
     }
  } 

\* Returns the position of the left paren matching a ")" at pos-1.
\* If there is none, it returns -1.
procedure findMatchingLeftParen(pos) 
{ if (line[pos-1] # ")") {vreturn(pos)};
  call findMatchingLeftInner(pos, 0);
  return;
 }

procedure findMatchingLeftInner(pos, delim) 
 variables ipos = pos; jdelim; delimLen;
{ delimLen := JavaLen(LeftDelimiters[delim]);
  ipos := pos - delimLen;
  while (JavaSubseq(line, ipos-delimLen, ipos) # LeftDelimiters[delim])
   { if (line[ipos-1] = ";") {vreturn(-1)};
     ipos := ipos-1;
     jdelim := 0;
     while (jdelim < JavaLen(LeftDelimiters))
      { if (JavaSubseq(line, ipos-delimLen, ipos) = RightDelimiters[jdelim])
         { call findMatchingLeftInner(ipos, jdelim);
           ipos := returnVal;
           if (ipos < 0) { vreturn(-1)};
           jdelim := 99 ; \* exit while loop
         };
        jdelim := jdelim+1;
      }
   };
   vreturn(ipos-delimLen);
 }

\* Returns the position of the right paren matching a "(" at position pos.
\* If there is none, it returns -1.
procedure findMatchingRightParen(pos) 
{ if (line[pos] # "(") {vreturn(pos)};
  call findMatchingRightInner(pos, 0);
  return;
 }

procedure findMatchingRightInner(pos, delim) 
 variables ipos = pos; jdelim; delimLen; 
{ delimLen := JavaLen(RightDelimiters[delim]);
  ipos := pos + delimLen;
  while (JavaSubseq(line, ipos, ipos+delimLen) # RightDelimiters[delim])
   { if (line[ipos] = ";") {vreturn(-1)};
     ipos := ipos+1;
     jdelim := 0;
     while (jdelim < JavaLen(RightDelimiters))
      { if (JavaSubseq(line, ipos, ipos+delimLen) = LeftDelimiters[jdelim])
         { call findMatchingRightInner(ipos, jdelim);
           ipos := returnVal;
           if (ipos < 0) { vreturn(-1)};
           jdelim := 99 ; \* exit while loop
         };
        jdelim := jdelim+1;
      }
   };
   vreturn(ipos+delimLen);
 }

\* Assumes that leftTok and rightTok are two TokenSpecs, 
\* possibly NullTokenSpecs, separated by a ">".  Checks
\* if they form a step name.  If so, it returns the
\* TokenSpec for that step name; otherwise it returns
\* NullTokenSpec.
procedure checkIfStepName(leftTok, rightTok)
{ if (leftTok = NullTokenSpec \/ rightTok = NullTokenSpec)
    { vreturn(NullTokenSpec) };
  if ( /\ IsNumber(leftTok.token)
       /\ line[leftTok.leftPos-1] = "<"
       /\ line[leftTok.leftPos-2] # "<" )
     { vreturn( [token |-> JavaSubseq(line, 
                                      leftTok.leftPos-1,
                                      rightTok.rightPos),
                 leftPos |-> leftTok.leftPos-1,
                 rightPos |-> rightTok.rightPos] )
     };
   else { vreturn(NullTokenSpec) };
}
procedure skipLeftOverSpaces() 
{ while (line[curPos-1] = " ") { curPos := curPos - 1; };
  return;
}

procedure skipRightOverSpaces() 
{ while (line[curPos] = " ") { curPos := curPos+1; };
  return;
}

\* Returns a TokenSpec array of possible tokens to be selected
\* when the cursor is at position curPos of line.  It 
\* returns a zero-length array if there are none.
\*
\* Known Bug: This will not work right in some cases when curPos
\* are spaces inside a name, as in
\*
\*    Foo   (x, y)!bar
\*        ^
procedure findTokenSpecs()
variables currentToken; left; rt; notDone; foundBangToken;
temp1; temp2; temp3;
{ \* Try to find the current TokenSpec and put it in foundTokenSpecs, 
  \* leaving curPos to the left of that token.  If the token is a
  \* step name, we can return that single TokenSpec as the spec.  
  \* If it is an unnamed step, or if it is not a possible identifier
  \* or operator symbol, we return << >> (a zero-length array).
  
  \* First, we must check if we may be inside a string of form (" ")^* "!" (" ")^*
  \* and, if so, move to its left, setting notLastToken to TRUE
  if (line[curPos] = " ") 
    { call skipLeftOverSpaces() ;
      if (line[curPos-1] = "!"  /\ line[curPos-2] # "!")
        { notLastToken := TRUE;
          curPos := curPos - 1;
          call skipLeftOverSpaces();
        }
    }
  else if (line[curPos] = "!" /\ line[curPos-1] # "!" /\ line[curPos+1] # "!")
    { notLastToken := TRUE;
      call skipLeftOverSpaces()
    };
    
  \* If we're to the right of a ")", we could be inside something like
  \*
  \*   Foo(42) ! bar
  \*          ^
  \* so we set notLastToken true and move to the left of the parentesized string.
  if ( /\ \/ notLastToken
          \/ line[curPos] = " "
       /\ line[curPos-1] = ")")
    { notLastToken := TRUE;
      call findMatchingLeftParen(curPos);
      if (returnVal < 0) {vreturn(<< >>)};
      curPos := returnVal;
      call skipLeftOverSpaces();
    };
  \* If notLastToken is true, then we should be just to the right
  \* of the token we are expecting to find to the left of the "!" or the
  \* parenthesized expression. 
  \* Otherwise, if we're not at an IdChar or at an operator, then
  \* let's try one character to the left.  
  \* Note: this happens to work if we're right before "<4>7" or "\in"
  \* because both "<" and "\\" are operators.

  if (notLastToken) { curPos := curPos - 1; };
  else 
    { if (line[curPos] \notin IdChar) 
        { call findTokenIn(curPos, Operators);
          if ( returnVal = NullTokenSpec )
            { curPos := curPos - 1
            }
        }

    } ;
\* \* Following code replaced by preceding "else" clause
\*
\*  \* If we didn't move left and we're at a "(" or "." that's not the beginning
\*  \* of an operator, let's move left 1.
\*  if (~ notLastToken /\ line[curPos] = "(")
\*    { call findTokenIn(curPos, ParenOperators);
\*      if (returnVal = NullTokenSpec) { curPos := curPos - 1 }
\*    }
\*  else if ( /\ ~ notLastToken 
\*            /\ line[curPos] = "."
\*            /\ line[curPos+1] # "." 
\*            /\ line[curPos-1] # "." )
\*         { curPos := curPos - 1 };
\*  
\*  \* If we're at a space (which means we haven't found a "!" or moved left
\*  \* over a parenthesized string), then try as if the cursor were
\*  \* one character to the left.
\*  if (line[curPos] = " ") { curPos := curPos - 1};
  
  if (line[curPos] \in IdChar)
    { \* Check if we're at an "X" that is inside an "\X" or "\X".
      \* Note: this works because there are no TeXSymbols besides
      if (line[curPos] = "X") { call findTokenIn(curPos, XSymbols); }
      else {returnVal := NullTokenSpec} ;
      if (returnVal # NullTokenSpec)
        { foundTokenSpecs := JavaSeq(<<returnVal>>);
          curPos := returnVal.leftPos;
          lastToken := TRUE;
         }
      else 
         { call findMaximalIdCharSeq(curPos);
           currentToken := returnVal;
           \* Check if token is part of step name.  If it is, we set
           \* First, see if currentToken could be the token after the "<...>".
           if ( line[currentToken.leftPos-1] = ">" )
             { call findMaximalIdCharSeq(currentToken.leftPos - 1);
               call checkIfStepName(returnVal, currentToken);
               if (returnVal # NullTokenSpec)
                 { foundTokenSpecs := JavaSeq(<<returnVal>>);
                   vreturn(FixOrigin(foundTokenSpecs));
                 }
             };
           \* Next see if it's the token to the left of the ">"
           if (line[currentToken.rightPos] = ">" )
             { call findMaximalIdCharSeq(currentToken.rightPos+1);
               call checkIfStepName(currentToken, returnVal);
               if (returnVal # NullTokenSpec)
                 { foundTokenSpecs := JavaSeq(<<returnVal>>);
                   vreturn(FixOrigin(foundTokenSpecs));
                 }
             };

           \* Next, check if it's a number, and abort if it is.
           if (IsNumber(currentToken.token)) 
             { vreturn(<< >>)
             };
           
           \* Next, check if the token appears as "\\"token, in
           \* which case we adjust currentTok
           left := currentToken.leftPos ;
           rt   := currentToken.rightPos ;
           if ( /\ line[left-1] = "\\" 
                /\ line[left-2] # "\\"
                /\ \E ii \in DOMAIN TeXSymbols :
                         JavaSubseq(line, left-1, rt) = TeXSymbols[ii] )
             { lastToken := TRUE;
               currentToken.leftPos := left - 1 ||
               currentToken.token := JavaSubseq(line, left-1, rt);
             };
           foundTokenSpecs := 
                 JavaSeq( << currentToken >>);
           curPos := left;
         }
    }
  else 
    { call findTokenIn(curPos, Operators);
      currentToken  := returnVal;
      if (currentToken = NullTokenSpec)
        { vreturn(<< >>);
        };
      call findTokenIn(curPos, NonOperators);
      if (returnVal # NullTokenSpec)
        { vreturn(<< >>);
        };

      \* Need to check if beginning or end of level specifier
      \* of step number.  
      if ( currentToken.token = JavaSeq(<< "<" >>) )
        { call findMaximalIdCharSeq(currentToken.rightPos);
          temp1 := returnVal;
          if (/\ temp1 # NullTokenSpec
              /\ line[temp1.rightPos] = ">")
            { call findMaximalIdCharSeq(temp1.rightPos + 1);
              temp2 := returnVal;
              call checkIfStepName(temp1, temp2);
              if (returnVal # NullTokenSpec)
               { foundTokenSpecs := JavaSeq(<<returnVal>>);
                 vreturn(FixOrigin(foundTokenSpecs));
               }
            }
          }
       else if (currentToken.token = JavaSeq(<< ">" >>))
         { call findMaximalIdCharSeq(currentToken.leftPos);
           temp1 := returnVal;
           call findMaximalIdCharSeq(currentToken.rightPos);
           temp2 := returnVal;
           call checkIfStepName(temp1, temp2);
              if (returnVal # NullTokenSpec)
               { foundTokenSpecs := JavaSeq(<<returnVal>>);
                 vreturn(FixOrigin(foundTokenSpecs));
               }
         };

      \* We check for the case of a "\\" starting a TeX token.
      if (currentToken.token = JavaSeq(<<"\\">>))
        { call findMaximalIdCharSeq(currentToken.rightPos);
          if ( /\ returnVal # NullTokenSpec
               /\ \E ii \in DOMAIN TeXSymbols :
                         JavaSubseq(line, 
                                    currentToken.leftPos, 
                                    returnVal.rightPos) = TeXSymbols[ii] )
            { currentToken.rightPos := returnVal.rightPos ||
              currentToken.token := JavaSubseq(line, 
                                    currentToken.leftPos, 
                                    returnVal.rightPos) 
            }
        };

      foundTokenSpecs := JavaSeq(<<currentToken>>);
      curPos := currentToken.leftPos;
      lastToken := TRUE;
     };

  assert JavaLen(foundTokenSpecs) = 1;

\*print <<"1", foundTokenSpecs[0]>>;
  \** We have now found the base token.  We now look to find extenders
  \*  to the left of the form  idtoken "!".  These must be part of the
  \*  name, so we prepend them to foundTokenSpecs[0].
  curPos := foundTokenSpecs[0].leftPos;
  notDone := TRUE;
  while (notDone) 
    { call skipLeftOverSpaces();
      if (curPos <  0 \/ line[curPos-1] = ";") 
        { notDone := FALSE; }
      else
        { if (line[curPos-1] = "!" /\ (line[curPos-2] # "!"))
            { curPos := curPos - 1;
              call skipLeftOverSpaces();
              call findMatchingLeftParen(curPos);
              curPos := returnVal;
              if (curPos < 0) { notDone := FALSE }
              else 
                { call skipLeftOverSpaces();
                  call findMaximalIdCharSeq(curPos);
                  currentToken := returnVal ;
                  if ( \/ currentToken = NullTokenSpec
                       \/ IsNumber(currentToken.token) )
                    { notDone := FALSE }
                  else
                    { curPos := currentToken.leftPos;
                      foundTokenSpecs[0] := 
                             [token |-> JavaConcatenate(
                                            JavaAppend(currentToken.token, "!"),
                                            foundTokenSpecs[0].token),
                              leftPos |-> curPos, 
                              rightPos |-> foundTokenSpecs[0].rightPos];
                    }
               }
             }
         else {notDone := FALSE;}
       };
       
    };

  assert foundTokenSpecs # << >> ;

  if (lastToken = TRUE) {vreturn(FixOrigin(foundTokenSpecs))};
  
\*  print <<"2", foundTokenSpecs[0]>>;
  
  curPos := foundTokenSpecs[0].rightPos;
  foundBangToken := FALSE;
  notDone := TRUE;
  while (notDone) 
    { call skipRightOverSpaces();
      call findMatchingRightParen(curPos);
      curPos := returnVal;
      if (curPos < 0) {notDone := FALSE}
      else
        { call skipRightOverSpaces();
          if (line[curPos] # "!"  \/ line[curPos+1] = "!")
            { notDone := FALSE } 
          else
            { curPos := curPos + 1;
              call skipRightOverSpaces();
              call findMaximalIdCharSeq(curPos);
              currentToken := returnVal ;
              if ( \/ currentToken = NullTokenSpec
                   \/ IsNumber(currentToken.token) )
                { notDone := FALSE }
              else
                { foundBangToken := TRUE;
                  foundTokenSpecs :=
                    JavaConcatenate(
                      JavaSeq( 
                        << [token |-> 
                              JavaConcatenate(JavaAppend(foundTokenSpecs[0].token,
                                                          "!"),
                                              currentToken.token),
                            leftPos |-> foundTokenSpecs[0].leftPos,
                            rightPos |-> currentToken.rightPos]
                         >> ) ,
                        foundTokenSpecs); 
                  curPos := currentToken.rightPos;
                }
            }
        }
    };

  if (notLastToken /\ ~ foundBangToken) { vreturn (<< >>) };

  vreturn(FixOrigin(foundTokenSpecs));
} \* end findTokenSpecs

\* Main Body:
{ curPos := JavaLen(Padding);
  tempVar1 := (-1 :> "");
  tempVar2 := JavaLen(Padding);
\*curPos := 15;
\*call findTokenSpecs();
\*print returnVal;
  print line;
  while (tempVar2 < JavaLen(lineInput) + JavaLen(Padding))
    { print <<"curPos: ", tempVar2>>;
      curPos := tempVar2;
      foundTokenSpecs := << >>  ;
      lastToken := FALSE;
      notLastToken := FALSE;
      call findTokenSpecs();
\*      if (tempVar2 >= 0 + JavaLen(Padding))
\*        { print "done with run" ;
\*          assert FALSE
\*        };
      if (returnVal = tempVar1)
        { print "same" \* ,"lastToken: ", lastToken, ", notLastToken: ", notLastToken>> 
        }
      else 
        { print returnVal;
   \*          print <<"lastToken: ", lastToken, ", notLastToken: ", notLastToken>>;
        };
      tempVar1 := returnVal;
      tempVar2 := tempVar2 + 1;
    };
  print "goodby world";

} \* end Main Body
} \* End algorithm
  
*****************************************************************************************)
\* BEGIN TRANSLATION
\* Procedure variable left of procedure findMaximalIdCharSeq at line 316 col 28 changed to left_
\* Procedure variable rt of procedure findMaximalIdCharSeq at line 316 col 40 changed to rt_
\* Procedure variable ipos of procedure findMatchingLeftInner at line 342 col 12 changed to ipos_
\* Procedure variable jdelim of procedure findMatchingLeftInner at line 342 col 24 changed to jdelim_
\* Procedure variable delimLen of procedure findMatchingLeftInner at line 342 col 32 changed to delimLen_
\* Parameter pos of procedure findTokenIn at line 291 col 23 changed to pos_
\* Parameter pos of procedure findMaximalIdCharSeq at line 315 col 32 changed to pos_f
\* Parameter pos of procedure findMatchingLeftParen at line 335 col 33 changed to pos_fi
\* Parameter pos of procedure findMatchingLeftInner at line 341 col 33 changed to pos_fin
\* Parameter delim of procedure findMatchingLeftInner at line 341 col 38 changed to delim_
\* Parameter pos of procedure findMatchingRightParen at line 364 col 34 changed to pos_find
CONSTANT defaultInitValue
VARIABLES line, foundTokenSpecs, lastToken, notLastToken, curPos, returnVal, 
          tempVar1, tempVar2, tempVar3, pc, stack

(* define statement *)
FixOrigin(tokarray) ==
[i \in DOMAIN tokarray |->
         [token |->tokarray[i].token, rightPos |-> tokarray[i].rightPos - JavaLen(Padding),
          leftPos |-> tokarray[i].leftPos - JavaLen(Padding)]]

VARIABLES pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, pos_fi, 
          pos_fin, delim_, ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
          ipos, jdelim, delimLen, leftTok, rightTok, currentToken, left, rt, 
          notDone, foundBangToken, temp1, temp2, temp3

vars == << line, foundTokenSpecs, lastToken, notLastToken, curPos, returnVal, 
           tempVar1, tempVar2, tempVar3, pc, stack, pos_, tokArray, i, tokIdx, 
           pos_f, token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
           delimLen_, pos_find, pos, delim, ipos, jdelim, delimLen, leftTok, 
           rightTok, currentToken, left, rt, notDone, foundBangToken, temp1, 
           temp2, temp3 >>

Init == (* Global variables *)
        /\ line = JavaConcatenate (Padding, JavaConcatenate(lineInput, Padding))
        /\ foundTokenSpecs = << >>
        /\ lastToken = FALSE
        /\ notLastToken = FALSE
        /\ curPos = currentPosition  + JavaLen(Padding)
        /\ returnVal = defaultInitValue
        /\ tempVar1 = defaultInitValue
        /\ tempVar2 = defaultInitValue
        /\ tempVar3 = defaultInitValue
        (* Procedure findTokenIn *)
        /\ pos_ = defaultInitValue
        /\ tokArray = defaultInitValue
        /\ i = defaultInitValue
        /\ tokIdx = defaultInitValue
        (* Procedure findMaximalIdCharSeq *)
        /\ pos_f = defaultInitValue
        /\ token = << >>
        /\ left_ = pos_f
        /\ rt_ = pos_f
        (* Procedure findMatchingLeftParen *)
        /\ pos_fi = defaultInitValue
        (* Procedure findMatchingLeftInner *)
        /\ pos_fin = defaultInitValue
        /\ delim_ = defaultInitValue
        /\ ipos_ = pos_fin
        /\ jdelim_ = defaultInitValue
        /\ delimLen_ = defaultInitValue
        (* Procedure findMatchingRightParen *)
        /\ pos_find = defaultInitValue
        (* Procedure findMatchingRightInner *)
        /\ pos = defaultInitValue
        /\ delim = defaultInitValue
        /\ ipos = pos
        /\ jdelim = defaultInitValue
        /\ delimLen = defaultInitValue
        (* Procedure checkIfStepName *)
        /\ leftTok = defaultInitValue
        /\ rightTok = defaultInitValue
        (* Procedure findTokenSpecs *)
        /\ currentToken = defaultInitValue
        /\ left = defaultInitValue
        /\ rt = defaultInitValue
        /\ notDone = defaultInitValue
        /\ foundBangToken = defaultInitValue
        /\ temp1 = defaultInitValue
        /\ temp2 = defaultInitValue
        /\ temp3 = defaultInitValue
        /\ stack = << >>
        /\ pc = "Lbl_77"

Lbl_1 == /\ pc = "Lbl_1"
         /\ i' = 0
         /\ pc' = "Lbl_2"
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                         stack, pos_, tokArray, tokIdx, pos_f, token, left_, 
                         rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                         delimLen_, pos_find, pos, delim, ipos, jdelim, 
                         delimLen, leftTok, rightTok, currentToken, left, rt, 
                         notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_2 == /\ pc = "Lbl_2"
         /\ IF i < JavaLen(tokArray)
               THEN /\ tokIdx' = JavaIndex(tokArray[i], line[pos_], 0)
                    /\ pc' = "Lbl_3"
                    /\ UNCHANGED << returnVal, stack, pos_, tokArray, i >>
               ELSE /\ returnVal' = NullTokenSpec
                    /\ pc' = Head(stack).pc
                    /\ i' = Head(stack).i
                    /\ tokIdx' = Head(stack).tokIdx
                    /\ pos_' = Head(stack).pos_
                    /\ tokArray' = Head(stack).tokArray
                    /\ stack' = Tail(stack)
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, tempVar1, tempVar2, tempVar3, pos_f, token, 
                         left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                         delimLen_, pos_find, pos, delim, ipos, jdelim, 
                         delimLen, leftTok, rightTok, currentToken, left, rt, 
                         notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_3 == /\ pc = "Lbl_3"
         /\ IF tokIdx # -1
               THEN /\ LET ftlft == pos_ - tokIdx IN
                         LET ftrt == pos_ - tokIdx + JavaLen(tokArray[i]) IN
                           IF tokArray[i] = JavaSubseq(line, ftlft, ftrt)
                              THEN /\ returnVal' = [token |-> tokArray[i],
                                                         leftPos |-> ftlft, rightPos |-> ftrt]
                                   /\ pc' = Head(stack).pc
                                   /\ i' = Head(stack).i
                                   /\ tokIdx' = Head(stack).tokIdx
                                   /\ pos_' = Head(stack).pos_
                                   /\ tokArray' = Head(stack).tokArray
                                   /\ stack' = Tail(stack)
                              ELSE /\ pc' = "Lbl_4"
                                   /\ UNCHANGED << returnVal, stack, pos_, 
                                                   tokArray, i, tokIdx >>
               ELSE /\ i' = i+1
                    /\ pc' = "Lbl_2"
                    /\ UNCHANGED << returnVal, stack, pos_, tokArray, tokIdx >>
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, tempVar1, tempVar2, tempVar3, pos_f, token, 
                         left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                         delimLen_, pos_find, pos, delim, ipos, jdelim, 
                         delimLen, leftTok, rightTok, currentToken, left, rt, 
                         notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_4 == /\ pc = "Lbl_4"
         /\ tokIdx' = JavaIndex(tokArray[i], line[pos_], tokIdx+1)
         /\ pc' = "Lbl_3"
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                         stack, pos_, tokArray, i, pos_f, token, left_, rt_, 
                         pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                         pos_find, pos, delim, ipos, jdelim, delimLen, leftTok, 
                         rightTok, currentToken, left, rt, notDone, 
                         foundBangToken, temp1, temp2, temp3 >>

findTokenIn == Lbl_1 \/ Lbl_2 \/ Lbl_3 \/ Lbl_4

Lbl_5 == /\ pc = "Lbl_5"
         /\ IF line[left_-1] \in IdChar
               THEN /\ left_' = left_-1
                    /\ pc' = "Lbl_5"
               ELSE /\ pc' = "Lbl_6"
                    /\ UNCHANGED left_
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                         stack, pos_, tokArray, i, tokIdx, pos_f, token, rt_, 
                         pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                         pos_find, pos, delim, ipos, jdelim, delimLen, leftTok, 
                         rightTok, currentToken, left, rt, notDone, 
                         foundBangToken, temp1, temp2, temp3 >>

Lbl_6 == /\ pc = "Lbl_6"
         /\ IF line[rt_] \in IdChar
               THEN /\ rt_' = rt_+1
                    /\ pc' = "Lbl_6"
                    /\ UNCHANGED << returnVal, stack, pos_f, token, left_ >>
               ELSE /\ IF left_ = rt_
                          THEN /\ returnVal' = NullTokenSpec
                               /\ pc' = Head(stack).pc
                               /\ token' = Head(stack).token
                               /\ left_' = Head(stack).left_
                               /\ rt_' = Head(stack).rt_
                               /\ pos_f' = Head(stack).pos_f
                               /\ stack' = Tail(stack)
                          ELSE /\ returnVal' = [token |-> JavaSubseq(line, left_, rt_),
                                                leftPos |-> left_, rightPos |-> rt_]
                               /\ pc' = Head(stack).pc
                               /\ token' = Head(stack).token
                               /\ left_' = Head(stack).left_
                               /\ rt_' = Head(stack).rt_
                               /\ pos_f' = Head(stack).pos_f
                               /\ stack' = Tail(stack)
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                         i, tokIdx, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                         delimLen_, pos_find, pos, delim, ipos, jdelim, 
                         delimLen, leftTok, rightTok, currentToken, left, rt, 
                         notDone, foundBangToken, temp1, temp2, temp3 >>

findMaximalIdCharSeq == Lbl_5 \/ Lbl_6

Lbl_7 == /\ pc = "Lbl_7"
         /\ IF line[pos_fi-1] # ")"
               THEN /\ returnVal' = pos_fi
                    /\ pc' = Head(stack).pc
                    /\ pos_fi' = Head(stack).pos_fi
                    /\ stack' = Tail(stack)
               ELSE /\ pc' = "Lbl_8"
                    /\ UNCHANGED << returnVal, stack, pos_fi >>
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                         i, tokIdx, pos_f, token, left_, rt_, pos_fin, delim_, 
                         ipos_, jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                         jdelim, delimLen, leftTok, rightTok, currentToken, 
                         left, rt, notDone, foundBangToken, temp1, temp2, 
                         temp3 >>

Lbl_8 == /\ pc = "Lbl_8"
         /\ /\ delim_' = 0
            /\ pos_fin' = pos_fi
            /\ stack' = << [ procedure |->  "findMatchingLeftInner",
                             pc        |->  Head(stack).pc,
                             ipos_     |->  ipos_,
                             jdelim_   |->  jdelim_,
                             delimLen_ |->  delimLen_,
                             pos_fin   |->  pos_fin,
                             delim_    |->  delim_ ] >>
                         \o Tail(stack)
         /\ ipos_' = pos_fin'
         /\ jdelim_' = defaultInitValue
         /\ delimLen_' = defaultInitValue
         /\ pc' = "Lbl_9"
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                         tokArray, i, tokIdx, pos_f, token, left_, rt_, pos_fi, 
                         pos_find, pos, delim, ipos, jdelim, delimLen, leftTok, 
                         rightTok, currentToken, left, rt, notDone, 
                         foundBangToken, temp1, temp2, temp3 >>

findMatchingLeftParen == Lbl_7 \/ Lbl_8

Lbl_9 == /\ pc = "Lbl_9"
         /\ delimLen_' = JavaLen(LeftDelimiters[delim_])
         /\ ipos_' = pos_fin - delimLen_'
         /\ pc' = "Lbl_10"
         /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                         curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                         stack, pos_, tokArray, i, tokIdx, pos_f, token, left_, 
                         rt_, pos_fi, pos_fin, delim_, jdelim_, pos_find, pos, 
                         delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                         currentToken, left, rt, notDone, foundBangToken, 
                         temp1, temp2, temp3 >>

Lbl_10 == /\ pc = "Lbl_10"
          /\ IF JavaSubseq(line, ipos_-delimLen_, ipos_) # LeftDelimiters[delim_]
                THEN /\ IF line[ipos_-1] = ";"
                           THEN /\ returnVal' = -1
                                /\ pc' = Head(stack).pc
                                /\ ipos_' = Head(stack).ipos_
                                /\ jdelim_' = Head(stack).jdelim_
                                /\ delimLen_' = Head(stack).delimLen_
                                /\ pos_fin' = Head(stack).pos_fin
                                /\ delim_' = Head(stack).delim_
                                /\ stack' = Tail(stack)
                           ELSE /\ pc' = "Lbl_11"
                                /\ UNCHANGED << returnVal, stack, pos_fin, 
                                                delim_, ipos_, jdelim_, 
                                                delimLen_ >>
                ELSE /\ returnVal' = ipos_-delimLen_
                     /\ pc' = Head(stack).pc
                     /\ ipos_' = Head(stack).ipos_
                     /\ jdelim_' = Head(stack).jdelim_
                     /\ delimLen_' = Head(stack).delimLen_
                     /\ pos_fin' = Head(stack).pos_fin
                     /\ delim_' = Head(stack).delim_
                     /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_11 == /\ pc = "Lbl_11"
          /\ ipos_' = ipos_-1
          /\ jdelim_' = 0
          /\ pc' = "Lbl_12"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_12 == /\ pc = "Lbl_12"
          /\ IF jdelim_ < JavaLen(LeftDelimiters)
                THEN /\ IF JavaSubseq(line, ipos_-delimLen_, ipos_) = RightDelimiters[jdelim_]
                           THEN /\ /\ delim_' = jdelim_
                                   /\ pos_fin' = ipos_
                                   /\ stack' = << [ procedure |->  "findMatchingLeftInner",
                                                    pc        |->  "Lbl_13",
                                                    ipos_     |->  ipos_,
                                                    jdelim_   |->  jdelim_,
                                                    delimLen_ |->  delimLen_,
                                                    pos_fin   |->  pos_fin,
                                                    delim_    |->  delim_ ] >>
                                                \o stack
                                /\ ipos_' = pos_fin'
                                /\ jdelim_' = defaultInitValue
                                /\ delimLen_' = defaultInitValue
                                /\ pc' = "Lbl_9"
                           ELSE /\ pc' = "Lbl_16"
                                /\ UNCHANGED << stack, pos_fin, delim_, ipos_, 
                                                jdelim_, delimLen_ >>
                ELSE /\ pc' = "Lbl_10"
                     /\ UNCHANGED << stack, pos_fin, delim_, ipos_, jdelim_, 
                                     delimLen_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_16 == /\ pc = "Lbl_16"
          /\ jdelim_' = jdelim_+1
          /\ pc' = "Lbl_12"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          delimLen_, pos_find, pos, delim, ipos, jdelim, 
                          delimLen, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_13 == /\ pc = "Lbl_13"
          /\ ipos_' = returnVal
          /\ IF ipos_' < 0
                THEN /\ returnVal' = -1
                     /\ pc' = "Lbl_14"
                ELSE /\ pc' = "Lbl_15"
                     /\ UNCHANGED returnVal
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_14 == /\ pc = "Lbl_14"
          /\ pc' = Head(stack).pc
          /\ ipos_' = Head(stack).ipos_
          /\ jdelim_' = Head(stack).jdelim_
          /\ delimLen_' = Head(stack).delimLen_
          /\ pos_fin' = Head(stack).pos_fin
          /\ delim_' = Head(stack).delim_
          /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_15 == /\ pc = "Lbl_15"
          /\ jdelim_' = 99
          /\ pc' = "Lbl_16"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          delimLen_, pos_find, pos, delim, ipos, jdelim, 
                          delimLen, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

findMatchingLeftInner == Lbl_9 \/ Lbl_10 \/ Lbl_11 \/ Lbl_12 \/ Lbl_16
                            \/ Lbl_13 \/ Lbl_14 \/ Lbl_15

Lbl_17 == /\ pc = "Lbl_17"
          /\ IF line[pos_find] # "("
                THEN /\ returnVal' = pos_find
                     /\ pc' = Head(stack).pc
                     /\ pos_find' = Head(stack).pos_find
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_18"
                     /\ UNCHANGED << returnVal, stack, pos_find >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok, currentToken, 
                          left, rt, notDone, foundBangToken, temp1, temp2, 
                          temp3 >>

Lbl_18 == /\ pc = "Lbl_18"
          /\ /\ delim' = 0
             /\ pos' = pos_find
             /\ stack' = << [ procedure |->  "findMatchingRightInner",
                              pc        |->  Head(stack).pc,
                              ipos      |->  ipos,
                              jdelim    |->  jdelim,
                              delimLen  |->  delimLen,
                              pos       |->  pos,
                              delim     |->  delim ] >>
                          \o Tail(stack)
          /\ ipos' = pos'
          /\ jdelim' = defaultInitValue
          /\ delimLen' = defaultInitValue
          /\ pc' = "Lbl_19"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

findMatchingRightParen == Lbl_17 \/ Lbl_18

Lbl_19 == /\ pc = "Lbl_19"
          /\ delimLen' = JavaLen(RightDelimiters[delim])
          /\ ipos' = pos + delimLen'
          /\ pc' = "Lbl_20"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, jdelim, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_20 == /\ pc = "Lbl_20"
          /\ IF JavaSubseq(line, ipos, ipos+delimLen) # RightDelimiters[delim]
                THEN /\ IF line[ipos] = ";"
                           THEN /\ returnVal' = -1
                                /\ pc' = Head(stack).pc
                                /\ ipos' = Head(stack).ipos
                                /\ jdelim' = Head(stack).jdelim
                                /\ delimLen' = Head(stack).delimLen
                                /\ pos' = Head(stack).pos
                                /\ delim' = Head(stack).delim
                                /\ stack' = Tail(stack)
                           ELSE /\ pc' = "Lbl_21"
                                /\ UNCHANGED << returnVal, stack, pos, delim, 
                                                ipos, jdelim, delimLen >>
                ELSE /\ returnVal' = ipos+delimLen
                     /\ pc' = Head(stack).pc
                     /\ ipos' = Head(stack).ipos
                     /\ jdelim' = Head(stack).jdelim
                     /\ delimLen' = Head(stack).delimLen
                     /\ pos' = Head(stack).pos
                     /\ delim' = Head(stack).delim
                     /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_21 == /\ pc = "Lbl_21"
          /\ ipos' = ipos+1
          /\ jdelim' = 0
          /\ pc' = "Lbl_22"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, delimLen, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_22 == /\ pc = "Lbl_22"
          /\ IF jdelim < JavaLen(RightDelimiters)
                THEN /\ IF JavaSubseq(line, ipos, ipos+delimLen) = LeftDelimiters[jdelim]
                           THEN /\ /\ delim' = jdelim
                                   /\ pos' = ipos
                                   /\ stack' = << [ procedure |->  "findMatchingRightInner",
                                                    pc        |->  "Lbl_23",
                                                    ipos      |->  ipos,
                                                    jdelim    |->  jdelim,
                                                    delimLen  |->  delimLen,
                                                    pos       |->  pos,
                                                    delim     |->  delim ] >>
                                                \o stack
                                /\ ipos' = pos'
                                /\ jdelim' = defaultInitValue
                                /\ delimLen' = defaultInitValue
                                /\ pc' = "Lbl_19"
                           ELSE /\ pc' = "Lbl_26"
                                /\ UNCHANGED << stack, pos, delim, ipos, 
                                                jdelim, delimLen >>
                ELSE /\ pc' = "Lbl_20"
                     /\ UNCHANGED << stack, pos, delim, ipos, jdelim, delimLen >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_26 == /\ pc = "Lbl_26"
          /\ jdelim' = jdelim+1
          /\ pc' = "Lbl_22"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, ipos, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_23 == /\ pc = "Lbl_23"
          /\ ipos' = returnVal
          /\ IF ipos' < 0
                THEN /\ returnVal' = -1
                     /\ pc' = "Lbl_24"
                ELSE /\ pc' = "Lbl_25"
                     /\ UNCHANGED returnVal
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, jdelim, delimLen, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_24 == /\ pc = "Lbl_24"
          /\ pc' = Head(stack).pc
          /\ ipos' = Head(stack).ipos
          /\ jdelim' = Head(stack).jdelim
          /\ delimLen' = Head(stack).delimLen
          /\ pos' = Head(stack).pos
          /\ delim' = Head(stack).delim
          /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_25 == /\ pc = "Lbl_25"
          /\ jdelim' = 99
          /\ pc' = "Lbl_26"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, ipos, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

findMatchingRightInner == Lbl_19 \/ Lbl_20 \/ Lbl_21 \/ Lbl_22 \/ Lbl_26
                             \/ Lbl_23 \/ Lbl_24 \/ Lbl_25

Lbl_27 == /\ pc = "Lbl_27"
          /\ IF leftTok = NullTokenSpec \/ rightTok = NullTokenSpec
                THEN /\ returnVal' = NullTokenSpec
                     /\ pc' = Head(stack).pc
                     /\ leftTok' = Head(stack).leftTok
                     /\ rightTok' = Head(stack).rightTok
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_28"
                     /\ UNCHANGED << returnVal, stack, leftTok, rightTok >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, currentToken, left, 
                          rt, notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_28 == /\ pc = "Lbl_28"
          /\ IF /\ IsNumber(leftTok.token)
                /\ line[leftTok.leftPos-1] = "<"
                /\ line[leftTok.leftPos-2] # "<"
                THEN /\ returnVal' = [token |-> JavaSubseq(line,
                                                           leftTok.leftPos-1,
                                                           rightTok.rightPos),
                                      leftPos |-> leftTok.leftPos-1,
                                      rightPos |-> rightTok.rightPos]
                     /\ pc' = Head(stack).pc
                     /\ leftTok' = Head(stack).leftTok
                     /\ rightTok' = Head(stack).rightTok
                     /\ stack' = Tail(stack)
                ELSE /\ returnVal' = NullTokenSpec
                     /\ pc' = Head(stack).pc
                     /\ leftTok' = Head(stack).leftTok
                     /\ rightTok' = Head(stack).rightTok
                     /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, currentToken, left, 
                          rt, notDone, foundBangToken, temp1, temp2, temp3 >>

checkIfStepName == Lbl_27 \/ Lbl_28

Lbl_29 == /\ pc = "Lbl_29"
          /\ IF line[curPos-1] = " "
                THEN /\ curPos' = curPos - 1
                     /\ pc' = "Lbl_29"
                     /\ UNCHANGED stack
                ELSE /\ pc' = Head(stack).pc
                     /\ stack' = Tail(stack)
                     /\ UNCHANGED curPos
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

skipLeftOverSpaces == Lbl_29

Lbl_30 == /\ pc = "Lbl_30"
          /\ IF line[curPos] = " "
                THEN /\ curPos' = curPos+1
                     /\ pc' = "Lbl_30"
                     /\ UNCHANGED stack
                ELSE /\ pc' = Head(stack).pc
                     /\ stack' = Tail(stack)
                     /\ UNCHANGED curPos
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

skipRightOverSpaces == Lbl_30

Lbl_31 == /\ pc = "Lbl_31"
          /\ IF line[curPos] = " "
                THEN /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                      pc        |->  "Lbl_32" ] >>
                                  \o stack
                     /\ pc' = "Lbl_29"
                     /\ UNCHANGED notLastToken
                ELSE /\ IF line[curPos] = "!" /\ line[curPos-1] # "!" /\ line[curPos+1] # "!"
                           THEN /\ notLastToken' = TRUE
                                /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                                 pc        |->  "Lbl_33" ] >>
                                             \o stack
                                /\ pc' = "Lbl_29"
                           ELSE /\ pc' = "Lbl_33"
                                /\ UNCHANGED << notLastToken, stack >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, curPos, returnVal, 
                          tempVar1, tempVar2, tempVar3, pos_, tokArray, i, 
                          tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_32 == /\ pc = "Lbl_32"
          /\ IF line[curPos-1] = "!"  /\ line[curPos-2] # "!"
                THEN /\ notLastToken' = TRUE
                     /\ curPos' = curPos - 1
                     /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                      pc        |->  "Lbl_33" ] >>
                                  \o stack
                     /\ pc' = "Lbl_29"
                ELSE /\ pc' = "Lbl_33"
                     /\ UNCHANGED << notLastToken, curPos, stack >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, returnVal, 
                          tempVar1, tempVar2, tempVar3, pos_, tokArray, i, 
                          tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_33 == /\ pc = "Lbl_33"
          /\ IF /\ \/ notLastToken
                   \/ line[curPos] = " "
                /\ line[curPos-1] = ")"
                THEN /\ notLastToken' = TRUE
                     /\ /\ pos_fi' = curPos
                        /\ stack' = << [ procedure |->  "findMatchingLeftParen",
                                         pc        |->  "Lbl_34",
                                         pos_fi    |->  pos_fi ] >>
                                     \o stack
                     /\ pc' = "Lbl_7"
                ELSE /\ pc' = "Lbl_36"
                     /\ UNCHANGED << notLastToken, stack, pos_fi >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, curPos, returnVal, 
                          tempVar1, tempVar2, tempVar3, pos_, tokArray, i, 
                          tokIdx, pos_f, token, left_, rt_, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_34 == /\ pc = "Lbl_34"
          /\ IF returnVal < 0
                THEN /\ returnVal' = << >>
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_35"
                     /\ UNCHANGED << returnVal, stack, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

Lbl_35 == /\ pc = "Lbl_35"
          /\ curPos' = returnVal
          /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                           pc        |->  "Lbl_36" ] >>
                       \o stack
          /\ pc' = "Lbl_29"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_36 == /\ pc = "Lbl_36"
          /\ IF notLastToken
                THEN /\ curPos' = curPos - 1
                     /\ pc' = "Lbl_38"
                     /\ UNCHANGED << stack, pos_, tokArray, i, tokIdx >>
                ELSE /\ IF line[curPos] \notin IdChar
                           THEN /\ /\ pos_' = curPos
                                   /\ stack' = << [ procedure |->  "findTokenIn",
                                                    pc        |->  "Lbl_37",
                                                    i         |->  i,
                                                    tokIdx    |->  tokIdx,
                                                    pos_      |->  pos_,
                                                    tokArray  |->  tokArray ] >>
                                                \o stack
                                   /\ tokArray' = Operators
                                /\ i' = defaultInitValue
                                /\ tokIdx' = defaultInitValue
                                /\ pc' = "Lbl_1"
                           ELSE /\ pc' = "Lbl_38"
                                /\ UNCHANGED << stack, pos_, tokArray, i, 
                                                tokIdx >>
                     /\ UNCHANGED curPos
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok, currentToken, 
                          left, rt, notDone, foundBangToken, temp1, temp2, 
                          temp3 >>

Lbl_37 == /\ pc = "Lbl_37"
          /\ IF returnVal = NullTokenSpec
                THEN /\ curPos' = curPos - 1
                ELSE /\ TRUE
                     /\ UNCHANGED curPos
          /\ pc' = "Lbl_38"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_38 == /\ pc = "Lbl_38"
          /\ IF line[curPos] \in IdChar
                THEN /\ IF line[curPos] = "X"
                           THEN /\ /\ pos_' = curPos
                                   /\ stack' = << [ procedure |->  "findTokenIn",
                                                    pc        |->  "Lbl_39",
                                                    i         |->  i,
                                                    tokIdx    |->  tokIdx,
                                                    pos_      |->  pos_,
                                                    tokArray  |->  tokArray ] >>
                                                \o stack
                                   /\ tokArray' = XSymbols
                                /\ i' = defaultInitValue
                                /\ tokIdx' = defaultInitValue
                                /\ pc' = "Lbl_1"
                                /\ UNCHANGED returnVal
                           ELSE /\ returnVal' = NullTokenSpec
                                /\ pc' = "Lbl_39"
                                /\ UNCHANGED << stack, pos_, tokArray, i, 
                                                tokIdx >>
                ELSE /\ /\ pos_' = curPos
                        /\ stack' = << [ procedure |->  "findTokenIn",
                                         pc        |->  "Lbl_48",
                                         i         |->  i,
                                         tokIdx    |->  tokIdx,
                                         pos_      |->  pos_,
                                         tokArray  |->  tokArray ] >>
                                     \o stack
                        /\ tokArray' = Operators
                     /\ i' = defaultInitValue
                     /\ tokIdx' = defaultInitValue
                     /\ pc' = "Lbl_1"
                     /\ UNCHANGED returnVal
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, ipos, jdelim, 
                          delimLen, leftTok, rightTok, currentToken, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_39 == /\ pc = "Lbl_39"
          /\ IF returnVal # NullTokenSpec
                THEN /\ foundTokenSpecs' = JavaSeq(<<returnVal>>)
                     /\ curPos' = returnVal.leftPos
                     /\ lastToken' = TRUE
                     /\ pc' = "Lbl_62"
                     /\ UNCHANGED << stack, pos_f, token, left_, rt_ >>
                ELSE /\ /\ pos_f' = curPos
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_40",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                     /\ UNCHANGED << foundTokenSpecs, lastToken, curPos >>
          /\ UNCHANGED << line, notLastToken, returnVal, tempVar1, tempVar2, 
                          tempVar3, pos_, tokArray, i, tokIdx, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_40 == /\ pc = "Lbl_40"
          /\ currentToken' = returnVal
          /\ IF line[currentToken'.leftPos-1] = ">"
                THEN /\ /\ pos_f' = currentToken'.leftPos - 1
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_41",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                ELSE /\ pc' = "Lbl_43"
                     /\ UNCHANGED << stack, pos_f, token, left_, rt_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, left, rt, 
                          notDone, foundBangToken, temp1, temp2, temp3 >>

Lbl_41 == /\ pc = "Lbl_41"
          /\ /\ leftTok' = returnVal
             /\ rightTok' = currentToken
             /\ stack' = << [ procedure |->  "checkIfStepName",
                              pc        |->  "Lbl_42",
                              leftTok   |->  leftTok,
                              rightTok  |->  rightTok ] >>
                          \o stack
          /\ pc' = "Lbl_27"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_42 == /\ pc = "Lbl_42"
          /\ IF returnVal # NullTokenSpec
                THEN /\ foundTokenSpecs' = JavaSeq(<<returnVal>>)
                     /\ returnVal' = FixOrigin(foundTokenSpecs')
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_43"
                     /\ UNCHANGED << foundTokenSpecs, returnVal, stack, 
                                     currentToken, left, rt, notDone, 
                                     foundBangToken, temp1, temp2, temp3 >>
          /\ UNCHANGED << line, lastToken, notLastToken, curPos, tempVar1, 
                          tempVar2, tempVar3, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok >>

Lbl_43 == /\ pc = "Lbl_43"
          /\ IF line[currentToken.rightPos] = ">"
                THEN /\ /\ pos_f' = currentToken.rightPos+1
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_44",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                ELSE /\ pc' = "Lbl_46"
                     /\ UNCHANGED << stack, pos_f, token, left_, rt_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_44 == /\ pc = "Lbl_44"
          /\ /\ leftTok' = currentToken
             /\ rightTok' = returnVal
             /\ stack' = << [ procedure |->  "checkIfStepName",
                              pc        |->  "Lbl_45",
                              leftTok   |->  leftTok,
                              rightTok  |->  rightTok ] >>
                          \o stack
          /\ pc' = "Lbl_27"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_45 == /\ pc = "Lbl_45"
          /\ IF returnVal # NullTokenSpec
                THEN /\ foundTokenSpecs' = JavaSeq(<<returnVal>>)
                     /\ returnVal' = FixOrigin(foundTokenSpecs')
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_46"
                     /\ UNCHANGED << foundTokenSpecs, returnVal, stack, 
                                     currentToken, left, rt, notDone, 
                                     foundBangToken, temp1, temp2, temp3 >>
          /\ UNCHANGED << line, lastToken, notLastToken, curPos, tempVar1, 
                          tempVar2, tempVar3, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok >>

Lbl_46 == /\ pc = "Lbl_46"
          /\ IF IsNumber(currentToken.token)
                THEN /\ returnVal' = << >>
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_47"
                     /\ UNCHANGED << returnVal, stack, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

Lbl_47 == /\ pc = "Lbl_47"
          /\ left' = currentToken.leftPos
          /\ rt' = currentToken.rightPos
          /\ IF /\ line[left'-1] = "\\"
                /\ line[left'-2] # "\\"
                /\ \E ii \in DOMAIN TeXSymbols :
                         JavaSubseq(line, left'-1, rt') = TeXSymbols[ii]
                THEN /\ lastToken' = TRUE
                     /\ currentToken' = [currentToken EXCEPT !.leftPos = left' - 1,
                                                             !.token = JavaSubseq(line, left'-1, rt')]
                ELSE /\ TRUE
                     /\ UNCHANGED << lastToken, currentToken >>
          /\ foundTokenSpecs' = JavaSeq( << currentToken' >>)
          /\ curPos' = left'
          /\ pc' = "Lbl_62"
          /\ UNCHANGED << line, notLastToken, returnVal, tempVar1, tempVar2, 
                          tempVar3, stack, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_48 == /\ pc = "Lbl_48"
          /\ currentToken' = returnVal
          /\ IF currentToken' = NullTokenSpec
                THEN /\ returnVal' = << >>
                     /\ pc' = "Lbl_49"
                ELSE /\ pc' = "Lbl_50"
                     /\ UNCHANGED returnVal
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_49 == /\ pc = "Lbl_49"
          /\ pc' = Head(stack).pc
          /\ currentToken' = Head(stack).currentToken
          /\ left' = Head(stack).left
          /\ rt' = Head(stack).rt
          /\ notDone' = Head(stack).notDone
          /\ foundBangToken' = Head(stack).foundBangToken
          /\ temp1' = Head(stack).temp1
          /\ temp2' = Head(stack).temp2
          /\ temp3' = Head(stack).temp3
          /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok >>

Lbl_50 == /\ pc = "Lbl_50"
          /\ /\ pos_' = curPos
             /\ stack' = << [ procedure |->  "findTokenIn",
                              pc        |->  "Lbl_51",
                              i         |->  i,
                              tokIdx    |->  tokIdx,
                              pos_      |->  pos_,
                              tokArray  |->  tokArray ] >>
                          \o stack
             /\ tokArray' = NonOperators
          /\ i' = defaultInitValue
          /\ tokIdx' = defaultInitValue
          /\ pc' = "Lbl_1"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_f, token, left_, rt_, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_51 == /\ pc = "Lbl_51"
          /\ IF returnVal # NullTokenSpec
                THEN /\ returnVal' = << >>
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_52"
                     /\ UNCHANGED << returnVal, stack, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

Lbl_52 == /\ pc = "Lbl_52"
          /\ IF currentToken.token = JavaSeq(<< "<" >>)
                THEN /\ /\ pos_f' = currentToken.rightPos
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_53",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                ELSE /\ IF currentToken.token = JavaSeq(<< ">" >>)
                           THEN /\ /\ pos_f' = currentToken.leftPos
                                   /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                                    pc        |->  "Lbl_56",
                                                    token     |->  token,
                                                    left_     |->  left_,
                                                    rt_       |->  rt_,
                                                    pos_f     |->  pos_f ] >>
                                                \o stack
                                /\ token' = << >>
                                /\ left_' = pos_f'
                                /\ rt_' = pos_f'
                                /\ pc' = "Lbl_5"
                           ELSE /\ pc' = "Lbl_59"
                                /\ UNCHANGED << stack, pos_f, token, left_, 
                                                rt_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_53 == /\ pc = "Lbl_53"
          /\ temp1' = returnVal
          /\ IF /\ temp1' # NullTokenSpec
                /\ line[temp1'.rightPos] = ">"
                THEN /\ /\ pos_f' = temp1'.rightPos + 1
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_54",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                ELSE /\ pc' = "Lbl_59"
                     /\ UNCHANGED << stack, pos_f, token, left_, rt_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp2, temp3 >>

Lbl_54 == /\ pc = "Lbl_54"
          /\ temp2' = returnVal
          /\ /\ leftTok' = temp1
             /\ rightTok' = temp2'
             /\ stack' = << [ procedure |->  "checkIfStepName",
                              pc        |->  "Lbl_55",
                              leftTok   |->  leftTok,
                              rightTok  |->  rightTok ] >>
                          \o stack
          /\ pc' = "Lbl_27"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp3 >>

Lbl_55 == /\ pc = "Lbl_55"
          /\ IF returnVal # NullTokenSpec
                THEN /\ foundTokenSpecs' = JavaSeq(<<returnVal>>)
                     /\ returnVal' = FixOrigin(foundTokenSpecs')
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_59"
                     /\ UNCHANGED << foundTokenSpecs, returnVal, stack, 
                                     currentToken, left, rt, notDone, 
                                     foundBangToken, temp1, temp2, temp3 >>
          /\ UNCHANGED << line, lastToken, notLastToken, curPos, tempVar1, 
                          tempVar2, tempVar3, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok >>

Lbl_56 == /\ pc = "Lbl_56"
          /\ temp1' = returnVal
          /\ /\ pos_f' = currentToken.rightPos
             /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                              pc        |->  "Lbl_57",
                              token     |->  token,
                              left_     |->  left_,
                              rt_       |->  rt_,
                              pos_f     |->  pos_f ] >>
                          \o stack
          /\ token' = << >>
          /\ left_' = pos_f'
          /\ rt_' = pos_f'
          /\ pc' = "Lbl_5"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp2, temp3 >>

Lbl_57 == /\ pc = "Lbl_57"
          /\ temp2' = returnVal
          /\ /\ leftTok' = temp1
             /\ rightTok' = temp2'
             /\ stack' = << [ procedure |->  "checkIfStepName",
                              pc        |->  "Lbl_58",
                              leftTok   |->  leftTok,
                              rightTok  |->  rightTok ] >>
                          \o stack
          /\ pc' = "Lbl_27"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp3 >>

Lbl_58 == /\ pc = "Lbl_58"
          /\ IF returnVal # NullTokenSpec
                THEN /\ foundTokenSpecs' = JavaSeq(<<returnVal>>)
                     /\ returnVal' = FixOrigin(foundTokenSpecs')
                     /\ pc' = Head(stack).pc
                     /\ currentToken' = Head(stack).currentToken
                     /\ left' = Head(stack).left
                     /\ rt' = Head(stack).rt
                     /\ notDone' = Head(stack).notDone
                     /\ foundBangToken' = Head(stack).foundBangToken
                     /\ temp1' = Head(stack).temp1
                     /\ temp2' = Head(stack).temp2
                     /\ temp3' = Head(stack).temp3
                     /\ stack' = Tail(stack)
                ELSE /\ pc' = "Lbl_59"
                     /\ UNCHANGED << foundTokenSpecs, returnVal, stack, 
                                     currentToken, left, rt, notDone, 
                                     foundBangToken, temp1, temp2, temp3 >>
          /\ UNCHANGED << line, lastToken, notLastToken, curPos, tempVar1, 
                          tempVar2, tempVar3, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok >>

Lbl_59 == /\ pc = "Lbl_59"
          /\ IF currentToken.token = JavaSeq(<<"\\">>)
                THEN /\ /\ pos_f' = currentToken.rightPos
                        /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                                         pc        |->  "Lbl_60",
                                         token     |->  token,
                                         left_     |->  left_,
                                         rt_       |->  rt_,
                                         pos_f     |->  pos_f ] >>
                                     \o stack
                     /\ token' = << >>
                     /\ left_' = pos_f'
                     /\ rt_' = pos_f'
                     /\ pc' = "Lbl_5"
                ELSE /\ pc' = "Lbl_61"
                     /\ UNCHANGED << stack, pos_f, token, left_, rt_ >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_60 == /\ pc = "Lbl_60"
          /\ IF /\ returnVal # NullTokenSpec
                /\ \E ii \in DOMAIN TeXSymbols :
                          JavaSubseq(line,
                                     currentToken.leftPos,
                                     returnVal.rightPos) = TeXSymbols[ii]
                THEN /\ currentToken' = [currentToken EXCEPT !.rightPos = returnVal.rightPos,
                                                             !.token = JavaSubseq(line,
                                                                       currentToken.leftPos,
                                                                       returnVal.rightPos)]
                ELSE /\ TRUE
                     /\ UNCHANGED currentToken
          /\ pc' = "Lbl_61"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          stack, pos_, tokArray, i, tokIdx, pos_f, token, 
                          left_, rt_, pos_fi, pos_fin, delim_, ipos_, jdelim_, 
                          delimLen_, pos_find, pos, delim, ipos, jdelim, 
                          delimLen, leftTok, rightTok, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_61 == /\ pc = "Lbl_61"
          /\ foundTokenSpecs' = JavaSeq(<<currentToken>>)
          /\ curPos' = currentToken.leftPos
          /\ lastToken' = TRUE
          /\ pc' = "Lbl_62"
          /\ UNCHANGED << line, notLastToken, returnVal, tempVar1, tempVar2, 
                          tempVar3, stack, pos_, tokArray, i, tokIdx, pos_f, 
                          token, left_, rt_, pos_fi, pos_fin, delim_, ipos_, 
                          jdelim_, delimLen_, pos_find, pos, delim, ipos, 
                          jdelim, delimLen, leftTok, rightTok, currentToken, 
                          left, rt, notDone, foundBangToken, temp1, temp2, 
                          temp3 >>

Lbl_62 == /\ pc = "Lbl_62"
          /\ Assert(JavaLen(foundTokenSpecs) = 1, 
                    "Failure of assertion at line 618, column 3.")
          /\ curPos' = foundTokenSpecs[0].leftPos
          /\ notDone' = TRUE
          /\ pc' = "Lbl_63"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_63 == /\ pc = "Lbl_63"
          /\ IF notDone
                THEN /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                      pc        |->  "Lbl_64" ] >>
                                  \o stack
                     /\ pc' = "Lbl_29"
                     /\ UNCHANGED << returnVal, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
                ELSE /\ Assert(foundTokenSpecs # << >>, 
                               "Failure of assertion at line 660, column 3.")
                     /\ IF lastToken = TRUE
                           THEN /\ returnVal' = FixOrigin(foundTokenSpecs)
                                /\ pc' = Head(stack).pc
                                /\ currentToken' = Head(stack).currentToken
                                /\ left' = Head(stack).left
                                /\ rt' = Head(stack).rt
                                /\ notDone' = Head(stack).notDone
                                /\ foundBangToken' = Head(stack).foundBangToken
                                /\ temp1' = Head(stack).temp1
                                /\ temp2' = Head(stack).temp2
                                /\ temp3' = Head(stack).temp3
                                /\ stack' = Tail(stack)
                           ELSE /\ pc' = "Lbl_69"
                                /\ UNCHANGED << returnVal, stack, currentToken, 
                                                left, rt, notDone, 
                                                foundBangToken, temp1, temp2, 
                                                temp3 >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

Lbl_64 == /\ pc = "Lbl_64"
          /\ IF curPos <  0 \/ line[curPos-1] = ";"
                THEN /\ notDone' = FALSE
                     /\ pc' = "Lbl_63"
                     /\ UNCHANGED << curPos, stack >>
                ELSE /\ IF line[curPos-1] = "!" /\ (line[curPos-2] # "!")
                           THEN /\ curPos' = curPos - 1
                                /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                                 pc        |->  "Lbl_65" ] >>
                                             \o stack
                                /\ pc' = "Lbl_29"
                                /\ UNCHANGED notDone
                           ELSE /\ notDone' = FALSE
                                /\ pc' = "Lbl_63"
                                /\ UNCHANGED << curPos, stack >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_65 == /\ pc = "Lbl_65"
          /\ /\ pos_fi' = curPos
             /\ stack' = << [ procedure |->  "findMatchingLeftParen",
                              pc        |->  "Lbl_66",
                              pos_fi    |->  pos_fi ] >>
                          \o stack
          /\ pc' = "Lbl_7"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fin, delim_, ipos_, jdelim_, delimLen_, pos_find, 
                          pos, delim, ipos, jdelim, delimLen, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_66 == /\ pc = "Lbl_66"
          /\ curPos' = returnVal
          /\ IF curPos' < 0
                THEN /\ notDone' = FALSE
                     /\ pc' = "Lbl_63"
                     /\ UNCHANGED stack
                ELSE /\ stack' = << [ procedure |->  "skipLeftOverSpaces",
                                      pc        |->  "Lbl_67" ] >>
                                  \o stack
                     /\ pc' = "Lbl_29"
                     /\ UNCHANGED notDone
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_67 == /\ pc = "Lbl_67"
          /\ /\ pos_f' = curPos
             /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                              pc        |->  "Lbl_68",
                              token     |->  token,
                              left_     |->  left_,
                              rt_       |->  rt_,
                              pos_f     |->  pos_f ] >>
                          \o stack
          /\ token' = << >>
          /\ left_' = pos_f'
          /\ rt_' = pos_f'
          /\ pc' = "Lbl_5"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_68 == /\ pc = "Lbl_68"
          /\ currentToken' = returnVal
          /\ IF \/ currentToken' = NullTokenSpec
                \/ IsNumber(currentToken'.token)
                THEN /\ notDone' = FALSE
                     /\ UNCHANGED << foundTokenSpecs, curPos >>
                ELSE /\ curPos' = currentToken'.leftPos
                     /\ foundTokenSpecs' = [foundTokenSpecs EXCEPT ![0] = [token |-> JavaConcatenate(
                                                                                         JavaAppend(currentToken'.token, "!"),
                                                                                         foundTokenSpecs[0].token),
                                                                           leftPos |-> curPos',
                                                                           rightPos |-> foundTokenSpecs[0].rightPos]]
                     /\ UNCHANGED notDone
          /\ pc' = "Lbl_63"
          /\ UNCHANGED << line, lastToken, notLastToken, returnVal, tempVar1, 
                          tempVar2, tempVar3, stack, pos_, tokArray, i, tokIdx, 
                          pos_f, token, left_, rt_, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_69 == /\ pc = "Lbl_69"
          /\ curPos' = foundTokenSpecs[0].rightPos
          /\ foundBangToken' = FALSE
          /\ notDone' = TRUE
          /\ pc' = "Lbl_70"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, stack, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, temp1, 
                          temp2, temp3 >>

Lbl_70 == /\ pc = "Lbl_70"
          /\ IF notDone
                THEN /\ stack' = << [ procedure |->  "skipRightOverSpaces",
                                      pc        |->  "Lbl_71" ] >>
                                  \o stack
                     /\ pc' = "Lbl_30"
                     /\ UNCHANGED << returnVal, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
                ELSE /\ IF notLastToken /\ ~ foundBangToken
                           THEN /\ returnVal' = << >>
                                /\ pc' = Head(stack).pc
                                /\ currentToken' = Head(stack).currentToken
                                /\ left' = Head(stack).left
                                /\ rt' = Head(stack).rt
                                /\ notDone' = Head(stack).notDone
                                /\ foundBangToken' = Head(stack).foundBangToken
                                /\ temp1' = Head(stack).temp1
                                /\ temp2' = Head(stack).temp2
                                /\ temp3' = Head(stack).temp3
                                /\ stack' = Tail(stack)
                           ELSE /\ pc' = "Lbl_76"
                                /\ UNCHANGED << returnVal, stack, currentToken, 
                                                left, rt, notDone, 
                                                foundBangToken, temp1, temp2, 
                                                temp3 >>
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

Lbl_71 == /\ pc = "Lbl_71"
          /\ /\ pos_find' = curPos
             /\ stack' = << [ procedure |->  "findMatchingRightParen",
                              pc        |->  "Lbl_72",
                              pos_find  |->  pos_find ] >>
                          \o stack
          /\ pc' = "Lbl_17"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos, delim, ipos, jdelim, delimLen, leftTok, 
                          rightTok, currentToken, left, rt, notDone, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_72 == /\ pc = "Lbl_72"
          /\ curPos' = returnVal
          /\ IF curPos' < 0
                THEN /\ notDone' = FALSE
                     /\ pc' = "Lbl_70"
                     /\ UNCHANGED stack
                ELSE /\ stack' = << [ procedure |->  "skipRightOverSpaces",
                                      pc        |->  "Lbl_73" ] >>
                                  \o stack
                     /\ pc' = "Lbl_30"
                     /\ UNCHANGED notDone
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_73 == /\ pc = "Lbl_73"
          /\ IF line[curPos] # "!"  \/ line[curPos+1] = "!"
                THEN /\ notDone' = FALSE
                     /\ pc' = "Lbl_70"
                     /\ UNCHANGED << curPos, stack >>
                ELSE /\ curPos' = curPos + 1
                     /\ stack' = << [ procedure |->  "skipRightOverSpaces",
                                      pc        |->  "Lbl_74" ] >>
                                  \o stack
                     /\ pc' = "Lbl_30"
                     /\ UNCHANGED notDone
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok, currentToken, left, rt, 
                          foundBangToken, temp1, temp2, temp3 >>

Lbl_74 == /\ pc = "Lbl_74"
          /\ /\ pos_f' = curPos
             /\ stack' = << [ procedure |->  "findMaximalIdCharSeq",
                              pc        |->  "Lbl_75",
                              token     |->  token,
                              left_     |->  left_,
                              rt_       |->  rt_,
                              pos_f     |->  pos_f ] >>
                          \o stack
          /\ token' = << >>
          /\ left_' = pos_f'
          /\ rt_' = pos_f'
          /\ pc' = "Lbl_5"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar1, tempVar2, tempVar3, 
                          pos_, tokArray, i, tokIdx, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_75 == /\ pc = "Lbl_75"
          /\ currentToken' = returnVal
          /\ IF \/ currentToken' = NullTokenSpec
                \/ IsNumber(currentToken'.token)
                THEN /\ notDone' = FALSE
                     /\ UNCHANGED << foundTokenSpecs, curPos, foundBangToken >>
                ELSE /\ foundBangToken' = TRUE
                     /\ foundTokenSpecs' = JavaConcatenate(
                                             JavaSeq(
                                               << [token |->
                                                     JavaConcatenate(JavaAppend(foundTokenSpecs[0].token,
                                                                                 "!"),
                                                                     currentToken'.token),
                                                   leftPos |-> foundTokenSpecs[0].leftPos,
                                                   rightPos |-> currentToken'.rightPos]
                                                >> ) ,
                                               foundTokenSpecs)
                     /\ curPos' = currentToken'.rightPos
                     /\ UNCHANGED notDone
          /\ pc' = "Lbl_70"
          /\ UNCHANGED << line, lastToken, notLastToken, returnVal, tempVar1, 
                          tempVar2, tempVar3, stack, pos_, tokArray, i, tokIdx, 
                          pos_f, token, left_, rt_, pos_fi, pos_fin, delim_, 
                          ipos_, jdelim_, delimLen_, pos_find, pos, delim, 
                          ipos, jdelim, delimLen, leftTok, rightTok, left, rt, 
                          temp1, temp2, temp3 >>

Lbl_76 == /\ pc = "Lbl_76"
          /\ returnVal' = FixOrigin(foundTokenSpecs)
          /\ pc' = Head(stack).pc
          /\ currentToken' = Head(stack).currentToken
          /\ left' = Head(stack).left
          /\ rt' = Head(stack).rt
          /\ notDone' = Head(stack).notDone
          /\ foundBangToken' = Head(stack).foundBangToken
          /\ temp1' = Head(stack).temp1
          /\ temp2' = Head(stack).temp2
          /\ temp3' = Head(stack).temp3
          /\ stack' = Tail(stack)
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, tempVar1, tempVar2, tempVar3, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok >>

findTokenSpecs == Lbl_31 \/ Lbl_32 \/ Lbl_33 \/ Lbl_34 \/ Lbl_35 \/ Lbl_36
                     \/ Lbl_37 \/ Lbl_38 \/ Lbl_39 \/ Lbl_40 \/ Lbl_41 \/ Lbl_42
                     \/ Lbl_43 \/ Lbl_44 \/ Lbl_45 \/ Lbl_46 \/ Lbl_47 \/ Lbl_48
                     \/ Lbl_49 \/ Lbl_50 \/ Lbl_51 \/ Lbl_52 \/ Lbl_53 \/ Lbl_54
                     \/ Lbl_55 \/ Lbl_56 \/ Lbl_57 \/ Lbl_58 \/ Lbl_59 \/ Lbl_60
                     \/ Lbl_61 \/ Lbl_62 \/ Lbl_63 \/ Lbl_64 \/ Lbl_65 \/ Lbl_66
                     \/ Lbl_67 \/ Lbl_68 \/ Lbl_69 \/ Lbl_70 \/ Lbl_71 \/ Lbl_72
                     \/ Lbl_73 \/ Lbl_74 \/ Lbl_75 \/ Lbl_76

Lbl_77 == /\ pc = "Lbl_77"
          /\ curPos' = JavaLen(Padding)
          /\ tempVar1' = ( -1 :> "")
          /\ tempVar2' = JavaLen(Padding)
          /\ PrintT(line)
          /\ pc' = "Lbl_78"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          returnVal, tempVar3, stack, pos_, tokArray, i, 
                          tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Lbl_78 == /\ pc = "Lbl_78"
          /\ IF tempVar2 < JavaLen(lineInput) + JavaLen(Padding)
                THEN /\ PrintT(<<"curPos: ", tempVar2>>)
                     /\ curPos' = tempVar2
                     /\ foundTokenSpecs' = << >>
                     /\ lastToken' = FALSE
                     /\ notLastToken' = FALSE
                     /\ stack' = << [ procedure |->  "findTokenSpecs",
                                      pc        |->  "Lbl_79",
                                      currentToken |->  currentToken,
                                      left      |->  left,
                                      rt        |->  rt,
                                      notDone   |->  notDone,
                                      foundBangToken |->  foundBangToken,
                                      temp1     |->  temp1,
                                      temp2     |->  temp2,
                                      temp3     |->  temp3 ] >>
                                  \o stack
                     /\ currentToken' = defaultInitValue
                     /\ left' = defaultInitValue
                     /\ rt' = defaultInitValue
                     /\ notDone' = defaultInitValue
                     /\ foundBangToken' = defaultInitValue
                     /\ temp1' = defaultInitValue
                     /\ temp2' = defaultInitValue
                     /\ temp3' = defaultInitValue
                     /\ pc' = "Lbl_31"
                ELSE /\ PrintT("goodby world")
                     /\ pc' = "Done"
                     /\ UNCHANGED << foundTokenSpecs, lastToken, notLastToken, 
                                     curPos, stack, currentToken, left, rt, 
                                     notDone, foundBangToken, temp1, temp2, 
                                     temp3 >>
          /\ UNCHANGED << line, returnVal, tempVar1, tempVar2, tempVar3, pos_, 
                          tokArray, i, tokIdx, pos_f, token, left_, rt_, 
                          pos_fi, pos_fin, delim_, ipos_, jdelim_, delimLen_, 
                          pos_find, pos, delim, ipos, jdelim, delimLen, 
                          leftTok, rightTok >>

Lbl_79 == /\ pc = "Lbl_79"
          /\ IF returnVal = tempVar1
                THEN /\ PrintT("same")
                ELSE /\ PrintT(returnVal)
          /\ tempVar1' = returnVal
          /\ tempVar2' = tempVar2 + 1
          /\ pc' = "Lbl_78"
          /\ UNCHANGED << line, foundTokenSpecs, lastToken, notLastToken, 
                          curPos, returnVal, tempVar3, stack, pos_, tokArray, 
                          i, tokIdx, pos_f, token, left_, rt_, pos_fi, pos_fin, 
                          delim_, ipos_, jdelim_, delimLen_, pos_find, pos, 
                          delim, ipos, jdelim, delimLen, leftTok, rightTok, 
                          currentToken, left, rt, notDone, foundBangToken, 
                          temp1, temp2, temp3 >>

Next == findTokenIn \/ findMaximalIdCharSeq \/ findMatchingLeftParen
           \/ findMatchingLeftInner \/ findMatchingRightParen
           \/ findMatchingRightInner \/ checkIfStepName \/ skipLeftOverSpaces
           \/ skipRightOverSpaces \/ findTokenSpecs \/ Lbl_77 \/ Lbl_78 \/ Lbl_79
           \/ (* Disjunct to prevent deadlock on termination *)
              (pc = "Done" /\ UNCHANGED vars)

Spec == Init /\ [][Next]_vars

Termination == <>(pc = "Done")

\* END TRANSLATION
=============================================================================
\* Modification History
\* Last modified Fri Sep 24 02:20:56 PDT 2010 by lamport
\* Created Mon Sep 20 06:42:12 PDT 2010 by lamport
****************************************************************************)


*************************************************************************/


<|start_filename|>tlatools/org.lamport.tlatools/test/tlc2/TestDriver.java<|end_filename|>
package tlc2;

import util.SimpleFilenameToStream;
import util.ToolIO;

public class TestDriver
{
    private static final int COUNT = 3;

    private static final long TIMEOUT = 1000 * 5;

    private static int reported;
    private static TLCThread tlcThread;

    // runs TLC twice, to control the side effects
    public static void main(String[] args)
    {
        for (int i = 0; i < COUNT; i++)
        {
            System.out.println("Run " + (i + 1) + " ----------------------------------------------");
            callTLC(args);
            System.out.println("---------------------------------------- complete.\n");
        }
        System.exit(0);
    }

    private static void callTLC(String[] args)
    {
        report("entering callTLC()");
        ToolIO.reset();
        ToolIO.setMode(ToolIO.TOOL);
        ToolIO.setUserDir(args[5]);
        
        reported = 0;
        TLC tlc = new TLC();
        report("tlc created " + tlc.toString());
        // handle parameters
        if (tlc.handleParameters(args))
        {
            tlc.setResolver(new SimpleFilenameToStream());

            // call the actual processing method
            tlcThread = new TLCThread(tlc);
            tlcThread.setName("TLC Thread");

            report("tlcThread created " + tlcThread.getId());
            tlcThread.start();
            report("tlcThread " + tlcThread.getId() + "started ");
            
            while (checkAndSleep())
            {
                report("begin report");
                reportProgress();
                report("finished report");
            }
            report("after while");
            
            reportProgress();
        }
        report("leaving callTLC()");
    }

    // decrement the number and sleep
    private static boolean checkAndSleep()
    {
        report("entering checkAndSleep()");
        try
        {
            // go sleep
            report("go to sleep " + System.currentTimeMillis());
            Thread.sleep(TIMEOUT);
            report("wake up " + System.currentTimeMillis());

        } catch (InterruptedException e)
        {
            // nothing to do
            e.printStackTrace();
        }
        // return true if the tlc is still calculating

        boolean isRunning = tlcThread.isRunning();
        report("leaving checkAndSleep() with " + isRunning);
        return isRunning;
    }

    private static void reportProgress()
    {
        // report progress
        report("entering reportProgress()");
        String[] messages = ToolIO.getAllMessages();
        for (; reported < messages.length; reported++)
        {
            System.out.println(messages[reported]);
        }
        report("leaving reportProgress()");
    }

    public static void report(String message)
    {
        // System.out.println(Thread.currentThread().getId() + "\t" + message);
    }

    /**
     * Thread to run TLC in
     */
    static class TLCThread extends Thread
    {
        private boolean isRunning;
        private final TLC tlc;

        public TLCThread(TLC tlc)
        {
            this.tlc = tlc;
            synchronized (this)
            {
                this.isRunning = false;
            }
        }

        public void run()
        {
            synchronized (this)
            {
                System.out.println("TLC Thread: ------------ {START}");
                isRunning = true;
            }

            // start TLC
            this.tlc.process();

            synchronized (this)
            {
                System.out.println("TLC Thread: ------------ {FINISHED}");
                isRunning = false;
            }
        }

        public synchronized void setIsRunning(boolean value)
        {
            isRunning = value;
        }

        /**
         * 
         * @return
         */
        public synchronized boolean isRunning()
        {
            return isRunning;
        }
    }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/Vect.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
// Last modified on Mon 30 Apr 2007 at 13:26:42 PST by lamport
//      modified on Sun Jul 29 23:32:03 PDT 2001 by yuanyu
package tlc2.util;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Vector;

/**
 * TODO it's unclear why we've written our own list implementation; we should consider using existing framework code for this;
 * 		we've also written our own "Vector" class in SANY...
 */
@SuppressWarnings("unchecked")
public class Vect<E> implements Cloneable, Serializable {
	private static final long serialVersionUID = 1L;

	
  private E[] elementData;
  private int elementCount;
         
  final class Enumerator implements Enumeration<E> {
    int index = 0;

    public final boolean hasMoreElements () {
      return (this.index < elementCount);
    }

    public final E nextElement() {
      return (E) elementData[index++];
    }
  }

  public Vect() { this(10); }

  public Vect(int initialCapacity) {
    this.elementCount = 0;
    if (initialCapacity == 0) {
      this.elementData = (E[]) new Object[0];
    }
    else {
      this.elementData = (E[]) new Object[initialCapacity];
    }
  }

  public Vect(Vector<E> v) {
    this(v.size());
    int sz = v.size();    
    for (int i = 0; i < sz; i++) {
      this.addElement(v.elementAt(i));
    }
  }

  public final void addElement(E obj) {
    if (this.elementCount == this.elementData.length) {
      this.ensureCapacity(this.elementCount+1);
    }
    this.elementData[this.elementCount++] = obj;
  }

  public final Vect<E> concat(Vect<E> elems) {
    Vect<E> v = new Vect<>();
    for (int i = 0; i < this.elementCount; i++) {
      v.addElement(this.elementData[i]);
    }
    for (int i = 0; i < elems.size(); i++) {
      v.addElement(elems.elementAt(i));
    }
    return v;
  }

  public int capacity() { return this.elementData.length; }

  public Object clone() {
    Vect<E> v = new Vect<>(this.elementData.length);
    System.arraycopy(this.elementData, 0, v.elementData, 0, this.elementCount);
    v.elementCount = this.elementCount;
    return v;
  }

  public final boolean contains(Object elem) {
    return (this.indexOf(elem) != -1);
  }

  public final void copyInto(Object anArray[]) {
    System.arraycopy(this.elementData, 0, anArray, 0, this.elementCount);
  }

  public final E elementAt(int index) {
    return this.elementData[index];
  }

  @SuppressWarnings("rawtypes")
  public Enumeration<E> elements() { return new Vect.Enumerator(); }

  public final void ensureCapacity(int minCapacity) { 
    if (this.elementData.length < minCapacity) {
      int newCapacity = elementData.length + elementData.length;
      if (newCapacity < minCapacity) {
	newCapacity = minCapacity;
      }
      Object oldBuffer[] = elementData;
      elementData = (E[]) new Object[newCapacity];
      System.arraycopy( oldBuffer, 0, elementData, 0, elementCount);
    }
  }

  public final Object firstElement() {
    return this.elementData[0];
  }

  public final int indexOf(Object elem) { return this.indexOf(elem, 0); }

  public final int indexOf(Object elem, int index) {
    for (int pos = index; pos < elementCount; pos++) {
      if (elem.equals(elementData[pos])) return pos;
    }
    return -1;
  }

  public final void insertElementAt(E obj, int index) {
    if (elementCount == elementData.length)
      ensureCapacity(elementCount+1);

    if ((index > elementCount) || (index < 0)) {
      throw new ArrayIndexOutOfBoundsException();
    }
    else if (index < elementCount) {
      System.arraycopy(elementData, index, elementData, index+1, elementCount-index);
    }

    elementData[index] = obj;
    elementCount++;
  }

  public final boolean isEmpty() { return (this.elementCount == 0); }

  public final Object lastElement() {
    return this.elementData[this.elementCount-1];
  }

  public final void removeLastElement() {
    if (this.elementCount == 0) {
      throw new NoSuchElementException();
    }
    this.elementCount--;
    this.elementData[this.elementCount] = null;
  }
  
  public final void setElementAt(E obj, int index)	{
    this.elementData[index] = obj;
  }

  public final void removeElementAt(int index) {
    for (int i = index+1; i < this.elementCount; i++) {
      this.elementData[i-1] = this.elementData[i];
    }
    this.elementCount--;
    this.elementData[this.elementCount] = null;
  }

  /* Remove all elements except the first cnt elements.  */
  public final void removeAll(int cnt) {
    this.elementCount = cnt;
  }
  
  public final Object pop() {
    Object elem = this.lastElement();
    this.removeLastElement();
    return elem;
  }

  public final void push(E elem) {
    this.addElement(elem);
  }
  
  public final int size() { return this.elementCount; }

  public final int hashCode() {
    int code = 0;
    for (int i = 0; i < this.elementCount; i++) {
      code ^= this.elementData[i].hashCode();
    }
    return code;
  }

  public final boolean equals(Object obj) {
    if (!(obj instanceof Vect)) return false;
    Vect<E> v = (Vect<E>)obj;
    if (v.size() != this.elementCount) return false;
    for (int i = 0; i < this.elementCount; i++) {
      if (!this.elementData[i].equals(v.elementAt(i))) return false;
    }
    return true;
  }
  
  public String toString() {  
    StringBuffer buf = new StringBuffer("{");
    if (this.size() != 0) {
      buf.append(this.elementAt(0).toString());
    }
    for (int i = 1; i < this.size(); i++) {
      buf.append(",");
      buf.append(this.elementAt(i).toString());
    }
    buf.append("}");
    return buf.toString();
  }

}


<|start_filename|>tlatools/org.lamport.tlatools/src/tlc2/util/BigSet.java<|end_filename|>
// Copyright (c) 2003 Compaq Corporation.  All rights reserved.
// Portions Copyright (c) 2003 Microsoft Corporation.  All rights reserved.
package tlc2.util;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Enumeration;

import util.FileUtil;
import util.Set;

/**
 * @deprecated currently not used
 * @version $Id$
 */
public class BigSet implements Cloneable {
  private static int MaxSize = 10000;
  // four rehashings give ~(>) 13440 els., and .75*13440 ~ 10000
  private static int InitialSize = 840; 
  private boolean USEBUFFERS = true;
  private boolean USEGZIP = false; // note that gzip uses buffering.
  private int BUFFERSIZE = 1024;
  
  private int maxSize;      // max size of set before it gets written to disk
  private int initialSize;  // size of set when new one is built
  private String file;      // prefix of file to which it gets written
  private int filePtr;      // suffix of file to which it gets written
  public Set els;           // the actual elements

  // Constructors
  /**
   * @deprecated currently not used
   */
  public BigSet(String file) {
    this(MaxSize, InitialSize, file); 
  }

  /**
   * @deprecated currently not used
   */
  public BigSet(int maxSize, String file) {
    this(maxSize, InitialSize, file);
  }

  /**
   * @deprecated currently not used
   */
  public BigSet(int maxSize, int initialSize, String file) {
    this.maxSize = maxSize;
    this.initialSize = initialSize;
    this.file = file;
    this.filePtr = 0;
    this.els = new Set(initialSize);

    // SZ Feb 24, 2009: useless code?
    /*
    try {
      OutputStream out0 = new FileOutputStream(file + "0");
      OutputStream out1 = new FileOutputStream(file + "1");
      out0.close(); 
      out1.close();
    }
    catch (IOException e) {
    }*/
    try
    {
        new File(file + "0").createNewFile();
        new File(file + "1").createNewFile();
    } catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
  }

  public int size() { return this.els.size(); }
  
  /* writes out the set to disk, as elements* & closes file. */
  public void write() throws IOException {
    Enumeration e = this.els.elements();
    OutputStream out = FileUtil.newBZFileOutputStream(this.file + this.filePtr, USEGZIP,
						      USEBUFFERS, BUFFERSIZE, true);
    int size = this.size();
    BigInt[] bA = new BigInt[size];

    for (int i = 0; i < size(); i++) {
      bA[i] = (BigInt)e.nextElement();
    }

    Arrays.sort(bA, 0, size-1);
    
    ByteUtils.writeInt(out, size);
    for (int i = 0; i < size(); i++) {
      // sT.write(out, bA[i]);
    }
    out.close();
    
    // filePtr goes from 0 to 1 & back.
    this.filePtr = (this.filePtr == 0) ? 1 : 0;
  }
 
  /* clears this set and all it's files */
  public void clear() throws IOException {
    this.delete();
    this.els = new Set();
  }

  /* deletes the files associated with this set.  */
  public void delete() throws IOException {
    File f0, f1;
    f0 = new File(this.file + "0");
    f1 = new File(this.file + "1");
    
    f0.delete();
    f1.delete();
    
    this.filePtr = 0;
  }

  public void put(Object key) throws IOException {
    els.put(key);
    if (this.size() >= this.maxSize) {
      write();
      els = new Set (initialSize);
    }
  }
  
  public boolean contains(Object key) {
    return els.contains(key);
  }
  
}
