Skip to content

rla/llj

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

Releases

No releases published

Packages

No packages published

Languages