npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lisp2js

v0.0.36

Published

A simple lisp to javascript translater

Downloads

15

Readme

lisp2js beta (clojure like syntax)

By Yiyi Wang (shd101wyy)

Simple Lisp that compiles to JavaScript ~~(targeting ECMAScript 6)~~
~~So ECMAScript 5 might not work.~~
As es6 is not fully supported, the language will compile to es5.

npm / github

npm
github

Installation

    npm -g install lisp2js  

How to run

    lisp2js                               # repl
    lisp2js   [file1.lisp]                # run file1.lisp
    lisp2js   [file1.lisp]  [file2.js]    # compile [file1.lisp] to js file [file2.js]

Use lisp2js in Browser

<script src="lisp2js.js"></script>
<script>
    var output = lisp.compile("(def x 12)"); // compile/eval expression, then return compiled result.
</script>

Click Me to Try it Online

Online REPL


all comma, tab, space will be ignored.


Examples

Basics

  • comment
    ; semicolon is used as comment
    ;; this is comment
  • define variable value
    (def x 12)
    (def ->this*name$invalid@in*js 13)   ;; a invalid js variable name, which will be replaced with another name.
    (def ** Math.pow)
    var x = 12;
    var _$45__$62_this_$42_name$invalid_$64_in_$42_js = 13;  // all invalid characters are replaced with its own charcode.
    var _$42__$42_ = Math.pow;
  • change variable value
    (set! x 15)  
    x = 15;
  • define function
    (defn add [a b]
        (+ a b))
    function add(a, b){
        return a + b;
    }
  • call function
    (add 3 4)
    add(3, 4);
  • define function with default parameters
    (defn add [:a 12 :b 3]
        (+ a b))
    function add(a, b) {
        a = (a === void 0 ? 12 : a);
        b = (b === void 0 ? 3 : b);
        return (a + b);
    };
  • define function with keyword parameters
    (defn add [x {:y 1 :z 2}]
        (+ x y z))
    (add 0)        ;;  3
    (add 1 :y 3)   ;;  6
    function add(x, __lisp_args__) {
        var __lisp_args_v__;
        __lisp_args__ = (__lisp_args__ === void 0 ? {} : __lisp_args__);
        var y = ((__lisp_args_v__ = __lisp_args__.y) === void 0 ? 1 : __lisp_args_v__);
        var z = ((__lisp_args_v__ = __lisp_args__.z) === void 0 ? 2 : __lisp_args_v__);
        return (x + y + z);
    };
    add(0);
    add(1, {
        y: 3
    });
  • call function with named(keyword) parameters
    (defn add [{:a 1 :b 2}] (+ a b))
    (add)                  ;; => 3
    (add :a 3 :b 4)        ;; => 7
    (add :b 3)             ;; => 4
    function add(__lisp_args__) {
        var __lisp_args_v__;
        __lisp_args__ = (__lisp_args__ === void 0 ? {} : __lisp_args__);
        var a = ((__lisp_args_v__ = __lisp_args__.a) === void 0 ? 1 : __lisp_args_v__);
        var b = ((__lisp_args_v__ = __lisp_args__.b) === void 0 ? 2 : __lisp_args_v__);
        return (a + b);
    };
    add();
    add({
        a: 3,
        b: 4
    });
    add({
        b: 3
    });
  • define function with rest parameters
    (defn add [a & b]   ;; b here is Array
        (+ a b[0]))
    (defn add [a . b]   ;; b here is List
        (+ a (car b)))
    function add(a) {
        for (var b = [], $__0 = 1; $__0 < arguments.length; $__0++) b[$__0 - 1] = arguments[$__0];
        return (a + b[0]);
    };  
    function add(a) {
        for (var b = [], $__0 = 1; $__0 < arguments.length; $__0++) b[$__0 - 1] = arguments[$__0];
        b = list.apply(null, b);
        return (a + car(b));
    };
  • anonymous function
    (fn [a :b 13 & c]
        (+ a b c[0]))
    function (a, b){
        for (var c = [], $__0 = 2; $__0 < arguments.length; $__0++) c[$__0 - 2] = arguments[$__0];
        b = (b === void 0 ? 13 : b);
        return (a + b + c[0]);
    };
  • do. run a series of exps.
    (do  (+ 1 2)
         (- 3 4)
         (* 5 6))

    (fn []
        (do (+ 1 2)
            (- 3 4)
            (* 5 6)))
    (if 1
        (do (def x 1) (def y 2))
        (do (def x 2) (def y 1)))
    (1 + 2);
    (3 - 4);
    (5 * 6);;

    function() {
        (1 + 2);
        (3 - 4);
        return (5 * 6);;
    };
    if (1) {
        var x = 1;
        var y = 2;
    } else {
        var x = 2;
        var y = 1;
    };
  • if
    (if 1 2 3)
    (def x (if 1 2 3))
    if (1) {
        2
    } else {
        3
    };
    var x = (1 ? 2 : 3);
  • cond
    (cond test1 (do stm1 stm2)
          test2 (do stm3 stm4)
          test3 stm5
          else stm6)
    if (test1) {
      stm1;
      stm2;
    } else if (test2) {
      stm3;
      stm4;
    } else if (test3) {
      stm5;
    } else {
      stm6;
    };
  • case
    (defn test [x]
        (case x
            "apple" "This is apple"
            "orange" "This is orange"
            else "This is nothing"))
    function test(x) {
        switch (x) {
            case "apple":
                return "This is apple";
            case "orange":
                return "This is orange";
            default:
                return "This is nothing";
        };
    };
  • let (es5) // I might change this to es6 let in the future
    (let [x 1
          y 2
          x (+ x y)
          z 4]
        (+ x y z))
    (+ (let [x 1 y 2] (- x y))
        3)
    (defn test []
        (let x 1 y 2 (+ x y)))
    ((function() {
        var x = 1;
        var y = 2;
        x = (x + y);
        var z = 4;
        return (x + y + z)
    })());
    (((function() {
        var x = 1;
        var y = 2;
        return (x - y)
    })()) + 3);
    function test() {
        return ((function() {
            var x = 1;
            var y = 2;
            return (x + y)
        })());
    };
  • throw
    (throw "Too Big")
    throw "Too Big";
  • yield
    (defn test []
        (yield 1)
        (yield 2))
    (def x (test))
    (x.next)   ;; 1
    (x.next)   ;; 2
    (x.next)   ;; stop
    function test() {
        yield 1;
        yield 2;
        return;
    };
    var x = test();
    x.next();
    x.next();
    x.next();
  • try/catch/finally
    (try (console.log "This is try")
    catch e (console.log "This is catch")
    finally (console.log "This is finally"))
    try {
      console.log("This is try");
    } catch (e) {
      console.log("This is catch");
    } finally {
      console.log("This is finally");
    };
  • some operators
    (= 1 1)
    (+ 1 2 3)
    (- 1 2 3)
    (* 1 2 3)
    (/ 1 2 3)
    (* (+ 1 2) (- 3 4))
    (> 1 2 3 4)
    (<= 1 2 3 4)
    (&& true false)
    (|| 1 2)
    (| 1 0x12)
    (and true false)
    (or true false)
    (not true)
    (1 === 1);
    (1 + 2 + 3);
    (1 - 2 - 3);
    (1 * 2 * 3);
    (1 / 2 / 3);
    ((1 + 2) * (3 - 4));
    (1 > 2 && 2 > 3 && 3 > 4);
    (1 <= 2 && 2 <= 3 && 3 <= 4);
    (true && false);
    (1 || 2);
    (1 | 0x12);
    (true && false);
    (true || false);
    (!true);
  • get
    (get "abcd" 'length)
    (get console .log)
    "abcd"["length"];
    console.log;
  • ->
    (-> console (.log "Hello World"))
    (-> $ (.post "test.php")
          (.done (fn () "done"))
          (.fail (fn () "fail")))
    (-> "i am cool"
        .length)
    console.log("Hello World");
    $.post("test.php").done(function() {
        return "done";
    }).fail(function() {
        return "fail";
    });
    "i am cool".length;
  • class (this might be buggy, I will implement class in es6 in the future)
    (class Animal
        :constructor (fn [age]                ;; define constructor
                        (set! this.age age))
        :showAge (fn []                       ;; define method
                    (console.log "Called from Animal")
                    (console.log this.age)))
    (class Dog extends Animal
        :constructor (fn [age]                ;; define constructor
                        (super age))          ;; call superclass constructor
        :showAge (fn []                       ;; define method
                    (console.log "Called from Dog")
                    (super.showAge))          ;; call superclass method
        :bark (fn []                          ;; define method
                (console.log "Bark!")))

    (def dog (new Dog 5))
    (dog.showAge)  ;;  Called from Dog
                   ;;  Called from Animal
                   ;;  5

    (dog.bark)     ;;  Bark!
  • loop
    ;; calculate factorial 10
    (loop [i 10
           acc 1]
        (if (= i 0)
            acc
            (recur (- i 1)
                   (* i acc))))
    (function __lisp__recur__$0(i, acc) {
        if ((i === 0)) {
            return acc
        } else {
            return __lisp__recur__$0((i - 1), (i * acc))
        };
    })(10, 1);
  • new
    (def x (new Array 1 2 3 4))
    var x = (new Array(1, 2, 3, 4));
  • in
    (in 'a {'a 12})
    ("a" in {"a": 12});
  • instanceof
    (instanceof [1 2 3] Array)
    ([1, 2, 3] instanceof Array)

  • List functions
    • To enable List datatype, include lisp.js from https://github.com/shd101wyy/List_for_FP
    • after you compile your .lisp file to javascript file.
    • This file will give you 4 functions: car, cdr, cons, list.
    •                  and 1 datatype: $List  
    • See the link above for more information.
  • define a list.
    (def x '(1 2 3))
    var x = cons(1, cons(2, cons(3, null)));
  • quasiquote
    (def x 12)
    `(~x x)     ;; => (12 x)
    var x = 12;
    cons(x, cons("x", null));
  • car, cdr, cons, list
    (def a 1)
    (def b 2)
    (def c (cons a (cons b '())))   ;; => (1 2)
    (car c)                         ;; => 1
    (cdr c)                         ;; => (2)
    (def l (list a b))           ;; => (1 2)
    var a = 1;
    var b = 2;
    var c = cons(a, cons(b, null));
    car(c);
    cdr(c);
    var l = list(a, b);

  • Use JavaScript Object/Array

  • define Array

    (def x [1 2 3])
    var x = [1, 2, 3];
  • define Object
    (def x {:a 12 b 13 "c" 14})
    // es6
    var x = {a: 12, [b]: 13, "c": 14};
  • es6 define value
    (def [x y z] [1 2 3])
    (def {:m :n} {:m 12 :n 20})
    // es6
    var [x, y, z] = [1, 2, 3];
    var {
        m, n
    } = {
        m: 12,
        n: 20
    };
  • change value
    (def x [1 2 3])
    (set! x[0] 12)
    (def y {:a 12 :b 13 :c (fn (a b) (+ a b))})
    (set! y.a 13)
    (set! y["a"] 13)
    var x = [1, 2, 3];
    x[0] = 12;
    var y = {
        a: 12,
        b: 13,
        c: function(a, b) {
            return (a + b);
        }
    };
    y.a = 13;
    y["a"] = 13;
  • get value
    (def y {:a 12 :b 13 :c (fn (a b) (+ a b))})
    (y.add y.a y.b)
    var y = {
        a: 12,
        b: 13,
        c: function(a, b) {
            return (a + b);
        }
    };
    y.add(y.a, y.b);

recur

similar to recur in clojure
  • recur
    (defn test [n]
      (cond (= n 0) 0
            1 (recur (- n 2))                ;; recur here means test
            else (recur (- n 1))))

    ;; anonymous function recur
    ((fn [n acc]
      (if (= n 0)
        acc
        (recur (- n 1) (* n acc)))) 10 1)  ;; recur <=> that anonymous function
    var test = function(n) {
      if ((n === 0)) {
        return 0;
      } else if (1) {
        return test((n - 2));
      } else {
        return test((n - 1));
      };
    };
    (function __lisp__recur__$0(n, acc) {
      if ((n === 0)) {
        return acc;
      } else {
        return __lisp__recur__$0((n - 1), (n * acc));
      };
    })(10, 1)

Macro

  • define a macro (unhygienic right now)
    (defmacro square [x] `(* ~x ~x))
    (square 12)
    (defmacro square-with-different-params
        [x] `(* ~x ~x)
        [x y] `(+ (* ~x ~x) (* ~y ~y)))
    (square-with-different-params 12)
    (square-with-different-params 15 16)
    (12 * 12);
    (12 * 12);
    ((15 * 15) + (16 * 16));
  • macro-expand: expand a macro form
    (defmacro square [x] `(* ~x ~x))
    ;; the macro-expand function will expand the macro until it no longer represents a macro form.
    (macro-expand '(square 12))  ; => '(* 12 12)

    (defmacro test [x] `(test (+ 1 ~x)))
    ;; macro-expand can also expand macro forms for n times.
    (macro-expand '(test 1) 2)   ; => '(test (+ 1 (+ 1 1)))   this will expand macro twice.
    (macro-expand '(test 1) 3)   ; => '(test (+ 1 (+ 1 (+ 1 1))))   this will expand macro for 3 times.
However, the macro implementation still has errors.

Change Log

  • Version 0.0.36

  • 2015/6/14

    • begin to use clojure like syntax.
  • 2015/3/15

  • Version 0.0.33

    • fix one macro bug
    • add =>
    • eg:
        (=> (x y) (+ x y))   ;; es6 (x, y) => {return x + y};
  • Version 0.0.31 ~ 0.0.32

  • 2015/3/8

    • change code generation for class statement.
    • add macro-expand function.
    • eg:
        (defmacro square (x) `(* ~x ~x))
        ;; the macro-expand function will expand the macro until it no longer represents a macro form.
        (macro-expand '(square 12))  ; => '(* 12 12)
    
        (defmacro test (x) `(test (+ 1 ~x)))
        ;; macro-expand can also expand macro forms for n times.
        (macro-expand '(test 1) 2)   ; => '(test (+ 1 (+ 1 1)))   this will expand macro twice.
        (macro-expand '(test 1) 3)   ; => '(test (+ 1 (+ 1 (+ 1 1))))   this will expand macro for 3 times.
  • 2015/3/4

    • fix one macro bug.
  • Version 0.0.30

    • add class support (this might be buggy though)
    • eg:
        (class Animal
            :constructor (fn (age)                ;; define constructor
                            (= this.age age))
            :showAge (fn ()
                        (console.log "Called from Animal")
                        (console.log this.age)))
        (class Dog extends Animal
            :constructor (fn (age)                ;; define constructor
                            (super age))          ;; call superclass constructor
            :showAge (fn ()
                        (console.log "Called from Dog")
                        (super.showAge))          ;; call superclass method
            :bark (fn ()
                    (console.log "Bark!")))
    
        (def dog (new Dog 5))
        (dog.showAge)  ;;  Called from Dog
                       ;;  Called from Animal
                       ;;  5
    
        (dog.bark)     ;;  Bark!
  • Version 0.0.28

  • 2015/3/1

    • add case statement.
    • eg:
        (def test (x)
            (case x
                "apple" "This is apple"
                "orange" "This is orange"
                else "This is nothing"))
        (test "pear")    ;; => This is nothing
        (test "apple")   ;; => This is apple
        (test "orange")  ;; => This is orange
    • fix one if and cond bug.
  • 2015/2/25

    • fix demo link error.
  • 2015/2/24

    • add loop macro
    • eg:
        ;; calculate factorial 10
        (loop i 10
              acc 1
            (if (== i 0)
                acc
                (recur (- i 1)
                       (* i acc))))
  • 2015/2/23

    • add REPL demo
    • fix <= >= < > == != comparison operator bug, they now support multiple arguments.
    • eg:
        (== 1 1 1)
        (<= 1 2 3 4 5 2)
  • Version 0.0.24

  • 2015/2/22

    • add -> macro
    • eg:
        (-> console (.log "Hello World"))
        (-> $ (.post "test.php")
              (.done (fn () "done"))
              (.fail (fn () "fail")))
        (-> "i am cool"
            .length)
        console.log("Hello World");
        $.post("test.php").done(function() {
            return "done";
        }).fail(function() {
            return "fail";
        });
        "i am cool".length;
  • Version 0.0.20 - 0.0.22

  • 2015/2/17

    • Happy New Year []~( ̄▽ ̄)~*
    • Add and, or, not macros that behave the same as && || !
    • Change default parameters and keyword parameters.
    • For example:
    • Default Parameters
        (def add (:a 1 :b 2)
            (+ a b))
        (add)     ;; => 3
        (add 2)   ;; => 4
        (add 3 4) ;; => 7
    • Keyword Parameters
        (def add ({:x 1 :y 2})
            (+ x y))
        (add)            ;; => 3
        (add :x 3)       ;; => 5
        (add :y 6)       ;; => 7
        (add :x 4 :y 5)  ;; => 9
        (add :y 1 :x 5)  ;; => 6
  • Version 0.0.18

  • 2015/2/16

    • Add yield and throw support.
  • 2015/2/9

    • Improve compatibility with es5
  • 2015/2/7

    • Change the way of defining the default parameters and calling function with named parameters
  • 2015/1/31

    • Fix one macro bug.
  • 2015/1/26

    • Change do function.
      (do ...) will be wrapped as function when it is argument or assignment value.
  • Version 0.0.13

    • add in support.
    (in 'a {'a 12})
    ("a" in {"a": 12});
  • Version 0.0.12

    • fix one macro bug.
  • 2015/1/23

    • change . & for rest parameters
    • . => list
    • & => array
    (def add (a & b)   ;; b here is Array
        (+ a b[0]))
    (def add (a . b)   ;; b here is List
        (+ a (car b)))
    // es6
    var add = function(a, ...b){
        return a + b[0];
    }
    var add = function(a, ...b) {
        b = list.apply(null, b);
        return (a + car(b));
    };
  • 2015/1/19

    • add get fn
    • fix "abc".length like exp bug.
  • 2015/1/14

    • add cond
    • add recur support
    • add try/catch/finally support
    • change if statement
      Went snowboarding and fell down too many times. I twisted my wrist unfortunately. (T_T)
  • 2015/1/7

    • add support for fn with name .
    (fn add (x) (+ x y))
    function add(x) {
        return (x + y);
    };
* fix one macro bug
  • 2015/1/5
    • add support for const
    • change let . see doc above.
    • fix several bugs.
  • 2015/1/5 First Release
    • There are still lots of bugs.
    • ...

MIT License ;)