diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-31 18:28:10 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-31 18:28:10 +0000 |
| commit | 16962e1836251526fa08895b1a76dd72b7fd5ef9 (patch) | |
| tree | ef60d08e792825407d41fb77c14c26ecb135e2fc | |
| parent | nested parens in comments (diff) | |
| download | alive-16962e1836251526fa08895b1a76dd72b7fd5ef9.tar.gz alive-16962e1836251526fa08895b1a76dd72b7fd5ef9.zip | |
modularize
| -rw-r--r-- | ast.moon | 10 | ||||
| -rw-r--r-- | base.moon | 8 | ||||
| -rw-r--r-- | boot.lua | 22 | ||||
| -rw-r--r-- | conf.lua | 3 | ||||
| -rw-r--r-- | copilot.moon | 12 | ||||
| -rw-r--r-- | gui.moon | 85 | ||||
| -rw-r--r-- | init.moon | 34 | ||||
| -rw-r--r-- | lib/debug.moon | 12 | ||||
| -rw-r--r-- | lib/gui.moon | 45 | ||||
| -rw-r--r-- | lib/math.moon | 68 | ||||
| -rw-r--r-- | lib/time.moon | 33 | ||||
| -rw-r--r-- | lib/util.moon | 13 | ||||
| -rw-r--r-- | main.lua | 5 | ||||
| -rw-r--r-- | main.moon | 19 | ||||
| -rw-r--r-- | old_base.moon | 70 | ||||
| -rw-r--r-- | registry.moon | 26 | ||||
| -rw-r--r-- | test.alv | 31 |
17 files changed, 265 insertions, 231 deletions
@@ -1,4 +1,4 @@ -import Constant from require 'base' +import Const from require 'base' unpack or= table.unpack unescape = (str) -> @@ -9,7 +9,7 @@ unescape = (str) -> class Atom new: (@raw, @style='', value) => - @value = Constant value + @value = Const value _walk_sexpr: => @@ -81,7 +81,11 @@ class Xpr make_nexpr: (parts) -> Xpr parts, 'naked' - __tostring: => @stringify! + __tostring: => + if @tag + "<Xpr[#{@tag}] #{@value}>" + else + "<Xpr #{@value}>" { :Atom @@ -1,11 +1,11 @@ -class Constant +class Const new: (@value) => get: => @value getc: => @value __tostring: => "<const: #{@value}>" -class OP +class Op new: (@node) => @setup @node\tail! @@ -27,6 +27,6 @@ class OP cls.__base.__tostring = @__tostring { - :Constant - :OP + :Const + :Op } diff --git a/boot.lua b/boot.lua deleted file mode 100644 index 4226cba..0000000 --- a/boot.lua +++ /dev/null @@ -1,22 +0,0 @@ -require 'moonscript' - -MODS = MODS or {} --- table.insert(MODS, 'base') --- table.insert(MODS, 'debug') --- table.insert(MODS, 'math') --- table.insert(MODS, 'time') - -for _,mod in ipairs(MODS) do - package.loaded[mod] = nil -end -for _,mod in ipairs(MODS) do - require(mod) -end -for k,v in pairs(require 'base') do - _G[k] = v -end - -function reload() - package.loaded.boot = nil - require 'boot' -end diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..8f46767 --- /dev/null +++ b/conf.lua @@ -0,0 +1,3 @@ +function love.conf(t) + t.window.resizable = true +end diff --git a/copilot.moon b/copilot.moon index 88aa8fa..d0dec92 100644 --- a/copilot.moon +++ b/copilot.moon @@ -20,17 +20,21 @@ class Copilot error "not a file: #{@file}" patch: => + root = assert (program\match slurp @file), "parse error" + @registry\patch_root root + spit @file, root\stringify! + + poll: => { :mode, :modification } = (lfs.attributes @file) or {} if mode != 'file' return if @last_modification < modification print "---" + ok, err = pcall @patch, @ + if not ok + print "ERROR: #{err}" - root = assert (program\match slurp @file), "error parsing" - @registry\patch_root root - - spit @file, root\stringify! @last_modification = os.time! :Copilot diff --git a/gui.moon b/gui.moon deleted file mode 100644 index 804e212..0000000 --- a/gui.moon +++ /dev/null @@ -1,85 +0,0 @@ -{ graphics: lg } = love -import Registry from require 'registry' -import Copilot from require 'copilot' -import Constant, OP from require 'base' - -env = Registry! -copilot = Copilot arg[#arg], env - -env.globals.lfo = class LFO extends OP - tau = math.pi * 2 - new: (...) => - super ... - @phase = 0 - - setup: (@speed, @wave=Constant 'sin') => - - update: (dt) => - @phase += dt * @speed\get! - @value = switch @wave\get! - when 'sin' then .5 + .5 * math.cos @phase * tau - when 'saw' then @phase % 1 - when 'tri' then math.abs (2*@phase % 2) - 1 - else error "unknown wave type" - -env.globals.tick = class Tick extends OP - new: (...) => - super ... - @phase = 0 - - setup: (@speed, @wave=Constant 'sin') => - - update: (dt) => - @phase += dt / @speed\get! - @value = math.floor @phase - -env.globals.pick = class Pick extends OP - setup: (@i, ...) => - @choices = { ... } - - update: => - i = 1 + (math.floor @i\get!) % #@choices - @value = @choices[i]\get! - -env.globals.mix = class Mix extends OP - setup: (@a, @b, @i) => - - update: (dt) => - i = @i\get! - @value = i*@b\get! + (1-i)*@a\get! - -env.globals['gui/out'] = class Out extends OP - setup: (name, @chld) => - @@instances[@name] = nil if @name - @name = name\getc! - @@instances[@name] = @ - - update: => - @value = @chld\get! - - destroy: => - @@instances[@name] = nil - - MARGIN = 16 - WIDTH = 24 - HEIGHT = 120 - @instances: {} - @draw_all: -> - outs = [name for name in pairs @@instances] - table.sort outs - - x = MARGIN - lg.setColor 1, 1, 1 - for name in *outs - value = @@instances[name].value * HEIGHT - lg.rectangle 'line', x, MARGIN, WIDTH, HEIGHT - lg.rectangle 'fill', x, MARGIN + HEIGHT - value, WIDTH, value - lg.print name, x, MARGIN + HEIGHT + MARGIN - x += WIDTH + MARGIN - -love.update = (dt) -> - copilot\patch! - env\update dt - -love.draw = -> - Out.draw_all! diff --git a/init.moon b/init.moon new file mode 100644 index 0000000..c028e50 --- /dev/null +++ b/init.moon @@ -0,0 +1,34 @@ +import Registry from require 'registry' + +env = Registry! +env\add_module 'math' +env\add_module 'time' +env\add_module 'util' +env\add_module 'debug' + +if ... == 'init' + return env + +-- run from CLI +import clock_gettime, nanosleep, CLOCK_MONOTONIC from require 'posix.time' +import Copilot from require 'copilot' + +delta = do + gettime = -> + spec = clock_gettime CLOCK_MONOTONIC + spec.tv_sec + spec.tv_nsec * 1e-9 + + local last, time + -> + time = gettime! + with time - (last or time) + last = time + +copilot = Copilot arg[1], env +while true + copilot\poll! + + dt = delta! + env\update dt + + assert nanosleep tv_sec: 0, tv_nsec: math.floor 1e9 / 60 diff --git a/lib/debug.moon b/lib/debug.moon new file mode 100644 index 0000000..c2d0d52 --- /dev/null +++ b/lib/debug.moon @@ -0,0 +1,12 @@ +import Op from require 'base' + +class out extends Op + setup: (name, @chld) => + @name = name\getc! + + update: => + print "#{@name} << ", @chld\get! + +{ + :out +} diff --git a/lib/gui.moon b/lib/gui.moon new file mode 100644 index 0000000..979854f --- /dev/null +++ b/lib/gui.moon @@ -0,0 +1,45 @@ +{ graphics: lg } = love +import Op from require 'base' +import Copilot from require 'copilot' + +class out extends Op + setup: (name, @chld) => + @@instances[@name] = nil if @name + @name = name\getc! + @@instances[@name] = @ + + update: => + @value = @chld\get! + + destroy: => + @@instances[@name] = nil + + MARGIN = 16 + WIDTH = 24 + HEIGHT = 120 + @instances: {} + @draw_all: -> + outs = [name for name in pairs @@instances] + table.sort outs + + x = MARGIN + lg.setColor 1, 1, 1 + for name in *outs + value = @@instances[name].value * HEIGHT + lg.rectangle 'line', x, MARGIN, WIDTH, HEIGHT + lg.rectangle 'fill', x, MARGIN + HEIGHT - value, WIDTH, value + lg.print name, x, MARGIN + HEIGHT + MARGIN + x += WIDTH + MARGIN + +copilot = Copilot arg[#arg], env + +love.update = (dt) -> + copilot\poll! + env\update dt + +love.draw = -> + out.draw_all! + +{ + :out +} diff --git a/lib/math.moon b/lib/math.moon new file mode 100644 index 0000000..8ada38a --- /dev/null +++ b/lib/math.moon @@ -0,0 +1,68 @@ +import Op from require 'base' +unpack or= table.unpack + +class BinOp extends Op + setup: (...) => + @children = { ... } + assert #@children >= 2, "#{@} needs at least two parameters" + +class add extends BinOp + update: => + @value = 0 + for child in *@children + @value += child\get! + +class sub extends BinOp + update: => + @value = @children[1]\get! + for child in *@children[2,] + @value -= child\get! + +class mul extends BinOp + update: => + @value = 1 + for child in *@children + @value *= child\get! + +class div extends BinOp + update: => + @value = @children[1]\get! + for child in *@children[2,] + @value /= child\get! + +func_op = (name, arity, func) -> + k = class extends Op + setup: (...) => + @params = { ... } + if arity != '*' + assert #@params == arity, "#{@} needs exactly #{arity} parameters" + + update: => + @value = func unpack [param\get! for param in *@params] + + k.__name = name + k + +module = { + :add, '+': add + :sub, '-': sub + :mul, '*': mul + :div, '/': div + + mix: func_op 'mix', 3, (a, b, i) -> i*b + (1-i)*a +} + +for name, arity in pairs { + exp: 1, log: 2, log10: 1, sqrt: 1 + + cos: 1, sin: 1, tan: 1 + asin: 1, acos: 1, atan: 1, atan2: 2 + sinh: 1, cosh: 1, tanh: 1 + + min: '*', max: '*' + + floor: 1, ceil: 1, abs: 1 +} + module[name] = func_op name, arity, math[name] + +module diff --git a/lib/time.moon b/lib/time.moon new file mode 100644 index 0000000..f2ad70c --- /dev/null +++ b/lib/time.moon @@ -0,0 +1,33 @@ +import Op, Const from require 'base' + +class lfo extends Op + tau = math.pi * 2 + new: (...) => + super ... + @phase = 0 + + setup: (@freq, @wave=Const 'sin') => + + update: (dt) => + @phase += dt * @freq\get! + @value = switch @wave\get! + when 'sin' then .5 + .5 * math.cos @phase * tau + when 'saw' then @phase % 1 + when 'tri' then math.abs (2*@phase % 2) - 1 + else error "unknown wave type" + +class tick extends Op + new: (...) => + super ... + @phase = 0 + + setup: (@freq) => + + update: (dt) => + @phase += dt / @freq\get! + @value = math.floor @phase + +{ + :lfo + :tick +} diff --git a/lib/util.moon b/lib/util.moon new file mode 100644 index 0000000..7306fbc --- /dev/null +++ b/lib/util.moon @@ -0,0 +1,13 @@ +import Op from require 'base' + +class pick extends Op + setup: (@i, ...) => + @choices = { ... } + + update: => + i = 1 + (math.floor @i\get!) % #@choices + @value = @choices[i]\get! + +{ + :pick +} @@ -1,2 +1,3 @@ -MODS = {'gui'} -require 'boot' +require 'moonscript' +env = require 'init' +env:add_module 'gui' diff --git a/main.moon b/main.moon deleted file mode 100644 index 9d15f34..0000000 --- a/main.moon +++ /dev/null @@ -1,19 +0,0 @@ -sleep = require 'sleep' -import Copilot from require 'copilot' - -class Environment - spawn: (sexpr) => - print "spawning [#{sexpr.tag}]" - - patch: (new, old) => - -- print "patching [#{new.tag}]" - - destroy: (sexpr) => - print "destroying [#{sexpr.tag}]" - -env = Environment! -copilot = Copilot arg[1], env - -while True - sleep 0.01 - copilot\patch! diff --git a/old_base.moon b/old_base.moon deleted file mode 100644 index 950ea16..0000000 --- a/old_base.moon +++ /dev/null @@ -1,70 +0,0 @@ -DISP, OP, OUT = {}, {}, {} - -class Value - new: (@value) => - - __tostring: => "<value: #{@value}>" - -class Dispatcher - new: => - @operators = {} - - dispatch: (...) => - for op in pairs @operators - op\dispatch ... - op\update! - - register: (op, params=true) => - @operators[op] = params - - unregister: (op) => - @operators[op] = nil - -class Op - new: (opts={}, defaults) => - assert defaults, "OP-def needs default arguments" - for k,v in pairs defaults - @[k] = opts[k] or v - - @parents = 0 - @setup! - - setup: => - destroy: => - update: => -- return current value (pure) - - mount: (lastval) => - @parents += 1 - - if lastval and @parents == 1 - @setup lastval - - unmount: => - @parents -= 1 - if @parents == 0 - @destroy! - -class Out - new: (@handle) => - @values = {} - @mapping = {} - - __call: (key, op) => - if @mapping[key] - @mapping[key]\unmount! - - @mapping[key] = op - @mapping[key]\mount @values[key] - - update: => - for key, op in pairs @mapping - @values[key] = op\update! - - @handle! if @handle - -{ - :Value, - :DISP, :Dispatcher - :OP, :Op - :OUT, :Out -} diff --git a/registry.moon b/registry.moon index 65c26a5..a7b4c9d 100644 --- a/registry.moon +++ b/registry.moon @@ -3,6 +3,12 @@ class Registry @globals = {} @map = {} + add_module: (name, tbl=require "lib.#{name}") => + for k,v in pairs tbl + @globals["#{name}/#{k}"] = v + + -- + gentag: => #@map + 1 patch: (sexpr) => @@ -38,13 +44,6 @@ class Registry @destroy_expr expr @map[tag] = nil - -- - - update: (dt) => - -- for tag, sexpr in pairs @map - for sexpr in @root\walk_sexpr! - sexpr.value\update dt - spawn_expr: (sexpr) => ref = sexpr\head!\getc! if sexpr.tag @@ -52,7 +51,7 @@ class Registry else print "spawning '#{ref}'" - def = rawget @globals, ref + def = assert @globals[ref], "no such function: '#{ref}'" sexpr.value = def sexpr patch_expr: (new, old) => @@ -69,4 +68,15 @@ class Registry sexpr.value\destroy! print "destroying [#{sexpr.tag}]" + -- + + update: (dt) => + -- for tag, sexpr in pairs @map + for sexpr in @root\walk_sexpr! + continue unless sexpr.value + + ok, err = pcall sexpr.value.update, sexpr.value, dt + if not ok + print "@#{sexpr}: #{err}" + :Registry @@ -1,17 +1,20 @@ -(osc "/radius" (lfo (cc 14))) +#(this is a comment) +([2]debug/out 'a' ([6]math/mix 0.5 1 ([5]time/lfo 1))) -(set kick (note 38)) -(set pitch (const 440)) -(osc rot - (step - kick - (random-rot) - (random-rot) - (random-rot) - (random-rot) - ) -) +([16]util/pick 2 3) + +([14]math/mix 0 2 0.5) + +([13]debug/out 'b' ([12]math/mix 0 ([11]util/pick ([10]time/tick 4) + 0.25 + 0.5 + 0.75 + 1) ([3]time/lfo 1 tri))) + +([9]debug/out 'name' ([8]util/pick ([7]time/tick 1) + 0.1 + 0.6 + 0.3 + 0.9)) -(amp (env kick 02 10 05) - (sineosc pitch)) |
