
Table of Contents
Requires J2SE 1.2 or greater.
Go to llava.org
Download llava.zip
Unzip it resulting in llava.jar
Startup: java -jar llava.jar
Or: java -cp llava.jar org.llava.Llava
Note, you should start up with the main class, org.llava.Llava, if you want to import llava files (i.e., *.lva) from locations on your classpath
Examples: check out the libraries in org.llava.lib in llava.jar
Optional source code: llavasrc.zip
For a full list of improvements see the TODO list
where category may be "syntax" or "procedure", and where location specifies the package containing the feature. If the location is contained inside (import location) then the package must be imported in order to use the feature. Otherwise the feature is already imported and location simply gives the package location of the feature.
(* 5 8) ==> 40
means that the expression (* 5 8) evalutes to the object 40.
(new packagePathAndClassName obj ...)
Examples:
(new 'java.util.Date) (new 'java.lang.Integer 3)
Note: if the class has been imported then you can call the constructor directly:
(import java.lang.Integer) (Integer 3)
or you can use new shorthand:
(new 'Integer 3)
Also note, even though new is syntax, all arguments are evaluated.
(-i methodName targetObj obj ...)
Examples:
(-i 'getMonth (new 'java.util.Date))
Note, virtual methods may use standard (and preferred) prefix generic procedure notation:
(methodName targetObj obj ...)
If methodName has not been bound or has been bound to a generic procedure then this is equivalent to:
(-i methodName targetObj obj ...)
The above example is best written as:
(getMonth (new 'java.util.Date))
(-f fieldName targetObj optionalSetterValue)
Examples:
(-f 'minor (new 'org.omg.CORBA.BAD_PARAM)) ; get (-f 'minor (new 'org.omg.CORBA.BAD_PARAM) 56) ; set
Note, virtual fields may be accessed directly after their class has been imported. The above example can then be written:
(import org.omg.CORBA.SystemException) (minor (new 'org.omg.CORBA.BAD_PARAM)) (minor! (new 'org.omg.CORBA.BAD_PARAM) 56)
(-sf fieldName classOrClassName optionalSetterValue)
Examples:
(-sf 'out 'java.lang.System) ; get (-sf 'out 'java.lang.System 0) ; set - and an error since Field is final
Note, static fields may be accessed directly after their class has been imported. The above example can then be witten as:
(import java.lang.System) (out) (out! 0)
or, preferred
(System.out)
(define ( variable requiredArg ... . optionalArg ) body)
Binds a procedure to variable that, when called, will first use Java reflection to find a method on the first argument that matches the types of the remaining arguments. If one is found it is invoked. Otherwise body is executed after the arguments are bound.
Example:
(define (name requiredArg1 requiredArg2 . optionalArgs) body)
Defines a generic procedure which, when called as:
(name 1 2)
will first try:
(-i name 1 2)
If no Java method is found (and invoked) then the generic procedure body will be called:
((lambda (requiredArg1 requiredArg2 . optionalArgs) body) 1 2)
Example:
(define (getMessage x) (cdr x)) (getMessage '(1 2 3)) ==> (2 3) (getMessage (new 'java.lang.Exception "test msg")) ==> test msg
(define variable ( lambda ( requiredArg ... . optionalArgs ) body ) )
Binds a procedure to variable that, when called, will always execute body after the arguments are bound.
Example:
(define name (lambda (requiredArg1 requiredArg2 . optionalArgs) body)
defines a generic procedure which, when called as:
(name 1 2)
will always call:
((lambda (requiredArg1 requiredArg2 . optionalArgs) body) 1 2)
Example:
(let ((bomb 1))
(define (demo)
(try
(begin
(if (< bomb 0)
(throw (new 'java.lang.RuntimeException "Give up!")))
(list "Normal result is: " (/ 2 bomb)))
(catch (java.lang.ArithmeticException e)
(list "Arithmetic: " e))
(catch (java.lang.Exception e)
(list "Exception: " e))
(finally
(set! bomb (- bomb 1))))))
(demo) ==> (Normal result is: 2)
(demo) ==> (Arithmetic: java.lang.ArithmeticException: / by zero)
(demo) ==> (Exception: java.lang.RuntimeException: Give up!)
Note, it is not necessary to give the full classpath in the catch clause if the class has been imported.
Also see org.llava.lib.Thread
package and import create, load and reference namespaces.
import searches the roots of CLASSPATH for files ending in *.lva with the given path and name. If one is found it is loaded.
The first form in an imported *.lva file must be a package declaration.
The namespace of the imported package is added to the end of list of namespaces imported into the package current when the import statement is evaluated.
Variable definitions and references occur with respect to the current package. If the variable is not found in the current package the import list is searched in order. If not found in the import list the top-level org.llava package is searched last.
If symbol names a *.class file instead then it results in generic procedure definitions for all virtual methods and results in non-generic procedure definitions of static methods and fields (both static and virtual):
(import java.lang.System)
then
(java.lang.System.out)
and
(System.out) ;; both equivalent to (-sf 'out 'java.lang.System)
(import java.lang.Integer)
then
(java.lang.Integer.TYPE)
and
(Integer.TYPE) ;; both equivalent to (-sf 'TYPE 'java.lang.Integer)
(java.lang.Integer.parseInt "ff" 16)
and
(Integer.parseInt "ff" 16)
;; both equivalent to (-si 'parseInt 'java.lang.Integer "ff" 16)
Note: these definitions take places in the current package. In the future this will change such that a llava namespace is created, the definitions will be placed in that package and that package will be added to the import list of the current package.
llava is statically scoped.
llava is dynamically typed.
llava is properly tail-recursive.
Arguments to llava procedures are passed by value.
Like Scheme, llava is a Lisp-1, meaning that functions and variables are stored in the same namespaces (which is different from Common Lisp, a Lisp-2, which uses different namespaces for functions and variables).
llava uses a parenthesized prefix notation for programs and (other) data.
The -read procedure performs syntactic as well as lexical decomposition of the data it reads.
The following llava syntax (i.e., special forms) is immutable.
From (or similar to) Scheme:
begin define define-final lambda let letrec quote set!
From Java:
if
llava is case-sensitive. For example, Foo is not the same identifier as FOO.
A block comment. Recognized by org.llava.lib.LlavaDoc.
. + - Used in numbers and identifiers, as in R5RS.
( ) Used for grouping and to notate lists, as in R5RS.
' Indicates literal data, as in R5RS.
` Indicates almost constant data, as in R5RS.
, ,@ Used in conjunction with backquote, as in R5RS.
" Used to delimit strings, as in R5RS.
\ Used in character constants and as an escape within string constants, as in R5RS.
true false These are the boolean constants.
#\ Introduces a character constants, as in R5RS.
#( Introduces a vector constant, as in R5RS.
<variable>
-- syntax
An expression consisting of a identifier is a variable reference.
Misc., looping, mapping, case.
-- syntax -- (import org.llava.lib.Control)
Like let* but <bindings> happen inside a try and <body> can contain catch and finally.
Known bug: if you bind a variable which shadows an outer variable and uses the value of the outer variable for its initial value the newly bound variable will always have false for a value:
(define (foo b)
(list
(tlet* ((b b))
b
(catch (java.lang.Exception e) -1))
b))
(foo 3) ==> (false 3)
Generates package and procedure documentation in DocBook format.
Utilities to help with writing macros.
Procedures to manipulate strings.
Common Lisp control features.
Common Lisp macros.
Common Lisp sequence procedures.
Generic procedures to walk the contents of a file.
Java operations.