summaryrefslogtreecommitdiff
path: root/Data/Libraries/Penlight/examples
diff options
context:
space:
mode:
Diffstat (limited to 'Data/Libraries/Penlight/examples')
-rw-r--r--Data/Libraries/Penlight/examples/seesubst.lua55
-rw-r--r--Data/Libraries/Penlight/examples/sipscan.lua34
-rw-r--r--Data/Libraries/Penlight/examples/symbols.lua223
-rw-r--r--Data/Libraries/Penlight/examples/test-cmp.lua3
-rw-r--r--Data/Libraries/Penlight/examples/test-listcallbacks.lua11
-rw-r--r--Data/Libraries/Penlight/examples/test-pretty.lua13
-rw-r--r--Data/Libraries/Penlight/examples/test-symbols.lua85
-rw-r--r--Data/Libraries/Penlight/examples/testclone.lua40
-rw-r--r--Data/Libraries/Penlight/examples/testconfig.lua51
-rw-r--r--Data/Libraries/Penlight/examples/testglobal.lua28
-rw-r--r--Data/Libraries/Penlight/examples/testinputfields.lua13
-rw-r--r--Data/Libraries/Penlight/examples/testinputfields2.lua9
-rw-r--r--Data/Libraries/Penlight/examples/testxml.lua83
-rw-r--r--Data/Libraries/Penlight/examples/which.lua30
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
+
+