From acea1ad26d80ce134a556f8b49ac1e3ebac8124f Mon Sep 17 00:00:00 2001
From: Quentin Leonetti <q.leonetti@gmail.com>
Date: Tue, 16 Jul 2019 20:49:22 +0200
Subject: [PATCH] refactor for async

---
 desktop/sources/scripts/library.js | 35 ++++++++++++++++-------------
 desktop/sources/scripts/lisp.js    | 16 ++++++-------
 desktop/sources/scripts/surface.js | 36 +++++++++++++++---------------
 examples/crop.lisp                 | 13 ++---------
 examples/glitch.lisp               |  7 +++---
 examples/open.lisp                 | 14 +++++-------
 examples/pixels.lisp               | 19 +++++-----------
 examples/random.lisp               | 19 ++++++++--------
 examples/resize.lisp               | 13 ++---------
 9 files changed, 74 insertions(+), 98 deletions(-)

diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index 0c9d93c..7223dc2 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -1,7 +1,6 @@
 function Library (ronin) {
-  this.open = (path, callback) => {
-    ronin.surface.open(path, callback)
-    return path
+  this.open = async (path) => {
+    return ronin.surface.open(path)
   }
 
   this.export = (path, type = 'image/png', quality = 1.0) => {
@@ -12,27 +11,24 @@ function Library (ronin) {
     return path
   }
 
-  this.draw = (path, rect, callback) => {
+  this.draw = async (path, rect) => {
     const img = new Image()
     img.src = path
-    ronin.surface.draw(img, rect, callback)
-    return rect
+    return ronin.surface.draw(img, rect)
   }
 
-  this.resize = (w = 1, h = 1, callback) => {
+  this.resize = async (w = 1, h = 1) => {
     const rect = w <= 1 || h <= 1 ? { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h } : { x: 0, y: 0, w, h }
     const a = document.createElement('img')
     const b = document.createElement('img')
     a.src = ronin.surface.el.toDataURL()
     ronin.surface.resizeImage(a, b)
     ronin.surface.resize(rect, true)
-    ronin.surface.draw(b, rect, callback)
-    return rect
+    return ronin.surface.draw(b, rect)
   }
 
-  this.crop = (rect, callback) => {
-    ronin.surface.crop(rect, callback)
-    return rect
+  this.crop = async (rect) => {
+    return ronin.surface.crop(rect)
   }
 
   this.folder = (path = ronin.source.path) => {
@@ -77,13 +73,22 @@ function Library (ronin) {
 
   // Arrays
 
-  this.map = (fn, arr) => {
-    return arr.map(fn)
+  this.map = async (fn, arr) => {
+    return Promise.all(arr.map(fn))
   }
 
-  this.filter = (fn, arr) => {
+  this._filter = (fn, arr) => {
     return arr.filter(fn)
   }
+  this.filter= (fn, arr) => {
+   const list = Array.from(arr);
+   return Promise.all(list.map((element, index) => fn(element, index, list)))
+     .then(result => {
+       return list.filter((_, index) => {
+         return result[index];
+       });
+    });
+  }
 
   this.reduce = (fn, arr, acc = 0) => {
     return arr.reduce(fn, acc)
diff --git a/desktop/sources/scripts/lisp.js b/desktop/sources/scripts/lisp.js
index 2b7788e..fe9b520 100644
--- a/desktop/sources/scripts/lisp.js
+++ b/desktop/sources/scripts/lisp.js
@@ -50,7 +50,7 @@ function Lisp (input, lib) {
         // docstring
         console.log(input[2].value)
       }
-      context.scope[identifier] = function () {
+      context.scope[identifier] = async function () {
         const lambdaArguments = arguments
         const lambdaScope = argumentNames.reduce(function (acc, x, i) {
           acc[x.value] = lambdaArguments[i]
@@ -60,7 +60,7 @@ function Lisp (input, lib) {
       }
     },
     lambda: function (input, context) {
-      return function () {
+      return async function () {
         const lambdaArguments = arguments
         const lambdaScope = input[1].reduce(function (acc, x, i) {
           acc[x.value] = lambdaArguments[i]
@@ -69,23 +69,23 @@ function Lisp (input, lib) {
         return interpret(input[2], new Context(lambdaScope, context))
       }
     },
-    if: function (input, context) {
-      if (interpret(input[1], context)) {
+    if: async function (input, context) {
+      if (await interpret(input[1], context)) {
         return interpret(input[2], context)
       }
       return input[3] ? interpret(input[3], context) : []
     }
   }
 
-  const interpretList = function (input, context) {
+  const interpretList = async function (input, context) {
     if (input.length > 0 && input[0].value in special) {
       return special[input[0].value](input, context)
     }
-    const list = input.map(function (x) { return interpret(x, context) })
+    const list = await Promise.all(input.map(function (x) { return interpret(x, context) }))
     return list[0] instanceof Function ? list[0].apply(undefined, list.slice(1)) : list
   }
 
-  const interpret = function (input, context) {
+  const interpret = async function (input, context) {
     if (!input) { console.warn('error', context.scope); return null }
 
     if (context === undefined) {
@@ -134,7 +134,7 @@ function Lisp (input, lib) {
     return parenthesize(tokenize(input))
   }
 
-  this.toPixels = function () {
+  this.toPixels = async function () {
     return interpret(this.parse(input))
   }
 }
diff --git a/desktop/sources/scripts/surface.js b/desktop/sources/scripts/surface.js
index ef054ae..621ce02 100644
--- a/desktop/sources/scripts/surface.js
+++ b/desktop/sources/scripts/surface.js
@@ -106,32 +106,32 @@ function Surface (ronin) {
 
   // IO
 
-  this.open = function (path, callback = () => {}) {
-    const img = new Image()
-    img.src = path
-    img.onload = () => {
-      ronin.log(`Open ${img.width}x${img.height}`)
-      const rect = { x: 0, y: 0, w: img.width, h: img.height }
-      this.resize(rect, true)
-      this.context.drawImage(img, 0, 0, img.width, img.height)
-      if (typeof callback === 'function') {
-        callback()
+  this.open = function (path) {
+    return new Promise(resolve => {
+      const img = new Image()
+      img.src = path
+      img.onload = () => {
+        //ronin.log(`Open ${img.width}x${img.height}`)
+        const rect = { x: 0, y: 0, w: img.width, h: img.height }
+        this.resize(rect, true)
+        this.context.drawImage(img, 0, 0, img.width, img.height)
+        resolve()
       }
-    }
+    })
   }
 
-  this.draw = function (img, rect = this.getFrame(), callback = () => {}) {
-    img.onload = () => {
-      ronin.log(`Draw ${img.width}x${img.height}`)
+  this.draw = function (img, rect = this.getFrame()) {
+    return new Promise(resolve => {
+      img.onload = () => {
+      //ronin.log(`Draw ${img.width}x${img.height}`)
       this.context.drawImage(img, rect.x, rect.y, rect.w, rect.h) // no strect: img.height * (rect.w / img.width)
-      if (typeof callback === 'function') {
-        callback()
-      }
+      resolve()
     }
+    });
   }
 
   this.crop = function (rect) {
-    ronin.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
+    // ronin.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
     const crop = this.getCrop(rect)
     this.resize(rect, true)
     this.context.drawImage(crop, 0, 0)
diff --git a/examples/crop.lisp b/examples/crop.lisp
index d0e57de..0a8168a 100644
--- a/examples/crop.lisp
+++ b/examples/crop.lisp
@@ -2,15 +2,6 @@
 
 (
   (clear)
-
-  ; Filter
-
-  (def filter-action 
-    (lambda () (crop (rect 100 100 400 400))))
-
-  ; Draw photo 
-  
-  (open 
-    "../../PREVIEW.jpg" 
-    filter-action)
+  (open "../static/crystal.jpg")
+  (crop (rect 100 100 400 400))
 )
\ No newline at end of file
diff --git a/examples/glitch.lisp b/examples/glitch.lisp
index 6804bc2..f84b501 100644
--- a/examples/glitch.lisp
+++ b/examples/glitch.lisp
@@ -3,7 +3,7 @@
 (
   (clear)
 
-  ; Filter
+  ; Glitch
 
   (defn glitch 
     (rec) 
@@ -19,6 +19,7 @@
   
   (draw 
     "../static/crystal.jpg" 
-    (rect 0 0 400 400) 
-    (lambda () (glitch 2000)))
+    (rect 0 0 400 400))
+
+  (glitch 500)
 )
\ No newline at end of file
diff --git a/examples/open.lisp b/examples/open.lisp
index 817d061..6166815 100644
--- a/examples/open.lisp
+++ b/examples/open.lisp
@@ -1,13 +1,9 @@
 ; scale file
 (
-  ; Filter
 
-  (def filter-action 
-    (lambda () (pixels 
-      (frame)
-      saturation
-      0.5)
-    ))
-
-(open (path "/Users/VillaMoirai/Desktop/clip.jpg") filter-action)
+  (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 e58fb38..d45baa9 100644
--- a/examples/pixels.lisp
+++ b/examples/pixels.lisp
@@ -2,20 +2,11 @@
 
 (
   (clear)
-
-  ; Filter
-
-  (def filter-action 
-    (lambda () (pixels 
-      (rect 0 0 500 500)
-      saturation
-      0.5)
-    ))
-
-  ; Draw photo 
-  
   (draw 
     "../../PREVIEW.jpg" 
-    (frame) 
-    filter-action)
+    (frame))
+  (pixels 
+    (rect 0 0 500 500)
+    saturation
+    0.5)
 )
\ No newline at end of file
diff --git a/examples/random.lisp b/examples/random.lisp
index 490b2b6..0753a05 100644
--- a/examples/random.lisp
+++ b/examples/random.lisp
@@ -6,15 +6,16 @@
   (defn place
     (rec)
     (if (gt rec 0)
-      ((draw "../static/crystal.jpg"
-      (rect 
-        (random 200)
-        (random 200) 
-        (random 200) 
-        (random 200))
-      (lambda () (place (sub rec 1)))
-    )))
-)
+      (
+        (draw "../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/resize.lisp b/examples/resize.lisp
index 9cac33a..620a36c 100644
--- a/examples/resize.lisp
+++ b/examples/resize.lisp
@@ -2,15 +2,6 @@
 
 (
   (clear)
-
-  ; Filter
-
-  (def filter-action 
-    (lambda () (resize 0.5 0.5)))
-
-  ; Draw photo 
-  
-  (open 
-    "../../PREVIEW.jpg" 
-    filter-action)
+  (open "../../PREVIEW.jpg")
+  (resize 0.5 0.5)
 )
\ No newline at end of file