mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
136 lines
2.8 KiB
Plaintext
136 lines
2.8 KiB
Plaintext
|
|
util = require "moonscript.util"
|
|
lua = { :debug, :type }
|
|
|
|
local *
|
|
|
|
dump = util.dump
|
|
|
|
p = (...) ->
|
|
print dump ...
|
|
|
|
is_object = (value) -> -- is a moonscript object
|
|
lua.type(value) == "table" and value.__class
|
|
|
|
type = (value) -> -- class aware type
|
|
base_type = lua.type value
|
|
if base_type == "table"
|
|
cls = value.__class
|
|
return cls if cls
|
|
base_type
|
|
|
|
debug = setmetatable {
|
|
upvalue: (fn, k, v) ->
|
|
upvalues = {}
|
|
i = 1
|
|
while true
|
|
name = lua.debug.getupvalue(fn, i)
|
|
break if name == nil
|
|
upvalues[name] = i
|
|
i += 1
|
|
|
|
if not upvalues[k]
|
|
error "Failed to find upvalue: " .. tostring k
|
|
|
|
if not v
|
|
_, value = lua.debug.getupvalue fn, upvalues[k]
|
|
value
|
|
else
|
|
lua.debug.setupvalue fn, upvalues[k], v
|
|
}, __index: lua.debug
|
|
|
|
-- run a function with scope injected before its function environment
|
|
run_with_scope = (fn, scope, ...) ->
|
|
old_env = getfenv fn
|
|
env = setmetatable {}, {
|
|
__index: (name) =>
|
|
val = scope[name]
|
|
if val != nil
|
|
val
|
|
else
|
|
old_env[name]
|
|
}
|
|
setfenv fn, env
|
|
fn ...
|
|
|
|
-- wrap obj such that calls to methods do not need a reference to self
|
|
bind_methods = (obj) ->
|
|
setmetatable {}, {
|
|
__index: (name) =>
|
|
val = obj[name]
|
|
if val and lua.type(val) == "function"
|
|
bound = (...) -> val obj, ...
|
|
self[name] = bound
|
|
bound
|
|
else
|
|
val
|
|
}
|
|
|
|
-- use a function to provide default values to table
|
|
-- optionally specify a starting table
|
|
-- fibanocci table:
|
|
-- t = defaultbl {[0]: 0, [1]: 1}, (i) -> self[i - 1] + self[i - 2]
|
|
defaultbl = (t, fn) ->
|
|
if not fn
|
|
fn = t
|
|
t = {}
|
|
setmetatable t, {
|
|
__index: (name) =>
|
|
val = fn self, name
|
|
rawset self, name, val
|
|
val
|
|
}
|
|
|
|
-- chain together tables by __index metatables
|
|
extend = (...) ->
|
|
tbls = {...}
|
|
return if #tbls < 2
|
|
|
|
for i = 1, #tbls - 1
|
|
a = tbls[i]
|
|
b = tbls[i + 1]
|
|
|
|
setmetatable a, __index: b
|
|
|
|
tbls[1]
|
|
|
|
-- shallow copy
|
|
copy = =>
|
|
{key,val for key,val in pairs self}
|
|
|
|
-- mixin class properties into self, call new
|
|
mixin = (cls, ...) =>
|
|
for key, val in pairs cls.__base
|
|
self[key] = val if not key\match"^__"
|
|
cls.__init self, ...
|
|
|
|
-- mixin methods from an object into self
|
|
mixin_object = (object, methods) =>
|
|
for name in *methods
|
|
self[name] = (parent, ...) ->
|
|
object[name](object, ...)
|
|
|
|
-- mixin table values into self
|
|
mixin_table = (tbl, keys) =>
|
|
if keys
|
|
for key in *keys
|
|
self[key] = tbl[key]
|
|
else
|
|
for key, val in pairs tbl
|
|
self[key] = val
|
|
|
|
fold = (items, fn)->
|
|
len = #items
|
|
if len > 1
|
|
accum = fn items[1], items[2]
|
|
for i=3,len
|
|
accum = fn accum, items[i]
|
|
accum
|
|
else
|
|
items[1]
|
|
|
|
{
|
|
:dump, :p, :is_object, :type, :debug, :run_with_scope, :bind_methods,
|
|
:defaultbl, :extend, :copy, :mixin, :mixin_object, :mixin_table, :fold
|
|
}
|