home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / packs / skeem / skutil.icn < prev    next >
Text File  |  2000-07-29  |  4KB  |  207 lines

  1. ############################################################################
  2. #
  3. #    Name:    skutil.icn
  4. #
  5. #    Title:    Scheme in Icon
  6. #
  7. #    Author: Bob Alexander
  8. #
  9. #    Date:    February 19, 1995
  10. #
  11. #    Description: see skeem.icn
  12. #
  13. ############################################################################
  14.  
  15. #
  16. # skeem -- Scheme in Icon
  17. #
  18. # Miscellaneous utility procedures
  19. #
  20.  
  21. #
  22. # Eval()
  23. #
  24. procedure Eval(ex,env)
  25.    local saveEnv,result
  26.    if LLIsNull(ex) then return NIL
  27.    saveEnv := CurrentEnv
  28.    CurrentEnv := \env
  29.    result :=  Eval1(ex) | Failure
  30.    CurrentEnv := saveEnv
  31.    return Failure ~=== result
  32. end
  33.  
  34. procedure Eval1(ex)
  35.    local fcn,arg
  36.    return {
  37.       if LLIsNotPair(ex) then {
  38.      if SymbolP(ex) then
  39.         GetVar(ex) | Error(ex,"unbound variable")
  40.      else ex
  41.      }
  42.       else {
  43.      fcn := Eval(LLFirst(ex)) | fail
  44.      arg := LLRest(ex)
  45.      if type(fcn) == ("Function" | "Lambda") then
  46.         arg := EvLList(arg) | fail
  47.      Apply(fcn,arg)
  48.      }
  49.       }
  50. end
  51.  
  52. procedure Apply(fcn,arg)
  53.    local value,fName,traced,fProc,oldFName,argList
  54.    oldFName := FuncName
  55.    FuncName := fName := \fcn.name | "<anonymous function>"
  56.    if traced := \(FTrace | fcn.traced) then
  57.       write(repl(" ",&level),Print(LLPair(fName,arg)))
  58.    fProc := fcn.proc
  59.    (value := case type(fcn) of {
  60.       "Function" | "Syntax": {
  61.      argList := LLToList(arg)
  62.      CheckArgs(fcn,*argList) &
  63.         fProc!argList
  64.      }
  65.       "Lambda": {
  66.      CheckArgs(fcn,LLLength(arg)) &
  67.         DoLambda(fProc,arg,fcn.env)
  68.      }
  69.       "Macro": {
  70.      CheckArgs(fcn,LLLength(arg)) &
  71.         Eval(DoLambda(fProc,arg,fcn.env))
  72.      }
  73.       default: Error("Invoke",Print(fcn),": can't invoke as function")
  74.       }) | {/FailProc := fName; fail}
  75.    if \traced then
  76.       write(repl(" ",&level),fName," -> ",Print(value))
  77.    FuncName := oldFName
  78.    return value
  79. end
  80.  
  81. #
  82. # DoLambda() - Invoke a lambda-defined function.
  83. #
  84. procedure DoLambda(def,actuals,env)
  85.    local result,arg,p,saveEnv,formals
  86.    formals := LLFirst(def)
  87.    saveEnv := CurrentEnv
  88.    CurrentEnv := \env
  89.    PushFrame()
  90.    if LLIsList(formals) then {
  91.       p := actuals
  92.       every DefVar(LLFirst(arg := LLPairs(formals)),LLFirst(p)) do
  93.      p := LLRest(p)
  94.       DefVar(\LLRest(arg),p)
  95.       }
  96.    else DefVar(formals,actuals)
  97.    result := EvalSeq(LLRest(def)) | {CurrentEnv := saveEnv; fail}
  98.    CurrentEnv := saveEnv
  99.    return result
  100. end
  101.  
  102. procedure CheckArgs(fcn,nbrArgs)
  103.    return if fcn.minArgs > nbrArgs then Error(fcn.name,"too few args")
  104.      else if \fcn.maxArgs < nbrArgs then Error(fcn.name,"too many args")
  105.      else nbrArgs
  106. end
  107.  
  108. procedure EvalSeq(L)
  109.    local value,element
  110.    if /L then fail
  111.    every element := LLElements(L) do
  112.       value := Eval(element) | fail
  113.    return value
  114. end
  115.  
  116. #
  117. # EvList() - Evaluate everything in a list, producing an Icon list.
  118. #
  119. procedure EvList(L)
  120.    local arglist,arg
  121.    arglist := []
  122.    every arg := LLElements(L) do
  123.       put(arglist,Eval(arg)) | fail
  124.    return arglist
  125. end
  126.  
  127. #
  128. # EvLList() - Evaluate everything in a list, producing a LList.
  129. #
  130. procedure EvLList(L)
  131.    local arglist,arg
  132.    arglist := LLNull
  133.    every arg := LLElements(L) do
  134.       arglist := LLPair(Eval(arg),arglist) | fail
  135.    return LLInvert(arglist)
  136. end
  137.  
  138. #
  139. # Retrieve a bound variable value, failing if none.
  140. #
  141. procedure GetVar(sym,env)
  142.    /env := CurrentEnv
  143.    return Unbound ~=== LLElements(env)[sym]
  144. end
  145.  
  146. #
  147. # Set a currently bound variable, failing if none.
  148. #
  149. procedure SetVar(sym,value,env)
  150.    local frame
  151.    /env := CurrentEnv
  152.    return if Unbound ~=== (frame := LLElements(env))[sym] then
  153.       .(frame[sym] := value)
  154. end
  155.  
  156. #
  157. # Define and set a variable in the specified environment (default current env).
  158. #
  159. procedure DefVar(sym,value,env)
  160.    /env := CurrentEnv
  161.    return .(LLFirst(env)[sym] := value)
  162. end
  163.  
  164. procedure UndefVar(sym,env)
  165.    /env := CurrentEnv
  166.    delete(LLFirst(env),sym)
  167.    return
  168. end
  169.  
  170. procedure PushFrame(env)
  171.    /env := table(Unbound)
  172.    return .(CurrentEnv := LLPair(env,CurrentEnv))
  173. end
  174.  
  175. procedure PopFrame()
  176.    return 1(LLFirst(CurrentEnv),CurrentEnv := LLRest(CurrentEnv))
  177. end
  178.  
  179. procedure DiscardFrame()
  180.    CurrentEnv := LLRest(CurrentEnv)
  181.    return
  182. end
  183.  
  184. procedure Error(tag,s[])
  185.    if type(tag) == "procedure" then tag := ProcName(tag)
  186.    writes(&errout,"\n### Error: ")
  187.    writes(&errout,\tag," -- ")
  188.    every writes(&errout,!s)
  189.    write(&errout)
  190. end
  191.  
  192. procedure SymbolP(x)
  193.    return (type(x) == "string",x)
  194. end
  195.  
  196. procedure VectorP(x)
  197.    return (type(x) == "list",x)
  198. end
  199.  
  200. procedure StringP(x)
  201.    return (type(x) == "String",x)
  202. end
  203.  
  204. procedure CharP(x)
  205.    return (type(x) == "Char",x)
  206. end
  207.