From 7966b81830aec7befad99ed1cf81990b4cf74fab Mon Sep 17 00:00:00 2001
From: Devine Lu Linvega <aliceffekt@gmail.com>
Date: Sat, 20 Jul 2019 19:18:23 +0900
Subject: [PATCH 01/14] Fixed benchmark

---
 desktop/sources/scripts/commander.js | 5 +++--
 desktop/sources/scripts/library.js   | 2 +-
 desktop/sources/scripts/source.js    | 6 +-----
 examples/benchmark.lisp              | 4 ++--
 4 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/desktop/sources/scripts/commander.js b/desktop/sources/scripts/commander.js
index 95892a5..f42d1d1 100644
--- a/desktop/sources/scripts/commander.js
+++ b/desktop/sources/scripts/commander.js
@@ -35,12 +35,13 @@ function Commander (ronin) {
     if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return }
     const inter = new Lisp(txt, ronin.library)
     inter.toPixels()
-    ronin.always && requestAnimationFrame(() => this.run(txt))
+    ronin.always === true && requestAnimationFrame(() => this.run(txt))
   }
 
   this.load = function (txt) {
+    ronin.animate(false)
     this._input.value = txt
-    this.run()
+    this.run(txt)
   }
 
   this.reindent = function () {
diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index ea3483a..f9cf304 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -324,7 +324,7 @@ function Library (ronin) {
   this.open = async (path) => { // Imports a graphic file and resizes the frame.
     return ronin.surface.open(path)
   }
-  
+
   // File System
 
   this.dir = (path = ronin.source.path) => { // Returns the content of a directory.
diff --git a/desktop/sources/scripts/source.js b/desktop/sources/scripts/source.js
index c6bfd72..d0abb44 100644
--- a/desktop/sources/scripts/source.js
+++ b/desktop/sources/scripts/source.js
@@ -66,7 +66,7 @@ function Source (ronin) {
     if (!fs.existsSync(loc)) { console.warn('Source', 'File does not exist: ' + loc); return }
     console.log('Source', 'Reading ' + loc)
     this.path = loc
-    this.load(fs.readFileSync(this.path, 'utf8'))
+    ronin.commander.load(fs.readFileSync(this.path, 'utf8'))
     ronin.log(`Reading file.`)
   }
 
@@ -74,10 +74,6 @@ function Source (ronin) {
     ronin.commander.run()
   }
 
-  this.load = function (data) {
-    ronin.commander._input.value = data
-  }
-
   this.quit = function (force = false) {
     if (this.hasChanges() === true && force === false) {
       this.verify()
diff --git a/examples/benchmark.lisp b/examples/benchmark.lisp
index ab6fa3d..70832bf 100644
--- a/examples/benchmark.lisp
+++ b/examples/benchmark.lisp
@@ -56,6 +56,6 @@
   (test "str" (str 1 4 "-" (add 3 4) ".jpg") "14-7.jpg")
 
 ; Interop
-  (test "interop" ((of (of js "Math") "max") 2 4) 4)
-  (test "recursive key selector" ((of js "Math" "max") 2 4) 4)
+  (test "interop" ((of (of (js) "Math") "max") 2 4) 4)
+  (test "recursive key selector" ((of (js) "Math" "max") 2 4) 4)
 )
\ No newline at end of file

From 2d1e08cf9f047beff2d288efeb6a8ea1ed637d79 Mon Sep 17 00:00:00 2001
From: Devine Lu Linvega <aliceffekt@gmail.com>
Date: Sat, 20 Jul 2019 19:37:32 +0900
Subject: [PATCH 02/14] Replace (str) with (concat)

---
 desktop/sources/scripts/library.js     | 48 ++++++++++----------------
 examples/benchmark.fs.lisp             | 14 ++++++++
 examples/benchmark.lisp                |  2 +-
 examples/{fs.lisp => random.file.lisp} |  0
 4 files changed, 34 insertions(+), 30 deletions(-)
 create mode 100644 examples/benchmark.fs.lisp
 rename examples/{fs.lisp => random.file.lisp} (100%)

diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index f9cf304..4c9e399 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -13,6 +13,10 @@ function Library (ronin) {
     return path
   }
 
+  this.open = async (path) => { // Imports a graphic file and resizes the frame.
+    return ronin.surface.open(path)
+  }
+
   // Shapes
 
   this.pos = (x, y, t = 'pos') => { // Returns a position shape.
@@ -62,7 +66,7 @@ function Library (ronin) {
 
   // Strings
 
-  this.concat = function (...items) {
+  this.concat = function (...items) { // Concat multiple strings.
     return items.reduce((acc, item) => { return `${acc}${item}` }, '')
   }
 
@@ -223,7 +227,7 @@ function Library (ronin) {
     return item[key]
   }
 
-  this.of = (h, ...keys) => {
+  this.of = (h, ...keys) => { // Gets object parameters with names.
     return keys.reduce((acc, key) => {
       return acc[key]
     }, h)
@@ -240,10 +244,6 @@ function Library (ronin) {
     return this.pos(rect.w / 2, rect.h / 2)
   }
 
-  this.scale = (rect, w, h) => {
-    return { x: rect.x, y: rect.y, w: rect.w * w, h: rect.h * h }
-  }
-
   this.resize = async (w, h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
     const rect = { x: 0, y: 0, w, h }
     const a = document.createElement('img')
@@ -264,7 +264,7 @@ function Library (ronin) {
     return ronin.surface.draw(b, rect)
   }
 
-  this.crop = async (rect) => {
+  this.crop = async (rect) => { // Crop canvas to rect.
     return ronin.surface.crop(rect)
   }
 
@@ -310,43 +310,33 @@ function Library (ronin) {
     return [pixel.r * q + intercept, pixel.g * q + intercept, pixel.b * q + intercept, pixel.a]
   }
 
-  // Misc
-
-  this.echo = (...args) => {
-    ronin.log(args)
-    return args
-  }
-
-  this.str = (...args) => {
-    return args.reduce((acc, val) => { return acc + val }, '')
-  }
-
-  this.open = async (path) => { // Imports a graphic file and resizes the frame.
-    return ronin.surface.open(path)
-  }
-
   // File System
 
-  this.dir = (path = ronin.source.path) => { // Returns the content of a directory.
+  this.dir = (path = this.dirpath()) => { // Returns the content of a directory.
     return fs.existsSync(path) ? fs.readdirSync(path) : []
   }
 
-  this.file = (path = ronin.source.path) => { // Returns the content of a file
-    return fs.existsSync(path) ? fs.readFileSync(p, 'utf8') : ''
+  this.file = (path = this.filepath()) => { // Returns the content of a file.
+    return fs.existsSync(path) ? fs.readFileSync(path, 'utf8') : ''
   }
 
-  this.dirpath = (path = ronin.source.path) => { // Returns the path of a directory.
+  this.dirpath = (path = this.filepath()) => { // Returns the path of a directory.
     return require('path').dirname(path)
   }
 
-  this.filepath = (path = ronin.source.path) => { // Returns the path of a file
-    return fs.existsSync(path) ? fs.readdirSync(path) : []
+  this.filepath = (path = ronin.source.path) => { // Returns the path of a file.
+    return path
   }
 
   this.exit = (force = false) => { // Exits Ronin.
     ronin.source.quit(force)
   }
 
+  this.echo = (...args) => {
+    ronin.log(args)
+    return args
+  }
+
   this.time = () => { // Returns timestamp in milliseconds.
     return Date.now()
   }
@@ -368,7 +358,7 @@ function Library (ronin) {
     return a === b
   }
 
-  this.benchmark = async (fn) => { // logs time taken to execute a function
+  this.benchmark = async (fn) => { // logs time taken to execute a function.
     const start = Date.now()
     const result = await fn()
     console.log(`time taken: ${Date.now() - start}ms`)
diff --git a/examples/benchmark.fs.lisp b/examples/benchmark.fs.lisp
new file mode 100644
index 0000000..cd80cef
--- /dev/null
+++ b/examples/benchmark.fs.lisp
@@ -0,0 +1,14 @@
+; filesystem
+(
+  ; print path 
+  (echo 
+    (filepath))
+  ; print folder path 
+  (echo 
+    (dirpath))
+  ; print file content 
+  (echo 
+    (file))
+  ; print folder content 
+  (echo 
+    (dir)))
\ No newline at end of file
diff --git a/examples/benchmark.lisp b/examples/benchmark.lisp
index 70832bf..1e0d5da 100644
--- a/examples/benchmark.lisp
+++ b/examples/benchmark.lisp
@@ -53,7 +53,7 @@
 
 ; Generics
 
-  (test "str" (str 1 4 "-" (add 3 4) ".jpg") "14-7.jpg")
+  (test "concat" (concat 1 4 "-" (add 3 4) ".jpg") "14-7.jpg")
 
 ; Interop
   (test "interop" ((of (of (js) "Math") "max") 2 4) 4)
diff --git a/examples/fs.lisp b/examples/random.file.lisp
similarity index 100%
rename from examples/fs.lisp
rename to examples/random.file.lisp

From 9e8c65ea13982dd46fd49194dce56d91f5a82baa Mon Sep 17 00:00:00 2001
From: Devine Lu Linvega <aliceffekt@gmail.com>
Date: Sat, 20 Jul 2019 19:44:30 +0900
Subject: [PATCH 03/14] Added rate to time.

---
 README.md                          | 20 +++++++++-----------
 desktop/sources/scripts/library.js |  4 ++--
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/README.md b/README.md
index 1f1aa21..d49c62f 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ npm start
 
 - `(import path rect)` Imports a graphic file with format.
 - `(export path ~format ~quality)` Exports a graphic file with format.
+- `(open path)` Imports a graphic file and resizes the frame.
 - `(pos x y ~t)` Returns a position shape.
 - `(size w h ~t)` Returns a size shape.
 - `(rect x y w h ~t)` Returns a rect shape.
@@ -37,7 +38,7 @@ npm start
 - `(stroke ~shape)` Strokes a shape.
 - `(fill ~rect)` Fills a shape.
 - `(clear ~rect)` Clears a rect.
-- `(concat ...items)` 
+- `(concat ...items)` Concat multiple strings.
 - `(add ...args)` Adds values.
 - `(sub ...args)` Subtracts values.
 - `(mul ...args)` Multiplies values.
@@ -69,32 +70,29 @@ npm start
 - `(range start end ~step)` 
 - `(get item key)` Gets an object's parameter with name.
 - `(set item key val)` Sets an object's parameter with name as value.
-- `(of h ...keys)` 
+- `(of h ...keys)` Gets object parameters with names.
 - `(frame)` Returns a rect of the frame.
 - `(center)` Returns a position of the center of the frame.
-- `(scale rect w h)` 
 - `(resize w h ~fit)` Resizes the canvas to target w and h, returns the rect.
 - `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect.
-- `(crop rect)` 
+- `(crop rect)` Crop canvas to rect.
 - `(clone a b)` 
 - `(theme variable ~el)` 
 - `(gradient [x1 y1 x2 y2] ~colors 'black'])` 
 - `(pixels rect fn q)` 
 - `(saturation pixel ~q)` 
 - `(contrast pixel ~q)` 
-- `(echo ...args)` 
-- `(str ...args)` 
-- `(open path)` Imports a graphic file and resizes the frame.
 - `(dir ~path)` Returns the content of a directory.
-- `(file ~path)` Returns the content of a file
+- `(file ~path)` Returns the content of a file.
 - `(dirpath ~path)` Returns the path of a directory.
-- `(filepath ~path)` Returns the path of a file
+- `(filepath ~path)` Returns the path of a file.
 - `(exit ~force)` Exits Ronin.
-- `(time)` Returns timestamp in milliseconds.
+- `(echo ...args)` 
+- `(time ~rate)` Returns timestamp in milliseconds.
 - `(animate ~play)` Toggles animation.
 - `(js)` Javascript interop.
 - `(test name a b)` 
-- `(benchmark fn)` logs time taken to execute a function
+- `(benchmark fn)` logs time taken to execute a function.
 
 ## Extras
 
diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index 4c9e399..e0a5ea4 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -337,8 +337,8 @@ function Library (ronin) {
     return args
   }
 
-  this.time = () => { // Returns timestamp in milliseconds.
-    return Date.now()
+  this.time = (rate = 1) => { // Returns timestamp in milliseconds.
+    return (Date.now() * rate)
   }
 
   this.animate = (play = true) => { // Toggles animation.

From b87e2cf965b63cadf5fb0ba899f1406b0e00db02 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 16:52:50 +0200
Subject: [PATCH 04/14] add '() lambda shorthand

---
 desktop/sources/scripts/lisp.js | 23 ++++++++++++++++++++++-
 examples/lambda.lisp            |  6 ++++++
 2 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 examples/lambda.lisp

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 7459f97..1f9b40f 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -60,6 +60,16 @@ function Lisp (input, lib) {
         return interpret(input[2], new Context(lambdaScope, context))
       }
     },
+    fn: function (input, context) {
+      return async function () {
+        const lambdaArguments = arguments
+        const lambdaScope = [].reduce(function (acc, x, i) {
+          acc[x.value] = lambdaArguments[i]
+          return acc
+        }, {})
+        return interpret(input.slice(1), new Context(lambdaScope, context))
+      }
+    },
     if: async function (input, context) {
       if (await interpret(input[1], context)) {
         return interpret(input[2], context)
@@ -110,6 +120,10 @@ function Lisp (input, lib) {
     const token = input.shift()
     if (token === undefined) {
       return list.pop()
+    } else if (token === '\'(') {
+      input.unshift('fn')
+      list.push(parenthesize(input, []))
+      return parenthesize(input, list)
     } else if (token === '(') {
       list.push(parenthesize(input, []))
       return parenthesize(input, list)
@@ -121,7 +135,14 @@ function Lisp (input, lib) {
   }
 
   const tokenize = function (input) {
-    return input.replace(/^\;.*\n?/gm, '').split('"').map(function (x, i) { return i % 2 === 0 ? x.replace(/\(/g, ' ( ').replace(/\)/g, ' ) ') : x.replace(/ /g, '!whitespace!') }).join('"').trim().split(/\s+/).map(function (x) { return x.replace(/!whitespace!/g, ' ') })
+    const i = input.replace(/^\;.*\n?/gm, '').split('"')
+    return i.map(function (x, i) { 
+      return i % 2 === 0 ? 
+        x.replace(/\(/g, ' ( ').replace(/\)/g, ' ) ').replace(/' \( /g, ' \'( ')
+        : x.replace(/ /g, '!whitespace!') 
+    })
+    .join('"').trim().split(/\s+/)
+    .map(function (x) { return x.replace(/!whitespace!/g, ' ') })
   }
 
   this.parse = function (input) {
diff --git a/examples/lambda.lisp b/examples/lambda.lisp
new file mode 100644
index 0000000..2c1be4c
--- /dev/null
+++ b/examples/lambda.lisp
@@ -0,0 +1,6 @@
+(
+
+(echo (map '(echo 1 2 3) (4 5 6))
+
+)
+

From 7624bef7f906135ca220096894705800d75c1368 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 16:56:53 +0200
Subject: [PATCH 05/14] update dejong with '()

---
 examples/dejong.lisp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/examples/dejong.lisp b/examples/dejong.lisp
index 9e3eac6..b446040 100644
--- a/examples/dejong.lisp
+++ b/examples/dejong.lisp
@@ -25,11 +25,11 @@
       (2 1)
     )
   )
-  (benchmark (lambda ()
-    (dejong 12800 
+  (benchmark 
+    '(dejong 12800 
       (random -2 2)
       (random -2 2)
       (random -2 2)
       (random -2 2) 
-  )))
+  ))
 )

From 143a45807efd8c4670ae8a796c98e7f42a4ed105 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 17:13:40 +0200
Subject: [PATCH 06/14] update examples with no global ( )

---
 desktop/sources/scripts/lisp.js |  2 +-
 examples/animate.lisp           | 32 +++++------
 examples/arrays.lisp            | 36 +++++-------
 examples/basics.lisp            | 14 ++---
 examples/benchmark.fs.lisp      | 26 ++++-----
 examples/benchmark.lisp         |  4 +-
 examples/crop.lisp              |  8 +--
 examples/dejong.lisp            | 58 ++++++++++---------
 examples/glitch.lisp            | 34 +++++------
 examples/gradient.lisp          |  4 +-
 examples/guides.lisp            | 99 ++++++++++++++++-----------------
 examples/import.lisp            |  4 +-
 examples/include.lisp           |  5 +-
 examples/lambda.lisp            |  2 +-
 examples/open.lisp              | 14 ++---
 examples/pixels.lisp            | 12 ++--
 examples/random.file.lisp       | 26 ++++-----
 examples/random.lisp            | 32 +++++------
 examples/recursive.lisp         | 30 +++++-----
 examples/resize.lisp            |  8 +--
 examples/shapes.lisp            | 39 +++++++------
 examples/spiral.lisp            |  4 +-
 examples/svg.lisp               | 16 +++---
 examples/theme.lisp             | 74 ++++++++++++------------
 24 files changed, 279 insertions(+), 304 deletions(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 1f9b40f..2d8f16e 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -146,7 +146,7 @@ function Lisp (input, lib) {
   }
 
   this.parse = function (input) {
-    return parenthesize(tokenize(input))
+    return parenthesize(tokenize(`(${input})`))
   }
 
   this.toPixels = async function () {
diff --git a/examples/animate.lisp b/examples/animate.lisp
index 4adaf64..9621338 100644
--- a/examples/animate.lisp
+++ b/examples/animate.lisp
@@ -1,17 +1,17 @@
 ; animate
-(
-  (clear) 
-  (def t 
-    (sin 
-      (div 
-        (time) 100))) 
-  (def pos 
-    (add 200 30 
-      (mul 30 t))) 
-  (defn square 
-    (a) 
-    (rect a a a a)) 
-  (stroke 
-    (square pos) 1 "red") 
-  ; set false to stop 
-  (animate true))
\ No newline at end of file
+
+(clear) 
+(def t 
+  (sin 
+    (div 
+      (time) 100))) 
+(def pos 
+  (add 200 30 
+    (mul 30 t))) 
+(defn square 
+  (a) 
+  (rect a a a a)) 
+(stroke 
+  (square pos) 1 "red") 
+; set false to stop 
+(animate true)
\ No newline at end of file
diff --git a/examples/arrays.lisp b/examples/arrays.lisp
index e6c7db1..76c2054 100644
--- a/examples/arrays.lisp
+++ b/examples/arrays.lisp
@@ -1,9 +1,7 @@
 (echo (map (lambda (a) (add a 1)) (1 2 3)))
 
-(
-  (echo (first (1 2 3)))
-  (echo (rest (1 2 3)))
-)
+(echo (first (1 2 3)))
+(echo (rest (1 2 3)))
 
 (echo
   (filter 
@@ -11,21 +9,17 @@
     (1 2 3 4 5))
 )
 
-(
-  (clear)
-  (map (lambda (a)
-    (stroke (rect (mul a 30) 20 50 50)
-  1 "red"))
-  (range 0 20 5))
-)
+(clear) 
+(map (lambda (a)
+  (stroke (rect (mul a 30) 20 50 50)
+1 "red"))
+(range 0 20 5))
 
-(
-  (clear) 
-  (map (lambda (a)
-    (stroke 
-      (rect 
-        (mul a 10) 
-        (add 50 (mul (sin a) 40)) 
-        a 
-        (add 20 (mul (cos a) 50))) 1 "red"))
-    (range 0 200 5)))
\ No newline at end of file
+(map (lambda (a)
+  (stroke 
+    (rect 
+      (mul a 10) 
+      (add 50 (mul (sin a) 40)) 
+      a 
+      (add 20 (mul (cos a) 50))) 1 "red"))
+  (range 0 200 5))
\ No newline at end of file
diff --git a/examples/basics.lisp b/examples/basics.lisp
index c1832ea..997be5d 100644
--- a/examples/basics.lisp
+++ b/examples/basics.lisp
@@ -1,9 +1,9 @@
 ; basics
-( 
-  ; define a variable 
-  (def a 25) 
-  (echo a) 
 
-  ; define a function 
-  (defn add-two (a) (add 2 a)) 
-  (echo (add-two 4)))
\ No newline at end of file
+; define a variable 
+(def a 25) 
+(echo a) 
+
+; define a function 
+(defn add-two (a) (add 2 a)) 
+(echo (add-two 4))
\ No newline at end of file
diff --git a/examples/benchmark.fs.lisp b/examples/benchmark.fs.lisp
index cd80cef..7867c03 100644
--- a/examples/benchmark.fs.lisp
+++ b/examples/benchmark.fs.lisp
@@ -1,14 +1,14 @@
 ; filesystem
-(
-  ; print path 
-  (echo 
-    (filepath))
-  ; print folder path 
-  (echo 
-    (dirpath))
-  ; print file content 
-  (echo 
-    (file))
-  ; print folder content 
-  (echo 
-    (dir)))
\ No newline at end of file
+
+; print path 
+(echo 
+  (filepath))
+; print folder path 
+(echo 
+  (dirpath))
+; print file content 
+(echo 
+  (file))
+; print folder content 
+(echo 
+  (dir))
\ No newline at end of file
diff --git a/examples/benchmark.lisp b/examples/benchmark.lisp
index 1e0d5da..e0b698e 100644
--- a/examples/benchmark.lisp
+++ b/examples/benchmark.lisp
@@ -1,6 +1,5 @@
 ; benchmark
 
-(
 ; Basics
 
   (test "add" (add 8 4 2) 14)
@@ -57,5 +56,4 @@
 
 ; Interop
   (test "interop" ((of (of (js) "Math") "max") 2 4) 4)
-  (test "recursive key selector" ((of (js) "Math" "max") 2 4) 4)
-)
\ No newline at end of file
+  (test "recursive key selector" ((of (js) "Math" "max") 2 4) 4)
\ No newline at end of file
diff --git a/examples/crop.lisp b/examples/crop.lisp
index 0a8168a..771a7c6 100644
--- a/examples/crop.lisp
+++ b/examples/crop.lisp
@@ -1,7 +1,5 @@
 ; crop
 
-(
-  (clear)
-  (open "../static/crystal.jpg")
-  (crop (rect 100 100 400 400))
-)
\ No newline at end of file
+(clear)
+(open "../static/crystal.jpg")
+(crop (rect 100 100 400 400))
\ No newline at end of file
diff --git a/examples/dejong.lisp b/examples/dejong.lisp
index b446040..654271c 100644
--- a/examples/dejong.lisp
+++ b/examples/dejong.lisp
@@ -1,35 +1,33 @@
 ; dejong attractor
 
-(
-  (clear) 
-  (defn point (x y color) 
-    (fill (rect x y 1 1) color))
+(clear) 
+(defn point (x y color) 
+  (fill (rect x y 1 1) color))
 
-  (defn _dejong (x y a b c d)
-    (rest ((point 
-      (add 300 (mul 100 x))
-      (add 400 (mul 100 y))
-      "red")
-    (add (sin (mul a y)) (mul x (cos (mul b x))))
-    (add (mul x (sin (mul x c))) (cos (mul d y)))
-    ))
-  )
-
-  (defn dejong (r a b c d)
-    (reduce  
-      (lambda (acc val)
-        (first (
-          (_dejong (first acc) (last acc) a b c d)
-        )))
-      (range 0 r)
-      (2 1)
-    )
-  )
-  (benchmark 
-    '(dejong 12800 
-      (random -2 2)
-      (random -2 2)
-      (random -2 2)
-      (random -2 2) 
+(defn _dejong (x y a b c d)
+  (rest ((point 
+    (add 300 (mul 100 x))
+    (add 400 (mul 100 y))
+    "red")
+  (add (sin (mul a y)) (mul x (cos (mul b x))))
+  (add (mul x (sin (mul x c))) (cos (mul d y)))
   ))
 )
+
+(defn dejong (r a b c d)
+  (reduce  
+    (lambda (acc val)
+      (first (
+        (_dejong (first acc) (last acc) a b c d)
+      )))
+    (range 0 r)
+    (2 1)
+  )
+)
+(benchmark 
+  '(dejong 12800 
+    (random -2 2)
+    (random -2 2)
+    (random -2 2)
+    (random -2 2) 
+))
diff --git a/examples/glitch.lisp b/examples/glitch.lisp
index b5f723e..5491fc8 100644
--- a/examples/glitch.lisp
+++ b/examples/glitch.lisp
@@ -1,25 +1,19 @@
-; pixels
+; Glitch
 
-(
-  (clear)
+(clear)
 
-  ; Glitch
-
-  (defn glitch 
-    (rec) 
-    (if (gt rec 1)
-    ((clone 
-      (rect (random 400) (random 400) 2 2)
-      (rect (random 400) (random 400) 
+(defn glitch 
+  (rec) 
+  (if (gt rec 1)
+  ((clone 
+    (rect (random 400) (random 400) 2 2)
+    (rect (random 400) (random 400) 
 (random 10) (random 30)))
-      (glitch (sub rec 1))))
-  )
+    (glitch (sub rec 1))))
+)
 
-  ; Draw photo 
-  
-  (import 
-    "../static/crystal.jpg" 
-    (rect 0 0 400 400))
+(import 
+  "../static/crystal.jpg" 
+  (rect 0 0 400 400))
 
-  (glitch 500)
-)
\ No newline at end of file
+(glitch 500)
\ No newline at end of file
diff --git a/examples/gradient.lisp b/examples/gradient.lisp
index b11e9aa..3637db9 100644
--- a/examples/gradient.lisp
+++ b/examples/gradient.lisp
@@ -1,4 +1,3 @@
-(
 ; gradients
 
 (clear)
@@ -12,5 +11,4 @@
   (svg "M255,60 L255,60 L135,180 L75,60 L195,210 L120,225 L105,225 L165,255 L225,195 L255,135 L285,150") 1
   (gradient 
     (50 0 180 0)
-    ("black" "white" "blue" "green")))
-)
\ No newline at end of file
+    ("black" "white" "blue" "green")))
\ No newline at end of file
diff --git a/examples/guides.lisp b/examples/guides.lisp
index f956c75..66c9758 100644
--- a/examples/guides.lisp
+++ b/examples/guides.lisp
@@ -1,57 +1,56 @@
 ; guides
-(
-  (clear) 
-  (stroke 
-    (frame) 1 "red") 
-  (stroke 
-    (line 
-      (pos 0 0) 
-      (pos 
+(clear) 
+(stroke 
+  (frame) 1 "red") 
+(stroke 
+  (line 
+    (pos 0 0) 
+    (pos 
+      (of 
+        (frame) "w") 
+      (of 
+        (frame) "h"))) 1 "red") 
+(stroke 
+  (line 
+    (pos 
+      (of 
+        (frame) "w") 0) 
+    (pos 0 
+      (of 
+        (frame) "h"))) 1 "red") 
+(stroke 
+  (line 
+    (pos 
+      (div 
         (of 
-          (frame) "w") 
+          (frame) "w") 2) 0) 
+    (pos 
+      (div 
         (of 
-          (frame) "h"))) 1 "red") 
-  (stroke 
-    (line 
-      (pos 
+          (frame) "w") 2) 
+      (of 
+        (frame) "h"))) 1 "red") 
+(stroke 
+  (line 
+    (pos 0 
+      (div 
         (of 
-          (frame) "w") 0) 
-      (pos 0 
+          (frame) "h") 2)) 
+    (pos 
+      (div 
         (of 
-          (frame) "h"))) 1 "red") 
-  (stroke 
-    (line 
-      (pos 
-        (div 
-          (of 
-            (frame) "w") 2) 0) 
-      (pos 
-        (div 
-          (of 
-            (frame) "w") 2) 
+          (frame) "w") 2) 
+      (of 
+        (frame) "h"))) 1 "#72dec2") 
+(stroke 
+  (line 
+    (pos 
+      (div 
         (of 
-          (frame) "h"))) 1 "red") 
-  (stroke 
-    (line 
-      (pos 0 
-        (div 
-          (of 
-            (frame) "h") 2)) 
-      (pos 
-        (div 
-          (of 
-            (frame) "w") 2) 
+          (frame) "w") 2) 0) 
+    (pos 
+      (of 
+        (frame) "w") 
+      (div 
         (of 
-          (frame) "h"))) 1 "#72dec2") 
-  (stroke 
-    (line 
-      (pos 
-        (div 
-          (of 
-            (frame) "w") 2) 0) 
-      (pos 
-        (of 
-          (frame) "w") 
-        (div 
-          (of 
-            (frame) "h") 2))) 1 "#72dec2"))
\ No newline at end of file
+          (frame) "h") 2))) 1 "#72dec2")
\ No newline at end of file
diff --git a/examples/import.lisp b/examples/import.lisp
index 36841c2..4fa5b9a 100644
--- a/examples/import.lisp
+++ b/examples/import.lisp
@@ -1,5 +1,5 @@
-(
+(clear)
 (def a (import 
   "../static/crystal.jpg" 
   (rect 0 0 400 400)))
-(echo a))
\ No newline at end of file
+(echo a)
\ No newline at end of file
diff --git a/examples/include.lisp b/examples/include.lisp
index bb1fdb9..fce452b 100644
--- a/examples/include.lisp
+++ b/examples/include.lisp
@@ -1,4 +1,3 @@
 ; include
-(
-  (include "../examples/recursive.lisp") 
-  (echo line-color))
\ No newline at end of file
+(include "../examples/recursive.lisp") 
+(echo line-color)
\ No newline at end of file
diff --git a/examples/lambda.lisp b/examples/lambda.lisp
index 2c1be4c..ed62eb4 100644
--- a/examples/lambda.lisp
+++ b/examples/lambda.lisp
@@ -1,6 +1,6 @@
 (
 
-(echo (map '(echo 1 2 3) (4 5 6))
+(echo (map '(add 1 2) (4 5 6))
 
 )
 
diff --git a/examples/open.lisp b/examples/open.lisp
index 6166815..399edf4 100644
--- a/examples/open.lisp
+++ b/examples/open.lisp
@@ -1,9 +1,7 @@
-; scale file
-(
+; saturate image 
 
-  (open "../static/crystal.jpg")
-  (pixels 
-    (frame)
-    saturation
-    12)
-)
\ No newline at end of file
+(open "../static/crystal.jpg")
+(pixels 
+  (frame)
+  saturation
+  12)
\ No newline at end of file
diff --git a/examples/pixels.lisp b/examples/pixels.lisp
index d4edbff..761a462 100644
--- a/examples/pixels.lisp
+++ b/examples/pixels.lisp
@@ -1,7 +1,7 @@
 ; pixels
-(
-  (clear) 
-  (import "../../PREVIEW.jpg" 
-    (frame)) 
-  (pixels 
-    (rect 0 0 500 500) saturation 0.5))
\ No newline at end of file
+
+(clear) 
+(import "../../PREVIEW.jpg" 
+  (frame)) 
+(pixels 
+  (rect 0 0 500 500) saturation 0.5)
\ No newline at end of file
diff --git a/examples/random.file.lisp b/examples/random.file.lisp
index b63101e..f95064b 100644
--- a/examples/random.file.lisp
+++ b/examples/random.file.lisp
@@ -1,14 +1,14 @@
 ; filesystem
-( 
-  ; get files 
-  (def files 
-    (dir 
-      (dirpath))) 
-  ; pick a random file 
-  (def random-index 
-    (floor 
-      (random 
-        (len files)))) 
-  ; print random file name
-  (echo 
-    (get files random-index)))
\ No newline at end of file
+
+; get files 
+(def files 
+  (dir 
+    (dirpath))) 
+; pick a random file 
+(def random-index 
+  (floor 
+    (random 
+      (len files)))) 
+; print random file name
+(echo 
+  (get files random-index))
\ No newline at end of file
diff --git a/examples/random.lisp b/examples/random.lisp
index ff3754c..f6cdf0d 100644
--- a/examples/random.lisp
+++ b/examples/random.lisp
@@ -1,17 +1,17 @@
 ; random 
-(
-  (clear) 
-  (defn place 
-    (rec) 
-    (if 
-      (gt rec 0) 
-      (
-        (import "../static/crystal.jpg" 
-          (rect 
-            (random 200) 
-            (random 200) 
-            (random 200) 
-            (random 200))) 
-        (place 
-          (sub rec 1))))) 
-  (place 30))
\ No newline at end of file
+
+(clear) 
+(defn place 
+  (rec) 
+  (if 
+    (gt rec 0) 
+    (
+      (import "../static/crystal.jpg" 
+        (rect 
+          (random 200) 
+          (random 200) 
+          (random 200) 
+          (random 200))) 
+      (place 
+        (sub rec 1))))) 
+(place 30)
\ No newline at end of file
diff --git a/examples/recursive.lisp b/examples/recursive.lisp
index fb7003f..8580107 100644
--- a/examples/recursive.lisp
+++ b/examples/recursive.lisp
@@ -1,16 +1,16 @@
 ; recursive
-(
-  (clear) 
-  (defn rec 
-    (v) 
-    (if 
-      (gt v 0) 
-      (
-        (stroke 
-          (circle 
-            (mul 5 v) 
-            (mul 5 v) 
-            (mul 5 v)) 1 "red") 
-        (rec 
-          (sub v 5))))) 
-  (rec 100))
\ No newline at end of file
+
+(clear) 
+(defn rec 
+  (v) 
+  (if 
+    (gt v 0) 
+    (
+      (stroke 
+        (circle 
+          (mul 5 v) 
+          (mul 5 v) 
+          (mul 5 v)) 1 "red") 
+      (rec 
+        (sub v 5))))) 
+(rec 100)
\ No newline at end of file
diff --git a/examples/resize.lisp b/examples/resize.lisp
index 5dbd409..bc206c4 100644
--- a/examples/resize.lisp
+++ b/examples/resize.lisp
@@ -1,5 +1,5 @@
 ; resize
-(
-  (clear) 
-  (open "../../PREVIEW.jpg") 
-  (resize 0.5 0.5))
\ No newline at end of file
+
+(clear) 
+(open "../../PREVIEW.jpg") 
+(resize 0.5 0.5)
\ No newline at end of file
diff --git a/examples/shapes.lisp b/examples/shapes.lisp
index 29f0ea8..d9712c4 100644
--- a/examples/shapes.lisp
+++ b/examples/shapes.lisp
@@ -1,25 +1,24 @@
 ; Shapes
 
-((clear)
+(clear)
 
-  ; variables
-  (def center-w (div (of (frame) "w") 2))
-  (def center-h (div (of (frame) "h") 2))
-  (def rad (div (of (frame) "h") 4))
-  
-  ; draw circle
-  (stroke 
-    (circle center-w center-h rad) 2 "white")
+; variables
+(def center-w (div (of (frame) "w") 2))
+(def center-h (div (of (frame) "h") 2))
+(def rad (div (of (frame) "h") 4))
 
-  ; draw rect
-  (stroke 
-    (rect 
-      (sub center-w rad) (sub center-h rad) center-h center-h) 2 "white")
+; draw circle
+(stroke 
+  (circle center-w center-h rad) 2 "white")
 
-  ; draw line
-  (stroke 
-    (line 
-      (pos (sub center-w rad) center-h)
-      (pos (add center-w rad) center-h)))
-  (stroke (text 10 170 200 "HELL") 2 "pink")
-)
\ No newline at end of file
+; draw rect
+(stroke 
+  (rect 
+    (sub center-w rad) (sub center-h rad) center-h center-h) 2 "white")
+
+; draw line
+(stroke 
+  (line 
+    (pos (sub center-w rad) center-h)
+    (pos (add center-w rad) center-h)))
+(stroke (text 10 170 200 "HELL") 2 "pink")
\ No newline at end of file
diff --git a/examples/spiral.lisp b/examples/spiral.lisp
index 6ca0c55..39027a8 100644
--- a/examples/spiral.lisp
+++ b/examples/spiral.lisp
@@ -1,6 +1,6 @@
 ; animated recusive spiral
 ; by @local_guru
-(
+
   (clear) 
   (defn rec 
     (v) 
@@ -27,4 +27,4 @@
           (sub v 0.3))))) 
   ; set false to stop 
   (animate true) 
-  (rec 300))
\ No newline at end of file
+  (rec 300)
\ No newline at end of file
diff --git a/examples/svg.lisp b/examples/svg.lisp
index 497871b..2966084 100644
--- a/examples/svg.lisp
+++ b/examples/svg.lisp
@@ -1,8 +1,8 @@
-(
-  (clear) 
-  ; ronin path 
-  (stroke 
-    (svg "M60,60 L195,60 A45,45 0 0,1 240,105 A45,45 0 0,1 195,150 L60,150 M195,150 A45,45 0 0,1 240,195 L240,240 ") 2 "white")
-  ; outline 
-  (stroke 
-    (svg "M15,15 L15,15 L285,15 L285,285 L15,285 Z") 1 "#555"))
\ No newline at end of file
+
+(clear) 
+; ronin path 
+(stroke 
+  (svg "M60,60 L195,60 A45,45 0 0,1 240,105 A45,45 0 0,1 195,150 L60,150 M195,150 A45,45 0 0,1 240,195 L240,240 ") 2 "white")
+; outline 
+(stroke 
+  (svg "M15,15 L15,15 L285,15 L285,285 L15,285 Z") 1 "#555")
\ No newline at end of file
diff --git a/examples/theme.lisp b/examples/theme.lisp
index 9c50830..cba7b21 100644
--- a/examples/theme.lisp
+++ b/examples/theme.lisp
@@ -1,38 +1,38 @@
 ; theme
-(
-  (clear) 
-  (def col 
-    (lambda 
-      (i) 
-      (of 
-        (
-          (theme "f_high") 
-          (theme "f_med") 
-          (theme "f_low") 
-          (theme "f_inv") 
-          (theme "b_high") 
-          (theme "b_med") 
-          (theme "b_low") 
-          (theme "b_inv")) 
-        (mod i 8)))) 
-  (def rec 
-    (lambda 
-      (v i) 
-      (if 
-        (gt v 0) 
-        (
-          (fill 
-            (circle 
-              (add 
-                (div 
-                  (of 
-                    (frame) "w") 1.6) 
-                (mul 1.5 v)) 
-              (mul 10 v) 
-              (mul v 
-                (div v 5))) 
-            (col i)) 
-          (rec 
-            (sub v 3) 
-            (add i 1)))))) 
-  (rec 40 0))
\ No newline at end of file
+
+(clear) 
+(def col 
+  (lambda 
+    (i) 
+    (of 
+      (
+        (theme "f_high") 
+        (theme "f_med") 
+        (theme "f_low") 
+        (theme "f_inv") 
+        (theme "b_high") 
+        (theme "b_med") 
+        (theme "b_low") 
+        (theme "b_inv")) 
+      (mod i 8)))) 
+(def rec 
+  (lambda 
+    (v i) 
+    (if 
+      (gt v 0) 
+      (
+        (fill 
+          (circle 
+            (add 
+              (div 
+                (of 
+                  (frame) "w") 1.6) 
+              (mul 1.5 v)) 
+            (mul 10 v) 
+            (mul v 
+              (div v 5))) 
+          (col i)) 
+        (rec 
+          (sub v 3) 
+          (add i 1)))))) 
+(rec 40 0)
\ No newline at end of file

From 3d5a17431e0353e785f638030bb76d5d44d984de Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 17:23:39 +0200
Subject: [PATCH 07/14] prefixing fn to __fn for scope safety

---
 desktop/sources/scripts/lisp.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 2d8f16e..4fd0f1e 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -60,7 +60,7 @@ function Lisp (input, lib) {
         return interpret(input[2], new Context(lambdaScope, context))
       }
     },
-    fn: function (input, context) {
+    __fn: function (input, context) {
       return async function () {
         const lambdaArguments = arguments
         const lambdaScope = [].reduce(function (acc, x, i) {
@@ -121,7 +121,7 @@ function Lisp (input, lib) {
     if (token === undefined) {
       return list.pop()
     } else if (token === '\'(') {
-      input.unshift('fn')
+      input.unshift('__fn')
       list.push(parenthesize(input, []))
       return parenthesize(input, list)
     } else if (token === '(') {

From 2574ad297b54ddf018c99ffb94917901517a87b5 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 19:46:52 +0200
Subject: [PATCH 08/14] add suport for {} objects

---
 desktop/sources/scripts/library.js |  8 ++++++++
 desktop/sources/scripts/lisp.js    | 27 +++++++++++++++++++++------
 examples/objects.lisp              | 11 +++++++++++
 3 files changed, 40 insertions(+), 6 deletions(-)
 create mode 100644 examples/objects.lisp

diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index e0a5ea4..0a8aa78 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -233,6 +233,14 @@ function Library (ronin) {
     }, h)
   }
 
+  this.keys = (item) => { // Returns a list of the object's keys
+    return Object.keys(item)
+  }
+
+  this.values = (item) => { // Returns a list of the object's values
+    return Object.values(item)
+  }
+
   // Frame
 
   this.frame = () => { // Returns a rect of the frame.
diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 4fd0f1e..3077df4 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -60,6 +60,12 @@ function Lisp (input, lib) {
         return interpret(input[2], new Context(lambdaScope, context))
       }
     },
+    if: async function (input, context) {
+      if (await interpret(input[1], context)) {
+        return interpret(input[2], context)
+      }
+      return input[3] ? interpret(input[3], context) : []
+    },
     __fn: function (input, context) {
       return async function () {
         const lambdaArguments = arguments
@@ -70,11 +76,12 @@ function Lisp (input, lib) {
         return interpret(input.slice(1), new Context(lambdaScope, context))
       }
     },
-    if: async function (input, context) {
-      if (await interpret(input[1], context)) {
-        return interpret(input[2], context)
+    __obj: async function (input, context) {
+      const obj = {}
+      for (let i = 1 ; i<input.length ; i+=2) {
+        obj[await interpret(input[i] ,context)] = await interpret(input[i+1], context)
       }
-      return input[3] ? interpret(input[3], context) : []
+      return obj
     }
   }
 
@@ -124,10 +131,14 @@ function Lisp (input, lib) {
       input.unshift('__fn')
       list.push(parenthesize(input, []))
       return parenthesize(input, list)
+    } else if (token === '{') {
+      input.unshift('__obj')
+      list.push(parenthesize(input, []))
+      return parenthesize(input, list)
     } else if (token === '(') {
       list.push(parenthesize(input, []))
       return parenthesize(input, list)
-    } else if (token === ')') {
+    } else if (token === ')' || token === '}') {
       return list
     } else {
       return parenthesize(input, list.concat(categorize(token)))
@@ -138,7 +149,11 @@ function Lisp (input, lib) {
     const i = input.replace(/^\;.*\n?/gm, '').split('"')
     return i.map(function (x, i) { 
       return i % 2 === 0 ? 
-        x.replace(/\(/g, ' ( ').replace(/\)/g, ' ) ').replace(/' \( /g, ' \'( ')
+        x.replace(/\(/g, ' ( ')
+        .replace(/\)/g, ' ) ')
+        .replace(/' \( /g, ' \'( ') // '()
+        .replace(/\{/g, ' { ') // {}
+        .replace(/\}/g, ' } ') // {}
         : x.replace(/ /g, '!whitespace!') 
     })
     .join('"').trim().split(/\s+/)
diff --git a/examples/objects.lisp b/examples/objects.lisp
new file mode 100644
index 0000000..31e681c
--- /dev/null
+++ b/examples/objects.lisp
@@ -0,0 +1,11 @@
+; objects
+
+(def ob {"a" 1 "b" 2})
+
+(echo (of ob "a"))
+
+(echo (keys ob))
+(echo (values ob))
+
+(set ob "a" 4)
+(echo (of ob "a"))
\ No newline at end of file

From 371615a8992614f3f34ddf16f3a59b8fef8a83f8 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 20:16:36 +0200
Subject: [PATCH 09/14] add symbol syntax

---
 desktop/sources/scripts/lisp.js |  2 ++
 examples/objects.lisp           | 12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 3077df4..19bab38 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -115,6 +115,8 @@ function Lisp (input, lib) {
       return { type: TYPES.number, value: parseFloat(input) }
     } else if (input[0] === '"' && input.slice(-1) === '"') {
       return { type: TYPES.string, value: input.slice(1, -1) }
+    } else if (input[0] === ':') {
+      return { type: TYPES.string, value: input.slice(1) }
     } else if (input === 'true' || input === 'false') {
       return { type: TYPES.bool, value: input === 'true' }
     } else {
diff --git a/examples/objects.lisp b/examples/objects.lisp
index 31e681c..e02eca0 100644
--- a/examples/objects.lisp
+++ b/examples/objects.lisp
@@ -1,11 +1,15 @@
 ; objects
 
-(def ob {"a" 1 "b" 2})
+(test "symbols" :a "a")
 
-(echo (of ob "a"))
+(def ob {:a "fantastic" :b 2})
+
+((of (js) :console :log) ob)
+
+(echo (of ob :a))
 
 (echo (keys ob))
 (echo (values ob))
 
-(set ob "a" 4)
-(echo (of ob "a"))
\ No newline at end of file
+(set ob :a 4)
+(echo (of ob :a))
\ No newline at end of file

From 4d437eaac1ad746ebb70282968b653a3ec7e670b Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 20:34:23 +0200
Subject: [PATCH 10/14] add lambda shorthand with params

---
 desktop/sources/scripts/lisp.js | 8 ++++++--
 examples/lambda.lisp            | 7 +------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 19bab38..71105dd 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -69,8 +69,12 @@ function Lisp (input, lib) {
     __fn: function (input, context) {
       return async function () {
         const lambdaArguments = arguments
-        const lambdaScope = [].reduce(function (acc, x, i) {
-          acc[x.value] = lambdaArguments[i]
+        const keys = input.slice(2).filter(i => 
+          i.type === TYPES.identifier &&
+          i.value[0] === '%'
+        ).map(x => x.value).sort()
+        const lambdaScope = keys.reduce(function (acc, x, i) {
+          acc[x] = lambdaArguments[i]
           return acc
         }, {})
         return interpret(input.slice(1), new Context(lambdaScope, context))
diff --git a/examples/lambda.lisp b/examples/lambda.lisp
index ed62eb4..d22fb5c 100644
--- a/examples/lambda.lisp
+++ b/examples/lambda.lisp
@@ -1,6 +1 @@
-(
-
-(echo (map '(add 1 2) (4 5 6))
-
-)
-
+(echo (map '(add %1 2) (4 5 6))

From 55bff65635cee1493ff38f79542092c52dc1f258 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 20:49:25 +0200
Subject: [PATCH 11/14] fix lambda shorthand, update array example

---
 desktop/sources/scripts/lisp.js |  4 ++--
 examples/arrays.lisp            | 25 +++++++++++++------------
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 71105dd..07b4165 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -69,10 +69,10 @@ function Lisp (input, lib) {
     __fn: function (input, context) {
       return async function () {
         const lambdaArguments = arguments
-        const keys = input.slice(2).filter(i => 
+        const keys = [...new Set(input.slice(2).flat(100).filter(i => 
           i.type === TYPES.identifier &&
           i.value[0] === '%'
-        ).map(x => x.value).sort()
+        ).map(x => x.value).sort())]
         const lambdaScope = keys.reduce(function (acc, x, i) {
           acc[x] = lambdaArguments[i]
           return acc
diff --git a/examples/arrays.lisp b/examples/arrays.lisp
index 76c2054..e2dbf47 100644
--- a/examples/arrays.lisp
+++ b/examples/arrays.lisp
@@ -1,25 +1,26 @@
-(echo (map (lambda (a) (add a 1)) (1 2 3)))
+(echo (map '(add %1 1) (1 2 3)))
 
 (echo (first (1 2 3)))
 (echo (rest (1 2 3)))
 
 (echo
   (filter 
-    (lambda (a) (eq 0 (mod a 2))) 
+    '(eq 0 (mod %1 2)) 
     (1 2 3 4 5))
 )
 
 (clear) 
-(map (lambda (a)
-  (stroke (rect (mul a 30) 20 50 50)
-1 "red"))
+(map
+  '(stroke (rect (mul a 30) 20 50 50)
+1 "red")
 (range 0 20 5))
 
-(map (lambda (a)
-  (stroke 
+(map
+  '(stroke 
     (rect 
-      (mul a 10) 
-      (add 50 (mul (sin a) 40)) 
-      a 
-      (add 20 (mul (cos a) 50))) 1 "red"))
-  (range 0 200 5))
\ No newline at end of file
+      (mul %1 10) 
+      (add 50 (mul (sin %1) 40)) 
+      %1
+      (add 20 (mul (cos %1) 50))) 1 "red")
+  (range 0 200 5))
+

From fade8cb3968ba04ad1de5547c145cd723961a241 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 20:51:19 +0200
Subject: [PATCH 12/14] update array example

---
 examples/arrays.lisp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/examples/arrays.lisp b/examples/arrays.lisp
index e2dbf47..2f99e20 100644
--- a/examples/arrays.lisp
+++ b/examples/arrays.lisp
@@ -19,8 +19,8 @@
   '(stroke 
     (rect 
       (mul %1 10) 
-      (add 50 (mul (sin %1) 40)) 
-      %1
+      (add 250 (mul (sin %1) 250)) 
+      (mul 4 %1)
       (add 20 (mul (cos %1) 50))) 1 "red")
   (range 0 200 5))
 

From 0f2acc0d0e8690a88a863fac37018f3059d0eb55 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 21:25:28 +0200
Subject: [PATCH 13/14] add prelude.lisp

---
 desktop/sources/lisp/prelude.lisp | 11 +++++++++++
 desktop/sources/scripts/lisp.js   |  6 ++++--
 examples/glitch.lisp              | 11 +++++------
 3 files changed, 20 insertions(+), 8 deletions(-)
 create mode 100644 desktop/sources/lisp/prelude.lisp

diff --git a/desktop/sources/lisp/prelude.lisp b/desktop/sources/lisp/prelude.lisp
new file mode 100644
index 0000000..82c0999
--- /dev/null
+++ b/desktop/sources/lisp/prelude.lisp
@@ -0,0 +1,11 @@
+(echo "Loading prelude.lisp")
+
+(defn translate 
+    (r p)
+    (clone 
+        r
+        (rect 
+            (of p :x)
+            (of p :y)
+            (of r :w)
+            (of r :h))))
diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 07b4165..46a55d4 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -167,10 +167,12 @@ function Lisp (input, lib) {
   }
 
   this.parse = function (input) {
-    return parenthesize(tokenize(`(${input})`))
+    return parenthesize(tokenize(input))
   }
 
   this.toPixels = async function () {
-    return interpret(this.parse(input))
+    return interpret(this.parse(`(
+    (include "./sources/lisp/prelude.lisp") 
+    ${input})`))
   }
 }
diff --git a/examples/glitch.lisp b/examples/glitch.lisp
index 5491fc8..064d5e1 100644
--- a/examples/glitch.lisp
+++ b/examples/glitch.lisp
@@ -5,12 +5,11 @@
 (defn glitch 
   (rec) 
   (if (gt rec 1)
-  ((clone 
-    (rect (random 400) (random 400) 2 2)
-    (rect (random 400) (random 400) 
-(random 10) (random 30)))
-    (glitch (sub rec 1))))
-)
+    (
+      (translate
+        (rect (random 400) (random 400) (random 10) (random 10))
+        (pos (random 400) (random 400)))
+      (glitch (sub rec 1)))))
 
 (import 
   "../static/crystal.jpg" 

From a559269b2dc74fc8a1dab39270c2d82d3a1b0771 Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Sat, 20 Jul 2019 21:49:25 +0200
Subject: [PATCH 14/14] update include

---
 desktop/sources/scripts/lisp.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 46a55d4..d2a9541 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -22,7 +22,7 @@ function Lisp (input, lib) {
     include: (input, context) => {
       if (!input[1].value || !fs.existsSync(input[1].value)) { console.warn('Source', input[1].value); return [] }
       const file = fs.readFileSync(input[1].value, { encoding: 'utf-8' })
-      return interpret(this.parse(file), context)
+      return interpret(this.parse(`(${file})`), context)
     },
     let: function (input, context) {
       const letContext = input[1].reduce(function (acc, x) {