Merge pull request #4 from hundredrabbits/master

sync
This commit is contained in:
Nikolaus Gradwohl 2019-07-20 21:50:23 +02:00 committed by GitHub
commit d6399f2740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 402 additions and 349 deletions

View File

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

View File

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

View File

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

View File

@ -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,12 +227,20 @@ 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)
}
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.
@ -240,10 +252,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 +272,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,45 +318,35 @@ 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.time = () => { // Returns timestamp in milliseconds.
return Date.now()
this.echo = (...args) => {
ronin.log(args)
return args
}
this.time = (rate = 1) => { // Returns timestamp in milliseconds.
return (Date.now() * rate)
}
this.animate = (play = true) => { // Toggles animation.
@ -368,7 +366,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`)

View File

@ -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) {
@ -65,6 +65,27 @@ function Lisp (input, lib) {
return interpret(input[2], 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) }
} 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 {
@ -110,10 +133,18 @@ 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 === '{') {
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)))
@ -121,7 +152,18 @@ 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, ' \'( ') // '()
.replace(/\{/g, ' { ') // {}
.replace(/\}/g, ' } ') // {}
: x.replace(/ /g, '!whitespace!')
})
.join('"').trim().split(/\s+/)
.map(function (x) { return x.replace(/!whitespace!/g, ' ') })
}
this.parse = function (input) {
@ -129,6 +171,8 @@ function Lisp (input, lib) {
}
this.toPixels = async function () {
return interpret(this.parse(input))
return interpret(this.parse(`(
(include "./sources/lisp/prelude.lisp")
${input})`))
}
}

View File

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

View File

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

View File

@ -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 (rest (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"))
(range 0 20 5))
)
(clear)
(map
'(stroke (rect (mul a 30) 20 50 50)
1 "red")
(range 0 20 5))
(map
'(stroke
(rect
(mul %1 10)
(add 250 (mul (sin %1) 250))
(mul 4 %1)
(add 20 (mul (cos %1) 50))) 1 "red")
(range 0 200 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)))

View File

@ -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)))
; define a variable
(def a 25)
(echo a)
; define a function
(defn add-two (a) (add 2 a))
(echo (add-two 4))

View File

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

View File

@ -1,6 +1,5 @@
; benchmark
(
; Basics
(test "add" (add 8 4 2) 14)
@ -53,9 +52,8 @@
; 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)
(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)

View File

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

View File

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

View File

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

View File

@ -1,25 +1,18 @@
; pixels
; Glitch
(
(clear)
(clear)
; Glitch
(defn glitch
(rec)
(if (gt rec 1)
(
(translate
(rect (random 400) (random 400) (random 10) (random 10))
(pos (random 400) (random 400)))
(glitch (sub rec 1)))))
(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))))
)
(import
"../static/crystal.jpg"
(rect 0 0 400 400))
; Draw photo
(import
"../static/crystal.jpg"
(rect 0 0 400 400))
(glitch 500)
)
(glitch 500)

View File

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

View File

@ -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"))
(frame) "h") 2))) 1 "#72dec2")

View File

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

View File

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

1
examples/lambda.lisp Normal file
View File

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

15
examples/objects.lisp Normal file
View 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))

View File

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

View File

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

14
examples/random.file.lisp Normal file
View 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))

View File

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

View File

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

View File

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

View File

@ -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))
; 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")
; draw circle
(stroke
(circle center-w center-h rad) 2 "white")
; draw rect
(stroke
(rect
(sub center-w rad) (sub center-h rad) center-h center-h) 2 "white")
; 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")
)
; 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")

View File

@ -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))
(rec 300)

View File

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

View File

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