Module interpreter
Require Import String hashset streams stringmap.
Require Export executable frontend architecture_spec.
Local Open Scope string_scope.
Local Open Scope list_scope.
Local Open Scope ctype_scope.
Record istate (
K E : 
Set) := 
IState {
  
events_new : 
list E; 
(* the events generated in the last step  *)
  events_all : 
list E; 
(* all previously generated events,
    including those in the last step  *)
  sem_state : 
state K
}.
Arguments IState {
_ _} 
_ _ _.
Instance istate_dec {
K E : 
Set} `{
Env K, ∀ ε1 ε2 : 
E, 
Decision (ε1 = ε2)}
  (
iS1 iS2 : 
istate K E) : 
Decision (
iS1 = 
iS2).
Proof.
 solve_decision. Defined.
Section interpreter.
Context (
A : 
architecture).
Notation K := (
arch_rank A).
Context {
E : 
Set} `{∀ ε1 ε2 : 
E, 
Decision (ε1 = ε2)}.
Context (
e : ∀ `{
Env K}, 
env K → 
state K → 
list E).
Notation M := (
error (
frontend_state K) 
string).
Fixpoint interpreter_args_go (
args : 
list (
list Z)) : 
M (
list (
val K)) :=
  
match args with
  | [] => 
mret [
ptrV (
NULL (
charT{
K}))]
  | 
zs :: 
args =>
     '(
v,
n) ← 
error_of_option (
to_string_const zs)
       "
char of string constant out of range";
     
o ← 
insert_object perm_full v;
     
vs ← 
interpreter_args_go args;
     
mret (
ptrV (
Ptr (
addr_top_array o (
charT{
K}) (
Z.of_nat n))) :: 
vs)
  
end.
Fixpoint interpreter_args (σ
s : 
list (
type K))
    (
args : 
list (
list Z)) : 
M (
list (
val K)) :=
  
if decide (σ
s = []) 
then mret []
  
else if decide (σ
s = [
sintT; 
charT{
K}.*.*])%
T then
    vs ← 
interpreter_args_go args;
    
o ← 
insert_object perm_full (
VArray (
charT{
K}.*) 
vs);
    
mret [
intV{
sintT} (
length vs);
          
ptrV (
Ptr (
addr_top_array o (
charT{
K}.*) (
length vs)))]
  
else fail "
function `
main` 
should have argument types `
int` 
and `
char*`".
Definition interpreter_initial (Θ : 
list (
string * 
decl))
    (
args : 
list (
list Z)) : 
M (
istate K E) :=
  
_ ← 
alloc_program Θ;
  Δ
g ← 
gets to_globals;
  '(
_,σ
s,σ,
_) ← 
error_of_option (Δ
g !! "
main" ≫= 
maybe4 Fun)
    ("
function `
main` 
undeclared`");
  
guard (σ = 
sintT%
T ∨ σ = 
uintT%
T) 
with
    ("
function `
main` 
should have return type `
int`");
  
vs ← 
interpreter_args σ
s args;
  
m ← 
gets to_mem;
  
mret (
IState [] [] (
initial_state m "
main" 
vs)).
Definition interpreter_initial_eval (Θ : 
list (
string * 
decl))
    (
args : 
list (
list Z)) : 
string + 
istate K E :=
  
error_eval (
interpreter_initial Θ 
args) ∅.
Definition cexec' (Γ : 
env K) (δ : 
funenv K)
    (
iS : 
istate K E) : 
listset (
istate K E) :=
  
let (
_,ε
s,
S) := 
iS in
  (λ 
S_new,
    
let ε
s_new := 
e _ Γ 
S_new in IState ε
s_new (ε
s ++ ε
s_new) 
S_new
  ) <$> 
cexec Γ δ 
S.
Context (
hash : 
istate K E → 
Z).
Definition cexec_all (Γ : 
env K) (δ : 
funenv K) (
iS : 
istate K E) :
    
listset (
istate K E) * 
listset (
istate K E) :=
  
let nexts := 
cexec' Γ δ 
iS in
  if decide (
nexts ≡ ∅) 
then (∅, {[ 
iS ]}) 
else (
nexts, ∅).
Definition csteps_exec_all (Γ : 
env K) (δ : 
funenv K) :
    
listset (
istate K E) →
    
stream (
listset (
istate K E) * 
listset (
istate K E)) :=
  
cofix go iSs :=
  
let nexts := 
cexec_all Γ δ <$> 
iSs in
  let reds := 
listset_normalize hash (
nexts ≫= 
fst) 
in
  let nfs := 
listset_normalize hash (
nexts ≫= 
snd) 
in
  (
reds,
nfs) :.: 
go reds.
Definition interpreter_all
    (Θ : 
list (
string * 
decl)) (
args : 
list (
list Z)) :
    
M (
stream (
listset (
istate K E) * 
listset (
istate K E))) :=
  
iS ← 
interpreter_initial Θ 
args;
  Γ ← 
gets to_env; δ ← 
gets to_funenv;
  
mret (
csteps_exec_all Γ δ {[ 
iS ]}).
Definition interpreter_all_eval
    (Θ : 
list (
string * 
decl)) (
args : 
list (
list Z)) :
    
string + 
stream (
listset (
istate K E) * 
listset (
istate K E)) :=
  
error_eval (
interpreter_all Θ 
args) ∅.
Context (
rand : 
nat → 
nat).
Definition csteps_exec_rand (Γ : 
env K) (δ : 
funenv K) :
    
istate K E → 
stream (
istate K E + 
istate K E) :=
  
cofix go iS :=
  
match listset_car (
cexec' Γ δ 
iS) 
with
  | [] => 
srepeat (
inr iS)
  | (
iS' :: 
_) 
as iSs =>
     
let next := 
from_option iS' (
iSs !! 
rand (
length iSs)) 
in
     inl next :.: 
go next
  end.
Definition interpreter_rand
    (Θ : 
list (
string * 
decl)) (
args : 
list (
list Z)) :
    
M (
stream (
istate K E + 
istate K E)) :=
  
iS ← 
interpreter_initial Θ 
args;
  Γ ← 
gets to_env; δ ← 
gets to_funenv;
  
mret (
csteps_exec_rand Γ δ 
iS).
Definition interpreter_rand_eval
    (Θ : 
list (
string * 
decl)) (
args : 
list (
list Z)) :
    
string + 
stream (
istate K E + 
istate K E) :=
  
error_eval (
interpreter_rand Θ 
args) ∅.
End interpreter.