globals
.
newscope
creates a copy of an environment that can be added to
without having a side effect on the original.
add_to_rho
does the adding.
lookup
searches for the first binding of string val
in
the environment.
lookuptype
searches for val
in the environment and if
it exists, checks that its type is ty
.
<*>= [D->] procedure is_defined(ident, rho) return (<value ofident
inrho
>) # parens handle newline from -L end procedure lookup(ident, rho) return (<value ofident
inrho
>) | error("`", ident, "' is undefined") end procedure lookuptype(ident, ty, rho) type(v := <value ofident
inrho
>) == ty | typeerror(v, ty, ident, rho) return v end
Definesis_defined
,lookup
,lookuptype
(links are to index).
<value ofident
inrho
>= (<-U) { /rho := globals; \(!rho)[ident] }
<*>+= [<-D->] procedure add_to_rho(name, val, rho) #write("rho ", *rho, " ", name, " ", expimage(val)) add_to_frame(name, val, rho[1]) | impossible("bogus environment") return rho end procedure add_to_frame(name, val, frame) (/frame[name] := val) | deferror(name) return frame end
Definesadd_to_frame
,add_to_rho
(links are to index).
<*>+= [<-D->] procedure newscope(rho) return push(copy(rho), table()) end
Definesnewscope
(links are to index).
Here we extend an environment with a new frame. I take care not to modify the environment.
<*>+= [<-D->] procedure extendscope(rho, frame) (type(frame) == "table" & type(rho) == "list") | impossible("rho extension") return push(copy(rho), frame) end
Definesextendscope
(links are to index).
<*>+= [<-D->] procedure envimage(env, envname) local hidden /envname := "env" s := "" <ifenv
is a list, convert to a table and create stringhidden
> if *env = 0 then s ||:= "\nEnvironment " || envname || " is empty" every p := !sort(env) do s ||:= pairimage(envname, p[1], p[2]) if \hidden then { s ||:= " -------- hidden --------\n" return s || hidden } else return s end
Definesenvimage
(links are to index).
<ifenv
is a list, convert to a table and create stringhidden
>= (<-U) if type(env) == "list" then { t := table() every e := !env & ident := key(e) do (/t[ident] := e[ident]) | { /hidden := "" ; hidden ||:= pairimage(envname, ident, e[ident]) } env := t }
<*>+= [<-D->] procedure pairimage(envname, ident, v) return "\n " || envname || "[" || expimage(ident) ||"]" || " = " || case type(v) of { # "pattern" : "<pattern> " || patternimage(v) # "field" : "<field> " || fieldimage(v) "string" : image(v) default : expimage(v) } end
Definespairimage
(links are to index).
<*>+= [<-D->] procedure deferror(t, v) error(t, " ", v," is already defined.") end
Definesdeferror
(links are to index).
<*>+= [<-D->] procedure typeerror(x, typename, ident, rho) error("Expected ", (\ident || " to be a " | ""), typename, "; found ", type(x), " ", expimage(x)) end
Definestypeerror
(links are to index).
<name of rho
>=
if rho === globals then "globals" else "rho"
project
fails.
<*>+= [<-D] record inject(pattern, integer, consop) procedure project(x, ty) return if type(x) == ty then x else if type(x) == "inject" then case ty of { "pattern" : \x.pattern "integer" : \x.integer "consop" : \x.consop } else if ty == "integer" then case type(x) of { "pattern" | "input" : fail exptypes() : x default : impossible("Bug in toolkit---can't use relocatable name", " in matching statement (was `rethink projection')") } end
Definesinject
,project
(links are to index).
I don't really know if the last clause here is right, but it was better than simply allowing anything to be projected into an integer, which I think would be unwarranted optimism.