prolog

package module
v0.15.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 31, 2022 License: MIT Imports: 10 Imported by: 32

README

prolog - the only reasonable scripting engine for Go

Go Reference Actions Status Go Report Card codecov Mentioned in Awesome Go

What is this?

ichiban/prolog is an embeddable scripting language for Go. Unlike any other scripting engines, ichiban/prolog implements logic programming language Prolog.

  • Easy to reason about: based on first-order logic
  • Easy to adopt: database/sql-like Go API
  • Intelligent: full-featured Prolog implementation
  • Highly customizable: sandboxing, custom predicates

ichiban/prolog vs otto vs go-lua

prolog otto go-lua
Language ISO Prolog ECMA Script Lua
Paradigm 🎓 Logic Object-oriented Object-oriented
Go API 😻 database/sql-like original original
Declarative
Sandboxing

Getting started

Install latest version
go get -u github.com/ichiban/prolog
Usage
Instantiate an interpreter
p := prolog.New(os.Stdin, os.Stdout) // Or `prolog.New(nil, nil)` if you don't need user_input/user_output.

Or, if you want a sandbox interpreter without any built-in predicates:

// See examples/sandboxing/main.go for details.
p := new(prolog.Interpreter)
Load a Prolog program
if err := p.Exec(`
	human(socrates).       % This is a fact.
	mortal(X) :- human(X). % This is a rule.
`); err != nil {
	panic(err)
}

Similar to database/sql, you can use placeholder ? to insert Go data as Prolog data.

if err := p.Exec(`human(?).`, "socrates"); err != nil { // Same as p.Exec(`human(socrates).`)
	panic(err)
}
Run the Prolog program
sols, err := p.Query(`mortal(?).`, "socrates") // Same as p.Query(`mortal(socrates).`)
if err != nil {
	panic(err)
}
defer sols.Close()

// Iterates over solutions.
for sols.Next() {
	fmt.Printf("Yes.\n") // ==> Yes.
}

// Check if an error occurred while querying.
if err := sols.Err(); err != nil {
	panic(err)
}

Or, if you want to query for the variable values for each solution:

sols, err := p.Query(`mortal(Who).`)
if err != nil {
	panic(err)
}
defer sols.Close()

// Iterates over solutions.
for sols.Next() {
	// Prepare a struct with fields which name corresponds with a variable in the query.
	var s struct {
		Who string
	}
	if err := sols.Scan(&s); err != nil {
		panic(err)
	}
	fmt.Printf("Who = %s\n", s.Who) // ==> Who = socrates
}

// Check if an error occurred while querying.
if err := sols.Err(); err != nil {
	panic(err)
}

The Default Language

Top Level

1pl is an experimental top level command for testing the default language and its compliance to the ISO standard.

You can install it with go install:

go install github.com/ichiban/prolog/cmd/1pl@latest

Then, you can enter the top level with 1pl:

$(go env GOPATH)/bin/1pl [<file>...]
Directives
  • :- dynamic(PI) Specifies the predicates indicated by PI are dynamic. ISO
  • :- multifile(PI) Specified the predicates indicated by PI may be in multiple files. ISO
  • :- discontiguous(PI) Specifies the predicates indicated by PI may be defined by clauses which are not consecutive read-terms. ISO
  • :- op(Priority, Specifier, Op) Alters the operator table. ISO
  • :- char_conversion(In, Out) Alters the character conversion mapping. ISO
  • :- initialization(T) Registers a goal for execution right before exiting Exec() or ExecContext(). ISO
  • :- include(F) Loads the content of the file F as if it were there instead of this directive. ISO
  • :- ensure_loaded(P) Loads the content of the file P if not loaded. ISO
  • :- set_prolog_flag(Flag, Value) Alters the value for the Prolog flag. ISO
Predicates
Control constructs
  • true Always succeeds. ISO
  • fail Always fails. ISO
  • call(Goal) Calls Goal. ISO
  • ! Cut. ISO
  • P, Q Conjunction. ISO
  • P; Q Disjunction. ISO
  • If -> Then If-then. ISO
  • If -> Then; Else If-then-else. ISO
  • catch(Goal, Catcher, Recovery) Calls Goal. If an exception is raised and unifies with Catcher, calls Recovery. ISO
  • throw(Ball) Raises an exception Ball. ISO
Term unification
  • X = Y Unifies X with Y. ISO
  • unify_with_occurs_check(X, Y) Unifies X with Y with occurs check. ISO
  • X \= Y Succeeds iff X and Y are not unifiable. ISO
  • subsumes_term(General, Specific) Succeeds iff there's a substitution θ such that Generalθ = Specificθ and Specificθ = Specific. ISO
Type testing
  • var(X) Succeeds iff X is a variable. ISO
  • atom(X) Succeeds iff X is an atom. ISO
  • integer(X) Succeeds iff X is an integer. ISO
  • float(X) Succeeds iff X is a float. ISO
  • atomic(X) Succeeds iff X is neither a variable nor a compound. ISO
  • compound(X) Succeeds iff X is a compound. ISO
  • nonvar(X) Succeeds iff X is not a variable. ISO
  • number(X) Succeeds iff X is either an integer or a float. ISO
  • callable(X) Succeeds iff X is either an atom or a compound. ISO
  • ground(X) Succeeds iff X is a ground term. ISO
  • acyclic_term(X) Succeeds iff X is acyclic. ISO
Term comparison
  • X @=< Y Either X == Y or X @< Y. ISO
  • X == Y Equivalent to compare(=, X, Y). ISO
  • X \== Y Equivalent to \+compare(=, X, Y). ISO
  • X @< Y Equivalent to compare(<, X, Y). ISO
  • X @> Y Equivalent to compare(>, X, Y). ISO
  • X @>= Y Either X == Y or X @> Y. ISO
  • compare(Order, X, Y) Compares X and Y and unifies Order with either <, =, or >. ISO
  • sort(List, Sorted) Succeeds iff Sorted unifies with a sorted list of List. ISO
  • keysort(Pairs, Sorted) Succeeds iff Pairs is a list of Key-Value pairs and Sorted unifies with a permutation of Pairs sorted by Key. ISO
Term creation and decomposition
  • functor(Term, Name, Arity) Succeeds iff Term ia either a compound term of Name and Arity or an atom of Name and Arity = 0. ISO
  • arg(N, Term, Arg) Succeeds iff Arg is the N-th argument of Term. ISO
  • Term =.. List Succeeds iff List is a list of the functor and arguments of Term. ISO
  • copy_term(Term1, Term2) Creates a copy of Term1 and unifies it with Term2. ISO
  • term_variables(Term, Vars) Succeeds iff Vars is a list of variables appear in Term. ISO
Arithmetic evaluation
  • Result is Expression Evaluates Expression and unifies it with Result. ISO
    • Expression is either:
      • integer,

      • float, or

      • evaluable functors
        • X + Y
        • X - Y
        • X * Y
        • X // Y
        • X / Y
        • X rem Y
        • X mod Y
        • -X
        • abs(X)
        • sign(X)
        • float_integer_part(X)
        • float_fractional_part(X)
        • float(X)
        • floor(X)
        • truncate(X)
        • round(X)
        • ceiling(X)
        • +(X)
        • X div Y
        • X ** Y
        • sin(X)
        • cos(X)
        • atan(X)
        • exp(X)
        • log(X)
        • sqrt(X)
        • max(X, Y)
        • min(X, Y)
        • X ^ Y
        • asin(X)
        • acos(X)
        • atan2(X, Y)
        • tan(X)
        • pi
        • X >> Y
        • X << Y
        • X /\ Y
        • X \/ Y
        • \X
        • xor(X, Y)
  • succ(X, S) Succeeds iff S is the successor of the non-negative integer X. prologue
Arithmetic comparison
  • E1 =:= E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 equals to EV2. ISO
  • E1 =\= E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 does not equal to EV2. ISO
  • E1 < E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 is greater than EV2. ISO
  • E1 =< E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 is greater than or equal to EV2. ISO
  • E1 > E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 is less than EV2. ISO
  • E1 >= E2 Succeeds iff E1 and E2 are evaluated to EV1 and EV2 respectively and EV1 is less than or equal to EV2. ISO
Clause retrieval and information
  • clause(Head, Body) Succeeds iff Head :- Body unifies with a clause in the DB. ISO
  • current_predicate(PI) Succeeds iff the predicate indicated by PI is in the DB. ISO
Clause creation and destruction
  • asserta(Clause) Prepends Clause to the DB. ISO
  • assertz(Clause) Appends Clause to the DB. ISO
  • retract(Clause) Removes a clause that unifies withClause from the DB. ISO
  • abolish(PI) Removes the predicate indicated by PI from the DB. ISO
  • retractall(Head) Removes all the clauses which head unifies with Head from the DB. ISO
All solutions
  • findall(Template, Goal, Instances) Succeeds iff Instances unifies with a list of Template for each solution of Goal. ISO
  • bagof(Template, Goal, Instances) Succeeds iff Instances unifies with a bag (multiset) of Template for each solution of Goal. ISO
  • setof(Template, Goal, Instances) Succeeds iff Instances unifies with a set of Template for each solution of Goal. ISO
Stream selection and control
  • current_input(Stream) Succeeds iff Stream unifies with the current input stream. ISO
  • current_output(Stream) Succeeds iff Stream unifies with the current output stream. ISO
  • set_input(S_or_a) Sets the current input stream to the stream indicated by S_or_a which is either the stream itself or its alias. ISO
  • set_output(S_or_a) Sets the current output stream to the stream indicated by S_or_a which is either the stream itself or its alias. ISO
  • open(File, Mode, Stream, Options) Opens the file File in Mode with Options and unifies the stream with Stream. ISO
    • Mode is either: read, write, or append.
    • Options is a list of stream options listed below:
      • type(T) Specifies the type of the stream. T is either text (default) or binary.
      • reposition(Bool) Specifies if the stream can be repositions. Bool is either true or false.
      • alias(A) Specifies the alias for the stream. A is an atom.
      • eof_action(Action) Specifies the action that will be taken when the input stream reached to the end. Action is either:
        • error which throws an exception,
        • eof_code which returns a value indicating the end of stream (default), or
        • reset which resets the stream.
  • open(File, Mode, Stream) Equivalent to open(File, Mode, Stream, []). ISO
  • close(S_or_a, Options) Closes the stream indicated by S_or_a which is the stream itself or its alias. ISO
    • Options is a list of:
      • force(Bool) Specifies if an exception will be raised when it failed to close the stream. Bool is either false (default) or true.
  • close(S_or_a) Equivalent to close(S_or_a, []). ISO
  • flush_output(S_or_a) Sends any buffered output to the stream indicated by S_or_a which is either the stream itself or its alias. ISO
  • flush_output Equivalent to current_output(S), flush_output(S). ISO
  • stream_property(Stream, Property) Succeeds iff the stream Stream has the property Property. ISO
    • Property is either:
      • file_name(F)
      • mode(M)
      • input
      • output
      • alias(A)
      • position(P)
      • end_of_stream(E)
      • eof_action(A)
      • reposition(Bool)
      • type(T)
  • at_end_of_stream Equivalent to current_input(S), at_end_of_stream(S). ISO
  • at_end_of_stream(S_or_a) Succeeds iff the stream indicated by S_or_a which is either a stream or an alias has the property either end_of_stream(at) or end_of_stream(past). ISO
  • set_stream_position(S_or_a, Position) Sets the position of the stream indicated by S_or_a which is either a stream or an alias to the position Position. ISO
Character input/output
  • get_char(S_or_a, Char) Succeeds iff Char unifies with the next character from the stream indicated by S_or_a which is either a stream or an alias. ISO
  • get_char(Char) Equivalent to current_input(S), get_char(S, Char). ISO
  • get_code(S_or_a, Code) Succeeds iff Char unifies with the next code from the stream indicated by S_or_a which is either a stream or an alias. ISO
  • get_code(Code) Equivalent to current_input(S), get_code(S, Code). ISO
  • peek_char(S_or_a, Char) Similar to get_char(S_or_a, Char) but doesn't consume the character. ISO
  • peek_char(Char) Equivalent to current_input(S), peek_char(S, Char). ISO
  • peek_code(S_or_a, Code) Similar to get_code(S_or_a, Code) but doesn't consume the code. ISO
  • peek_code(Code) Equivalent to current_input(S), peek_code(S, Code). ISO
  • put_char(S_or_a, Char) Outputs the character Char to the stream indicated by S_or_a which is either a stream or an alias. ISO
  • put_char(Char) Equivalent to current_output(S), put_char(S, Char). ISO
  • put_code(S_or_a, Code) Outputs the code Code to the stream indicated by S_or_a which is either a stream or an alias. ISO
  • put_code(Code) Equivalent to current_output(S), put_code(S, Code). ISO
  • nl(S_or_a) Outputs a newline to the stream indicated by S_or_a which is either a stream or an alias. ISO
  • nl Equivalent to current_output(S), nl(S). ISO
Byte input/output
  • get_byte(S_or_a, Byte) Succeeds iff Byte unifies with the next byte from the stream indicated by S_or_a which is a stream or an alias. ISO
  • get_byte(Byte) Equivalent to current_input(S), get_byte(S, Byte). ISO
  • peek_byte(S_or_a, Byte) Similar to get_byte(S_or_a, Byte) but doesn't consume the byte. ISO
  • peek_byte(Byte) Equivalent to current_input(S), peek_byte(S, Byte). ISO
  • put_byte(S_or_a, Byte) Outputs the byte Byte to the stream indicated by S_or_a which is either a stream or an alias. ISO
  • put_byte(Byte) Equivalent to current_output(S), put_byte(S, Byte). ISO
Term input/output
  • read_term(S_or_a, Term, Options) Succeeds iff Term unifies with the next term from the stream indicated by S_or_a which is a stream or an alias. ISO
    • Options is a list of read options listed below:
      • variables(Vars) the list of variables appeared in Term
      • variable_names(VN_list) the list of A = V where A is an atom which name is the string representation of V and V is a variable appeared in Term
      • singletons(VN_list) similar to variable_names(VN_list) but those of variables that appeared once.
  • read_term(Term, Options) Equivalent to current_input(S), read_term(S, Term, Options). ISO
  • read(S_or_a, Term) Equivalent to read_term(S_or_a, Term, []). ISO
  • read(Term) Equivalent to current_input(S), read(S, Term). ISO
  • write_term(S_or_a, Term, Options) Outputs Term to the stream indicated by S_or_a which is either a stream or an alias. ISO
    • Options is a list of write options listed below:
      • quoted(Bool) Bool is either true or false. If true, atoms and functors will be quoted as needed.
      • ignore_ops(Bool) Bool is either true or false. If true, operators will be written in functional notation.
      • variable_names(VN_list) VN_list is a proper list which element is a form of A = V where A is an atom and V is a variable. Each occurrence of V will be replaced by the leftmost and unquoted A.
      • numbervars(Bool) Bool is either true or false. If true, terms '$VAR'(0), '$VAR'(1), ... will be written as A, B, ...
  • write_term(Term, Options) Equivalent to current_output(S), write_term(S, Term, Options). ISO
  • write(S_or_a, Term) Equivalent to write_term(S_or_a, Term, [numbervars(true)]). ISO
  • write(Term) Equivalent to current_output(S), write(S, Term). ISO
  • writeq(S_or_a, Term) Equivalent to write_temr(S_or_a, Term, [quoted(true), numbervars(true)]). ISO
  • writeq(Term) Equivalent to current_output(S), writeq(S, Term). ISO
  • write_canonical(S_or_a, Term) Equivalent to write_term(S_or_a, Term, [quoted(true), ignore_ops(true)]). ISO
  • write_canonical(Term) Equivalent to current_output(S), write_canonical(S, Term). ISO
  • op(Priority, Specifier, Operator) Alters the operator table. ISO
  • current_op(Priority, Specifier, Operator) Succeeds iff the operator indicated by Priority, Specifier, Operator is in the operator table. ISO
  • char_conversion(In, Out) Alters the character conversion mapping. ISO
  • current_char_conversion(In, Out) Succeeds iff the character conversion from In to Out is in the conversion mapping. ISO
Logic and control
  • \+Goal Succeeds iff call(Goal) fails. ISO
  • once(Goal) Calls Goal but never redoes. ISO
  • repeat Repeats the following code until it succeeds. ISO
  • call(Closure, Arg1, ..., ArgN) N = 1..7. Succeeds iff call(Goal) where Goal is Closure with additional arguments Arg1, ..., ArgN. ISO
  • false Equivalent to fail. ISO
  • between(Lower, Upper, X) Succeeds iff Lower <= X <= Upper. prologue
Atomic term processing
  • atom_length(Atom, Length) Succeeds iff Length is the number of runes in Atom. ISO
  • atom_concat(Atom1, Atom2, Atom3) Succeeds iff Atom3 is a concatenation of Atom1 and Atom2. ISO
  • sub_atom(Atom, Before, Length, After, SubAtom) Succeeds iff SubAtom is a sub atom of Atom where Before is the number of runes before SubAtom, Length is the length of SubAtom, and After is the number of runes after SubAtom. ISO
  • atom_chars(Atom, List) Succeeds iff List is the list of single-rune atoms that Atom consists of. ISO
  • atom_codes(Atom, List) Succeeds iff List is the list of runes that Atom consists of. ISO
  • char_code(Char, Code) Succeeds iff Char is a single-rune atom which rune is Code. ISO
  • number_chars(Number, List) Succeeds iff List is the list of single-rune atoms that represents Number. ISO
  • number_codes(Number, List) Succeeds iff List is the list of runes that represents Number. ISO
Implementation defined hooks
  • set_prolog_flag(Flag, Value) Sets the Prolog flag Flag to Value. ISO
    • Flag is either:
      • char_conversion Value is either on or off (default).
      • debug Value is either on or off (default).
      • unknown Value is either error (default), fail, or warning.
      • double_quotes Value is either chars (default), codes, or atom.
  • current_prolog_flag(Flag, Value) Succeeds iff Value is the current value for the Prolog flag Flag. ISO
    • Flag is either:
      • bounded Value is always true.
      • max_integer Value is always 9223372036854775807.
      • min_integer Value is always -9223372036854775808.
      • integer_rounding_function Value is always toward_zero.
      • char_conversion Value is either on or off (default).
      • debug Value is either on or off (default).
      • max_arity Value is always unbounded.
      • unknown Value is either error (default), fail, or warning.
      • double_quotes Value is either chars (default), codes, or atom.
  • halt(X) Exits the host program with the status code of X. ISO
  • halt Equivalent to halt(0). ISO
Definite clause grammars
  • expand_term(In, Out) Succeeds iff Out is an expansion of the term In.
  • phrase(Phrase, List, Remainder) Succeeds iff the different list List-Remainder satisfies the grammar rule Phrase.
  • phrase(Phrase, List) Equivalent to phrase(Phrase, List, []).
List processing
  • member(X, L) Succeeds iff X is a member of the list L. prologue
  • append(Xs, Ys, Zs) Succeeds iff Zs is the concatenation of Xs and Ys. prologue
  • length(List, Length) Succeeds iff Length is the length of List. prologue
  • select(X, Xs, Ys) Succeeds iff X is an element of Xs and Ys is Xs with one occurence of X removed. prologue
  • maplist(Goal, List1, ..., Listn) n = 1..7. Succeeds iff List1, ..., Listn are the list of the same length and call(Goal, List1_i, ..., Listn_i) succeeds for all the i-th elements of List1, ..., Listn. prologue
  • nth0(N, List, Elem) Succeeds iff Elem is the N-th element of List counting from 0.
  • nth1(N, List, Elem) Succeeds iff Elem is the N-th element of List counting from 1.
Program
  • consult(File) Loads Prolog program files indicated by File. File is either an atom or a list of atoms. An atom abc indicates a Prolog program file ./abc or ./abc.pl.
  • [File|Files] Equivalent to consult([File|Files]).

Extensions

  • predicates: Native predicates for ichiban/prolog.

License

Distributed under the MIT license. See LICENSE for more information.

Contributing

See ARCHITECTURE.md for architecture details.

  1. Fork it (https://github.com/ichiban/prolog/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

Acknowledgments

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrClosed = errors.New("closed")

ErrClosed indicates the Solutions are already closed and unable to perform the operation.

View Source
var ErrNoSolutions = errors.New("no solutions")

ErrNoSolutions indicates there's no solutions for the query.

Functions

This section is empty.

Types

type Interpreter added in v0.2.0

type Interpreter struct {
	engine.VM
	// contains filtered or unexported fields
}

Interpreter is a Prolog interpreter. The zero value is a valid interpreter without any predicates/operators defined.

func New added in v0.2.0

func New(in io.Reader, out io.Writer) *Interpreter

New creates a new Prolog interpreter with predefined predicates/operators.

Example (AcyclicTerm)
p := New(nil, nil)

sols, _ := p.Query(`acyclic_term(a(1, _)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`X = f(X), acyclic_term(X).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()
Output:

true
false
Example (Arg)
p := New(nil, nil)

sols, _ := p.Query(`arg(1, foo(a, b), a).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`arg(1, foo(a, b), X).`)
for sols.Next() {
	var s struct {
		X string
	}
	_ = sols.Scan(&s)
	fmt.Printf("X = %s\n", s.X)
}
_ = sols.Close()

sols, _ = p.Query(`arg(1, foo(X, b), a).`)
for sols.Next() {
	var s struct {
		X string
	}
	_ = sols.Scan(&s)
	fmt.Printf("X = %s\n", s.X)
}
_ = sols.Close()

sols, _ = p.Query(`arg(1, foo(X, b), Y), X = a.`)
for sols.Next() {
	var s struct {
		X, Y string
	}
	_ = sols.Scan(&s)
	fmt.Printf("X = %s, Y = %s\n", s.X, s.Y)
}
_ = sols.Close()

sols, _ = p.Query(`arg(1, foo(a, b), b).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`arg(0, foo(a, b), foo).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`arg(3, foo(a, b), N).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`arg(X, foo(a, b), a).`)
sols.Next()
fmt.Printf("%v\n", sols.Err())
_ = sols.Close()

sols, _ = p.Query(`arg(1, X, a).`)
sols.Next()
fmt.Printf("%v\n", sols.Err())
_ = sols.Close()

sols, _ = p.Query(`arg(0, atom, A).`)
sols.Next()
fmt.Printf("%v\n", sols.Err())
_ = sols.Close()

sols, _ = p.Query(`arg(0, 3, A).`)
sols.Next()
fmt.Printf("%v\n", sols.Err())
_ = sols.Close()
Output:

true
X = a
X = a
X = a, Y = a
false
false
false
error(instantiation_error,arg/3)
error(instantiation_error,arg/3)
error(type_error(compound,atom),arg/3)
error(type_error(compound,3),arg/3)
Example (Callable)
p := New(nil, nil)

sols, _ := p.Query(`callable(a).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`callable(3).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`callable(X).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`callable((1,2)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()
Output:

true
false
false
true
Example (Ground)
p := New(nil, nil)

sols, _ := p.Query(`ground(3).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`ground(a(1, _)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()
Output:

true
false
Example (Phrase)
p := New(nil, nil)
_ = p.Exec(`
determiner --> [the].
determiner --> [a].

noun --> [boy].
noun --> [girl].

verb --> [likes].
verb --> [scares].

noun_phrase --> determiner, noun.
noun_phrase --> noun.

verb_phrase --> verb.
verb_phrase --> verb, noun_phrase.

sentence --> noun_phrase, verb_phrase.
`)

sols, _ := p.Query(`phrase([the], [the]).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`phrase(sentence, [the, girl, likes, the, boy]).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`phrase(sentence, [the, girl, likes, the, boy, today]).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`phrase(sentence, [the, girl, likes]).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`phrase(sentence, Sentence).`)
for sols.Next() {
	var s struct {
		Sentence []string
	}
	_ = sols.Scan(&s)
	fmt.Printf("Sentence = %s\n", s.Sentence)
	break // Many other sentences follow.
}
_ = sols.Close()

sols, _ = p.Query(`phrase(noun_phrase, [the, girl, scares, the, boy], Rest).`)
for sols.Next() {
	var s struct {
		Rest []string
	}
	_ = sols.Scan(&s)
	fmt.Printf("Rest = %s\n", s.Rest)
}
_ = sols.Close()
Output:

true
true
false
true
Sentence = [the boy likes]
Rest = [scares the boy]
Example (Sort)
p := New(nil, nil)

sols, _ := p.Query(`sort([1, 1], Sorted).`)
for sols.Next() {
	var s struct {
		Sorted []int
	}
	_ = sols.Scan(&s)
	fmt.Printf("Sorted = %d\n", s.Sorted)
}
_ = sols.Close()

sols, _ = p.Query(`sort([X, 1], [1, 1]).`)
for sols.Next() {
	var s struct {
		X int
	}
	_ = sols.Scan(&s)
	fmt.Printf("X = %d\n", s.X)
}
_ = sols.Close()

sols, _ = p.Query(`sort([1, 1], [1, 1]).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`sort([V], V).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`sort([f(U),U,U,f(V),f(U),V],L).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()
Output:

Sorted = [1]
X = 1
false
true
true
Example (Subsumes_term)
p := New(nil, nil)

sols, _ := p.Query(`subsumes_term(a, a).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`subsumes_term(f(X,Y), f(Z,Z)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`subsumes_term(f(Z,Z), f(X,Y)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`subsumes_term(g(X), g(f(X))).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`subsumes_term(X, f(X)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()

sols, _ = p.Query(`subsumes_term(X, Y), subsumes_term(Y, f(X)).`)
fmt.Printf("%t\n", sols.Next())
_ = sols.Close()
Output:

true
true
false
false
false
true

func (*Interpreter) Exec added in v0.2.0

func (i *Interpreter) Exec(query string, args ...interface{}) error

Exec executes a prolog program.

Example (Placeholders)
p := New(nil, os.Stdout)

_ = p.Exec(`my_atom(?).`, "foo")
sols, _ := p.Query(`my_atom(A), atom(A), write(A), nl.`)
sols.Next()
_ = sols.Close()

_ = p.Exec(`my_int(?, ?, ?, ?, ?).`, int8(1), int16(1), int32(1), int64(1), 1)
sols, _ = p.Query(`my_int(I, I, I, I, I), integer(I), write(I), nl.`)
sols.Next()
_ = sols.Close()

_ = p.Exec(`my_float(?, ?).`, float32(1), float64(1))
sols, _ = p.Query(`my_float(F, F), float(F), write(F), nl.`)
sols.Next()
_ = sols.Close()

_ = p.Exec(`my_atom_list(?).`, []string{"foo", "bar", "baz"})
sols, _ = p.Query(`my_atom_list(As), maplist(atom, As), write(As), nl.`)
sols.Next()
_ = sols.Close()

_ = p.Exec(`my_int_list(?).`, []int{1, 2, 3})
sols, _ = p.Query(`my_int_list(Is), maplist(integer, Is), write(Is), nl.`)
sols.Next()
_ = sols.Close()

_ = p.Exec(`my_float_list(?).`, []float64{1, 2, 3})
sols, _ = p.Query(`my_float_list(Fs), maplist(float, Fs), write(Fs), nl.`)
sols.Next()
_ = sols.Close()
Output:

foo
1
1.0
[foo,bar,baz]
[1,2,3]
[1.0,2.0,3.0]

func (*Interpreter) ExecContext added in v0.3.0

func (i *Interpreter) ExecContext(ctx context.Context, query string, args ...interface{}) error

ExecContext executes a prolog program with context.

func (*Interpreter) Query added in v0.2.0

func (i *Interpreter) Query(query string, args ...interface{}) (*Solutions, error)

Query executes a prolog query and returns *Solutions.

Example (Placeholders)
p := New(nil, os.Stdout)
sols, _ := p.Query(`A = ?, atom(A), write(A), nl.`, "foo")
sols.Next()
_ = sols.Close()
sols, _ = p.Query(`(I, I, I, I, I) = (?, ?, ?, ?, ?), integer(I), write(I), nl.`, int8(1), int16(1), int32(1), int64(1), 1)
sols.Next()
_ = sols.Close()
sols, _ = p.Query(`(F, F) = (?, ?), float(F), write(F), nl.`, float32(1), float64(1))
sols.Next()
_ = sols.Close()
sols, _ = p.Query(`L = ?, maplist(atom, L), write(L), nl.`, []string{"foo", "bar", "baz"})
sols.Next()
_ = sols.Close()
sols, _ = p.Query(`L = ?, maplist(integer, L), write(L), nl.`, []int{1, 2, 3})
sols.Next()
_ = sols.Close()
sols, _ = p.Query(`L = ?, maplist(float, L), write(L), nl.`, []float64{1, 2, 3})
sols.Next()
_ = sols.Close()
Output:

foo
1
1.0
[foo,bar,baz]
[1,2,3]
[1.0,2.0,3.0]

func (*Interpreter) QueryContext added in v0.3.0

func (i *Interpreter) QueryContext(ctx context.Context, query string, args ...interface{}) (*Solutions, error)

QueryContext executes a prolog query and returns *Solutions with context.

func (*Interpreter) QuerySolution added in v0.6.0

func (i *Interpreter) QuerySolution(query string, args ...interface{}) *Solution

QuerySolution executes a Prolog query for the first solution.

func (*Interpreter) QuerySolutionContext added in v0.6.0

func (i *Interpreter) QuerySolutionContext(ctx context.Context, query string, args ...interface{}) *Solution

QuerySolutionContext executes a Prolog query with context.

type Scanner added in v0.15.0

type Scanner interface {
	Scan(vm *engine.VM, term engine.Term, env *engine.Env) error
}

Scanner is an interface for custom conversion from term to Go value.

type Solution added in v0.6.0

type Solution struct {
	// contains filtered or unexported fields
}

Solution is the single result of a query.

func (*Solution) Err added in v0.6.0

func (s *Solution) Err() error

Err returns an error that occurred while querying for the Solution, if any.

func (*Solution) Scan added in v0.6.0

func (s *Solution) Scan(dest interface{}) error

Scan copies the variable values of the solution into the specified struct/map.

type Solutions added in v0.2.0

type Solutions struct {
	// contains filtered or unexported fields
}

Solutions is the result of a query. Everytime the Next method is called, it searches for the next solution. By calling the Scan method, you can retrieve the content of the solution.

func (*Solutions) Close added in v0.2.0

func (s *Solutions) Close() error

Close closes the Solutions and terminates the search for other solutions.

func (*Solutions) Err added in v0.2.0

func (s *Solutions) Err() error

Err returns the error if exists.

func (*Solutions) Next added in v0.2.0

func (s *Solutions) Next() bool

Next prepares the next solution for reading with the Scan method. It returns true if it finds another solution, or false if there's no further solutions or if there's an error.

func (*Solutions) Scan added in v0.2.0

func (s *Solutions) Scan(dest interface{}) error

Scan copies the variable values of the current solution into the specified struct/map.

Example
p := New(nil, nil)
sols, _ := p.Query(`A = foo, I = 42, F = 3.14.`)
for sols.Next() {
	var s struct {
		A string
		I int
		F float64
	}
	_ = sols.Scan(&s)
	fmt.Printf("A = %s\n", s.A)
	fmt.Printf("I = %d\n", s.I)
	fmt.Printf("F = %.2f\n", s.F)
}
Output:

A = foo
I = 42
F = 3.14
Example (List)
p := New(nil, nil)
sols, _ := p.Query(`Atoms = [foo, bar], Integers = [1, 2], Floats = [1.1, 2.1], Mixed = [foo, 1, 1.1].`)
for sols.Next() {
	var s struct {
		Atoms    []string
		Integers []int64
		Floats   []float64
		Mixed    []interface{}
	}
	_ = sols.Scan(&s)

	fmt.Printf("Atoms = %s\n", s.Atoms)
	fmt.Printf("Integers = %d\n", s.Integers)
	fmt.Printf("Floats = %.1f\n", s.Floats)
	fmt.Printf("Mixed = %v\n", s.Mixed)
}
Output:

Atoms = [foo bar]
Integers = [1 2]
Floats = [1.1 2.1]
Mixed = [foo 1 1.1]
Example (Tag)
p := New(nil, nil)
sols, _ := p.Query(`A = foo, I = 42, F = 3.14.`)
for sols.Next() {
	var s struct {
		Atom    string  `prolog:"A"`
		Integer int     `prolog:"I"`
		Float   float64 `prolog:"F"`
	}
	_ = sols.Scan(&s)
	fmt.Printf("Atom = %s\n", s.Atom)
	fmt.Printf("Integer = %d\n", s.Integer)
	fmt.Printf("Float = %.2f\n", s.Float)
}
Output:

Atom = foo
Integer = 42
Float = 3.14

type TermString added in v0.15.0

type TermString string

TermString is a string representation of term.

func (*TermString) Scan added in v0.15.0

func (t *TermString) Scan(vm *engine.VM, term engine.Term, env *engine.Env) error

Scan implements Scanner interface.

Directories

Path Synopsis
cmd
1pl
examples
dcg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL