############################################################################ # # File: sandgen.icn # # Subject: Procedures for "evaluation sandwiches" code # # Author: Ralph E. Griswold # # Date: November 19, 1997 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program is designed to be linked with the output of the meta- # translator. These procedures produce "evaluation sandwiches" # so that program execution can be monitored. # # See "Evaluation Sandwiches", Icon Analyst 6, pp. 8-10, 1991. # ############################################################################ # # Bug: The invocable declaration is not handled properly. "invocable all" # will get by, but some other forms produce syntax errors. The # problem is in the meta-translator itself, not in this program. # ############################################################################ # # Links: strings # ############################################################################ link strings global code_gen procedure main() code_gen := sandwich # so it can be changed easily write("link prepost") # link the sandwich slices Mp() # call meta-procedure end procedure Alt(e1, e2) # e1 | e2 return code_gen("(", e1, "|", e2, ")") end procedure Apply(e1, e2) # e1 ! e2 return code_gen("(", e1, "!", e2, ")") end procedure Arg(e) return e end procedure Asgnop(op, e1, e2) # e1 op e2 return code_gen("(", e1, " ", op, " ", e2, ")") end procedure Augscan(e1, e2) # e1 ?:= e2 return code_gen("(", e1, " ?:= ", e2, ")") end procedure Bamper(e1, e2) # e1 & e2 return code_gen("(", e1, " & ", e2, ")") end procedure Binop(op, e1, e2) # e1 op e2 return code_gen("(", e1, " ", op, " ", e2, ")") end procedure Body(es[]) # procedure body every write(!es) return end procedure Break(e) # break e return code_gen("break ", e) end procedure Case(e, clist) # case e of { caselist } return code_gen("case ", e, " of {", clist, "}") end procedure Cclause(e1, e2) # e1 : e2 return code_gen(e1, " : ", e2, "\n") end procedure Clist(cclause1, cclause2) # cclause1 ; cclause2 return code_gen(cclause1, ";", cclause2) end procedure Clit(c) # 'c' return image(c) end procedure Compound(es[]) # { e1; e2; ... } local result if *es = 0 then return "{}\n" result := "{\n" every result ||:= !es || "\n" return code_gen(result, "}\n") end procedure Create(e) # create e return code_gen("create ", e) end procedure Default(e) # default: e return code_gen("default: ", e) end procedure End() # end write("end") return end procedure Every(e) # every e return code_gen("every ", e) end procedure EveryDo(e1, e2) # every e1 do e2 return code_gen("every ", e1, " do ", e2) end procedure Fail() # fail return "fail" end procedure Field(e, f) # e . f return code_gen("(", e, ".", f, ")") end procedure Global(vs[]) # global v1, v2, ... local result result := "" every result ||:= !vs || ", " write("global ", result[1:-2]) return end procedure If(e1, e2) # if e1 then e2 return code_gen("if ", e1, " then ", e2) end procedure IfElse(e1, e2, e3) # if e1 then e2 else e3 return code_gen("if ", e1, " then ", e2, " else ", e3) end procedure Ilit(i) # i return i end procedure Initial(e) # initial e write("initial ", e) return end procedure Invocable(ss[]) # invocable s1, s2, ... (problem) if \ss then write("invocable all") else write("invocable ", ss) return end procedure Invoke(e, es[]) # e(e1, e2, ...) local result if *es = 0 then return code_gen(e, "()") result := "" every result ||:= !es || ", " return code_gen(e, "(", result[1:-2], ")") end procedure Key(s) # &s return code_gen("&", s) end procedure Limit(e1, e2) # e1 \ e2 return code_gen("(", e1, "\\", e2, ")") end procedure Link(vs[]) # link "v1, v2, ..." local result result := "" every result ||:= !vs || ", " write("link ", result[1:-2]) return end procedure List(es[]) # [e1, e2, ... ] local result if *es = 0 then return "[]" result := "" every result ||:= !es || ", " return code_gen("[", result[1:-2], "]") end procedure Local(vs[]) # local v1, v2, ... local result result := "" every result ||:= !vs || ", " write("local ", result[1:-2]) return end procedure Next() # next return "next" end procedure Not(e) # not e return code_gen("not(", e, ")") end procedure Null() # &null return "" end procedure Paren(es[]) # (e1, e2, ... ) local result if *es = 0 then return "()" result := "" every result ||:= !es || ", " return code_gen("(", result[1:-2], ")") end procedure Pdco(e, es[]) # e{e1, e2, ... } local result if *es = 0 then return code_gen(e, "{}") result := "" every result ||:= !es || ", " return code_gen(e, "{", result[1:-2], "}") end procedure Proc(n, vs[]) # procedure n(v1, v2, ...) local result, v if *vs = 0 then write("procedure ", n, "()") result := "" every v := !vs do if \v == "[]" then result[-2:0] := v || ", " else result ||:= (\v | "") || ", " write("procedure ", n, "(", result[1:-2], ")") return end procedure Record(n, fs[]) # record n(f1, f2, ...) local result, field if *fs = 0 then write("record ", n, "()") result := "" every field := !fs do result ||:= (\field | "") || ", " write("record ", n, "(", result[1:-2], ")") return end procedure Repeat(e) # repeat e return code_gen("repeat ", e) end procedure Return(e) # return e return code_gen("return ", e) end procedure Rlit(r) # r return r end procedure Scan(e1, e2) # e1 ? e2 return code_gen("(", e1 , " ? ", e2, ")") end procedure Section(op, e1, e2, e3) # e1[e2 op e3] return code_gen(e1, "[", e2, op, e3, "]") end procedure Slit(s) # "s" return image(s) end procedure Static(vs[]) # static v1, v2, .. local result result := "" every result ||:= !vs || ", " write("static ", result[1:-2]) return end procedure Subscript(e1, e2) # e1[e2] return code_gen(e1, "[", e2, "]") end procedure Suspend(e) # suspend e return code_gen("suspend ", e) end procedure SuspendDo(e1, e2) # suspend e1 do e2 return code_gen("suspend ", e1, " do ", e2) end procedure To(e1, e2) # e1 to e2 return code_gen("(", e1, " to ", e2, ")") end procedure ToBy(e1, e2, e3) # e1 to e2 by e3 return code_gen("(", e1, " to ", e2, " by ", e3, ")") end procedure Repalt(e) # |e return code_gen("(|", e, ")") end procedure Unop(op, e) # op e return code_gen("(", op, e, ")") end procedure Until(e) # until e return code_gen("until ", e) end procedure UntilDo(e1, e2) # until e1 do e2 return code_gen("until ", e1, " do ", e2) end procedure Var(v) # v return v end procedure While(e) # while e return code_gen("while ", e) end procedure WhileDo(e1, e2) # while e1 do e2 return code_gen("while ", e1, " do ", e2) end # Generate "evaluation sandwich" code. procedure sandwich(s[]) push(s, "(pre(), post(") put(s, "))") return cat ! s end