LLJ - Logic Language for JVM
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
conf
src
.gitignore
LICENSE
README.md
pom.xml
profile.sh

README.md

LLJ - Logic Language for JVM

LLJ is Prolog-like logic language for running on JVM. It allows close integration with Java libraries. LLJ was developed in 2008-2010. The code is fairly commented and covered with various test cases.

Differences from real Prolog

  • Code is loaded through Java classpath
  • Module names correspond to Java classpath entries
  • Syntax is based on UTF-8
  • Terms can be arbitrary Java objects
  • No term/goal expansion
  • No DCG's
  • No custom operators
  • Assert/retract can only be used for ground predicates
  • Most ISO-Prolog standard predicates are not implemented

Dependencies

For embedded usage there are no dependencies other than the Java Runtime Environment (>= 1.6). The interactive top-level command-line interface requires jline to be in the classpath.

Compiling

Compiling requires JDK (>= 1.6) and Maven. Run Maven goal mvn package to build the jar file into target/llj.jar.

Usage

Example module (queens benchmark):

:- module(ee:pri:rl:llj:benchmark:queens, [
	queens/2,
	count/2
]).

:- import(llj:list).
:- import(llj:lang).
:- import(llj:findall).

count(N, C):-
	findall(_, queens(N,_), L),
	length(L, C).

queens(N,Qs) :-
	range(1,N,Ns),
	queens(Ns,[],Qs).

queens([],Qs,Qs).
queens(UnplacedQs,SafeQs,Qs) :-
	select(UnplacedQs,UnplacedQs1,Q),
	not_attack(SafeQs,Q),
	queens(UnplacedQs1,[Q|SafeQs],Qs).

not_attack(Xs,X) :-
	not_attack(Xs,X,1).

not_attack([],_,_) :- !.
not_attack([Y|Ys],X,N) :-
	X =\= Y+N, X =\= Y-N,
	N1 is N+1,
	not_attack(Ys,X,N1).

select([X|Xs],Xs,X).
select([Y|Ys],[Y|Zs],X) :- select(Ys,Zs,X).

range(N,N,[N]) :- !.
range(M,N,[M|Ns]) :-
	M < N,
	M1 is M+1,
	range(M1,N,Ns).

Example code of using LLJ from Java:

public class MemberExample {
	
	public static void main(String[] args) throws LLJException {
	
		// Creates new LLJ context
		LLJContext context = new LLJContext("llj:list");
		
		// Creates new LLJ query
		RuntimeQuery query = context.createQuery("member(X, [1,2,3])");
		
		// Executes the query for the first answer
		if (query.execute()) {
			System.out.println("First answer: " + query.getBinding("X"));
		}
		
		// Tries to find more answers
		while (query.hasMore()) {
			System.out.println("Also: " + query.getBinding("X"));
		}
	}
}

The LLJContext class is thread safe while RuntimeQuery must be used only by a single thread at once. Multiple RuntimeQuery classes can be executed at once on the same context at the same time.

Defining predicates through Java code (this is example from llj:io module):

public class Io implements JavaModule {

	@Predicate(name="list_files", arity = 2)
	public AbstractGoal listFiles2(JavaCallGoal goal) throws Exception {
		File file = goal.getObject(0, File.class);
		goal.setVar(1, RuntimeListStruct.fromArray(file.listFiles()));
		
		return goal.G;
	}
}

Similar

  • WProlog is a Prolog implementation on JVM. While it lacks cut, arithmetics, modules and arithmetics I got some of my implementation ideas from it.
  • XProlog enhanced version of WProlog.

Authors

Some of the test cases were taken from example code of the excellent book Learn Prolog Now!.

License

LLJ is distributed under LGPL license.