loa

Virtual machine for the Logic of Assumptions
git clone git://juanmeleiro.mat.br/loa
Log | Files | Refs

2023-11-22-declare-prove-use.lua (3673B)


      1 local pprint = require("pprint").pprint
      2 -- Possible actions:
      3 -- * start subcontext
      4 -- * declare judgment
      5 -- * use declared judgment
      6 
      7 function die(err, msg, ...)
      8 	msg = tostring(msg or err)
      9 	if err then
     10 		io.stderr:write(string.format(msg .. "\n", ...))
     11 		os.exit(1)
     12 	end
     13 end
     14 
     15 local test = {
     16 	{
     17 		method = "down"
     18 	},
     19 	{
     20 		method = "declare",
     21 		params = {
     22 			name = "cv",
     23 			judgment = {
     24 				head = "var",
     25 				body = {
     26 					{
     27 						head = "x"
     28 					}
     29 				}
     30 			}
     31 		}
     32 	},
     33 	{
     34 		method = "up"
     35 	},
     36 	{
     37 		method = "declare",
     38 		params = {
     39 			name = "var-wff",
     40 			judgment = {
     41 				head = "wff",
     42 				body = {
     43 					{
     44 						head = "x"
     45 					}
     46 				}
     47 			}
     48 		}
     49 	}
     50 }
     51 
     52 local actions = {}
     53 
     54 function actions.down(state)
     55 	die(state.subcontext, "Unresolved subcontext")
     56 	table.insert(state.theories, {})
     57 	return state
     58 end
     59 
     60 function actions.up(state)
     61 	state.subcontext = state.theories[#state.theories]
     62 	table.remove(state.theories)
     63 	return state
     64 end
     65 
     66 function pressupositions(state, judgment)
     67 	-- This is a rabbit hole. Where do pressupositions come from? Two
     68 	-- options: 1) we fix the forms of judgments and hard-code the
     69 	-- pressupositions; 2) we find a way for the user to create
     70 	-- *declaration rules* that work just like assumptions but are
     71 	-- only used at top-level declarations.
     72 	return {}
     73 end
     74 
     75 function actions.declare(state, params)
     76 	die(state.focus, "Proof in progress")
     77 	local assumption = {
     78 		name = params.name,
     79 		conclusion = params.judgment,
     80 		subcontext = state.subcontext
     81 	}
     82 	state.subcontext = nil
     83 	table.insert(state.theories[#state.theories], assumption)
     84 	state.goals = pressupositions(state, params.judgment)
     85 	return state
     86 end
     87 
     88 function prune(state)
     89 	while #state.focus.subgoals == 0 do
     90  		die(not match(state.focus.goal, state.focus.candidate), "Used assumption does not prove the goal")
     91 		if state.focus.goal.head == "var" then
     92 			-- oh boy
     93 			-- perform unifications
     94 		end
     95 		if state.focus.parent then
     96 			state.focus = state.focus.parent
     97 			table.remove(state.focus.subgoals)
     98 		else
     99 			table.remove(state.goals)
    100 			if #state.goals > 0 then
    101 				state.focus = state.goals[#state.goals]
    102 			else
    103 				state.focus = nil
    104 			end
    105 			return state
    106 		end
    107 	end
    108 	return state
    109 end
    110 
    111 function use(state, assumption)
    112 	state.focus.candidate = assumption.conclusion
    113 	if #assumption.subcontext > 0 then
    114 		for i = #candidate.subcontext, 1, -1 do
    115 			table.insert(state.focus.subgoals, candidate.subcontext[i])
    116 			state.focus.subgoals[i].parent = state.focus
    117 		end
    118 		state.focus = state.focus.subgoals[#state.focus.subgoals]
    119 	end
    120 end
    121 
    122 function actions.use(state, name)
    123 	die(not state.goals.focus, "Nothing to prove")
    124 
    125 	local assumption = state.assets[name]
    126 	die(not assumption, "No assumption under that name")
    127 	state = use(state, assumption)
    128 	state = prune(state)
    129 	return state
    130 end
    131 
    132 function interpret(program, state)
    133 	for _,c in ipairs(program) do
    134 		die(not actions[c.method], "No such action '%s'", c.method)
    135 		state = actions[c.method](state, c.params)
    136 	end
    137 	return state
    138 end
    139 
    140 function judgment2str(judg)
    141 	local res = judg.head
    142 	if judg.body then
    143 		res = res .. "("
    144 		for i = 1, #judg.body do
    145 			res = res .. judgment2str(judg.body[i])
    146 			if i < #judg.body then
    147 				res = res .. ","
    148 			end
    149 		end
    150 		res = res .. ")"
    151 	end
    152 	return res
    153 end
    154 
    155 function printassumption(assump, level)
    156 	if assump.subcontext then
    157 		printtheory(assump.subcontext, level + 1)
    158 	end
    159 	io.write(string.rep(" ", level) .. assump.name .. " " .. judgment2str(assump.conclusion) .. "\n")
    160 end
    161 
    162 function printtheory(th, level)
    163 	level = level or 0
    164 	for _,a in ipairs(th) do
    165 		printassumption(a, level)
    166 	end
    167 end
    168 
    169 local init = {
    170 	goals = {},
    171 	theories = {{}}
    172 }
    173 
    174 local bigres = interpret(test, init)
    175 printtheory(bigres.theories[1])