Browse Source

Added a collection of scripts that were lying here without VCS

master
Thomas Johnson 2 years ago
commit
378842b52e
  1. 168
      brainfuck_parse.lua
  2. 172
      o_brainfuck.lua
  3. 127
      o_pbx_brainfuck.lua
  4. 382
      parse_manifest.lua
  5. 61
      parse_table.lua

168
brainfuck_parse.lua

@ -0,0 +1,168 @@
local node_plus_const = function(tape_offset, amount)
return
{
nodetype = "plus",
pure = true,
left = {valtype = "tape", offset = tape_offset},
right = {valtype = "immediate", value = amount},
out = {valtype = "tape", offset = tape_offset},
temporal_dependencies = {},
pure_dependencies = {},
}
end
local node_out = function(tape_offset)
return
{
nodetype = "out",
pure = false,
input = { valtype = "tape", offset = tape_offset },
temporal_dependencies = {},
pure_dependencies = {},
}
end
local node_in = function(tape_offset)
return
{
nodetype = "in",
pure = false,
output = { valtype = "tape", offset = tape_offset },
temporal_dependencies = {},
pure_dependencies = {},
}
end
local node_root = function()
return
{
nodetype = "root",
pure = true,
temporal_dependencies = {},
pure_dependencies = {}
}
end
local func_tab =
{
[1] = function(t)
t.head_pos = t.head_pos - 1
t.idx = t.idx + 1
end,
[2] = function(t)
t.head_pos = t.head_pos + 1
t.idx = t.idx + 1
end,
[3] = function(t)
local node = node_plus_const(tape_offset, 1)
node.temporal_dependencies = { t.current_node }
t.current_node = node
t.idx = t.idx + 1
end,
[4] = function(t)
local node = node_plus_const(tape_offset, 1)
node.temporal_dependencies = { t.current_node }
t.current_node = node
t.idx = t.idx + 1
end,
[5] = function(t)
local node = node_out(tape_offset)
node.temporal_dependencies = { t.current_node }
t.current_node = node
t.idx = t.idx + 1
end,
[6] = function(t)
local node = node_in(tape_offset)
node.temporal_dependencies = { t.current_node }
t.current_node = node
t.idx = t.idx + 1
end,
[7] = function(t)
error("unimplemented")
end,
[8] = function(t)
error("unimplemented")
end,
-- [nil] = function(t)
-- t.ret_idx = t.idx
-- end,
}
function do_parse_seq(sequence, idx)
local t =
{
sym = sequence[idx],
ret_idx = nil,
idx = idx,
head_pos = 0,
current_node = node_root(),
}
while t.ret_idx == nil do
func_tab[t.sym](t)
t.sym = sequence[t.idx]
if t.sym == nil then
t.ret_idx = t.idx
end
end
return t
end
function io_to_string(io)
if io.valtype == "immediate" then
return tostring(io.value)
elseif io.valtype == "tape" then
return "tape[" .. tostring(io.offset) .. "]"
else
return "unknown i/o"
end
end
function recursive_node_string(node)
if node.nodetype == "root" then
return { "root" }
elseif node.nodetype == "plus" then
local dep = recursive_node_string(node.temporal_dependencies[1])
table.insert(dep, "add " .. io_to_string(node.left) .. " + " .. io_to_string(node.right))
return dep
elseif node.nodetype == "out" then
local dep = recursive_node_string(node.temporal_dependencies[1])
table.insert(dep, "out " .. io_to_string(node.input))
return dep
elseif node.nodetype == "in" then
local dep = recursive_node_string(node.temporal_dependencies[1])
table.insert(dep, "in " .. tostring(node.output))
return dep
else
return { "unknown node" }
end
end
--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
--str = "+[-]..."
str = ".+.>.+.<.-.>.-."
--str = "+[+]"
char_table =
{
[">"] = 1,
["<"] = 2,
["+"] = 3,
["-"] = 4,
["."] = 5,
[","] = 6,
["["] = 7,
["]"] = 8,
}
prog = {}
for i = 1,#str do
prog[#prog + 1] = char_table[string.sub(str, i, i)]
end
local q = do_parse_seq(prog, 1)
print(table.concat(recursive_node_string(q.current_node), "\n"))

172
o_brainfuck.lua

@ -0,0 +1,172 @@
local look_for_closing_brace = function(context, idx)
if context.matching_indices[idx] ~= nil then
return context.matching_indices[idx]
end
local orig_idx = idx
local layer = 1
while layer ~= 0 do
idx = idx + 1
if context.program[idx] == nil then
return -1
end
if context.program[idx] == 7 then
layer = layer + 1
end
if context.program[idx] == 8 then
layer = layer - 1
end
end
context.matching_indices[orig_idx] = idx
return idx
end
local init_tape_at_head = function(context)
if context.tape[context.head_pos] == nil then
context.tape[context.head_pos] = context.initial_tape_func(context.head_pos)
end
end
local loop_jump = function(context)
init_tape_at_head(context)
if context.tape[context.head_pos] ~= 0 then
context.ip = context.jumpstack_left[#context.jumpstack_left] + 1
else
local idx = #context.jumpstack_left
context.jumpstack_left[idx] = nil
context.jumpstack_right[idx] = nil
context.ip = context.ip + 1
end
end
local do_open_bracket = function(context)
context.jumpstack_left[#context.jumpstack_left + 1] = context.ip
context.jumpstack_right[#context.jumpstack_left] = look_for_closing_brace(context, context.ip)
context.ip = context.jumpstack_right[#context.jumpstack_left]
loop_jump(context)
end
local do_close_bracket = function(context)
if context.jumpstack_right[#context.jumpstack_left] == context.ip then
loop_jump(context)
else
context.retval = {kind = "error", value = "unexpected right bracket"}
end
end
local instr_table =
{
[1] = function(context)
context.head_pos = context.head_pos - 1
context.ip = context.ip + 1
end,
[2] = function(context)
context.head_pos = context.head_pos + 1
context.ip = context.ip + 1
end,
[3] = function(context)
init_tape_at_head(context)
context.tape[context.head_pos] = context.tape[context.head_pos] + 1
context.ip = context.ip + 1
end,
[4] = function(context)
init_tape_at_head(context)
context.tape[context.head_pos] = context.tape[context.head_pos] - 1
context.ip = context.ip + 1
end,
[5] = function(context)
init_tape_at_head(context)
context.write(context.tape[context.head_pos])
context.ip = context.ip + 1
end,
[6] = function(context)
context.tape[context.head_pos] = context.read()
context.ip = context.ip + 1
end,
[7] = do_open_bracket,
[8] = do_close_bracket,
[9] = function(context)
context.debugfn(context.head_pos, context.ip, context.tape)
context.ip = context.ip + 1
end,
}
local step = function(context, app)
local f = instr_table[context.program[context.ip]]
if f == nil then
context.retval = {kind = "return", value = "success"}
else
f(context)
end
end
function new_brainfuck_context(log, program, write, read, debugfn, initial_tape_func)
local context =
{
program = program,
write = write,
read = read,
debugfn = debugfn,
log = log,
initial_tape_func = initial_tape_func,
head_pos = 0,
tape = {},
ip = 1,
jumpstack_left = {},
jumpstack_right = {},
matching_indices = {},
retval = nil,
}
context.step = step
return context
end
return { new_brainfuck_context = new_brainfuck_context }
--[[
--str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
--str = "+[-]..."
--str = ".+.>.+.<.-.>.-."
str = "+[+]"
char_table =
{
[">"] = 1,
["<"] = 2,
["+"] = 3,
["-"] = 4,
["."] = 5,
[","] = 6,
["["] = 7,
["]"] = 8,
}
prog = {}
for i = 1,#str do
prog[#prog + 1] = char_table[string.sub(str, i, i)]
end
out = ""
unmangled = ""
context = new_brainfuck_context(prog, function(v)
out = out .. " " .. tostring(v)
unmangled = unmangled .. string.char(v)
end, function() return 0 end, function() return 0 end)
count = 0
while context.retval == nil and count < 1000000 do
context:step()
count = count + 1
end
tab = context.retval
if tab.kind == "return" then
print(out)
print(unmangled)
elseif tab.kind == "error" then
print("error: " .. tab.value)
end
--]]

127
o_pbx_brainfuck.lua

@ -0,0 +1,127 @@
bf = require("o_brainfuck")
espeak = require("espeak")
local get_prog = function()
channel.TIMEOUT("response"):set(60)
app.read("up_prog", "", 0, "", 1, 1e6)
local up_prog = channel.up_prog:get()
local program = {}
local dig_tab =
{
["1"] = 1,
["2"] = 2,
["3"] = 3,
["4"] = 4,
["5"] = 5,
["6"] = 6,
["7"] = 7,
["8"] = 8,
["*"] = 9,
}
app.verbose(3, "running Brainfuck program: " .. up_prog)
for i=1,#up_prog do
local sym = string.sub(up_prog, i, i)
if sym == "9" and #program > 0 then
program[#program] = nil
else
if dig_tab[sym] ~= nil then
program[#program + 1] = dig_tab[sym]
end
end
end
return program
end
local read_number_context = function(program, globals)
local read = function()
app.read("input_digit", "", 0, "", 1, 1e6)
local convert_tab =
{
["0"] = 0,
["1"] = 1,
["2"] = 2,
["3"] = 3,
["4"] = 4,
["5"] = 5,
["6"] = 6,
["7"] = 7,
["8"] = 8,
["9"] = 9,
["*"] = 10,
["#"] = 11,
}
local digit = channel.input_digit:get()
local num = tonumber(digit)
if nil == num then
globals.err = "hung up"
return nil
end
return num
end
local write = function(n)
app.checkhangup()
if channel.HUNGUP:get() == "HUNGUP" then
globals.err = "hung up"
else
espeak(tostring(n))
end
end
local debug = function(head_pos, ip, tape)
app.verbose(3, "brainfuck program invoked debug\n");
espeak("DEBUG INFO")
espeak("head position: " .. tostring(head_pos))
espeak("instruction pointer: " .. tostring(ip))
espeak("tape:")
for k, v in pairs(tape) do
espeak("at " .. tostring(k) .. " is " .. tostring(v))
end
end
return bf.new_brainfuck_context(function(m) app.verbose(3, m) end, program, write, read, debug, function() return 0 end)
end
return function(ctx, mixc)
ctx[621] = function()
local globals = { err = nil }
local program = get_prog()
local bfc = read_number_context(program, globals)
local counter = 50000000
while bfc.retval == nil do
bfc:step(app)
if (counter == 0) then
counter = 50000000
app.checkhangup()
if channel.HUNGUP:get() == "HUNGUP" then
app.verbose(3, "hung up on running program")
globals.err = "hung up"
end
end
if globals.err ~= nil then
return
end
counter = counter - 1
end
local tab = bfc.retval
if tab.kind == "error" then
espeak("error " .. tab.value)
elseif tab.kind == "return" then
espeak("success")
else
espeak("unknown state")
end
app.hangup()
end
end

382
parse_manifest.lua

@ -0,0 +1,382 @@
local debugls = function(l) for k, v in pairs(l) do print("dbg: " .. tostring(k) .. " => " .. tostring(v)) end end
-- Not portable
local separate_path = function(path)
for i = #path,1,-1 do
if string.sub(path, i, i) == "/" then
return { dir = string.sub(path, 1, i), file = string.sub(path, i + 1, #path) }
end
end
return { file = path }
end
-- Not portable
local to_dir_name = function(s)
if string.sub(s, #s, #s) ~= "/" then
return s .. "/"
else
return s
end
end
-- Not portable
local abs_filename = function(cwd, path)
if string.sub(path, 1, 1) == "/" then
return path
else
if string.sub(cwd, #cwd, #cwd) ~= "/" then
return to_dir_name(cwd) .. path
else
return to_dir_name(cwd) .. path
end
end
end
-- Not portable
local normalize_abs_path = function(path, isdir)
local names = {}
for nm in string.gmatch(path, "[^/]+") do
names[#names + 1] = nm
end
-- Normalize away `.`
for i = #names,1,-1 do
if names[i] == "." or names[i] == "" then
table.remove(names, i)
end
end
-- Normalize away `..`
while names[1] == ".." do table.remove(names, 1) end
local c = true
while c do
c = false
for i = 1,(#names - 1) do
if names[i + 1] == ".." then
table.remove(names, i)
table.remove(names, i)
c = true
break
end
end
end
if isdir then
return "/" .. table.concat(names, "/") .. "/"
else
return "/" .. table.concat(names, "/")
end
end
local path_size = function(path)
local i = 0
for _ in string.gmatch(path, "[^/]+") do
i = i + 1
end
return i
end
-- Not portable
local is_dir = function(filename)
local c = false
local p = io.popen("[ -d '" .. filename .. "' ] && echo ''")
for l in p:lines() do c = true end
p:close()
return c
end
-- Not portable
local file_exists = function(filename)
local c = false
local p = io.popen("[ -e '" .. filename .. "' ] && echo ''")
for l in p:lines() do c = true end
p:close()
return c
end
-- Not portable
local ls_dir = function(dirpath)
local t = {}
local p = io.popen("ls -A '" .. dirpath .. "'")
for l in p:lines() do t[#t + 1] = l end
p:close()
return t
end
local read_manifest
read_manifest = function(filename, file_table, errout)
local parse_line = function(line, cwd)
local weight_specifier
local filepath
for i = 1,#line do
if string.sub(line, i, i) == " " then
weight_specifier = string.sub(line, 1, i - 1)
filepath = string.sub(line, i + 1, #line)
break
end
end
if weight_specifier == nil and filepath == nil then
return nil
end
-- True if a category is to be weighted as a unit, thereby reducing the effective
-- weight of each of its entries. This flag is meant to be employed for other manifests.
local weight_whole_category = false
-- Indicates that the entry is a directory whose applicable files should be read in.
local directory = false
-- This indicates that the entry is a manifest to be read in.
local manifest = false
-- This is the level to recurse into directories or the `here` case.
-- `nil` indicates unbounded recursion.
local recursion_level = 0
-- When `weight_whole_category` is on, this specifies how deeply the categorical
-- weighting will apply. Again, `nil` is unbounded.
local recursive_weighting_level = 0
local numstr = ""
local symbol_actions =
{
["#"] = function() weight_whole_category = true end,
["?"] = function() manifest = true end,
["/"] = function() if recursion_level ~= nil then recursion_level = recursion_level + 1 end end,
["*"] = function() recursion_level = nil end,
["$"] = function() if recursive_weighting_level ~= nil then recursive_weighting_level = recursive_weighting_level + 1 end end,
["%"] = function() recursive_weighting_level = nil end,
["0"] = true,
["1"] = true,
["2"] = true,
["3"] = true,
["4"] = true,
["5"] = true,
["6"] = true,
["7"] = true,
["8"] = true,
["9"] = true,
["-"] = true,
["."] = true,
["e"] = true,
}
for i = 1,#weight_specifier do
local sym = string.sub(weight_specifier, i, i)
local action = symbol_actions[sym]
if action == true then
numstr = numstr .. sym
elseif action == nil then
else
action()
end
end
local num = tonumber(numstr)
if num == nil then num = 1 end
return
{
weight = num,
manifest = manifest,
catweight = weight_whole_category,
directory = directory,
rclevel = recursion_level,
rcwlevel = recursive_weighting_level,
file = normalize_abs_path(abs_filename(cwd, filepath), false)
}
end
local is_iv_name = function(s) return string.sub(s, -4, -1) == ".ivz" or string.sub(s, -3, -1) == ".iv" end
local descend_dir
descend_dir = function(dirpath, file_table, total_weight, catweight, rclevel, rcwlevel, source)
local ftab = ls_dir(dirpath)
local nrcl
if rclevel == nil then nrcl = nil else nrcl = rclevel - 1 end
if catweight then
if rcwlevel == 0 then
local temp_table = {}
for _,en in pairs(ftab) do
local iv = normalize_abs_path(abs_filename(dirpath, en), false)
if is_dir(iv) and (rclevel == nil or rclevel > 0) then
descend_dir(to_dir_name(iv), temp_table, 1, false, nrcl, 0, source)
elseif is_iv_name(iv) then
temp_table[#temp_table + 1] =
{
file = iv,
-- Will be overwritten by loop below anyway
}
end
end
for _,ent in pairs(temp_table) do
file_table[#file_table + 1] =
{
file = ent.file,
weight = total_weight / #temp_table,
source = source
}
end
else
for _,en in pairs(ftab) do
local iv = normalize_abs_path(abs_filename(dirpath, en))
if is_dir(iv) and (rclevel == nil or rclevel > 0) then
if rcwlevel == nil then
descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, nil, source)
else
descend_dir(to_dir_name(iv), file_table, total_weight / #ftab, true, nrcl, rcwlevel - 1, source)
end
elseif is_iv_name(iv) then
file_table[#file_table + 1] =
{
file = iv,
weight = total_weight / #ftab,
source = source
}
end
end
end
return total_weight
else
local twc = 0
for _,en in pairs(ftab) do
local iv = normalize_abs_path(abs_filename(dirpath, en))
if is_dir(iv) and (rclevel == nil or rclevel > 0) then
descend_dir(to_dir_name(iv), file_table, total_weight, false, nrcl, 0, source)
elseif is_iv_name(iv) then
twc = twc + total_weight
file_table[#file_table + 1] =
{
file = iv,
weight = total_weight,
source = source
}
end
end
return twc
end
end
if filename == nil then return nil end
local mf = io.open(filename, "r")
if not mf then errout("Could not open manifest " .. filename) return nil end
local total_weight = 0
for line in mf:lines() do
local entry = parse_line(line, separate_path(filename).dir)
if entry == nil then goto endloop end
if entry.manifest then
if not file_exists(entry.file) or is_dir(entry.file) then
errout("warning: file " .. entry.file .. " is not a normal file")
end
local temp_table = {}
local tw = read_manifest(entry.file, temp_table, errout)
if entry.catweight then
total_weight = total_weight + entry.weight
for _,ent in pairs(temp_table) do
file_table[#file_table + 1] =
{
file = ent.file,
weight = entry.weight * ent.weight / tw,
source = ent.source,
}
end
else
for _,ent in pairs(temp_table) do
total_weight = total_weight + entry.weight * ent.weight
file_table[#file_table + 1] =
{
file = ent.file,
weight = entry.weight * ent.weight,
source = ent.source,
}
end
end
else
if not file_exists(entry.file) then
errout("warning: file " .. entry.file .. " does not exist")
end
if is_dir(entry.file) then
total_weight = total_weight + descend_dir(to_dir_name(entry.file), file_table, entry.weight, entry.catweight, entry.rclevel, entry.rcwlevel, { file = entry.file, manifest = normalize_abs_path(filename) })
else
total_weight = total_weight + entry.weight
file_table[#file_table + 1] =
{
file = entry.file,
weight = entry.weight,
source = { file = entry.file, manifest = normalize_abs_path(filename) }
}
end
end
::endloop::
end
mf:close()
return total_weight
end
local assemble_weights = function(entries, errout)
local ivs = {}
for _, ent in pairs(entries) do
if ivs[ent.file] ~= nil then
local sza = path_size(ivs[ent.file].source.file)
local szb = path_size(ent.source.file)
if sza < szb then
ivs[ent.file] = { weight = ent.weight, source = ent.source }
elseif sza == szb then
local namea = ivs[ent.file].source.manifest
local nameb = ent.source.manifest
if namea == nameb then
errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea)
else
errout("warning: two conflicting weights for " .. ent.file .. " in " .. namea .. " and " .. nameb)
end
end
else
ivs[ent.file] = { weight = ent.weight, source = ent.source }
end
end
return ivs
end
local function usage()
print("usage: <this program> <input manifest> <output table>")
end
if arg[1] == nil or arg[2] == nil then
usage()
return
end
local taboutf = io.open(arg[2], "w")
if taboutf == nil then
print("Could not open output file")
return
end
local tab = {}
read_manifest(arg[1], tab, function(s) print(s) end)
local weightmap = assemble_weights(tab, function(s) print(s) end)
local cumweights = {}
local cum = 0.0
for file, wt in pairs(weightmap) do
cum = cum + wt.weight
table.insert(cumweights, { cum = cum, file = file, wt = wt })
end
for idx, ent in ipairs(cumweights) do
taboutf:write(tostring(ent.cum) .. " : " .. ent.file .. "\n")
end
taboutf:close()

61
parse_table.lua

@ -0,0 +1,61 @@
local function read_table(filename, file_table, errout)
local function parse_line(line, file_table, errout)
local s, e = string.find(line, " : ")
if s == nil or e == nil then
errout("error: bad line")
return
end
local cum = tonumber(string.sub(line, 1, s - 1))
local file = string.sub(line, e + 1)
table.insert(file_table, { cum = cum, file = file })
end
local tabf = io.open(filename, "r")
if tabf == nil then
errout("could not open table file " .. filename)
return
end
for line in tabf:lines() do
parse_line(line, file_table, errout)
end
io.close(tabf)
end
local function search_table(file_table, cum)
local s = 1
local e = #file_table - 1
while true do
if s >= e then
return s
end
local sidx = math.floor((s + e) / 2)
if cum < file_table[sidx].cum then
e = sidx
else
s = sidx + 1
end
end
end
local ftab = {}
read_table("outtab.txt", ftab, function(em) print(em) end)
--for idx, ent in ipairs(ftab) do
-- print(tostring(idx) .. " cwgt(" .. tostring(ent.file) .. ") = " .. tostring(ent.cum))
--end
local uw = ftab[#ftab - 1].cum
math.randomseed(os.time())
for i=1,100 do
local eidx = search_table(ftab, math.random() * uw)
local fname = ftab[eidx].file
print(fname)
end
return { read_table = read_table, search_table = search_table }
Loading…
Cancel
Save