Skip to content
/ rockit Public

Rockit is Guile tooling to translate James, a lispy language, into Jessica, a Javascript subset

License

Notifications You must be signed in to change notification settings

cwebber/rockit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Blast off from Lisp to Javascript (and back?) with Team Rockit

This is an experimental repository to convert a lispy DSL named James to a subset of Javascript named Jessie. In the future, maybe more tools to translate between lispy and javascript worlds too! It uses Guile’s language tooling to do so.

It’s very experimental, not really usable yet. Warning, warning, warning.

Show me some examples!

You can see them yourself, run:

guile james-to-jessie.scm

Look at the bottom of the file to see the code that’s being converted.

(Thank you to Dan Connolly for supplying some of these examples, some of which were converted from the Agoric and Endo meta-codebases!)

Stateless singleton

James program:

(module
 (defconst makeCounter
   (fn (init)
     (let value init)
     (return (%r
              (: increment (fn () (+= value 1)))
              (: decrement (fn () (-= value 1)))
              (: makeOffsetCounter
                 (fn (delta)
                   (return (makeCounter (+ value delta)))))))))
 (defconst c1 (makeCounter 1))
 (c1 .increment)
 (console .log (c1 .decrement)))

Jessie output:

const makeCounter = function (init) {
  let value = init;
  return {
    increment: function () {
      value += value;
    },
    decrement: function () {
      value -= value;
    },
    makeOffsetCounter: delta => (makeCounter(value + delta))
  };
};

const c1 = makeCounter(1);

c1.increment();

console.log(c1.decrement());

Mint

(module
 (defn (makeMint)
   (defconst ledger (makeWeakMap))

   (defconst issuer
     (harden (%r (: makeEmptyPurse (fn () (mint.makePurse 0))))))

   (defconst mint
     (harden
      (%r
       (: makePurse
          (fn (initialBalance)
              (defconst purse
                (harden
                 (%r
                  (: getIssuer (fn () (return issuer)))
                  (: getBalance (fn () (ledger.get purse)))
                  (: deposit
                     (fn (amount src)
                       (Nat (+ (ledger.get purse) (Nat amount)))
                       (ledger.set src (- (Nat (ledger.get src))
                                          amount))
                       (ledger.set purse (+ (ledger.get purse) amount))))
                  (: withdraw
                     (fn (amount)
                       (defconst newPurse
                         (issuer.makeEmptyPurse))
                       (newPurse.deposit amount purse)
                       (return newPurse))))))

              (ledger.set purse initialBalance)
              (return purse))))))

   (return mint))

 ;; example from http://erights.org/elib/capability/ode/ode-capabilities.html
 (defconst carolMint (makeMint))
 (defconst aliceMainPurse (carolMint.makePurse 1000))
 (defconst bobMainPurse (carolMint.makePurse 0))
 (defconst paymentForBob (aliceMainPurse.withdraw 10))

 ;; (.-> bob (.foo paymentForBob))
 (bobMainPurse.deposit 10 paymentForBob)

 (console.log (aliceMainPurse.getBalance))
 (console.log (bobMainPurse.getBalance)))

Jessie output:

function makeMint () {
  const ledger = makeWeakMap();
  const issuer = harden({
    makeEmptyPurse: function () {
      mint.makePurse(0);
    }
  });
  const mint = harden({
    makePurse: function (initialBalance) {
      const purse = harden({
        getIssuer: () => issuer,
        getBalance: function () {
          ledger.get(purse);
        },
        deposit: function (amount, src) {
          Nat(ledger.get(purse) + Nat(amount));
          ledger.set(src, Nat(ledger.get(src)) - amount);
          ledger.set(purse, ledger.get(purse) + amount);
        },
        withdraw: function (amount) {
          const newPurse = issuer.makeEmptyPurse();
          newPurse.deposit(amount, purse);
          return newPurse;
        }
      });
      ledger.set(purse, initialBalance);
      return purse;
    }
  });
  return mint;
}

const carolMint = makeMint();

const aliceMainPurse = carolMint.makePurse(1000);

const bobMainPurse = carolMint.makePurse(0);

const paymentForBob = aliceMainPurse.withdraw(10);

bobMainPurse.deposit(10, paymentForBob);

console.log(aliceMainPurse.getBalance());

console.log(bobMainPurse.getBalance());

FAQ

Should I use this?

Not yet for anything serious. Maybe soon.

But I really want to!

I know, me too. It’s early, though.

Can I do the opposite? Can I actually hack this as a language in Guile?

Soon, I hope.

What license is this under?

Apache v2, though it might eventually include some LGPL bits borrowed from Guile.

Is this project’s name a Pokemon reference?

What? No. Whaaaaat???? Haha no.....

About

Rockit is Guile tooling to translate James, a lispy language, into Jessica, a Javascript subset

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages