-- 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.