/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.search.util.uninformed;

import com.thesett.aima.search.Traversable;
import com.thesett.aima.search.spi.QueueSearchAlgorithm;

/**
 * Implements a post-fix ordered search. This is done by passing a FIFO stack to the {@link QueueSearchAlgorithm}
 * implementation in combination with the 'peek at head' flag. The use of the peek at head flag ensures that successor
 * nodes are examined before parent nodes, resulting in a post-fix ordering of the search.
 *
 *
This type of search is not usefull on unbounded state spaces, because the leaf nodes will never be reached. It is
 * possible for it to be usefull on an unbounded state space when used in combination with a bound. The effect of this
 * type of search, is to reach out to the edge of the available state space and then to work back in to the starting
 * point.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Do a post-fix ordered search.
 *

 *
 * @author Rupert Smith
 */
public class PostFixSearch<O, T extends Traversable<O>> extends DepthFirstSearch<O, T>
{
    /** Creates a new postfix search. */
    public PostFixSearch()
    {
        super();
    }

    /**
     * Allows different queue search algorithms to replace the default one. This overidden method ensures that the peek
     * at head flag is always set on the search algorithm and that it expands it successor nodes in reverse, as for
     * depth first searches.
     *
     * @param algorithm The search algorithm to use.
     */
    protected void setQueueSearchAlgorithm(QueueSearchAlgorithm<O, T> algorithm)
    {
        algorithm.setPeekAtHead(true);
        algorithm.setReverseEnqueueOrder(true);
        super.setQueueSearchAlgorithm(algorithm);
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.search.impl;

import java.util.Collection;

import com.thesett.aima.search.SearchNode;
import com.thesett.aima.search.SearchNotExhaustiveException;
import com.thesett.aima.search.Traversable;
import com.thesett.aima.search.spi.QueueSearchState;

/**
 * Implements an iterative-bound search from any queue based search method. This progressively re-runs the search at
 * ever increasing bounds until a solution is found. It extends {@link BoundedAlgorithm} which implements the
 * {@link com.thesett.aima.search.spi.BoundProperty} interface to provide a depth bound by default. This algorithm
 * therefore defaults to being an iterative-deepening algorithm, if a different bound property extractor is not
 * substituted.
 *
 *
The algorithm can either increase the bound by a fixed amount, epsilon, at each iteration or can increase the
 * bound to the next smallest bound property value that was seen beyond the bound of the previous iteration on search
 * nodes just over the fringe of the search bound. The latter case only produces good search algorithms where the bound
 * property can only take a small number of values. In general if search nodes have real valued heuristics that are
 * mostly different for each node then this strategy will result in N^2 nodes being examined. Use the constructor that
 * accepts a value for epsilon to use the fixed increase strategy, use the other constructor to use the next minimal
 * bound beyond the fringe strategy.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Transform any {@link BaseQueueSearch} into an iterative deepening search.
 *      {@link BaseQueueSearch}
 *

 *
 * @author Rupert Smith
 */
public class IterativeBoundAlgorithm<O, T extends Traversable<O>> extends BoundedAlgorithm<O, T>
{
    /** Holds the bound to start at. */
    protected float startBound;

    /** Holds the amount to increase bound by at every iteration. */
    protected float epsilon;

    /** Indicates whether the epsilon increase strategy should be used or not. */
    protected boolean useEpsilon;

    /**
     * Creates a new IterativeBoundAlgorithm object.
     *
     * @param startBound The starting value of the maximum bound value for the first iteration.
     */
    public IterativeBoundAlgorithm(float startBound)
    {
        // Instantiate the super class with a bound of 0.0. This will be overriden with the correct iterative
        // bounds in the search algorithm anyway.
        super(0.0f);

        // Keep the start bound and increment.
        this.startBound = startBound;

        // Epsilon is not set so use the next minimal bund value beyond the fringe.
        useEpsilon = false;
    }

    /**
     * Creates a new IterativeBoundAlgorithm object.
     *
     * @param startBound The starting value of the maximum bound value for the first iteration.
     * @param epsilon    The amount to increase the maximum bound by on each sarch iteration.
     */
    public IterativeBoundAlgorithm(float startBound, float epsilon)
    {
        // Instantiate the super class with a bound of 0.0. This will be overriden with the correct iterative
        // bounds in the search algorithm anyway.
        super(0.0f);

        // Keep the start bound and increment.
        this.startBound = startBound;
        this.epsilon = epsilon;

        // Epsilon is set so used fixed increments.
        useEpsilon = true;
    }

    /**
     * Search iteratively on increasing maximum bound limits until the search space is exhausted or a goal state is
     * found.
     *
     * @param  initSearch  The algorithm to turn the start states into the intial set of search nodes, of the correct
     *                     type to begin the search with.
     * @param  startStates The set of start states to begin the search with.
     * @param  maxSteps    The maximum number of steps to search for before giving up. If this is 0 or less then no
     *                     maximum number is enforced.
     * @param  searchSteps The number of steps taken so far. This may be greater than 0 if this search is run
     *                     iteratively and previous iterations of it have already been run.
     *
     * @return The first {@link SearchNode} corresponding to a goal state that is found or null if none can be found
     *         after exhaustive searching.
     *
     * @throws SearchNotExhaustiveException SearchNotExhaustiveException If the search terminates prematurely because
     *                                      the maximum number of steps is reached.
     */
    public SearchNode search(QueueSearchState<O, T> initSearch, Collection<T> startStates, int maxSteps,
        int searchSteps) throws SearchNotExhaustiveException
    {
        // Iteratively increase the bound until a search succeeds.
        for (float bound = startBound;;)
        {
            // Set up the maximum bound for this iteration.
            maxBound = bound;

            // Use a try block as the depth bounded search will throw a MaxBoundException if it fails but there
            // are successors states known to exist beyond the current max depth fringe.
            try
            {
                // Get the number of search steps taken so far and pass this into the underlying depth bounded search
                // so that the step count limit carries over between successive iterations.
                int numStepsSoFar = initSearch.getStepsTaken();

                // Call the super class search method to perform a depth bounded search on this maximum bound starting
                // from the initial search state.
                initSearch.resetEnqueuedOnceFlag();

                SearchNode node = super.search(initSearch, startStates, maxSteps, numStepsSoFar);

                // Check if the current depth found a goal node
                if (node != null)
                {
                    return node;
                }

                // The depth bounded search returned null, so it has exhausted the search space. Return with null.
                else
                {
                    return null;
                }
            }

            // The depth bounded search failed but it knows that there are more successor states at deeper levels.
            catch (MaxBoundException e)
            {
                // Do nothing, no node found at this depth so continue at the next depth level
                e = null;
            }

            // Check if the bound should be increased by epsilon or to the next smallest bound property value
            // beyond the fringe and update the bound for the next iteration.
            if (useEpsilon)
            {
                bound = bound + epsilon;
            }
            else
            {
                bound = getMinBeyondBound();
            }
        }
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.logic.fol.wam.debugger.controller;

import com.thesett.aima.logic.fol.wam.debugger.monitor.MemoryLayoutMonitor;
import com.thesett.aima.logic.fol.wam.debugger.text.EnhancedTextGrid;
import com.thesett.aima.logic.fol.wam.debugger.text.EnhancedTextTable;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.CellBackgroundColorDelta;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.ColorScheme;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.ComponentFactory;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.ControllerLifecycle;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.Fader;
import com.thesett.aima.logic.fol.wam.debugger.uifactory.MainWindow;
import com.thesett.text.api.TextTableEvent;
import com.thesett.text.api.TextTableListener;

/**
 * MemoryLayoutMonitorController manages the memory layout monitor component. It creates this visual component and the
 * model behind it and wires them together. It is responsible for handling all user interaction with this component.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Build the memory layout monitor visual component.

 *

 *
 * @author Rupert Smith
 */
public class MemoryLayoutMonitorController implements ControllerLifecycle
{
    /** Holds the component factory used to build the application components. */
    private final ComponentFactory componentFactory;

    /** Holds the main application window frame. */
    private final MainWindow mainWindow;

    /** The text grid model behind the UI component. */
    private EnhancedTextGrid grid;

    /** A text table model that maps down onto the text grid. */
    private EnhancedTextTable table;

    /** Holds the memory layout monitor that translates value changes into changes to the table. */
    private MemoryLayoutMonitor monitor;

    /** A color fader used to highlight layout value changes. */
    private final Fader fader;

    /**
     * Builds the UI controller for the register monitor.
     *
     * @param componentFactory The UI component factory.
     * @param mainWindow       The main window to create the UI component within.
     */
    public MemoryLayoutMonitorController(ComponentFactory componentFactory, MainWindow mainWindow)
    {
        this.componentFactory = componentFactory;
        this.mainWindow = mainWindow;

        ColorScheme colorScheme = componentFactory.getColorScheme();
        fader =
            componentFactory.getColorFactory().createFader(colorScheme.getLowlightBackground(),
                colorScheme.getBackground());
    }

    /**
     * {@inheritDoc}
     *
     *
Creates the register monitor component and hooks it up to the register set.
     */
    public void open()
    {
        // Build a text grid panel in the left position.
        grid = componentFactory.createTextGrid();
        grid.insertVerticalSeparator(9, 10);
        grid.insertVerticalSeparator(17, 10);
        grid.insertVerticalSeparator(26, 10);

        mainWindow.showConsole(componentFactory.createTextGridPanel(grid));

        // Build a table model on the text grid, and construct a register monitor on the table.
        table = (EnhancedTextTable) grid.createTable(0, 0, 20, 20);
        monitor = new MemoryLayoutMonitor(table);

        // Attach a listener for updates to the register table.
        table.addTextTableListener(new TableUpdateHandler());
    }

    /** {@inheritDoc} */
    public void close()
    {
    }

    /**
     * Provides access to the underlying layout register set monitor.
     *
     * @return The layout register set monitor.
     */
    public MemoryLayoutMonitor getLayoutMonitor()
    {
        return monitor;
    }

    /**
     * Triggers color fades on table row updates.
     */
    private class TableUpdateHandler implements TextTableListener
    {
        /** {@inheritDoc} */
        public void changedUpdate(TextTableEvent event)
        {
            // Ignore attribute only updates, as these could be events initiated by the fader itself, only trigger
            // a fade on content changes.
            if (!event.isAttributeChangeOnly())
            {
                int col = event.getColumnChanged();
                int row = event.getRowChanged();

                // Only trigger a fade if the row is valid and not the currently selected one.
                if ((row >= 0) && (col >= 0))
                {
                    fader.doFade(new CellBackgroundColorDelta(col, row, table),
                        Integer.toString(row) + "/" + Integer.toString(col));
                }
            }
        }
    }
}


/*
 * Licensed 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.hobsoft.microbrowser.tck;

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

import org.hobsoft.microbrowser.Link;
import org.hobsoft.microbrowser.MicrodataDocument;
import org.junit.Test;

import com.squareup.okhttp.mockwebserver.MockResponse;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hobsoft.microbrowser.tck.support.MicrobrowserMatchers.item;
import static org.hobsoft.microbrowser.tck.support.mockwebserver.MockWebServerUtils.takeRequest;
import static org.hobsoft.microbrowser.tck.support.mockwebserver.MockWebServerUtils.url;
import static org.junit.Assert.assertThat;

/**
 * TCK for {@code Link}.
 */
public abstract class LinkTck extends AbstractMicrobrowserTest
{
	// ----------------------------------------------------------------------------------------------------------------
	// getRel tests
	// ----------------------------------------------------------------------------------------------------------------

	@Test
	public void getRelWhenAnchorReturnsRelationship()
	{
		server().enqueue(new MockResponse().setBody(""
			+ ""
			+ ""));

		String actual = newBrowser().get(url(server()))
			.getLink("x")
			.getRel();

		assertThat("link rel", actual, is("x"));
	}

	@Test
	public void getRelWhenLinkReturnsRelationship()
	{
		server().enqueue(new MockResponse().setBody(""
			+ "<link rel='x'/>"
			+ ""));

		String actual = newBrowser().get(url(server()))
			.getLink("x")
			.getRel();

		assertThat("link rel", actual, is("x"));
	}

	// ----------------------------------------------------------------------------------------------------------------
	// getHref tests
	// ----------------------------------------------------------------------------------------------------------------

	@Test
	public void getHrefWhenAnchorAndAbsoluteHrefReturnsUrl() throws MalformedURLException
	{
		server().enqueue(new MockResponse().setBody(""
			+ ""
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("r")
			.getHref();

		assertThat("link href", actual, is(new URL("http://x/")));
	}

	@Test
	public void getHrefWhenAnchorAndRelativeHrefReturnsAbsoluteUrl()
	{
		server().enqueue(new MockResponse().setBody(""
			+ ""
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("r")
			.getHref();

		assertThat("link href", actual, is(server().url("/x").url()));
	}

	@Test
	public void getHrefWhenAnchorAndNoHrefReturnsNull()
	{
		server().enqueue(new MockResponse().setBody(""
			+ ""
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("r")
			.getHref();

		assertThat("link href", actual, is(nullValue()));
	}

	@Test
	public void getHrefWhenLinkAndAbsoluteHrefReturnsUrl() throws MalformedURLException
	{
		server().enqueue(new MockResponse().setBody(""
			+ "<link rel='x' href='http://x/'/>"
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("x")
			.getHref();

		assertThat("link href", actual, is(new URL("http://x/")));
	}

	@Test
	public void getHrefWhenLinkAndRelativeHrefReturnsAbsoluteUrl()
	{
		server().enqueue(new MockResponse().setBody(""
			+ "<link rel='x' href='x'/>"
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("x")
			.getHref();

		assertThat("link href", actual, is(server().url("/x").url()));
	}

	@Test
	public void getHrefWhenLinkAndNoHrefReturnsNull()
	{
		server().enqueue(new MockResponse().setBody(""
			+ "<link rel='r'/>"
			+ ""));

		URL actual = newBrowser().get(url(server()))
			.getLink("r")
			.getHref();

		assertThat("link href", actual, is(nullValue()));
	}

	// ----------------------------------------------------------------------------------------------------------------
	// follow tests
	// ----------------------------------------------------------------------------------------------------------------

	@Test
	public void followWhenAnchorSubmitsRequest() throws InterruptedException
	{
		server().enqueue(new MockResponse().setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse());

		newBrowser().get(url(server()))
			.getLink("r")
			.follow();

		server().takeRequest();
		assertThat("request", takeRequest(server()).getPath(), is("/x"));
	}

	@Test
	public void followWhenAnchorSetsCookie()
	{
		server().enqueue(new MockResponse().setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse().addHeader("Set-Cookie", "x=y"));

		String actual = newBrowser().get(url(server()))
			.getLink("r")
			.follow()
			.getCookie("x");

		assertThat("cookie", actual, is("y"));
	}

	@Test
	public void followWhenAnchorSendsCookie() throws InterruptedException
	{
		server().enqueue(new MockResponse().addHeader("Set-Cookie", "x=y").setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse());

		newBrowser().get(url(server()))
			.getLink("r")
			.follow();

		server().takeRequest();
		assertThat("cookie", takeRequest(server()).getHeader("Cookie"), is("x=y"));
	}

	@Test
	public void followWhenAnchorSendsPreviousCookie() throws InterruptedException
	{
		server().enqueue(new MockResponse().addHeader("Set-Cookie", "x=y").setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse().setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse());

		newBrowser().get(url(server()))
			.getLink("r1")
			.follow()
			.getLink("r2")
			.follow();

		server().takeRequest();
		assertThat("cookie", takeRequest(server()).getHeader("Cookie"), is("x=y"));
	}

	@Test
	public void followWhenAnchorReturnsResponse() throws MalformedURLException
	{
		server().enqueue(new MockResponse().setBody(""
			+ "a"
			+ ""));
		server().enqueue(new MockResponse().setBody(""
			+ "
"
			+ ""));

		MicrodataDocument actual = newBrowser().get(url(server()))
			.getLink("r")
			.follow();

		assertThat("response", actual.getItem("http://i"), is(item("http://x")));
	}

	@Test
	public void followWhenInvalidUrlThrowsException()
	{
		server().enqueue(new MockResponse().setBody(""
			+ "a"
			+ ""));

		Link link = newBrowser().get(url(server()))
			.getLink("r");

		thrown().expect(IllegalArgumentException.class);
		thrown().expectMessage("Invalid URL: x:/a");

		link.follow();
	}

	// ----------------------------------------------------------------------------------------------------------------
	// unwrap tests
	// ----------------------------------------------------------------------------------------------------------------

	@Test
	public void unwrapWithUnknownTypeThrowsException()
	{
		server().enqueue(new MockResponse().setBody(""
			+ ""
			+ ""));

		Link link = newBrowser().get(url(server()))
			.getLink("x");

		thrown().expect(IllegalArgumentException.class);
		thrown().expectMessage("Cannot unwrap to: class java.lang.Void");

		link.unwrap(Void.class);
	}
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.search.impl;

import java.util.Collection;
import java.util.Queue;

import com.thesett.aima.search.SearchNode;
import com.thesett.aima.search.SearchNotExhaustiveException;
import com.thesett.aima.search.Traversable;
import com.thesett.aima.search.spi.QueueSearchState;
import com.thesett.common.util.logic.UnaryPredicate;

/**
 * Implements the simplest queue based search algorithm that checks the next element on the queue until the search space
 * is exhausted, or a maximum number of steps is reached.
 *
 *
By default the next element is removed from the queue and has its successors expanded on the queue (provided they
 * have not already been) and is then goal checked. The peek-at-head flag may be set to alter this behaviour (through
 * the {@link #setPeekAtHead} method), so that the next element on the queue has its successors expanded onto the queue
 * without being removed itself. The head element of the queue is then removed and goal checked. This head element may
 * be different to the next element that had its successors expanded where an ordered queue is used and the ordering is
 * such that some of the successors were placed before their parent node. This is usefull for producing searches that
 * examine child nodes before parent nodes, for example a post-fix search.
 *
 *
There is a reverse successors option that may be set (through the {@link #setReverseEnqueueOrder} method), which
 * causes the successors to be expanded onto the queue in reverse order to which they are presented. This is usefull for
 * stack based searches, such as depth first search, which by the nature of the stack reverse the order of elements.
 * Setting this flag will do a double reverse of the element order and restore an intuituve left-to-right search order
 * over elements. Generally speaking, set this flag whenever using a LIFO based queue.
 *
 *
A maximum number of node expansions may be set. If the search does not find a goal within this maximum number
 * then a {@link SearchNotExhaustiveException} is raised.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Search based on the queue ordering until a goal node is found or the maximum allowed number of steps is
 *          reached.
 *

 *
 * @author Rupert Smith
 */
public class MaxStepsAlgorithm<O, T extends Traversable<O>> extends BaseQueueSearchAlgorithm<O, T>
{
    /**
     * Search until a goal state is found or the maximum allowed number of steps is reached.
     *
     * @param  initSearch  The algorithm to turn the start states into the intial set of search nodes, of the correct
     *                     type to begin the search with.
     * @param  startStates The set of start states to begin the search with.
     * @param  maxSteps    The maximum number of steps to search for before giving up. If this is 0 or less then no
     *                     maximum number is enforced.
     * @param  searchSteps The number of steps taken so far. This may be greater than 0 if this search is run
     *                     iteratively and previous iterations of it have already been run.
     *
     * @return The first {@link SearchNode} corresponding to a goal state that is found or null if none can be found
     *         after exhaustive searching.
     *
     * @throws SearchNotExhaustiveException SearchNotExhaustiveException If the search terminates prematurely because
     *                                      the maximum number of steps is reached.
     */
    public SearchNode search(QueueSearchState<O, T> initSearch, Collection<T> startStates, int maxSteps,
        int searchSteps) throws SearchNotExhaustiveException
    {
        // Initialize the queue with the start states set up in search nodes if this has not already been done.
        // This will only be done on the first call to this method, as enqueueStartStates sets a flag when it is
        // done. Subsequent searches continue from where the previous search left off. Have to call reset on
        // the search method to really start the search again from the start states.
        Queue<SearchNode<O, T>> queue = initSearch.enqueueStartStates(startStates);

        // Get the goal predicate configured as part of the enqueueing start states process.
        UnaryPredicate<T> goalPredicate = initSearch.getGoalPredicate();

        // Keep running until the queue becomes empty or a goal state is found.
        while (!queue.isEmpty())
        {
            // Extract or peek at the head element from the queue.
            SearchNode<O, T> headNode = peekAtHead ? queue.peek() : queue.remove();

            // Expand the successors into the queue whether the current node is a goal state or not.
            // This prepares the queue for subsequent searches, ensuring that goal states do not block
            // subsequent goal states that exist beyond them.
            if (!headNode.isExpanded())
            {
                headNode.expandSuccessors(queue, reverseEnqueue);
            }

            // Get the node to be goal checked, either the head node or the new top of queue, depending on the
            // peek at head flag. Again this is only a peek, the node is only to be removed if it is to be
            // goal checked.
            SearchNode<O, T> currentNode = peekAtHead ? queue.peek() : headNode;

            // Only goal check leaves, or nodes already expanded. (The expanded flag will be set on leaves anyway).
            if (currentNode.isExpanded())
            {
                // If required, remove the node to goal check from the queue.
                currentNode = peekAtHead ? queue.remove() : headNode;

                // Check if the current node is a goal state.
                if (goalPredicate.evaluate(currentNode.getState()))
                {
                    return currentNode;
                }
            }

            // Check if there is a maximum number of steps limit and increase the step count and check the limit if so.
            if (maxSteps > 0)
            {
                searchSteps++;

                // Update the search state with the number of steps taken so far.
                initSearch.setStepsTaken(searchSteps);

                if (searchSteps >= maxSteps)
                {
                    // The maximum number of steps has been reached, however if the queue is now empty then the search
                    // has just completed within the maximum. Check if the queue is empty and return null if so.
                    if (queue.isEmpty())
                    {
                        return null;
                    }

                    // Quit without a solution as the max number of steps has been reached but because there are still
                    // more states in the queue then raise a search failure exception.
                    else
                    {
                        throw new SearchNotExhaustiveException("Maximum number of steps reached.", null);
                    }
                }
            }
        }

        // No goal state was found so return null
        return null;
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.logic.fol.wam.machine;

import com.thesett.aima.logic.fol.Clause;
import com.thesett.aima.logic.fol.LogicCompiler;
import com.thesett.aima.logic.fol.Parser;
import com.thesett.aima.logic.fol.Resolver;
import com.thesett.aima.logic.fol.Sentence;
import com.thesett.aima.logic.fol.VariableAndFunctorInterner;
import com.thesett.aima.logic.fol.interpreter.ResolutionEngine;
import com.thesett.aima.logic.fol.isoprologparser.SentenceParser;
import com.thesett.aima.logic.fol.isoprologparser.Token;
import com.thesett.aima.logic.fol.isoprologparser.TokenSource;
import com.thesett.aima.logic.fol.wam.compiler.WAMCompiledPredicate;
import com.thesett.aima.logic.fol.wam.compiler.WAMCompiledQuery;
import com.thesett.common.parsing.SourceCodeException;
import com.thesett.common.util.Source;

/**
 * WAMEngine implements a {@link ResolutionEngine} for an WAM-based Prolog with built-ins. This engine loads its
 * standard library of built-ins from a resource on the classpath.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Load the Prolog built-in library from a resource on the classpath when the engine is reset.
 *

 *
 * @author Rupert Smith
 */
public class WAMEngine extends ResolutionEngine<Clause, WAMCompiledPredicate, WAMCompiledQuery>
{
    /** Holds the name of the resource on the classpath that contains the built-in library. */
    private static final String BUILT_IN_LIB = "wam_builtins.pl";

    /**
     * Builds an logical resolution engine from a parser, interner, compiler and resolver.
     *
     * @param parser   The parser.
     * @param interner The interner.
     * @param compiler The compiler.
     * @param resolver The resolver.
     */
    public WAMEngine(Parser<Clause, Token> parser, VariableAndFunctorInterner interner,
        LogicCompiler<Clause, WAMCompiledPredicate, WAMCompiledQuery> compiler,
        Resolver<WAMCompiledPredicate, WAMCompiledQuery> resolver)
    {
        super(parser, interner, compiler, resolver);
    }

    /**
     * {@inheritDoc}
     *
     *
Loads the built-in library resource specified by {@link #BUILT_IN_LIB}.
     */
    public void reset()
    {
        // Reset the resolver to completely clear out its domain.
        resolver.reset();

        // Create a token source to load the model rules from.
        Source<Token> tokenSource =
            TokenSource.getTokenSourceForInputStream(WAMEngine.class.getClassLoader().getResourceAsStream(
                    BUILT_IN_LIB));

        // Set up a parser on the token source.
        Parser<Clause, Token> libParser = new SentenceParser(interner);
        libParser.setTokenSource(tokenSource);

        // Load the built-ins into the domain.
        try
        {
            while (true)
            {
                Sentence<Clause> sentence = libParser.parse();

                if (sentence == null)
                {
                    break;
                }

                compiler.compile(sentence);
            }

            compiler.endScope();
        }
        catch (SourceCodeException e)
        {
            // There should not be any errors in the built in library, if there are then the prolog engine just
            // isn't going to work, so report this as a bug.
            throw new IllegalStateException("Got an exception whilst loading the built-in library.", e);
        }
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.logic.fol.isoprologparser;

import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import com.thesett.aima.logic.fol.Clause;
import com.thesett.aima.logic.fol.Cons;
import com.thesett.aima.logic.fol.DoubleLiteral;
import com.thesett.aima.logic.fol.Functor;
import com.thesett.aima.logic.fol.IntLiteral;
import com.thesett.aima.logic.fol.Nil;
import com.thesett.aima.logic.fol.NumericType;
import com.thesett.aima.logic.fol.OpSymbol;
import static com.thesett.aima.logic.fol.OpSymbol.Associativity.FX;
import static com.thesett.aima.logic.fol.OpSymbol.Associativity.FY;
import static com.thesett.aima.logic.fol.OpSymbol.Associativity.XFX;
import static com.thesett.aima.logic.fol.OpSymbol.Associativity.XFY;
import static com.thesett.aima.logic.fol.OpSymbol.Associativity.YFX;
import com.thesett.aima.logic.fol.StringLiteral;
import com.thesett.aima.logic.fol.Term;
import com.thesett.aima.logic.fol.TermUtils;
import com.thesett.aima.logic.fol.Variable;
import com.thesett.aima.logic.fol.VariableAndFunctorInterner;
import com.thesett.aima.logic.fol.VariableAndFunctorInternerImpl;
import com.thesett.common.parsing.SourceCodeException;
import com.thesett.common.parsing.SourceCodePosition;
import com.thesett.common.parsing.SourceCodePositionImpl;
import com.thesett.common.util.Source;
import com.thesett.common.util.TraceIndenter;

/**
 * PrologParser is a recursive descent parser for the language Prolog, that parses its input into first order logic
 * {@link Term}s or {@link Clause}s. The {@link #sentence()}s generated by this parser are Terms in first order logic,
 * but not necessarily sentences in Prolog. A sentence in Prolog consists of either a Horn clause, to be added to the
 * current knowledge base, or a query, which is a Horn clause with no head, for immediate resolution against the current
 * knowledge base. Sentences in Prolog are Horn clauses and may be parsed through the {@link #clause()} method.
 *
 *
A deffered decision parser, {@link DynamicOperatorParser}, is used to parse sequences of terms possibly involving
 * operators. This cannot easily be achieved with a recursive descent parser. See {@link DynamicOperatorParser} for the
 * details.
 *
 *

CRC Card

 *
 Responsibilities
 *
 Create a parser for Prolog on a token source.  {@link Source}
 *
 Parse a sentence in first order logic with dynamic operators.  {@link DynamicOperatorParser}.
 *
 Parse a sequence of sentences followed by an end of file.
 *
 Intern all Prolog built in functors and operators.  {@link VariableAndFunctorInterner}.
 *
 Table all Prolog build in operators.  {@link OperatorTable}.
 *

 *
 * @author Rupert Smith
 */
public class PrologParser implements PrologParserConstants
{
    /** Used for debugging purposes. */
    /* private static final Logger log = Logger.getLogger(PrologParser.class.getName()); */

    /** Used for logging to the console. */
    private static final java.util.logging.Logger console =
        java.util.logging.Logger.getLogger("CONSOLE." + PrologParser.class.getName());

    /** Lists the tokens expected to begin a term expression as a string. */
    private static final String BEGIN_TERM_TOKENS =
        Arrays.toString(
            new String[]
            {
                tokenImage[FUNCTOR], tokenImage[LSQPAREN], tokenImage[VAR], tokenImage[INTEGER_LITERAL],
                tokenImage[FLOATING_POINT_LITERAL], tokenImage[STRING_LITERAL], tokenImage[ATOM], tokenImage[LPAREN]
            });

    /** Describes the possible system directives in interactive mode. */
    public enum Directive
    {
        Trace, Info, User, File
    }

    /** Holds the variable scoping context for the current sentence. */
    protected Map<Integer, Variable> variableContext = new HashMap<Integer, Variable>();

    /** Holds the byte code machine to compile into, if using compiled mode. */
    protected VariableAndFunctorInterner interner =
        new VariableAndFunctorInternerImpl("Prolog_Variable_Namespace", "Prolog_Functor_Namespace");

    /** Holds the dynamic operator parser for parsing terms involving operators. */
    protected DynamicOperatorParser operatorParser = new DynamicOperatorParser();

    /** Holds the table of operators. */
    protected OperatorTable operatorTable = operatorParser;

    /** Holds the tokenizer that supplies the next token on demand. */
    protected Source<Token> tokenSource;

    /** Holds the indenter to provide neatly indendet execution traces. */
    protected TraceIndenter indenter = new TraceIndenter(true);

    /**
     * Builds a prolog parser on a token source to be parsed.
     *
     * @param tokenSource The token source to be parsed.
     * @param interner    The interner for variable and functor names.
     */
    public PrologParser(Source<Token> tokenSource, VariableAndFunctorInterner interner)
    {
        /** Set this parser up to use the supplied interner. */
        this.interner = interner;

        /** Clears the variable scoping context for the first sentence. */
        variableContext.clear();

        /** Intern all of the built in symbols and functors in the language. */
        initializeBuiltIns();

        this.tokenSource = tokenSource;
    }

    /**
     * Parses statements and print the parse tree to the console for quick interactive testing of the parser.
     *
     * @param args The command line arguments.
     */
    public static void main(String[] args)
    {
        try
        {
            SimpleCharStream inputStream = new SimpleCharStream(System.in, null, 1, 1);
            PrologParserTokenManager tokenManager = new PrologParserTokenManager(inputStream);
            Source<Token> tokenSource = new TokenSource(tokenManager);

            PrologParser parser =
                new PrologParser(tokenSource,
                    new VariableAndFunctorInternerImpl("Prolog_Variable_Namespace", "Prolog_Functor_Namespace"));

            while (true)
            {
                // Parse the next sentence or directive.
                Object nextParsing = parser.clause();

                console.info(nextParsing.toString());
            }
        }
        catch (Exception e)
        {
            console.log(Level.SEVERE, e.getMessage(), e);
            System.exit(1);
        }
    }

    /**
     * Changes the token source the parser is consuming from.
     *
     * @param tokenSource The new token source the parser is to consume from.
     */
    public void setTokenSource(Source<Token> tokenSource)
    {
        this.tokenSource = tokenSource;
    }

    /**
     * Parses a single terms, or atom (a functor with arity zero), as a sentence in first order logic. The sentence will
     * be parsed in a fresh variable context, to ensure its variables are scoped to within the term only. The sentence
     * does not have to be terminated by a full stop. This method is not generally used by Prolog, but is provided as a
     * convenience to languages over terms, rather than clauses.
     *
     * @return A term parsed in a fresh variable context.
     *
     * @throws SourceCodeException If the token sequence does not parse into a valid term sentence.
     */
    public Term termSentence() throws SourceCodeException
    {
        // Each new sentence provides a new scope in which to make variables unique.
        variableContext.clear();

        Term sentence = term();

        return sentence;

    }

    /**
     * Parses a single horn clause as a sentence in first order logic. A sentence consists of a clause followed by a
     * full stop.
     *
     * @return A horn clause sentence in first order logic.
     *
     * @throws SourceCodeException If the token sequence does not parse into a valid sentence.
     */
    public Clause sentence() throws SourceCodeException
    {
        Clause sentence = clause();

        consumeToken(PERIOD);

        return sentence;
    }

    /**
     * Parses many consecutive sentences, until an <EOF> is reached. This method is intended to aid with consulting
     * files.
     *
     * @return A list of parsed clauses.
     *
     * @throws SourceCodeException If the token sequence does not parse into a sequence of clauses terminted by <EOF>.
     */
    public List<Clause> sentences() throws SourceCodeException
    {
        List<Clause> results = new LinkedList<Clause>();

        // Loop consuming clauses until end of file is encounterd.
        while (true)
        {
            if (peekAndConsumeEof())
            {
                break;
            }
            else
            {
                results.add(sentence());
            }
        }

        return results;
    }

    /**
     * Parses a single sentence in first order logic. A sentence consists of a term followed by a full stop.
     *
     * @return A sentence in first order logic.
     *
     * @throws SourceCodeException If the token sequence does not parse into a valid sentence.
     */
    public Clause clause() throws SourceCodeException
    {
        // Each new sentence provides a new scope in which to make variables unique.
        variableContext.clear();

        Term term = term();

        Clause clause = TermUtils.convertToClause(term, interner);

        if (clause == null)
        {
            throw new SourceCodeException("Only queries and clauses are valid sentences in Prolog, not " + term + ".",
                null, null, null, term.getSourceCodePosition());
        }

        return clause;
    }

    /**
     * Parses multiple sequential terms, and if more than one is encountered then the flat list of terms encountered
     * must contain operators in order to be valid Prolog syntax. In that case the flat list of terms is passed to the
     * {@link DynamicOperatorParser#parseOperators(Term[])} method for 'deferred decision parsing' of dynamic operators.
     *
     * @return A single first order logic term.
     *
     * @throws SourceCodeException If the sequence of tokens does not form a valid syntactical construction as a first
     *                             order logic term.
     */
    public Term term() throws SourceCodeException
    {
        List<Term> terms;
        terms = terms(new LinkedList<Term>());

        Term[] flatTerms = terms.toArray(new Term[terms.size()]);

        if (flatTerms.length > 1)
        {
            return operatorParser.parseOperators(flatTerms);
        }
        else
        {
            Term result = flatTerms[0];

            // If a single candidate op symbol has been parsed, promote it to a constant.
            if (result instanceof CandidateOpSymbol)
            {
                CandidateOpSymbol candidate = (CandidateOpSymbol) result;

                int nameId = interner.internFunctorName(candidate.getTextName(), 0);
                result = new Functor(nameId, null);
            }

            return result;
        }
    }

    /**
     * Recursively parses terms, which may be functors, atoms, variables, literals or operators, into a flat list in the
     * order in which they are encountered.
     *
     * @param  terms A list of terms to accumulate in.
     *
     * @return The list of terms encountered in order.
     *
     * @throws SourceCodeException If the sequence of tokens does not form a valid syntactical construction as a list of
     *                             first order logic terms.
     */
    public List<Term> terms(List<Term> terms) throws SourceCodeException
    {
        Term term;

        Token nextToken = tokenSource.peek();

        switch (nextToken.kind)
        {
        case FUNCTOR:
            term = functor();
            break;

        case LSQPAREN:
            term = listFunctor();
            break;

        case VAR:
            term = variable();
            break;

        case INTEGER_LITERAL:
            term = intLiteral();
            break;

        case FLOATING_POINT_LITERAL:
            term = doubleLiteral();
            break;

        case STRING_LITERAL:
            term = stringLiteral();
            break;

        case ATOM:
            term = atom();
            break;

        case LPAREN:
            consumeToken(LPAREN);

            term = term();

            // Mark the term as bracketed to ensure that this is its final parsed form. In particular the
            // #arglist method will not break it up if it contains commas.
            term.setBracketed(true);

            consumeToken(RPAREN);
            break;

        default:
            throw new SourceCodeException("Was expecting one of " + BEGIN_TERM_TOKENS + " but got " +
                tokenImage[nextToken.kind] + ".", null, null, null,
                new SourceCodePositionImpl(nextToken.beginLine, nextToken.beginColumn, nextToken.endLine,
                    nextToken.endColumn));
        }

        terms.add(term);

        switch (tokenSource.peek().kind)
        {
        case LPAREN:
        case LSQPAREN:
        case INTEGER_LITERAL:
        case FLOATING_POINT_LITERAL:
        case STRING_LITERAL:
        case VAR:
        case FUNCTOR:
        case ATOM:
            terms(terms);
            break;

        default:
        }

        return terms;
    }

    /**
     * Parses a single atom in first order logic. If the operator has been set up which has the same name as the atom
     * then the atom may actually be a functor expressed as a prefix, postfix or infix operator. If this is the case the
     * value returned by this method will be a {@link CandidateOpSymbol}. Otherwise it will be a {@link Functor} of
     * arity zero.
     *
     * @return A {@link CandidateOpSymbol} or a {@link Functor} or arity zero.
     *
     * @throws SourceCodeException If the token sequence does not parse as a valid atom.
     */
    public Term atom() throws SourceCodeException
    {
        Token name = consumeToken(ATOM);

        Term result;

        // Used to build the possible set of operators that this symbol could be parsed as.
        EnumMap<OpSymbol.Fixity, OpSymbol> possibleOperators =
            operatorTable.getOperatorsMatchingNameByFixity(name.image);

        // Check if the symbol mapped onto any candidate operators and if not create a constant for it.
        if ((possibleOperators == null) || possibleOperators.isEmpty())
        {
            int nameId = interner.internFunctorName(name.image, 0);
            result = new Functor(nameId, null);
        }
        else
        {
            // Set the possible associativities of the operator on the candidate.
            result = new CandidateOpSymbol(name.image, possibleOperators);
        }

        // Set the position that the name was parsed from.
        SourceCodePosition position =
            new SourceCodePositionImpl(name.beginLine, name.beginColumn, name.endLine, name.endColumn);
        result.setSourceCodePosition(position);

        return result;
    }

    /**
     * Parses a single functor in first order logic with its arguments.
     *
     * @return A single functor in first order logic with its arguments.
     *
     * @throws SourceCodeException If the token sequence does not parse as a valid functor.
     */
    public Term functor() throws SourceCodeException
    {
        Token name = consumeToken(FUNCTOR);
        Term[] args = arglist();
        consumeToken(RPAREN);

        int nameId =
            interner.internFunctorName((args == null) ? name.image : name.image.substring(0, name.image.length() - 1),
                (args == null) ? 0 : args.length);

        Functor result = new Functor(nameId, args);

        SourceCodePosition position =
            new SourceCodePositionImpl(name.beginLine, name.beginColumn, name.endLine, name.endColumn);
        result.setSourceCodePosition(position);

        return result;
    }

    /**
     * Parses a list expressed as a sequence of functors in first order logic. The empty list consists of the atom 'nil'
     * and a non-empty list consists of the functor 'cons' with arguments the head of the list and the remainder of the
     * list.
     *
     *
A list can be empty '[]', contains a sequence of terms seperated by commas '[a,...]', contain a sequence of
     * terms seperated by commas consed onto another term '[a,...|T]'. In the case where a term is consed onto the end,
     * if the term is itself a list the whole will form a list with a cons nil terminator, otherwise the term will be
     * consed onto the end as the list terminal.
     *
     * @return A list expressed as a sequence of functors in first order.
     *
     * @throws SourceCodeException If the token sequence does not parse as a valid list.
     */
    public Term listFunctor() throws SourceCodeException
    {
        // Get the interned names of the nil and cons functors.
        int nilId = interner.internFunctorName("nil", 0);
        int consId = interner.internFunctorName("cons", 2);

        // A list always starts with a '['.
        Token leftDelim = consumeToken(LSQPAREN);

        // Check if the list contains any arguments and parse them if so.
        Term[] args = null;

        Token nextToken = tokenSource.peek();

        switch (nextToken.kind)
        {
        case LPAREN:
        case LSQPAREN:
        case INTEGER_LITERAL:
        case FLOATING_POINT_LITERAL:
        case STRING_LITERAL:
        case VAR:
        case FUNCTOR:
        case ATOM:
            args = arglist();
            break;

        default:
        }

        // Work out what the terminal element in the list is. It will be 'nil' unless an explicit cons '|' has
        // been used to specify a different terminal element. In the case where cons is used explciitly, the
        // list prior to the cons must not be empty.
        Term accumulator;

        if (tokenSource.peek().kind == CONS)
        {
            if (args == null)
            {
                throw new SourceCodeException("Was expecting one of " + BEGIN_TERM_TOKENS + " but got " +
                    tokenImage[nextToken.kind] + ".", null, null, null,
                    new SourceCodePositionImpl(nextToken.beginLine, nextToken.beginColumn, nextToken.endLine,
                        nextToken.endColumn));
            }

            consumeToken(CONS);

            accumulator = term();
        }
        else
        {
            accumulator = new Nil(nilId, null);
        }

        // A list is always terminated with a ']'.
        Token rightDelim = consumeToken(RSQPAREN);

        // Walk down all of the lists arguments joining them together with cons/2 functors.
        if (args != null) // 'args' will contain one or more elements if not null.
        {
            for (int i = args.length - 1; i >= 0; i--)
            {
                Term previousAccumulator = accumulator;

                //accumulator = new Functor(consId.ordinal(), new Term[] { args[i], previousAccumulator });
                accumulator = new Cons(consId, new Term[] { args[i], previousAccumulator });
            }
        }

        // Set the position that the list was parsed from, as being the region between the '[' and ']' brackets.
        SourceCodePosition position =
            new SourceCodePositionImpl(leftDelim.beginLine, leftDelim.beginColumn, rightDelim.endLine,
                rightDelim.endColumn);
        accumulator.setSourceCodePosition(position);

        // The cast must succeed because arglist must return at least one argument, therefore the cons generating
        // loop must have been run at least once. If arglist is not called at all because an empty list was
        // encountered, then the accumulator will contain the 'nil' constant which is a functor of arity zero.
        return (Functor) accumulator;
    }

    /**
     * Parses a sequence of terms as a comma seperated argument list. The ',' operator in prolog can be used as an
     * operator, when it behaves as a functor of arity 2, or it can be used to separate a sequence of terms that are
     * arguments to a functor or list. The sequence of functors must first be parsed as a term, using the operator
     * precedence of "," to form the term. This method takes such a term and flattens it back into a list of terms,
     * breaking it only on a sequence of commas. Terms that have been parsed as a bracketed expression will not be
     * broken up.
     *
     *
For example, 'a, b, c' is broken into the list { a, b, c}. The example, 'a, (b, c), d' is broken into the
     * list { a, (b, c), d} and so on.
     *
     * @return A sequence of terms parsed as a term, then flattened back into a list seperated on commas.
     *
     * @throws SourceCodeException If the token sequence is not a valid term.
     */
    public Term[] arglist() throws SourceCodeException
    {
        Term term = term();
        List<Term> result = TermUtils.flattenTerm(term, Term.class, ",", interner);

        return result.toArray(new Term[result.size()]);
    }

    /**
     * Parses a variable in first order logic. Variables are scoped within the current sentence being parsed, so if the
     * variable has been seen previously in the sentence it is returned rather than a new one being created.
     *
     * @return A variable.
     *
     * @throws SourceCodeException If the next token in the sequence is not a variable.
     */
    public Term variable() throws SourceCodeException
    {
        Token name = consumeToken(VAR);

        // Intern the variables name.
        int nameId = interner.internVariableName(name.image);

        // Check if the variable already exists in this scope, or create a new one if it does not.
        // If the variable is the unidentified anonymous variable '_', a fresh one will always be created.
        Variable var = null;

        if (!"_".equals(name.image))
        {
            var = variableContext.get(nameId);
        }

        if (var != null)
        {
            return var;
        }
        else
        {
            var = new Variable(nameId, null, name.image.equals("_"));
            variableContext.put(nameId, var);

            return var;
        }
    }

    /**
     * Parses an integer literal.
     *
     * @return An integer literal.
     *
     * @throws SourceCodeException If the next token in the sequence is not an integer literal.
     */
    public Term intLiteral() throws SourceCodeException
    {
        Token valToken = consumeToken(INTEGER_LITERAL);

        NumericType result = new IntLiteral(Integer.parseInt(valToken.image));

        // Set the position that the literal was parsed from.
        SourceCodePosition position =
            new SourceCodePositionImpl(valToken.beginLine, valToken.beginColumn, valToken.endLine, valToken.endColumn);
        result.setSourceCodePosition(position);

        return result;
    }

    /**
     * Parses a real number literal.
     *
     * @return A real number literal.
     *
     * @throws SourceCodeException If the next token in the sequence is not a real number literal.
     */
    public Term doubleLiteral() throws SourceCodeException
    {
        Token valToken = consumeToken(FLOATING_POINT_LITERAL);

        NumericType result = new DoubleLiteral(Double.parseDouble(valToken.image));

        // Set the position that the literal was parsed from.
        SourceCodePosition position =
            new SourceCodePositionImpl(valToken.beginLine, valToken.beginColumn, valToken.endLine, valToken.endColumn);
        result.setSourceCodePosition(position);

        return result;
    }

    /**
     * Parses a string literal.
     *
     * @return A string literal.
     *
     * @throws SourceCodeException If the next token in the sequence is not a string literal.
     */
    public Term stringLiteral() throws SourceCodeException
    {
        Token valToken = consumeToken(STRING_LITERAL);

        String valWithQuotes = valToken.image;

        StringLiteral result = new StringLiteral(valWithQuotes.substring(1, valWithQuotes.length() - 1));

        // Set the position that the literal was parsed from.
        SourceCodePosition position =
            new SourceCodePositionImpl(valToken.beginLine, valToken.beginColumn, valToken.endLine, valToken.endColumn);
        result.setSourceCodePosition(position);

        return result;
    }

    /**
     * Peeks at the next token to see if it is {@link #EOF} and if it is consumes it. If the symbol is consumed then the
     * return value indicates that this has happened. This method is intended to be useful for interactive interpreters
     * to detect when to exit at the end of input.
     *
     * @return <tt>true</tt> if the next token is EOF and it is consumed.
     */
    public boolean peekAndConsumeEof()
    {
        return peekAndConsume(EOF);
    }

    /**
     * Peeks at the next token to see if it is the system trace directive, and consumes it if it is.
     *
     * @return <tt>true</tt> iff the next token is the trace directive.
     */
    public boolean peekAndConsumeTrace()
    {
        return peekAndConsume(TRACE) && peekAndConsume(PERIOD);
    }

    /**
     * Peeks at the next token to see if it is the system info directive, and consumes it if it is.
     *
     * @return <tt>true</tt> iff the next token is the info directive.
     */
    public boolean peekAndConsumeInfo()
    {
        return peekAndConsume(INFO) && peekAndConsume(PERIOD);
    }

    /**
     * Peeks at the next token to see if it is the system user directive, and consumes it if it is.
     *
     * @return <tt>true</tt> iff the next token is the user directive.
     */
    public boolean peekAndConsumeUser()
    {
        return peekAndConsume(USER) && peekAndConsume(PERIOD);
    }

    /**
     * Peeks at the next token to see if it is an {@link #ATOM} which is equal to ";" and if it is consumes it. If the
     * symbol is consumed then the return value indicates that this has happened. This is intended to be usefull for
     * interactive interpreters when querying the user to see if they want more solutions to be found.
     *
     * @return <tt>true</tt> if the next token is ";" and it is consumed.
     */
    public boolean peekAndConsumeMore()
    {
        Token nextToken = tokenSource.peek();

        if ((nextToken.kind == ATOM) && ";".equals(nextToken.image))
        {
            try
            {
                consumeToken(ATOM);
            }
            catch (SourceCodeException e)
            {
                // If the peek ahead kind can not be consumed then something strange has gone wrong so report this
                // as a bug rather than try to recover from it.
                throw new IllegalStateException(e);
            }

            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * Peeks and consumes the next interactive system directive.
     *
     * @return The directive, or <tt>null</tt> if none is found.
     *
     * @throws SourceCodeException If the source being parsed does not match the grammar.
     */
    public Directive peekAndConsumeDirective() throws SourceCodeException
    {
        if (peekAndConsumeTrace())
        {
            return Directive.Trace;
        }

        if (peekAndConsumeInfo())
        {
            return Directive.Info;
        }

        if (peekAndConsumeUser())
        {
            return Directive.User;
        }

        return null;
    }

    /**
     * Interns an operators name as a functor of appropriate arity for the operators fixity, and sets the operator in
     * the operator table.
     *
     * @param operatorName  The name of the operator to create.
     * @param priority      The priority of the operator, zero unsets it.
     * @param associativity The operators associativity.
     */
    public void internOperator(String operatorName, int priority, OpSymbol.Associativity associativity)
    {
        int arity;

        if ((associativity == XFY) | (associativity == YFX) | (associativity == XFX))
        {
            arity = 2;
        }
        else
        {
            arity = 1;
        }

        int name = interner.internFunctorName(operatorName, arity);
        operatorTable.setOperator(name, operatorName, priority, associativity);
    }

    /** Interns and inserts into the operator table all of the built in operators and functors in Prolog. */
    protected void initializeBuiltIns()
    {
        // Initializes the operator table with the standard ISO prolog built-in operators.
        internOperator(":-", 1200, XFX);
        internOperator(":-", 1200, FX);
        internOperator("-->", 1200, XFX);
        internOperator("?-", 1200, FX);

        internOperator(";", 1100, XFY);
        internOperator("->", 1050, XFY);
        internOperator(",", 1000, XFY);
        internOperator("\\+", 900, FY);

        internOperator("=", 700, XFX);
        internOperator("\\=", 700, XFX);
        internOperator("==", 700, XFX);
        internOperator("\\==", 700, XFX);
        internOperator("@<", 700, XFX);
        internOperator("@=<", 700, XFX);
        internOperator("@>", 700, XFX);
        internOperator("@>=", 700, XFX);
        internOperator("=..", 700, XFX);
        internOperator("is", 700, XFX);
        internOperator("=:=", 700, XFX);
        internOperator("=\\=", 700, XFX);
        internOperator("<", 700, XFX);
        internOperator("=<", 700, XFX);
        internOperator(">", 700, XFX);
        internOperator(">=", 700, XFX);

        internOperator("+", 500, YFX);
        internOperator("-", 500, YFX);

        internOperator("\\/", 500, YFX);
        internOperator("/\\", 500, YFX);

        internOperator("/", 400, YFX);
        internOperator("//", 400, YFX);
        internOperator("*", 400, YFX);
        internOperator(">>", 400, YFX);
        internOperator("<<", 400, YFX);
        internOperator("rem", 400, YFX);
        internOperator("mod", 400, YFX);

        internOperator("-", 200, FY);
        internOperator("^", 200, YFX);
        internOperator("**", 200, YFX);
        internOperator("\\", 200, FY);

        // Intern all built in functors.
        interner.internFunctorName("nil", 0);
        interner.internFunctorName("cons", 2);
        interner.internFunctorName("true", 0);
        interner.internFunctorName("fail", 0);
        interner.internFunctorName("!", 0);
    }

    /**
     * Consumes a token of the expected kind from the token sequence. If the next token in the sequence is not of the
     * expected kind an error will be raised.
     *
     * @param  kind The kind of token to consume.
     *
     * @return The consumed token of the expected kind.
     *
     * @throws SourceCodeException If the next token in the sequence is not of the expected kind.
     */
    protected Token consumeToken(int kind) throws SourceCodeException
    {
        Token nextToken = tokenSource.peek();

        if (nextToken.kind != kind)
        {
            throw new SourceCodeException("Was expecting " + tokenImage[kind] + " but got " +
                tokenImage[nextToken.kind] + ".", null, null, null,
                new SourceCodePositionImpl(nextToken.beginLine, nextToken.beginColumn, nextToken.endLine,
                    nextToken.endColumn));
        }
        else
        {
            nextToken = tokenSource.poll();

            return nextToken;
        }
    }

    /**
     * Peeks ahead for the given token type, and if one is foudn with that type, it is consumed.
     *
     * @param  kind The token kind to look for.
     *
     * @return <tt>true</tt> iff the token was found and consumed.
     */
    private boolean peekAndConsume(int kind)
    {
        Token nextToken = tokenSource.peek();

        if (nextToken.kind == kind)
        {
            try
            {
                consumeToken(kind);
            }
            catch (SourceCodeException e)
            {
                // If the peek ahead kind can not be consumed then something strange has gone wrong so report this
                // as a bug rather than try to recover from it.
                throw new IllegalStateException(e);
            }

            return true;
        }
        else
        {
            return false;
        }
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.common.tx;

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

/**
 * TxSessionImpl provides an implementation of a transactional session for spanning of multiple transactional resources.
 *
 *

CRC Card

 *
ResponsibilitiesCollaborations
 *
Apply commit or rollback over many transactional resources.
 *
Bind a session to the current thread.
 *
Unbind a session from the current thread.
 *
Accept transactional resource enlist notifications.
 *

 *
 * @author Rupert Smith
 */
public class TxSessionImpl implements TxSession
{
    /** Provides thread local variable assignment of sessions. */
    private static final ThreadLocal<TxSession> threadSession =
        new ThreadLocal<TxSession>()
        {
            /**
             * Session are always initialized to null before being assigned.
             *
             * @return Always null.
             */
            protected synchronized TxSession initialValue()
            {
                return null;
            }
        };

    /** Holds the transaction id of the session. */
    TxId txId;

    /** Holds all transactional resources that have been enlisted in this session. */
    Collection<Transactional> enlists = new HashSet<Transactional>();

    /**
     * Gets the session associated with the current thread, if any.
     *
     * @return The session associated with the current thread, or <tt>null</tt> if none has been associated.
     */
    public static TxSession getCurrentSession()
    {
        return threadSession.get();
    }

    /** Binds the session as a transactional context to the current thread, if it is not already bound. */
    public void bind()
    {
        // If necessary create a fresh transaction id.
        if ((txId == null) || !txId.isValid())
        {
            txId = TxManager.createTxId();
        }

        // Bind the transaction to the current thread.
        TxManager.assignTxIdToThread(txId);

        // Bind this session to the current thread.
        threadSession.set(this);
    }

    /** Unbinds the session as a transactional context from the current thread. */
    public void unbind()
    {
        // Unbind the transaction id from the current thread, but keep hold of it for subsequent rebinding.
        txId = TxManager.removeTxIdFromThread();

        // Unbind this session from the current thread.
        threadSession.remove();
    }

    /** Applies pending operations. */
    public void commit()
    {
        // Two phase commit over all hard resources enlisted.

        // Commit all soft resources.
        for (Transactional enlist : enlists)
        {
            enlist.commit();
        }

        // Clear all of the committed resources.
        enlists.clear();

        // Invalidate the transaction id, so that a fresh transaction is begun.
        txId = TxManager.removeTxIdFromThread();
        TxManager.invalidateTxId(txId);
        bind();
    }

    /** Forgets pending operations. */
    public void rollback()
    {
        // Rollback all soft resources.
        for (Transactional enlist : enlists)
        {
            enlist.rollback();
        }

        // Clear all of the rolled back resources.
        enlists.clear();

        // Invalidate the transaction id, so that a fresh transaction is begun.
        txId = TxManager.removeTxIdFromThread();
        TxManager.invalidateTxId(txId);
        bind();
    }

    /**
     * Enlists a transactional resource with this session.
     *
     * @param resource The resource to enlist.
     */
    public void enlist(Transactional resource)
    {
        // Enlist the resource if it has not already been enlisted.
        enlists.add(resource);
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.common.util;

import java.util.Collection;
import java.util.Iterator;

/**
 * Filterators is a utilty class providing convenience methods to assist with working with {@link Filterator}s.
 *
 *

CRC Card

 *
ResponsibilitiesCollaborations
 *
Apply a filterator to a collection, accumulating the results in another collection.
 *

 *
 * @author Rupert Smith
 */
public class Filterators
{
    /**
     * Extracts all elements from an iterator, usually created from a filterator, and adds them into the target
     * collection, returning that collection as the result.
     *
     * @param  <T>              The type of the iterator and collection to add to.
     * @param  iterator         The iterator to extract from.
     * @param  targetCollection The collection to add to.
     *
     * @return The collection added to.
     */
    public static <T> Collection<T> collectIterator(Iterator<T> iterator, Collection<T> targetCollection)
    {
        while (iterator.hasNext())
        {
            targetCollection.add(iterator.next());
        }

        return targetCollection;
    }
}


/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * Licensed 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 com.thesett.aima.logic.fol.bytecode;

import java.nio.ByteBuffer;

import com.thesett.aima.logic.fol.LinkageException;
import com.thesett.aima.logic.fol.VariableAndFunctorInterner;
import com.thesett.common.util.SizeableList;
import com.thesett.common.util.doublemaps.SymbolTable;
import com.thesett.common.util.visitor.Acceptor;

/**
 * BaseCodeMachine is a base for deriving abstract machines that hold executable code in a byte buffer, and use a
 * compiled entity type that can provide an instruction listing, and an encoder over that type of instructions to
 * provide a set of basic operations for dealing with encoding of the byte code into the machine, and tracking callable
 * entry points into the code.
 *
 *

CRC Card

 *
 Responsibilities  Collaborations
 *
 Accept byte code into the machine.
 *
 Resolve an interned name onto a call point.
 *
 Allow a call point for a procedure to be reserved.
 *
 Provide a byte buffer and current insertion point for new code.
 *

 *
 * @author Rupert Smith
 * @todo   No garbage collection of replaced call points is done. Should eventually remove unused code, and compact the
 *         still in use code buffer. Compacting the buffer is not straightforward as call points will need to be
 *         translated. Either keep track of all call points within the code buffer and translate them on compaction, or
 *         when a code buffer is to be garbage collected, simply create a new one and re-insert all live procedures into
 *         the new buffer.
 */
public abstract class BaseCodeMachine<I extends Acceptor, C extends InstructionListing> extends BaseMachine
    implements CodeMachine<C>, CallPointResolver
{
    /** Used for debugging purposes. */
    /* private static final Logger log = Logger.getLogger(BaseCodeMachine.class.getName()); */

    /** Holds the byte code emmitting encoder over the instruction set of the compiled entities. */
    protected InstructionEncoder instructionEncoder;

    /**
     * Creates a base machine using the specified instruction encoder.
     *
     * @param symbolTable        The symbol table for the machine.
     * @param interner           The symbo name interner for the machine.
     * @param instructionEncoder The insutruction encoder for the machine.
     */
    protected BaseCodeMachine(SymbolTable<Integer, String, Object> symbolTable, VariableAndFunctorInterner interner,
        InstructionEncoder instructionEncoder)
    {
        super(symbolTable, interner);

        this.instructionEncoder = instructionEncoder;

        // Set this up as the call point resolver for the instruction encoder. This enables it to call back onto
        // this every time the target address of a 'call' instruction needs to be resolved from its interned name.
        instructionEncoder.setCallPointResolver(this);
    }

    /**
     * Provides the name of the symbol field under which call points are stored in the symbol table.
     *
     * @return The name of the symbol field under which call points are stored in the symbol table.
     */
    public abstract String getCallPointSymbolField();

    /**
     * Provides a byte buffer that is correctly positioned to write fresh code into the code buffer.
     *
     * @param  callPoint The call point to provide the byte buffer for.
     *
     * @return A byte buffer that is correctly positioned to write fresh code into the code buffer.
     */
    public abstract ByteBuffer getCodeBuffer(CallPoint callPoint);

    /**
     * Provides the next available address at which new code may be added to the machine.
     *
     * @return The next available address at which new code may be added to the machine.
     */
    public abstract int getCodeInsertionPoint();

    /**
     * Increments the next available address at which new code may be added to the machine, by the specified amount.
     *
     * @param length The amount to advance the pointer by.
     */
    public abstract void advanceCodeInsertionPoint(int length);

    /**
     * {@inheritDoc}
     *
     *
It is expected that the compiled code being written into the machine, will not have its call resolved onto
     * call-points, and that call will be made to the {@link #resolveCallPoint(int)} method, during this procedure to
     * resolve them.
     */
    public void emmitCode(C compiled) throws LinkageException
    {
        /*log.fine("public void emmitCode(C compiled): called");*/

        SizeableList instructions = compiled.getInstructions();

        // Get the call point for the code to write.
        CallPoint callPoint = resolveCallPoint(compiled.getName());

        if (callPoint == null)
        {
            /*log.fine("call point not resolved, reserving new one.");*/
            callPoint = reserveCallPoint(compiled.getName(), (int) instructions.sizeof());
        }

        /*log.fine("insertion point = " + getCodeInsertionPoint());*/

        // Pass a reference to a buffer set to write to the call point in the code buffer on the encoder.
        instructionEncoder.setCodeBuffer(getCodeBuffer(callPoint));

        // Loop over all instructions encoding them to byte code in the machines code buffer.
        for (I instruction : instructions)
        {
            instruction.accept(instructionEncoder);
        }
    }

    /** {@inheritDoc} */
    public CallPoint resolveCallPoint(int name)
    {
        return (CallPoint) symbolTable.get(name, getCallPointSymbolField());
    }

    /**
     * Reserves a call point for a block of named callable code. The size of the block of code must be known fully in
     * advance. If the named block already has a call point, this will replace it with a new one.
     *
     *
Adding code into a code machine may be a two-stage process, first reserve call-points for all blocks of code,
     * then add the blocks of code into the machine, resolving internal call points within the code onto previously
     * reserved call points as this is done. A two-stage process is required to support recursive or mutually recursive
     * callable procedures.
     *
     * @param  name   The interned name of the procedure to create a call point for.
     * @param  length The length of the procedures code.
     *
     * @return A new call point for the procedure.
     */
    public CallPoint reserveCallPoint(int name, int length)
    {
        // Work out where the code will go and advance the insertion point beyond its end, so that additional code
        // will be added beyond the reserved space.
        int address = getCodeInsertionPoint();
        advanceCodeInsertionPoint(length);

        // Create a call point for the reserved space.
        CallPoint callPoint = new CallPoint(address, length, name);

        // Add the call point to the symbol table under the interned name.
        symbolTable.put(name, getCallPointSymbolField(), callPoint);

        return callPoint;
    }
}