Merge branch 'master' into feature/osc

This commit is contained in:
ngradwohl 2019-07-20 21:50:52 +02:00
commit 59634afa15
31 changed files with 402 additions and 349 deletions

@ -27,6 +27,7 @@ npm start
- `(import path rect)` Imports a graphic file with format. - `(import path rect)` Imports a graphic file with format.
- `(export path ~format ~quality)` Exports 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. - `(pos x y ~t)` Returns a position shape.
- `(size w h ~t)` Returns a size shape. - `(size w h ~t)` Returns a size shape.
- `(rect x y w h ~t)` Returns a rect shape. - `(rect x y w h ~t)` Returns a rect shape.
@ -37,7 +38,7 @@ npm start
- `(stroke ~shape)` Strokes a shape. - `(stroke ~shape)` Strokes a shape.
- `(fill ~rect)` Fills a shape. - `(fill ~rect)` Fills a shape.
- `(clear ~rect)` Clears a rect. - `(clear ~rect)` Clears a rect.
- `(concat ...items)` - `(concat ...items)` Concat multiple strings.
- `(add ...args)` Adds values. - `(add ...args)` Adds values.
- `(sub ...args)` Subtracts values. - `(sub ...args)` Subtracts values.
- `(mul ...args)` Multiplies values. - `(mul ...args)` Multiplies values.
@ -69,32 +70,29 @@ npm start
- `(range start end ~step)` - `(range start end ~step)`
- `(get item key)` Gets an object's parameter with name. - `(get item key)` Gets an object's parameter with name.
- `(set item key val)` Sets an object's parameter with name as value. - `(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. - `(frame)` Returns a rect of the frame.
- `(center)` Returns a position of the center 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. - `(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. - `(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)` - `(clone a b)`
- `(theme variable ~el)` - `(theme variable ~el)`
- `(gradient [x1 y1 x2 y2] ~colors 'black'])` - `(gradient [x1 y1 x2 y2] ~colors 'black'])`
- `(pixels rect fn q)` - `(pixels rect fn q)`
- `(saturation pixel ~q)` - `(saturation pixel ~q)`
- `(contrast 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. - `(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. - `(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. - `(exit ~force)` Exits Ronin.
- `(time)` Returns timestamp in milliseconds. - `(echo ...args)`
- `(time ~rate)` Returns timestamp in milliseconds.
- `(animate ~play)` Toggles animation. - `(animate ~play)` Toggles animation.
- `(js)` Javascript interop. - `(js)` Javascript interop.
- `(test name a b)` - `(test name a b)`
- `(benchmark fn)` logs time taken to execute a function - `(benchmark fn)` logs time taken to execute a function.
## Extras ## Extras

@ -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))))

@ -35,12 +35,13 @@ function Commander (ronin) {
if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return } if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return }
const inter = new Lisp(txt, ronin.library) const inter = new Lisp(txt, ronin.library)
inter.toPixels() inter.toPixels()
ronin.always && requestAnimationFrame(() => this.run(txt)) ronin.always === true && requestAnimationFrame(() => this.run(txt))
} }
this.load = function (txt) { this.load = function (txt) {
ronin.animate(false)
this._input.value = txt this._input.value = txt
this.run() this.run(txt)
} }
this.reindent = function () { this.reindent = function () {

@ -13,6 +13,10 @@ function Library (ronin) {
return path return path
} }
this.open = async (path) => { // Imports a graphic file and resizes the frame.
return ronin.surface.open(path)
}
// Shapes // Shapes
this.pos = (x, y, t = 'pos') => { // Returns a position shape. this.pos = (x, y, t = 'pos') => { // Returns a position shape.
@ -62,7 +66,7 @@ function Library (ronin) {
// Strings // Strings
this.concat = function (...items) { this.concat = function (...items) { // Concat multiple strings.
return items.reduce((acc, item) => { return `${acc}${item}` }, '') return items.reduce((acc, item) => { return `${acc}${item}` }, '')
} }
@ -223,12 +227,20 @@ function Library (ronin) {
return item[key] return item[key]
} }
this.of = (h, ...keys) => { this.of = (h, ...keys) => { // Gets object parameters with names.
return keys.reduce((acc, key) => { return keys.reduce((acc, key) => {
return acc[key] return acc[key]
}, h) }, 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 // Frame
this.frame = () => { // Returns a rect of the frame. this.frame = () => { // Returns a rect of the frame.
@ -240,10 +252,6 @@ function Library (ronin) {
return this.pos(rect.w / 2, rect.h / 2) 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. 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 rect = { x: 0, y: 0, w, h }
const a = document.createElement('img') const a = document.createElement('img')
@ -264,7 +272,7 @@ function Library (ronin) {
return ronin.surface.draw(b, rect) return ronin.surface.draw(b, rect)
} }
this.crop = async (rect) => { this.crop = async (rect) => { // Crop canvas to rect.
return ronin.surface.crop(rect) return ronin.surface.crop(rect)
} }
@ -310,45 +318,35 @@ function Library (ronin) {
return [pixel.r * q + intercept, pixel.g * q + intercept, pixel.b * q + intercept, pixel.a] 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 // 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) : [] return fs.existsSync(path) ? fs.readdirSync(path) : []
} }
this.file = (path = ronin.source.path) => { // Returns the content of a file this.file = (path = this.filepath()) => { // Returns the content of a file.
return fs.existsSync(path) ? fs.readFileSync(p, 'utf8') : '' 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) return require('path').dirname(path)
} }
this.filepath = (path = ronin.source.path) => { // Returns the path of a file this.filepath = (path = ronin.source.path) => { // Returns the path of a file.
return fs.existsSync(path) ? fs.readdirSync(path) : [] return path
} }
this.exit = (force = false) => { // Exits Ronin. this.exit = (force = false) => { // Exits Ronin.
ronin.source.quit(force) ronin.source.quit(force)
} }
this.time = () => { // Returns timestamp in milliseconds. this.echo = (...args) => {
return Date.now() ronin.log(args)
return args
}
this.time = (rate = 1) => { // Returns timestamp in milliseconds.
return (Date.now() * rate)
} }
this.animate = (play = true) => { // Toggles animation. this.animate = (play = true) => { // Toggles animation.
@ -368,7 +366,7 @@ function Library (ronin) {
return a === b 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 start = Date.now()
const result = await fn() const result = await fn()
console.log(`time taken: ${Date.now() - start}ms`) console.log(`time taken: ${Date.now() - start}ms`)

@ -22,7 +22,7 @@ function Lisp (input, lib) {
include: (input, context) => { include: (input, context) => {
if (!input[1].value || !fs.existsSync(input[1].value)) { console.warn('Source', input[1].value); return [] } 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' }) 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) { let: function (input, context) {
const letContext = input[1].reduce(function (acc, x) { const letContext = input[1].reduce(function (acc, x) {
@ -65,6 +65,27 @@ function Lisp (input, lib) {
return interpret(input[2], context) return interpret(input[2], context)
} }
return input[3] ? interpret(input[3], context) : [] return input[3] ? interpret(input[3], context) : []
},
__fn: function (input, context) {
return async function () {
const lambdaArguments = arguments
const keys = [...new Set(input.slice(2).flat(100).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))
}
},
__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 obj
} }
} }
@ -98,6 +119,8 @@ function Lisp (input, lib) {
return { type: TYPES.number, value: parseFloat(input) } return { type: TYPES.number, value: parseFloat(input) }
} else if (input[0] === '"' && input.slice(-1) === '"') { } else if (input[0] === '"' && input.slice(-1) === '"') {
return { type: TYPES.string, value: input.slice(1, -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') { } else if (input === 'true' || input === 'false') {
return { type: TYPES.bool, value: input === 'true' } return { type: TYPES.bool, value: input === 'true' }
} else { } else {
@ -110,10 +133,18 @@ function Lisp (input, lib) {
const token = input.shift() const token = input.shift()
if (token === undefined) { if (token === undefined) {
return list.pop() return list.pop()
} else if (token === '\'(') {
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 === '(') { } else if (token === '(') {
list.push(parenthesize(input, [])) list.push(parenthesize(input, []))
return parenthesize(input, list) return parenthesize(input, list)
} else if (token === ')') { } else if (token === ')' || token === '}') {
return list return list
} else { } else {
return parenthesize(input, list.concat(categorize(token))) return parenthesize(input, list.concat(categorize(token)))
@ -121,7 +152,18 @@ function Lisp (input, lib) {
} }
const tokenize = function (input) { 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, ' \'( ') // '()
.replace(/\{/g, ' { ') // {}
.replace(/\}/g, ' } ') // {}
: x.replace(/ /g, '!whitespace!')
})
.join('"').trim().split(/\s+/)
.map(function (x) { return x.replace(/!whitespace!/g, ' ') })
} }
this.parse = function (input) { this.parse = function (input) {
@ -129,6 +171,8 @@ function Lisp (input, lib) {
} }
this.toPixels = async function () { this.toPixels = async function () {
return interpret(this.parse(input)) return interpret(this.parse(`(
(include "./sources/lisp/prelude.lisp")
${input})`))
} }
} }

@ -66,7 +66,7 @@ function Source (ronin) {
if (!fs.existsSync(loc)) { console.warn('Source', 'File does not exist: ' + loc); return } if (!fs.existsSync(loc)) { console.warn('Source', 'File does not exist: ' + loc); return }
console.log('Source', 'Reading ' + loc) console.log('Source', 'Reading ' + loc)
this.path = loc this.path = loc
this.load(fs.readFileSync(this.path, 'utf8')) ronin.commander.load(fs.readFileSync(this.path, 'utf8'))
ronin.log(`Reading file.`) ronin.log(`Reading file.`)
} }
@ -74,10 +74,6 @@ function Source (ronin) {
ronin.commander.run() ronin.commander.run()
} }
this.load = function (data) {
ronin.commander._input.value = data
}
this.quit = function (force = false) { this.quit = function (force = false) {
if (this.hasChanges() === true && force === false) { if (this.hasChanges() === true && force === false) {
this.verify() this.verify()

@ -1,5 +1,5 @@
; animate ; animate
(
(clear) (clear)
(def t (def t
(sin (sin
@ -14,4 +14,4 @@
(stroke (stroke
(square pos) 1 "red") (square pos) 1 "red")
; set false to stop ; set false to stop
(animate true)) (animate true)

@ -1,31 +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 (first (1 2 3)))
(echo (rest (1 2 3))) (echo (rest (1 2 3)))
)
(echo (echo
(filter (filter
(lambda (a) (eq 0 (mod a 2))) '(eq 0 (mod %1 2))
(1 2 3 4 5)) (1 2 3 4 5))
) )
(
(clear) (clear)
(map (lambda (a) (map
(stroke (rect (mul a 30) 20 50 50) '(stroke (rect (mul a 30) 20 50 50)
1 "red")) 1 "red")
(range 0 20 5)) (range 0 20 5))
)
( (map
(clear) '(stroke
(map (lambda (a)
(stroke
(rect (rect
(mul a 10) (mul %1 10)
(add 50 (mul (sin a) 40)) (add 250 (mul (sin %1) 250))
a (mul 4 %1)
(add 20 (mul (cos a) 50))) 1 "red")) (add 20 (mul (cos %1) 50))) 1 "red")
(range 0 200 5))) (range 0 200 5))

@ -1,9 +1,9 @@
; basics ; basics
(
; define a variable ; define a variable
(def a 25) (def a 25)
(echo a) (echo a)
; define a function ; define a function
(defn add-two (a) (add 2 a)) (defn add-two (a) (add 2 a))
(echo (add-two 4))) (echo (add-two 4))

@ -0,0 +1,14 @@
; filesystem
; print path
(echo
(filepath))
; print folder path
(echo
(dirpath))
; print file content
(echo
(file))
; print folder content
(echo
(dir))

@ -1,6 +1,5 @@
; benchmark ; benchmark
(
; Basics ; Basics
(test "add" (add 8 4 2) 14) (test "add" (add 8 4 2) 14)
@ -53,9 +52,8 @@
; Generics ; 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 ; Interop
(test "interop" ((of (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) (test "recursive key selector" ((of (js) "Math" "max") 2 4) 4)
)

@ -1,7 +1,5 @@
; crop ; crop
(
(clear) (clear)
(open "../static/crystal.jpg") (open "../static/crystal.jpg")
(crop (rect 100 100 400 400)) (crop (rect 100 100 400 400))
)

@ -1,6 +1,5 @@
; dejong attractor ; dejong attractor
(
(clear) (clear)
(defn point (x y color) (defn point (x y color)
(fill (rect x y 1 1) color)) (fill (rect x y 1 1) color))
@ -25,11 +24,10 @@
(2 1) (2 1)
) )
) )
(benchmark (lambda () (benchmark
(dejong 12800 '(dejong 12800
(random -2 2) (random -2 2)
(random -2 2) (random -2 2)
(random -2 2) (random -2 2)
(random -2 2) (random -2 2)
))) ))
)

@ -1,14 +0,0 @@
; 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)))

@ -1,25 +1,18 @@
; pixels
(
(clear)
; Glitch ; Glitch
(clear)
(defn glitch (defn glitch
(rec) (rec)
(if (gt rec 1) (if (gt rec 1)
((clone (
(rect (random 400) (random 400) 2 2) (translate
(rect (random 400) (random 400) (rect (random 400) (random 400) (random 10) (random 10))
(random 10) (random 30))) (pos (random 400) (random 400)))
(glitch (sub rec 1)))) (glitch (sub rec 1)))))
)
; Draw photo
(import (import
"../static/crystal.jpg" "../static/crystal.jpg"
(rect 0 0 400 400)) (rect 0 0 400 400))
(glitch 500) (glitch 500)
)

@ -1,4 +1,3 @@
(
; gradients ; gradients
(clear) (clear)
@ -13,4 +12,3 @@
(gradient (gradient
(50 0 180 0) (50 0 180 0)
("black" "white" "blue" "green"))) ("black" "white" "blue" "green")))
)

@ -1,5 +1,4 @@
; guides ; guides
(
(clear) (clear)
(stroke (stroke
(frame) 1 "red") (frame) 1 "red")
@ -54,4 +53,4 @@
(frame) "w") (frame) "w")
(div (div
(of (of
(frame) "h") 2))) 1 "#72dec2")) (frame) "h") 2))) 1 "#72dec2")

@ -1,5 +1,5 @@
( (clear)
(def a (import (def a (import
"../static/crystal.jpg" "../static/crystal.jpg"
(rect 0 0 400 400))) (rect 0 0 400 400)))
(echo a)) (echo a)

@ -1,4 +1,3 @@
; include ; include
(
(include "../examples/recursive.lisp") (include "../examples/recursive.lisp")
(echo line-color)) (echo line-color)

1
examples/lambda.lisp Normal file

@ -0,0 +1 @@
(echo (map '(add %1 2) (4 5 6))

15
examples/objects.lisp Normal file

@ -0,0 +1,15 @@
; objects
(test "symbols" :a "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))

@ -1,9 +1,7 @@
; scale file ; saturate image
(
(open "../static/crystal.jpg") (open "../static/crystal.jpg")
(pixels (pixels
(frame) (frame)
saturation saturation
12) 12)
)

@ -1,7 +1,7 @@
; pixels ; pixels
(
(clear) (clear)
(import "../../PREVIEW.jpg" (import "../../PREVIEW.jpg"
(frame)) (frame))
(pixels (pixels
(rect 0 0 500 500) saturation 0.5)) (rect 0 0 500 500) saturation 0.5)

14
examples/random.file.lisp Normal file

@ -0,0 +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))

@ -1,5 +1,5 @@
; random ; random
(
(clear) (clear)
(defn place (defn place
(rec) (rec)
@ -14,4 +14,4 @@
(random 200))) (random 200)))
(place (place
(sub rec 1))))) (sub rec 1)))))
(place 30)) (place 30)

@ -1,5 +1,5 @@
; recursive ; recursive
(
(clear) (clear)
(defn rec (defn rec
(v) (v)
@ -13,4 +13,4 @@
(mul 5 v)) 1 "red") (mul 5 v)) 1 "red")
(rec (rec
(sub v 5))))) (sub v 5)))))
(rec 100)) (rec 100)

@ -1,5 +1,5 @@
; resize ; resize
(
(clear) (clear)
(open "../../PREVIEW.jpg") (open "../../PREVIEW.jpg")
(resize 0.5 0.5)) (resize 0.5 0.5)

@ -1,6 +1,6 @@
; Shapes ; Shapes
((clear) (clear)
; variables ; variables
(def center-w (div (of (frame) "w") 2)) (def center-w (div (of (frame) "w") 2))
@ -22,4 +22,3 @@
(pos (sub center-w rad) center-h) (pos (sub center-w rad) center-h)
(pos (add center-w rad) center-h))) (pos (add center-w rad) center-h)))
(stroke (text 10 170 200 "HELL") 2 "pink") (stroke (text 10 170 200 "HELL") 2 "pink")
)

@ -1,6 +1,6 @@
; animated recusive spiral ; animated recusive spiral
; by @local_guru ; by @local_guru
(
(clear) (clear)
(defn rec (defn rec
(v) (v)
@ -27,4 +27,4 @@
(sub v 0.3))))) (sub v 0.3)))))
; set false to stop ; set false to stop
(animate true) (animate true)
(rec 300)) (rec 300)

@ -1,8 +1,8 @@
(
(clear) (clear)
; ronin path ; ronin path
(stroke (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") (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 ; outline
(stroke (stroke
(svg "M15,15 L15,15 L285,15 L285,285 L15,285 Z") 1 "#555")) (svg "M15,15 L15,15 L285,15 L285,285 L15,285 Z") 1 "#555")

@ -1,5 +1,5 @@
; theme ; theme
(
(clear) (clear)
(def col (def col
(lambda (lambda
@ -35,4 +35,4 @@
(rec (rec
(sub v 3) (sub v 3)
(add i 1)))))) (add i 1))))))
(rec 40 0)) (rec 40 0)