############################################################################ # # File: qei.icn # # Subject: Program to evaluate Icon expressions interactively # # Authors: William H. Mitchell and Ralph E. Griswold # # Date: March 26, 2002 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program takes expressions entered at the command line and # evaluates them. # # A semicolon is required to complete an expression. If one is not # provided, the subsequent line is added to what already has been # entered. # # It is important to know that qei accumulates expressions and evaluates # all previously entered expressions before it evaluates a new one. # # A line beginning with a colon is a command. The commands are: # # # :clear clear the accumulated expressions. # # :every generate all the results from the expression; # otherwise, at most one is produced. # # :exit terminate the session # :quit terminate the session # # :list list the accumulated expressions. # # :type toggle switch that displays the type of the # result; the program starts with this switch on. # ############################################################################ # # "qei" is derived from the Latin "quod erat inveniendum" -- "which was # to be found out". # ############################################################################ # # Requires: co-expressions and system() # ############################################################################ procedure main() local a, tag, header, incfiles, prog, extras, showtype local uselines, line, inline, src, files, w, f, Generate, sfile local curexp, t, rc, sc write("Icon Expression Evaluator, Version 1.2, type :? for help") if not(&features == "co-expressions") | not(&features == "system function") then stop("*** This program requires co-expressions ***") tag := create "r" || seq() || "_" header := [ "global showtype, showimage, showImage", "procedure main()", "hwrite := -1; write :=: hwrite", "hwrites := -1; writes :=: hwrites", "hread := -1; read :=: hread" ] incfiles := [] prog := [] extras := ["write := hwrite", "read := hread", "writes := hwrites"] showtype := 1 uselines := [] repeat { line := "" repeat { if *uselines ~= 0 then { inline := get(uselines) } else { writes(if *line = 0 then "> " else "... ") inline := (read() | shut_down()) } inline := trim(inline, ' \t') case inline of { ":type": { (/showtype := 1) | (showtype := &null) write("Will ",(/showtype & "not ")|"","display types") next } ":exit" | ":quit": shut_down() ":clear": { prog := [] tag := ^tag # reset variable numbering next } ":list": { every(write(!prog)) next } ":help" | ":?": { Help() next } } inline ? { if =":edit" then { src := prog[-1][1:-1] src := replace(src, "\n#", "\n") src ? { tab(upto('(') + 1) & line := atos(Edit([tab(0)]), "\n") & break } } else if =":edit all" then { prog := Edit(prog) next } else if =":link" then { push(header, inline[2:0] ? tab(upto(';') | 0)) next } else if =":include" then { inline := replace(inline, ";", "") inline ? (tab(upto(' \t') + 1) & files := tab(0)) files := split(files, ', \t') incfiles |||:= files next } else if =":load" then { w := split(inline, ' ,\t\'\";') if f := open(w[2]) then { while put(uselines, read(f)) close(f) next } else { write("*** cannot open ", image(w[2])) next } } } line ||:= inline || "\n" if line[-2:0] == ";\n" then { line[-2:0] := "" break } } if \showtype then put(extras, "showtype := 1") if line ?:= (=":every " & tab(0)) then Generate := 1 sfile := open("qei_.icn","w") every write(sfile, !(header | prog | extras)) curexp := (t :=@tag) || " := (" || line || ")" if \Generate then { write(sfile, "every WR(\"\",", curexp, ")") } else { write(sfile, "if (", curexp, ") then WR(\"", t, " := \",", t, ")") write(sfile, "else write(\"Failure\")") } write(sfile, "end") WriteWR(sfile) close(sfile) $ifdef _MS_WINDOWS sc := system("wicont -s qei_.icn " || atos(incfiles, " ")) $else sc := system("icont -s qei_.icn " || atos(incfiles, " ")) $endif if sc = 0 then rc := system("qei_") if sc = 0 & rc = 0 then put(prog, curexp) else put(prog, "#" || replace(curexp, "\n", "\n#")) extras := ["write := hwrite", "read := hread", "writes := hwrites"] Generate := &null } end procedure WriteWR(f) write(f, "procedure WR(tag, e)") write(f, "writes(\" \",tag, image(e))") write(f, "\twrite(if \\showtype then \" (\"|| type(e)|| \")\" else \"\")") write(f, "end"); end procedure Help() write("Enter any Icon expression to evaluate it") write() write(":edit -- edit last expression") write(":edit all -- edit the list of expressions") write(":every -- show generated results for expresion") write(":exit or :quit -- exit qei") write(":help or :? -- print this message") write(":include , e.g. :include \"x.icn\" -- include Icon files") write(":limit -- limit results of :every to ") write(":link , e.g. link image -- link ucode files") write(":list -- list expressions") write(":load , e.g. :load x -- load expressions from the file x") write(":type -- toggle display of type") return end procedure Edit(p) local f f := open("qei_.icn", "w") | stop("*** cannot open program file") every write(f, !p) close(f) system("$EDITOR qei_.icn") f := open("qei_.icn") | stop("*** cannot re-open program file") p := [] while put(p, read(f)) return p end procedure atos(a,delim) local e, s s := "" /delim := "," every e := !a do (/s := e) | (s ||:= delim || e) return s end # # replace string (from the IPL) # procedure replace(s1,s2,s3) local result, i result := "" i := *s2 s1 ? { while result ||:= tab(find(s2)) do { result ||:= s3 move(i) } return result || tab(0) } end procedure split(line,dlms) local w /dlms := ' \t' w := [] line ? repeat { tab(upto(~dlms)) put(w, tab(many(~dlms))) | break } return w end procedure shut_down() remove("qei_") remove("qei_.icn") exit() end