OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / opencog / atoms / scope / PutLink.h

110 lines · c ref:
/*
 * opencog/atoms/scope/PutLink.h
 *
 * Copyright (C) 2015 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef _OPENCOG_PUT_LINK_H
#define _OPENCOG_PUT_LINK_H

#include <opencog/atoms/scope/PrenexLink.h>

namespace opencog
{
/** \addtogroup grp_atomspace
 *  @{
 */

/**
 * The PutLink implements a beta redex; it is similar to an imperative
 * version of MemberLink, with arguments reversed.
 *
 * A beta redex is a concatenation or composition of a combinator, and
 * a list of arguments.  Typically, the combinator will be a LambdaLink,
 * typically with N declared variables in it. To go with it, the PutLink
 * expects a list of N arguments to be plugged in for these variables.
 * Thus, for example:
 * (Put (Lambda (Variable "x") ...stuff...) (Concept "foo"))
 * when reduced, will plug "foo" into ...stuff...
 *
 * Another supported form for the combinator is any of the
 * FunctionLinks, e.g. the PlusLink, TimesLink, etc. in which case,
 * one can write (Put (Plus) (List (Number 2) (Number 2))) as the beta
 * redex that, when reduced, will return (Number 4). Fancier forms for
 * the combinator are allowed: for example,
 * (Put (Plus (Number 6) (Number 8)) (List (Number 5) (Number 9)))
 *
 * The natural form for a beta redex is in the unreduced
 * form: the arguments are not (yet) substituted for the variables; they
 * are simply sitting there, ready and waiting for that reduction to
 * happen.
 *
 * It defines a reduce() method, which implements the actual beta
 * reduction.  The reduce() method only performs the substitution; it
 * does not attempt to execute or evaluate the resulting expression.
 *
 * The implementation for PutLink is not a "pure" beta-redex, but
 * has extra stuff to make it play nice with GetLink.  That is, we'd
 * like to pipe the output of GetLink directly into PutLink as input,
 * but for one problem: GetLink returns it's stuff wrapped in SetLink's.
 * So, in order to play nice, we automatically unwrap these, beta reduce
 * them, and then wrap the answers back up with a SetLink.
 *
 * Another "enhancement" is that when there are N>1 variables, the
 * arguments must be wrapped in a ListLink, to be consistent with other
 * parts of atomese. However, for N=1, the ListLink is optional.
 */
class PutLink : public PrenexLink
{
protected:
	/// The arguments that are to be placed into the body.
	Handle _arguments;

	void init(void);
	void static_typecheck_arguments(void);

	Handle do_reduce(void) const;

public:
	PutLink(const HandleSeq&&, Type=PUT_LINK);
	PutLink(const PutLink&) = delete;
	PutLink& operator=(const PutLink&) = delete;
	virtual ~PutLink() {}

	// PutLink arguments may be the second or the third outgoing-set elt.
	Handle get_arguments() { return _arguments; }

	virtual bool is_executable() const { return true; }
	virtual ValuePtr execute(AtomSpace*, bool silent=false);

	// Crazy handling for historical PutLink reduction.
	virtual bool is_evaluatable() const { return true; }
	virtual bool bevaluate(AtomSpace*, bool silent=false);

	static Handle factory(const Handle&);
};

LINK_PTR_DECL(PutLink)
#define createPutLink CREATE_DECL(PutLink)

/** @}*/
}

#endif // _OPENCOG_PUT_LINK_H