Máquina para lenguajes procedimentales con alcance

Transcripción

Máquina para lenguajes procedimentales con alcance
Máquina para lenguajes procedimentales con alcance estático
Cómo leer este documento:
En este documento se definen funciones así:
Foo: Tipo1 x … x TipoN
Tipo
Estas funciones las podemos definir de una de las siguientes dos formas:
o Foo(x1, …, xn) = ….
,donde cada xi es de tipo Tipoi
o usando la notación de objetos: x1.foo(x2,…, xn) =..
Las pilas ya sean de valores o de ambientes se definen con la notación usada en CAML:
[] para la pila vacía
x::xs para la pila con al menos un elemento x, que está en el tope de la pila.
Suponemos la función top definida así:
o Top([]) = indefinida
o Top(x::xs) = x
La máquina tiene los siguientes componentes:
Pila de evaluación
Código
Pila de ambientes
El Código tiene los siguientes componentes
Cod: Arreglo de instrucciones
PC : posición en el arreglo
Instrucción actual = Cod[PC]
Un ambiente tiene los siguientes componentes:
<direcciónDeRetorno, idAmbiente, idAmbienteEstáticoPadre,Memoria>
idAmbiente
idAmbienteEstáticoPadre
Memoria
Dirección de retorno
Una memoria, MEM, es un arreglo de valores. Tenemos las siguientes funciones. Su definición es
intuitiva.
Una función para obtener el valor guardado en una posición de la memoria:
Get: arregloValores x int
valor
mem.get(pos)
Una función para obtener la memoria que se obtendría al modificar una memoria dada asignando un
valor en una posición.
Set: arregloValores x int x valor
arregloValores
mem.set(pos,val)
Dado un ambiente, fr, tenemos las siguientes funciones selectoras:
fr.mem()
fr.id()
fr.staticLink()
fr.return()
Ahora más funciones sobre un ambiente:
Para obtener el valor de que se encuentra en una posición de la memoria
GetValue: Ambiente x int
valor
fr.GetValue ( d) = fr.mem().get(d)
Para obtener el ambiente resultante de modificar la memoria asignando un valor en una posición
dada.
SetValue : Ambiente x int x valor
Ambiente
fr.setValue(pos,val) = <fr.return(),fr.id(),fr.parent(),fr.mem.set(pos,val)>
La máquina tiene una pila de ambientes. Necesitamos poder manejar esta pila también como un arreglo. La
base de la pila está en la posición cero del arreglo. Se tiene que si un ambiente, fr, que está en la posición
pos de la pila de ambientes, entonces fr.id() = pos.
Para obtener el n-ésimo ambiente:
getNthFrame: ambientes x int
ambiente
getNthFrame(fs, i)
Para modificar el n-ésimo ambiente:
setNthFrame: ambientes x int x ambiente
ambientes
setNthFrame(fs,i,f)
Para la pila de ambientes tenemos la siguiente función para recorrer el link estático n veces desde un
marco dado. Esta función se define así:
NthParent: Ambientes x int x int
Ambiente
NthParent(pilaAmbientes, id, n) =
If (n == 0) then actual
Else NthParent(pilaAmbientes, pilaAmbientes[id].StaticLink(), n-1)
Fi
El índice del N-ésimo padre se puede obtener así:
NthParent(pilaAmbientes,actual,cuantas).id()
Para obtener el valor que se encuentra en la posición d de la memoria del ambiente que se encuentra
recorriendo s pasos el enlace estático:
getValueFrames(frames, s, d) =
NthParent(frames, frames.top().id(), s).getValue(d)
Para modificar los ambientes modificando la posición d de la memoria del ambiente que se encuentra
recorriendo s pasos el enlace estático asignándole el valor val:
SetValueFrames : Ambientes x int x int x valor
Ambientes
SetValueFrames(frames,s,d,val) =
let f = NthParent(frames, frames.top().id(), s) in
setNthFrame(frames, f.pos(), f.setValue(d.val))
endLet
Las funciones descritas arriba nos sirven para describir el comportamiento de la máquina.
Tenemos las siguientes instrucciones sencillas sobre la pila
<Pila, Ambientes, <C, PC, push v>>
<C,PC+1,C[PC+1]>>
<v::Pila, Ambientes,
<Pila, fs, <C, PC, pushV s,d>>
Ambientes, <C,PC+1,C[PC+1]>>
<fs.getValueFrames(s,d)::Pila,
<v::Pila, fs, <C, PC, Asgmem s,d>>
<C,PC+1,C[PC+1]>>
<Pila, fs.setValueFrames(s,d),
<x:Pila, Ambientes, <C, PC, pop>>
<C,PC+1,C[PC+1]>>
<Pila, Ambientes,
<y::x:Pila, Ambientes, <C, PC, plus>>
<C,PC+1,C[PC+1]>>
<y::x:Pila, Ambientes, <C, PC, sub>>
<C,PC+1,C[PC+1]>>
<(x+y)::Pila, Ambientes,
<(x-y)::Pila, Ambientes,
…
Suponemos que antes de invocar un método se empilan los parámetros y la traducción de una función
empieza con desempilar sus parámetros y guardarlos en las posiciones de memoria respectivas.
Al comenzar la ejecución:
<[], [], <C, PC, start(dir)>>
<C,dir,C[dir]>>
<[], [< _,0,_, [0,..,0]>],
La configuración final: <[], [[< _,0,_, MEM], <C, PC, END>>
Un llamado de una función:
<Pila, a:as, <C, PC, call(s, dir)>>
<
Pila,
<PC+1,a.id()+1,nthParent(a::as,a.id(),s).id(),[0,..,0]>::a::as,
<C,dir,C[dir]>
>
La salida de una función:
<Pila, a::b::as, <C, PC, return >>
<Pila, b::as, <C,a.return(),C[a.return()]>>
Un ejemplo de traducción:
Program test;
Int
0
START
1
ASGMEM 0,0
2
3
4
5
6
7
8
9
10
11
PUSHV 1,0
PUSHV 0,0
PUSHV 0,0
TIMES
PLUS
ASGMEM 0,1
PUSHV 0,1
RETURN
/* Se sacan los parametros al principio de
la función */
ASGMEM 0,1
ASGMEM 0,0
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PUSHV 0,0
PUSHV 1,1
EQ
JMPF 19
PUSHV 0,1
ASGMEM 0,2
JMP 28
PUSHV 0,0
PUSH 1
PLUS
PUSHV 0,1
PUSHV 1,0
Call 2,1
PLUS
Call 1,10
ASGMEM 0,2
Pushv 0,2
RETURN
30
31
32
33
34
35
ASGMEM 0,1
ASGMEM 0,0
Push 0
Push 0
Call 0,10
return
36
37
38
39
40
41
42
Push 1
Asgmem 0,0
Push 3
Push 2
Call 0,30
Asgmem 0,1
End
x;
Int
plusX (int y)
{
Int a;
a := x + y*y;
return a;
}
Int foo (int x, int n)
Int goo(int i, int accum) {
int a;
if (i = n) then
A = accum
Else
A = goo(i+1,
acum+plusX(x))
Return A;
}
{
Return goo(0,0)
}
{
X:= 1;
R :=
}
foo(3,2);
Para el seguimiento solo denotaré el estado de la pila de los ambientes y el PC para no
tener que escribir tanto
<[],[], 0> = Start 36
<[],[<_,0,_,[0,0]>], 36> == push 1
<[1],[<_,0,_,[0,0]>], 37> == asgmem 0,0
<[],[<_,0,_,[1,0]>], 38> == push 3
<[3],[<_,0,_,[1,0]>], 39> == push 2
<[2,3],[<_,0,_,[1,0]>], 40> == call 0,30
<[2,3],[ <41,1,0,[0,0]>,<_,0,_,[1,0]>], 30> =asgnmem 0,1
<[3],[<41,1,0,[0,2]>,<_,0,_,[1,0]>], 31>==asgnmem 0,0
<[],[<41,1,0,[3,2]>,<_,0,_,[1,0]>], 32>== push 0
<[0],[ <41,1,0,[3,2]>,<_,0,_,[1,0]>], 33>== push 0
<[0,0],[ <41,1,0,[3,2]>,<_,0,_,[1,0]>], 34>== call 0,10
<[0,0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 10>== asgmem 0,1
<[0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 11>== asgmem 0,0
<[],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 12>== pushv 0,0
<[0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 13>== pushv 1,1
<[2,0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 14>== EQ
<[false],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 15>== JMPF 19
<[],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 19>== pushv 0,0
<[0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 20>== push 1
<[1,0],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 21>== plus
<[1],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 22>== pushV 0,1
<[0,1],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 23>== pushV 1,0
<[3,0,1],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 24>== call 2, 1
<[3,0,1],[ <25,3,0,[0,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 1>== asgmem 0,0
<[0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 2>== PUSHV 1,0
<[1,0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 3>== PUSHV 0,0
<[3,1,0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 4>== PUSHV 0,0
<[3,3,1,0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 5>== tIMES
<[9,1,0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 6>== pluS
<[10,0,1],[ <25,3,0,[3,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 7>== ASGMEM 0,1
<[0,1],[ <25,3,0,[3,10]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 8>== PUSHV 0,1
<[10,0,1],[ <25,3,0,[3,10]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 9>== RETURN
<[10,0,1],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 25>== PLUS
<[10,1],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 26>== call 1,10
<[10,1],[ <27,3,1,[0,0,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 10>== asgmem 0,1
<[1],[ <27,3,1,[0,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 11>== asgmem 0,0
<[],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 12>== pushv 0,0
<[1],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 13>== pushv 0,0
<[2,1],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 14>== EQ
<[false],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 15>== JMPF 19
<[],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 19>== pushV 0,0
<[1],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 20>== push 1
<[1,1],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 21>== plus
<[2],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 22>== pushV 0,1
<[10,2],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 23>== pushV 1,0
<[3,10,2],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 24>== call 2,1
<[3,10,2],[ <25,4,0,[0,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 1>==asgmem 0,0
<[10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 2>== pushV 1,0
<[1,10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 3>== pushV 0,0
<[3,1,10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 4>== pushV
0,0
<[3,3,1,10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 5>== timeS
<[9,1,10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 6>== PLUs
<[10,10,2],[ <25,4,0,[3,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 7>==asgmem 0,1
<[10,2],[ <25,4,0,[3,10]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 8>== PUSHv 0,1
<[10,10,2],[ <25,4,0,[3,10]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 8>== reTURN
<[10,10,2],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 25>==plus
<[20,2],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 26>==CALL 1,10
<[20,2],[ <27,4,1,[0,0,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 10>== ASGMEM
0,1
<[2],[ <27,4,1,[0,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 11>== ASGMEM 0,0
<[],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 12>== PUSHv 0,0
<[2],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 13>== PUSHv 1,1
<[2,2],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 14>== EQ
<[true],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 15>== JMPF 19
<[],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 16>== PUSHV 0,1
<[20],[ <27,4,1,[2,20,0]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 17>== ASGMEM 0,2
<[],[ <27,4,1,[2,20,20]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 18>== JMP 28
<[],[ <27,4,1,[2,20,20]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 28>== PUSHV 0,2
<[20],[ <27,4,1,[2,20,20]>,<27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 29>== RETURN
<[20],[ <27,3,1,[1,10,0]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 27>== ASGMEM 0,2
<[],[ <27,3,1,[1,10,20]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 28>== PUSHV 0,2
<[20],[ <27,3,1,[1,10,20]>,<35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 29>== RETURN
<[20],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 27>== ASGMEM 0,2
<[],[ <35,2,1,[0,0,20]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 28>== PUSHV 0,2
<[20],[ <35,2,1,[0,0,0]>,<41,1,0,[3,2]>,<_,0,_,[1,0]>], 29>== RETURN
<[20],[ <41,1,0,[3,2]>,<_,0,_,[1,0]>], 35>== RETURN
<[20],[ <_,0,_,[1,0]>], 41>== ASGMEM 0,1
<[],[ <_,0,_,[1,20]>], 42>== END
Solución tarea:
Suponga que en la pila podemos guardar parejas que denotan una dirección absoluta:
(Ambiente, posición en el ambiente)
Agregamos las siguientes instrucciones:
DEREF : supone que tenemos una dirección en el tope de la pila. Cambiamos la dirección por el
valor guardado en esa dirección.
AsgDirVal: supone que tenemos una dirección en el tope de la pila y debajo un valor. Se le asigna
a la dirección de memoria ese valor
PushDir s,d: empila la dirección en memoria correspondiente al ambiente que se encuentra
recorriendo s veces el enlace estático y la dirección d.
Suponga las siguientes funciones:
Para obtener el valor que se encuentra en la posición d de la memoria del n-ésimo
ambiente:
getValueFramesAbs(frames, n, d) =
frames.getNthFrame(n).getValue(d)
Para modificar los ambientes modificando la posición d de la memoria del n-ésimo
ambiente asignándole el valor val:
SetValueFrames : Ambientes x int x int x valor
Ambientes
SetValueFramesAbs(frames,n,d,val) =
let f = frames.getNthFrame(n) in
setNthFrame(frames,n, f.setValue(d.val))
endLet
<Pila, fs, <C, PC, pushDir s,d>>
<(fs.getNtParent(s).id(),d)::Pila, Ambientes,
<C,PC+1,C[PC+1]>>
<(f,d)::Pila, Ambientes, <C, PC, deRef>>
<getValueframesAbs(ambientes, f, d)::Pila, Ambientes,
<C,PC+1,C[PC+1]>>
<(f,d)::v::Pila, Ambientes, <C, PC, AsgDirVal >>
< Pila,
setValueframesAbs(Ambientes,f,d,v), <C,PC+1,C[PC+1]>>
Entonces si tenemos un procedimiento definido así:
Prog
test;
Int A, B;
Proc proo(REF int x; Val int y, VR int z)
{
Z := x+y;
X:= z+X;
Z := 0;
}
{
A := 1;
B:= 2;
Proo(A,B, B)
}
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
START 24
ASGMEM 0,2
ASGMEM 0,1
ASGMEM 0,0
pushV 0,2
deref
asgmem 0,3
pushV 0,0
deref
pushV 0,1
plus
AsgMem 0,3
pushV 0,3
pushV 0,0
deREF
plus
pushV 0,0
ASGDIRVAL
push 0
ASGMEM 0,3
pushV 0,3
pushV 0,2
ASGDIRVAL
return
push 1
asgmem 0,0
push 1
asgmem 1,1
pushDir 0,0
29
30
31
32
push 0,1
pushDir 0,1
call 0, 1
end

Documentos relacionados