/lice

A multi-paradigm programming language running on JVM

Primary LanguageKotlinGNU General Public License v3.0GPL-3.0

Lice

CI status
Travis CI Build Status
AppVeyor Build status
CircleCI CircleCI
CodeShip Codeship Status for lice-lang/lice

JitPack
Download
Gitter
Dependency Status
codecov
License: GPL v3
Awesome Kotlin Badge

About

This is the interpreter of Lice language, a dialect of Lisp, run on JVM platform.

It supports call-by-value, call-by-name, call-by-need(we sometimes call it lazy evaluation) at the same time. Functions and values are treated as the same. Dynamic scoping, because I can't find a better scoping solution for a interpreted language.

See FeatureTest to learn more about the language's features.

Also, as the main repo for the Lice language, this repo will not be updated very frequently.
Instead, I do language feature experiments in The tiny version of Lice, which is more actively updated and not guarenteed be backward capable.
Once a feature is finished and tested, and not considered harmful, I'll copy the codes here and publish releases.

It looks like

; print a string
(print "Hello " "World" "\n")

; travel through a range
(for-each i (.. 1 10) (print i "\n"))

; define a call-by-name function
(defexpr fold ls init op
 (for-each index-var ls
   (-> init (op init index-var))))

; invoke the function defined above
(fold (.. 1 4) 0 +)

; passing a call-by-value lambda to a call-by-value lambda
((lambda op (op 3 4)) (lambda a b (+ (* a a) (* b b))))

; to define a call-by-need lambda, use `lazy`.

Building

To use Lice with build tools, first add jcenter to your repositories list.

With gradle, add this to your dependencies list:

compile 'org.lice:lice:3.3.2'

Or with maven:

<dependency>
  <groupId>org.lice</groupId>
  <artifactId>lice</artifactId>
  <version>3.3.2</version>
  <type>pom</type>
</dependency>

Or with ivy:

<dependency org='org.lice' name='lice' rev='3.3.2'>
  <artifact name='lice' ext='pom'/>
</dependency>

Alternatively, you can download the nightly jar for the newest commit on AppVeyor.

Script API

import javax.script.*;

public class LiceScriptEngineTest {
    public static void main() throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("lice");
        engine.eval("(-> x 10)");
        engine.eval("(print x)");
    }
}

Lice performance

Code to run:

; loops
(def loop count block (|>
    (-> i 0)
    (while (< i count) (|> (block i)
    (-> i (+ i 1))))))

; invoking the function
(loop 200000 (lambda i (|>
    (defexpr let x y block (|>
        (-> x y) ; this is actually an issue of lice.
        (block)
        (undef x)))
    (let reimu 100 (lambda (|> x))))))

(print "loop count: " i)

Environment: Ubuntu Linux 16.04, HotSpot 1.8u151, Intel core i7 4720HQ 2.6 GHz

Condition Time
Lice call Java using extern 350ms
Lice call Java using Lice API 295ms
Pure Java 13ms
Pure Lice 897ms
Java call Lice using Lice API 629ms

Lice invoking Java

Lice has handy APIs for interacting with Java.

; declare an extern function
; must be a static Java function
(extern "java.util.Objects" "equals")

; calling the extern function
(equals 1 1)

Java invoking Lice

This project provides handy APIs for running Lice codes from Java.

class SomeClass {
  public static void main(String[] args){
    // Running Lice
    System.out.println(Lice.run("(+ 1 1)")); // prints 2
    System.out.println(Lice.run(new File("example.lice"))); // run codes in a file
    
    // Lice API
    SymbolList env = new SymbolList();
    Lice.run("(def blablabla a (+ a a)) (-> myVar 233)", env);
    env.extractLiceFunction("blablabla").invoke(233); // result: 466
    int var = ((Number) env.extractLiceVariable("myVar")).intValue(); // result: 233
  }
}