diff options
Diffstat (limited to 'Data/Libraries/Penlight/examples')
-rw-r--r-- | Data/Libraries/Penlight/examples/seesubst.lua | 55 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/sipscan.lua | 34 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/symbols.lua | 223 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/test-cmp.lua | 3 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/test-listcallbacks.lua | 11 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/test-pretty.lua | 13 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/test-symbols.lua | 85 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testclone.lua | 40 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testconfig.lua | 51 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testglobal.lua | 28 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testinputfields.lua | 13 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testinputfields2.lua | 9 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/testxml.lua | 83 | ||||
-rw-r--r-- | Data/Libraries/Penlight/examples/which.lua | 30 |
14 files changed, 678 insertions, 0 deletions
diff --git a/Data/Libraries/Penlight/examples/seesubst.lua b/Data/Libraries/Penlight/examples/seesubst.lua new file mode 100644 index 0000000..a2d0f18 --- /dev/null +++ b/Data/Libraries/Penlight/examples/seesubst.lua @@ -0,0 +1,55 @@ +-- shows how replacing '@see module' in the Markdown documentation +-- can be done more elegantly using PL. +-- We either have something like 'pl.config' (a module reference) +-- or 'pl.seq.map' (a function reference); these cases must be distinguished +-- and a Markdown link generated pointing to the LuaDoc file. + +local sip = require 'pl.sip' +local stringx = require 'pl.stringx' + +local res = {} +local s = [[ +(@see pl.bonzo.dog) +remember about @see pl.bonzo + +]] + +local _gsub_patterns = {} + +local function gsub (s,pat,subst,start) + local fpat = _gsub_patterns[pat] + if not fpat then + -- use SIP to generate a proper string pattern. + -- the _whole thing_ is a capture, to get the whole match + -- and the unnamed capture. + fpat = '('..sip.create_pattern(pat)..')' + _gsub_patterns[pat] = fpat + end + return s:gsub(fpat,subst,start) +end + + +local mod = sip.compile '$v.$v' +local fun = sip.compile '$v.$v.$v' + +for line in stringx.lines(s) do + line = gsub(line,'@see $p',function(see,path) + if fun(path,res) or mod(path,res) then + local ret = ('[see %s](%s.%s.html'):format(path,res[1],res[2]) + if res[3] then + return ret..'#'..res[3]..')' + else + return ret..')' + end + end + end) + print(line) +end + + + + + + + + diff --git a/Data/Libraries/Penlight/examples/sipscan.lua b/Data/Libraries/Penlight/examples/sipscan.lua new file mode 100644 index 0000000..78ac75b --- /dev/null +++ b/Data/Libraries/Penlight/examples/sipscan.lua @@ -0,0 +1,34 @@ +-- another SIP example, shows how an awkward log file format +-- can be parsed. It also prints out the actual Lua string +-- pattern generated: +-- SYNC%s*%[([+%-%d]%d*)%]%s*([+%-%d]%d*)%s*([+%-%d]%d*) + +local sip = require 'pl.sip' +local stringx = require 'pl.stringx' + +local s = [[ +SYNC [1] 0 547 (14679 sec) +SYNC [2] 0 555 (14679 sec) +SYNC [3] 0 563 (14679 sec) +SYNC [4] 0 571 (14679 sec) +SYNC [5] -1 580 (14679 sec) +SYNC [6] 0 587 (14679 sec) +]] + + +local first = true +local expected +local res = {} +local pat = 'SYNC [$i{seq}] $i{diff} $i{val}' +print(sip.create_pattern(pat)) +local match = sip.compile(pat) +for line in stringx.lines(s) do + if match(line,res) then + if first then + expected = res.val + first = false + end + print(res.val,expected - res.val) + expected = expected + 8 + end +end diff --git a/Data/Libraries/Penlight/examples/symbols.lua b/Data/Libraries/Penlight/examples/symbols.lua new file mode 100644 index 0000000..e73c4ba --- /dev/null +++ b/Data/Libraries/Penlight/examples/symbols.lua @@ -0,0 +1,223 @@ +require 'pl' +utils.import 'pl.func' +local ops = require 'pl.operator' +local List = require 'pl.List' +local append,concat = table.insert,table.concat +local compare,find_if,compare_no_order,imap,reduce,count_map = tablex.compare,tablex.find_if,tablex.compare_no_order,tablex.imap,tablex.reduce,tablex.count_map +local unpack = table.unpack + +function bindval (self,val) + rawset(self,'value',val) +end + +local optable = ops.optable + +function sexpr (e) + if isPE(e) then + if e.op ~= 'X' then + local args = tablex.imap(sexpr,e) + return '('..e.op..' '..table.concat(args,' ')..')' + else + return e.repr + end + else + return tostring(e) + end +end + + +psexpr = compose(print,sexpr) + + + +function equals (e1,e2) + local p1,p2 = isPE(e1),isPE(e2) + if p1 ~= p2 then return false end -- different kinds of animals! + if p1 and p2 then -- both PEs + -- operators must be the same + if e1.op ~= e2.op then return false end + -- PHs are equal if their representations are equal + if e1.op == 'X' then return e1.repr == e2.repr + -- commutative operators + elseif e1.op == '+' or e1.op == '*' then + return compare_no_order(e1,e2,equals) + else + -- arguments must be the same + return compare(e1,e2,equals) + end + else -- fall back on simple equality for non PEs + return e1 == e2 + end +end + +-- run down an unbalanced operator chain (like a+b+c) and return the arguments {a,b,c} +function tcollect (op,e,ls) + if isPE(e) and e.op == op then + for i = 1,#e do + tcollect(op,e[i],ls) + end + else + ls:append(e) + return + end +end + +function rcollect (e) + local res = List() + tcollect(e.op,e,res) + return res +end + + +-- balance ensures that +/* chains are collected together, operates in-place. +-- thus (+(+ a b) c) or (+ a (+ b c)) becomes (+ a b c), order immaterial +function balance (e) + if isPE(e) and e.op ~= 'X' then + local op,args = e.op + if op == '+' or op == '*' then + args = rcollect(e) + else + args = imap(balance,e) + end + for i = 1,#args do + e[i] = args[i] + end + end + return e +end + +-- fold constants in an expression +function fold (e) + if isPE(e) then + if e.op == 'X' then + -- there could be _bound values_! + local val = rawget(e,'value') + return val and val or e + else + local op = e.op + local addmul = op == '*' or op == '+' + -- first fold all arguments + local args = imap(fold,e) + if not addmul and not find_if(args,isPE) then + -- no placeholders in these args, we can fold the expression. + local opfn = optable[op] + if opfn then + return opfn(unpack(args)) + else + return '?' + end + elseif addmul then + -- enforce a few rules for + and * + -- split the args into two classes, PE args and non-PE args. + local classes = List.partition(args,isPE) + local pe,npe = classes[true],classes[false] + if npe then -- there's at least one non PE argument + -- so fold them + if #npe == 1 then npe = npe[1] + else npe = npe:reduce(optable[op]) + end + -- if the result is a constant, return it + if not pe then return npe end + + -- either (* 1 x) => x or (* 1 x y ...) => (* x y ...) + if op == '*' then + if npe == 0 then return 0 + elseif npe == 1 then -- identity + if #pe == 1 then return pe[1] else npe = nil end + end + else -- special cases for + + if npe == 0 then -- identity + if #pe == 1 then return pe[1] else npe = nil end + end + end + end + -- build up the final arguments + local res = {} + if npe then append(res,npe) end + for val,count in pairs(count_map(pe,equals)) do + if count > 1 then + if op == '*' then val = val ^ count + else val = val * count + end + end + append(res,val) + end + if #res == 1 then return res[1] end + return PE{op=op,unpack(res)} + elseif op == '^' then + if args[2] == 1 then return args[1] end -- identity + if args[2] == 0 then return 1 end + end + return PE{op=op,unpack(args)} + end + else + return e + end +end + +function expand (e) + if isPE(e) and e.op == '*' and isPE(e[2]) and e[2].op == '+' then + local a,b = e[1],e[2] + return expand(b[1]*a) + expand(b[2]*a) + else + return e + end +end + +function isnumber (x) + return type(x) == 'number' +end + +-- does this PE contain a reference to x? +function references (e,x) + if isPE(e) then + if e.op == 'X' then return x.repr == e.repr + else + return find_if(e,references,x) + end + else + return false + end +end + +local function muli (args) + return PE{op='*',unpack(args)} +end + +local function addi (args) + return PE{op='+',unpack(args)} +end + +function diff (e,x) + if isPE(e) and references(e,x) then + local op = e.op + if op == 'X' then + return 1 + else + local a,b = e[1],e[2] + if op == '+' then -- differentiation is linear + local args = imap(diff,e,x) + return balance(addi(args)) + elseif op == '*' then -- product rule + local res,d,ee = {} + for i = 1,#e do + d = fold(diff(e[i],x)) + if d ~= 0 then + ee = {unpack(e)} + ee[i] = d + append(res,balance(muli(ee))) + end + end + if #res > 1 then return addi(res) + else return res[1] end + elseif op == '^' and isnumber(b) then -- power rule + return b*x^(b-1) + end + end + else + return 0 + end +end + + + diff --git a/Data/Libraries/Penlight/examples/test-cmp.lua b/Data/Libraries/Penlight/examples/test-cmp.lua new file mode 100644 index 0000000..cbab394 --- /dev/null +++ b/Data/Libraries/Penlight/examples/test-cmp.lua @@ -0,0 +1,3 @@ +local A = require 'pl.tablex' +print(A.compare_no_order({1,2,3},{2,1,3})) +print(A.compare_no_order({1,2,3},{2,1,3},'==')) diff --git a/Data/Libraries/Penlight/examples/test-listcallbacks.lua b/Data/Libraries/Penlight/examples/test-listcallbacks.lua new file mode 100644 index 0000000..a9a31c3 --- /dev/null +++ b/Data/Libraries/Penlight/examples/test-listcallbacks.lua @@ -0,0 +1,11 @@ +-- demonstrates how to use a list of callbacks +local List = require 'pl.List' +local utils = require 'pl.utils' +local actions = List() +local L = utils.string_lambda + +actions:append(function() print 'hello' end) +actions:append(L '|| print "yay"') + +-- '()' is a shortcut for operator.call or function(x) return x() end +actions:foreach '()' diff --git a/Data/Libraries/Penlight/examples/test-pretty.lua b/Data/Libraries/Penlight/examples/test-pretty.lua new file mode 100644 index 0000000..7b2b553 --- /dev/null +++ b/Data/Libraries/Penlight/examples/test-pretty.lua @@ -0,0 +1,13 @@ +local pretty = require 'pl.pretty' + +local tb = { + 'one','two','three',{1,2,3}, + alpha=1,beta=2,gamma=3,['&']=true,[0]=false, + _fred = {true,true}, + s = [[ +hello dolly +you're so fine +]] +} + +print(pretty.write(tb)) diff --git a/Data/Libraries/Penlight/examples/test-symbols.lua b/Data/Libraries/Penlight/examples/test-symbols.lua new file mode 100644 index 0000000..2b80aac --- /dev/null +++ b/Data/Libraries/Penlight/examples/test-symbols.lua @@ -0,0 +1,85 @@ +require 'pl' +-- force us to look in the script's directory when requiring... +app.require_here() +require 'symbols' + +local MT = getmetatable(_1) + +add = MT.__add +mul = MT.__mul +pow = MT.__pow + + +function testeq (e1,e2) + if not equals(e1,e2) then + print ('Not equal',repr(e1),repr(e2)) + end +end + +sin = register(math.sin,'sin') + +f = register(function(x,y,z) end) + +--[[ +testeq (_1,_1) +testeq (_1+_2,_1+_2) +testeq (_1 + 3*_2,_1 + 3*_2) +testeq (_2+_1,_1+_2) +testeq (sin(_1),sin(_1)) +testeq (1+f(10,20,'ok'),f(10,20,'ok')+1) +--]] + + +function testexpand (e) + print(repr(fold(expand(e)))) --fold +end + +--[[ +testexpand (a*(a+1)) + +testexpand ((x+2)*(b+1)) +]]-- + +function testfold (e) + print(repr(fold(e))) +end + +a,b,c,x,y = Var 'a,b,c,x,y' + +--~ testfold(_1 + _2) +--~ testfold(add(10,20)) +--~ testfold(add(mul(2,_1),mul(3,_2))) +--[[ +testfold(sin(a)) +e = a^(b+2) +testfold(e) +bindval(b,1) +testfold(e) +bindval(a,2) +testfold(e) + +bindval(a) +bindval(b) +]] + + + +function testdiff (e) + balance(e) + e = diff(e,x) + balance(e) + print('+ ',e) + e = fold(e) + print('- ',e) +end + + +testdiff(x^2+1) +testdiff(3*x^2) +testdiff(x^2 + 2*x^3) +testdiff(x^2 + 2*a*x^3 + x^4) +testdiff(2*a*x^3) +testdiff(x*x*x) + + + diff --git a/Data/Libraries/Penlight/examples/testclone.lua b/Data/Libraries/Penlight/examples/testclone.lua new file mode 100644 index 0000000..b0d948f --- /dev/null +++ b/Data/Libraries/Penlight/examples/testclone.lua @@ -0,0 +1,40 @@ +--cloning a directory tree. +local lfs = require 'lfs' +local path = require 'pl.path' +local dir = require 'pl.dir' + +local p1 = [[examples]] +local p2 = [[copy/of/examples]] + +if not path.isfile 'examples/testclone.lua' then + return print 'please run this in the penlight folder (below examples)' +end + +-- make a copy of the examples folder +dir.clonetree(p1,p2,dir.copyfile) + +assert(path.isdir 'copy') + +print '---' +local t = os.time() +print(lfs.touch('examples/testclone.lua',t,t+10)) + +-- this should only update this file +dir.clonetree(p1,p2, +function(f1,f2) + local t1 = path.getmtime(f1) + local t2 = path.getmtime(f2) + --print(f1,t1,f2,t2) + if t1 > t2 then + dir.copyfile(f1,f2) + print(f1,f2,t1,t2) + end + return true +end) + +-- and get rid of the whole copy directory, with subdirs +dir.rmtree 'copy' + +assert(not path.exists 'copy') + + diff --git a/Data/Libraries/Penlight/examples/testconfig.lua b/Data/Libraries/Penlight/examples/testconfig.lua new file mode 100644 index 0000000..4712747 --- /dev/null +++ b/Data/Libraries/Penlight/examples/testconfig.lua @@ -0,0 +1,51 @@ +local stringio = require 'pl.stringio' +local config = require 'pl.config' + +local function dump(t,indent) + if type(t) == 'table' then + io.write(indent,'{\n') + local newindent = indent..' ' + for k,v in pairs(t) do + io.write(newindent,k,'=') + dump(v,indent) + io.write('\n') + end + io.write(newindent,'},\n') + else + io.write(indent,t,'(',type(t),')') + end +end + + +local function testconfig(test) + local f = stringio.open(test) + local c = config.read(f) + f:close() + dump(c,' ') + print '-----' +end + +testconfig [[ + ; comment 2 (an ini file) +[section!] +bonzo.dog=20,30 +config_parm=here we go again +depth = 2 +[another] +felix="cat" +]] + +testconfig [[ +# this is a more Unix-y config file +fred = 1 +alice = 2 +home = /bonzo/dog/etc +]] + +testconfig [[ +# this is just a set of comma-separated values +1000,444,222 +44,555,224 +]] + + diff --git a/Data/Libraries/Penlight/examples/testglobal.lua b/Data/Libraries/Penlight/examples/testglobal.lua new file mode 100644 index 0000000..0baaaef --- /dev/null +++ b/Data/Libraries/Penlight/examples/testglobal.lua @@ -0,0 +1,28 @@ +-- very simple lexer program which looks at all identifiers in a Lua +-- file and checks whether they're in the global namespace. +-- At the end, we dump out the result of count_map, which will give us +-- unique identifiers with their usage count. +-- (an example of a program which itself needs to be careful about what +-- goes into the global namespace) + +local utils = require 'pl.utils' +local file = require 'pl.file' +local lexer = require 'pl.lexer' +local List = require 'pl.List' +local pretty = require 'pl.pretty' +local seq = require 'pl.seq' +local path = require 'pl.path' + +utils.on_error 'quit' + +local txt = file.read(arg[1] or path.normpath('examples/testglobal.lua')) +local globals = List() +for t,v in lexer.lua(txt) do + if t == 'iden' and rawget(_G,v) then + globals:append(v) + end +end + +pretty.dump(seq.count_map(globals)) + + diff --git a/Data/Libraries/Penlight/examples/testinputfields.lua b/Data/Libraries/Penlight/examples/testinputfields.lua new file mode 100644 index 0000000..9269488 --- /dev/null +++ b/Data/Libraries/Penlight/examples/testinputfields.lua @@ -0,0 +1,13 @@ +local input = require 'pl.input' +local sum = 0.0 +local count = 0 +local text = [[ + 981124001 2.0 18988.4 10047.1 4149.7 + 981125001 0.8 19104.0 9970.4 5088.7 + 981127003 0.5 19012.5 9946.9 3831.2 +]] +for id,magn,x in input.fields(3,' ',text) do + sum = sum + x + count = count + 1 +end +print('average x coord is ',sum/count) diff --git a/Data/Libraries/Penlight/examples/testinputfields2.lua b/Data/Libraries/Penlight/examples/testinputfields2.lua new file mode 100644 index 0000000..fc649eb --- /dev/null +++ b/Data/Libraries/Penlight/examples/testinputfields2.lua @@ -0,0 +1,9 @@ +local input = require 'pl.input' +local seq = require 'pl.seq' +local text = [[ + 981124001 2.0 18988.4 10047.1 4149.7 + 981125001 0.8 19104.0 9970.4 5088.7 + 981127003 0.5 19012.5 9946.9 3831.2 +]] +local sum,count = seq.sum(input.fields ({3},' ',text)) +print(sum/count) diff --git a/Data/Libraries/Penlight/examples/testxml.lua b/Data/Libraries/Penlight/examples/testxml.lua new file mode 100644 index 0000000..2528020 --- /dev/null +++ b/Data/Libraries/Penlight/examples/testxml.lua @@ -0,0 +1,83 @@ +-- an example showing 'pl.lexer' doing some serious work. +-- The resulting Lua table is in the same LOM format used by luaexpat. +-- This is (clearly) not a professional XML parser, so don't use it +-- on your homework! + +local lexer = require 'pl.lexer' +local pretty = require 'pl.pretty' + +local append = table.insert +local skipws,expecting = lexer.skipws,lexer.expecting + +local function parse_element (tok,tag) + local tbl,t,v,attrib + tbl = {} + tbl.tag = tag -- LOM 'tag' is the element tag + t,v = skipws(tok) + while v ~= '/' and v ~= '>' do + if t ~= 'iden' then error('expecting attribute identifier') end + attrib = v + expecting(tok,'=') + v = expecting(tok,'string') + -- LOM: 'attr' subtable contains attrib/value pairs and an ordered list of attribs + if not tbl.attr then tbl.attr = {} end + tbl.attr[attrib] = v + append(tbl.attr,attrib) + t,v = skipws(tok) + end + if v == '/' then + expecting(tok,'>') + return tbl + end + -- pick up element data + t,v = tok() + while true do + if t == '<' then + t,v = skipws(tok) + if t == '/' then -- element end tag + t,v = tok() + if t == '>' then return tbl end + if t == 'iden' and v == tag then + if tok() == '>' then return tbl end + end + error('expecting end tag '..tag) + else + append(tbl,parse_element(tok,v)) -- LOM: child elements added to table + t,v = skipws(tok) + end + else + append(tbl,v) -- LOM: text added to table + t,v = skipws(tok) + end + end +end + +local function parse_xml (tok) + local t = skipws(tok) + local v + while t == '<' do + t,v = tok() + if t == '?' or t == '!' then + -- skip meta stuff and commentary + repeat t = tok() until t == '>' + t = expecting(tok,'<') + else + return parse_element(tok,v) + end + end +end + +local s = [[ +<?xml version="1.0" encoding="UTF-8"?> +<sensor name="closure-meter-2" id="7D7D0600006F0D00" loc="100,100,0" device="closure-meter" init="true"> +<detector name="closure-meter" phenomenon="closure" units="mm" id="1" + vmin="0" vmax="5000" device="closure-meter" calib="0,0;5000,5000" + sampling_interval="25000" measurement_interval="600000" +/> +</sensor> +]] + +local tok = lexer.scan(s,nil,{space=false},{string=true}) +local res = parse_xml(tok) +print(pretty.write(res)) + diff --git a/Data/Libraries/Penlight/examples/which.lua b/Data/Libraries/Penlight/examples/which.lua new file mode 100644 index 0000000..0544cfc --- /dev/null +++ b/Data/Libraries/Penlight/examples/which.lua @@ -0,0 +1,30 @@ +-- a simple implementation of the which command. This looks for +-- the given file on the path. On windows, it will assume an extension +-- of .exe if no extension is given. +local List = require 'pl.List' +local path = require 'pl.path' +local app = require 'pl.app' + +local pathl = List.split(os.getenv 'PATH',path.dirsep) + +local function which (file) + local res = pathl:map(path.join,file) + res = res:filter(path.exists) + if res then return res[1] end +end + +local _,lua = app.lua() +local file = arg[1] or lua -- i.e. location of lua executable +local try + +if not file then return print 'must provide a filename' end + +if path.extension(file) == '' and path.is_windows then + try = which(file..'.exe') +else + try = which(file) +end + +if try then print(try) else print 'cannot find on path' end + + |