diff options
author | Martin Peach <mrpeach@users.sourceforge.net> | 2011-03-15 20:53:57 +0000 |
---|---|---|
committer | Martin Peach <mrpeach@users.sourceforge.net> | 2011-03-15 20:53:57 +0000 |
commit | 267170167d52cab9e97f879d9127a1cf04f6bb58 (patch) | |
tree | 00260a90ce6472e34c5eff41602af57595c8830d /examples/lexpr.pd_lua |
This is a version of Claude Heiland-Allen's lua for Pd. The objects are named pdlua and pdluax instead of lua and luax. So far it seems to work on linux.svn2git-root
svn path=/trunk/externals/pdlua/; revision=15030
Diffstat (limited to 'examples/lexpr.pd_lua')
-rw-r--r-- | examples/lexpr.pd_lua | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/examples/lexpr.pd_lua b/examples/lexpr.pd_lua new file mode 100644 index 0000000..487c87e --- /dev/null +++ b/examples/lexpr.pd_lua @@ -0,0 +1,145 @@ +local lexpr = pd.Class:new():register("lexpr") + +local function sandbox(e, f) -- only supports nullary f() with one return + local g = getfenv(f) + setfenv(f, e) + local r = f() + setfenv(f, g) + return r +end + +local lexpr_globals = { + abs = math.abs, + acos = math.acos, + asin = math.asin, + atan = math.atan, + atan2 = math.atan2, + ceil = math.ceil, + cos = math.cos, + cosh = math.cosh, + deg = math.deg, + exp = math.exp, + floor = math.floor, + fmod = math.fmod, + log = math.log, + log10 = math.log10, + max = math.max, + min = math.min, + int = function (x) i,f = math.modf(x) ; return i end, + wrap = function (x) i,f = math.modf(x) ; return f end, + pi = math.pi, + pow = math.pow, + rad = math.rad, + sin = math.sin, + sinh = math.sinh, + sqrt = math.sqrt, + tan = math.tan, + tanh = math.tanh, + val = function (s) return (pd.getvalue(s) or 0) end, + choose = function (b,t,f) if b then return t else return f end end +} + +function lexpr:readexpr(atoms) + local vname = { } + local context = { } + local expr + local i + local k + local v + local j = 1 + local inlets + local f + local phase = "vars" + for k,v in pairs(lexpr_globals) do + context[k] = v + end + for i,v in ipairs(atoms) do + if phase == "vars" then -- create variables + if v == "->" then + inlets = i - 1 + phase = "expr" + expr = "" + else + if type(v) == "string" then + vname[j] = v + context[v] = 0 + j = j + 1 + else + self:error("lexpr: variable names must be symbols") + return -1 + end + end + else if phase == "expr" then -- build string + expr = expr .. " " .. v + else + self:error("lexpr: internal error parsing expression") + return -1 + end end + end + f = assert(loadstring("return {" .. expr .. " }")) + local outlets = #(sandbox(context, f)) + return inlets, vname, context, f, outlets +end + +function lexpr:initialize(sel, atoms) + self.vname = { } + self.context = { } + self.hot = { } + self.f = function () return 0 end + function self:in_1_bang() + local r = sandbox(self.context, self.f) + local i + for i = self.outlets,1,-1 do + if type(r[i]) == "number" then + self:outlet(i, "float", { r[i] }) + else if type(r[i]) == "string" then + self:outlet(i, "symbol", { r[i] }) + else + self:error("calculated a " .. type(r[i]) .. " but expected a number or a string") + end end + end + end + function self:in_n_float(i, f) + self.context[self.vname[i]] = f + if self.hot[i] then self:in_1_bang() end + end + function self:in_n_symbol(i, s) + self.context[self.vname[i]] = s + if self.hot[i] then self:in_1_bang() end + end + function self:in_n_hot(i, atoms) + if type(atoms[1]) == "number" then + self.hot[i] = atoms[1] ~= 0 + else + self:error("hot method expects a float") + end + end + function self:in_1_lexpr(atoms) + local inlets + local vname + local context + local f + local outlets + inlets, vname, context, f, outlets = self:readexpr(atoms) + if (inlets == self.inlets) and (outlets == self.outlets) then + self.vname = vname + self.context = context + self.f = f + else + self:error("new expression has different inlet/outlet count") + end + end + self.inlets, self.vname, self.context, self.f, self.outlets = self:readexpr(atoms) + if self.inlets < 1 then + pd.post("lexpr: error: would have no inlets") + return false + end + if self.outlets < 1 then + pd.post("lexpr: error: would have no outlets") + return false + end + for i = 1,self.inlets,1 do + self.hot[i] = i == 1 + end + return true +end |