Skip to content

ichiban/prolog

Repository files navigation

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 ISO Prolog interpreter in Go.

Comparison with Other Libraries

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

ichiban/prolog adheres the ISO standard and comes with the ISO predicates as well as the Prologue for Prolog and DCG predicates.

See the Wiki for the directives and the built-in predicates.

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>...]

Extensions

  • predicates: Native predicates for ichiban/prolog.
  • kagomelog: a Japanese morphological analyzing predicate.

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

We would like to extend our thanks to the following individuals for their contributions to this project:

We are grateful for the support and contributions of everyone involved in this project. Arigatou gozaimasu!