############################################################################ # # Name: skeem.icn # # Title: Scheme in Icon # # Author: Bob Alexander # # Date: February 19, 1995 # # Description: R4RS Scheme, with the exception that continuations # are escape procedures only (i.e. do no have unlimited # extent) # ############################################################################ # # skeem -- Scheme in Icon # # Main program, initialization, and read/eval/print procedure # link llist,escapesq,options link skfun,skbasic,skcontrl,skio,sklist,skmisc,sknumber,skstring,skextra link skutil,skin,skout #link skdebug #link ximage global GlobalEnv,UserEnv,CurrentEnv, # environments T,F,NIL,Unbound,Failure, # universal constants InputPortStack, OutputPortStack, EscapeData,FailProc,Resume,BreakLevel,FuncName, EOFObject, Space global TraceSet, # set of currently traced functions FTrace # flag for tracing all functions global TraceReader,EchoReader,NoError record String(value) # used for string datatyepe record Char(value) # used for character datatyepe record Port(file,option) # used for port datatyepe record Symbol(string,value) record Promise(proc,ready,result) record UniqueObject(name) record Value(value) record Function(proc,name,minArgs,maxArgs,traced) record Lambda(proc,name,minArgs,maxArgs,env,traced) record Macro(proc,name,minArgs,maxArgs,env,traced) record Syntax(proc,name,minArgs,maxArgs,traced) # # main() -- Analyzes the arguments and invokes the read/eval/print loop. # procedure main(arg) local fn,f Initialize(arg) if *arg = 0 then arg := ["-"] if \TraceReader then &trace := -1 every fn := !arg do { f := if fn == "-" then &input else open(fn) | stop("Can't open ",fn) ReadEvalPrint(f,,"top") } end # # Initialize() - Set up global values # procedure Initialize(arg) Options(arg) Space := ' \t\n\r\l\v\f' T := UniqueObject("#t") F := UniqueObject("#f") Unbound := UniqueObject("unbound") Failure := UniqueObject("failure") EOFObject := UniqueObject("EOF object") NIL := &null BreakLevel := 0 InputPortStack := [Port(&input,"r")] OutputPortStack := [Port(&output,"w")] TraceSet := set() GlobalEnv := PushFrame() InitFunctions() UserEnv := PushFrame() ######### ## every x := !sort(LLFirst(GlobalEnv)) do { ## y := x[2] ## sname := if ProcName(y.proc) == y.name then "" else " " || y.name ## write(right(y.minArgs,2),right(\y.maxArgs,2) | " -"," ",image(y.proc)[11:0],sname) ## } ######### return end procedure Options(arg) local opt opt := options(arg,"tre") TraceReader := opt["t"] EchoReader := opt["r"] NoError := opt["e"] return opt end # # ReadEvalPrint() -- The R/E/P loop. # procedure ReadEvalPrint(f,quiet,top) local sexpr,value,saveEnv every sexpr := ReadAllExprs(f) do { if \EchoReader then write("Read: ",Print(sexpr)) saveEnv := CurrentEnv EscapeData := Resume := &null if /NoError then &error := 1 if value := Eval(sexpr) then (if /quiet then write(Print(value))) else { # # The expression failed -- why? # if \Resume then { if /top then { if Resume === "top" then fail # (top) return 1(.Resume.value,Resume := &null) # (resume x) } if Resume ~=== "top" then { Error("READ-EVAL-PRINT","Can't resume from top level") Resume := &null } } else { EscapeCheck() # escape that doesn't exist (any more) ErrorCheck() # run-time error } CurrentEnv := saveEnv } } return value end procedure ErrorCheck() if &errornumber then { Error(FailProc,"Icon run-time error: ",&errortext, ("\n offending value:_ \n skeem representation: " || Print(&errorvalue) || "_ \n Icon representation: " || image(&errorvalue) | "")\1) FailProc := &null errorclear() } else return end