Merge branch 'master' into feature/osc
This commit is contained in:
@@ -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 () {
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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})`))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user