-- JunoBindImpl.mesa
-- June 6, 1983 2:04 pm Greg Nelson
-- Last Edited by: Gnelson, December 9, 1983 6:49 pm
-- An alist is a list of NILs and 2-element lists. Each two-element list [v, u] represents
-- a binding of the name v to the value u. Note that [v, u] means Cons[v, Cons[u, NIL]].
-- Each NIL in the alist represents a previous Push, and is searched for by Pop.
-- All of these procedures treat their alist as the complete environment except Lookup
-- and Bind, which, if the designated variable is not on their alist argument, use the
-- top-level alist from Juno2Top.
DIRECTORY JunoBind, Lisp, JunoSyntax, Juno2Top, Atom;
JunoBindImpl: PROGRAM IMPORTS Lisp, Juno2Top, Atom EXPORTS JunoBind =
BEGIN OPEN Lisp, JunoBind, JS: JunoSyntax;
Lookup2: PROC [v: JS.Variable, al: Alist]
RETURNS [alcdr: Alist] =
{WHILE al # NIL AND (Car[al] = NIL OR Car[Car[al]] # v)
DO al ← Cdr[al] ENDLOOP;
alcdr ← al};
nil: ATOM = Atom.MakeAtom["nil"];
Lookup: PUBLIC PROC [v: JS.Variable, al: Alist]
RETURNS [Value] =
{IF v = NIL OR v = nil THEN RETURN[NIL];
al ← Lookup2[v, al];
IF al = NIL THEN al ← Lookup2[v, Juno2Top.al];
IF al = NIL THEN ERROR ELSE RETURN [Cadr[Car[al]]]};
Bind: PUBLIC PROC[al: Alist, v: JS.Variable, u: Value] RETURNS [newal: Alist]
= {newal ← al;
al ← Lookup2[v, al];
IF al = NIL THEN al ← Lookup2[v, Juno2Top.al];
IF al = NIL THEN ERROR;
Rplaca[Cdr[Car[al]], u]};
BindLoop: PUBLIC PROC[al: Alist, al2: Alist] RETURNS [newal: Alist] =
{newal ← al;
WHILE al2 # NIL DO
IF Car[al2] # NIL THEN newal ← Bind[newal, Car[Car[al2]], Cadr[Car[al2]]];
al2 ← Cdr[al2]
ENDLOOP};
Push: PUBLIC PROC [al: Alist] RETURNS [Alist] = {RETURN [Cons[NIL, al]]};
Pop: PUBLIC PROC [al: Alist] RETURNS [Alist] =
{WHILE al # NIL AND Car[al] # NIL DO al ← Cdr[al] ENDLOOP;
IF al = NIL THEN ERROR;
RETURN [Cdr[al]]};
EmptyBinding: PUBLIC PROC RETURNS [Alist] = {RETURN [NIL]};
NewBind: PUBLIC PROC [al: Alist, v: JS.Variable, u: Value]
RETURNS [newal: Alist]
= {newal ← Cons[Cons[v, Cons[u, NIL]], al]};
Extend: PUBLIC PROC [al2, al: Alist] RETURNS [newal: Alist] =
{newal ← al;
WHILE al2 # NIL
DO newal ← NewBind[newal, Car[Car[al2]], Cadr[Car[al2]]]; al2 ← Cdr[al2] ENDLOOP;
-- error in the above loop means al2 has a NIL mark in it, which it shouldn't.
};
InDomain: PUBLIC PROC[arg: JS.Variable, al: Alist] RETURNS [BOOL] =
{WHILE al # NIL AND (Car[al] = NIL OR Car[Car[al]] # arg) DO al ← Cdr[al] ENDLOOP;
RETURN [al # NIL]};
END.