File: interp.sml

package info (click to toggle)
smlsharp 4.2.0-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 125,348 kB
  • sloc: ansic: 16,737; sh: 4,347; makefile: 2,228; java: 742; haskell: 493; ruby: 305; cpp: 284; pascal: 256; ml: 255; lisp: 141; asm: 97; sql: 74
file content (186 lines) | stat: -rw-r--r-- 5,134 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
(* interp.sml
 *
 * COPYRIGHT (c) 1992 AT&T Bell Laboratories
 *)

structure Interp =
  struct

    local
      val exit = OS.Process.exit
      fun ordof(s, i) = Char.ord(String.sub(s, i))
      exception NotAChar
      exception NotAReal
      fun fromStr x = 
        (case Char.fromString x
          of SOME c => c
           | NONE => raise NotAChar)

     fun strToReal s = 
      (case Real.fromString s
        of SOME r => r
        | _ => raise NotAReal)

    fun intToReal x = 
     (strToReal ((Int.toString x) ^ ".0"))


      val explode = (fn x => map Char.toString (explode x))
      val implode = (fn x => implode (map fromStr x))

      open Objects
      val dict = ref ([] : {key : string, value : object} list)
      fun dictInsert (NAME key, value) = let
	    fun find [] = [{key=key, value=value}]
	      | find (x::r) = if (key = #key x)
		  then {key=key, value=value}::r
		  else x :: (find r)
	    in
	      dict := find(!dict)
	    end
	| dictInsert _ = raise Fail "dictInsert"
      fun prObj outStrm obj = let
	    fun printf args = TextIO.output(outStrm, implode args)
	    fun pr (NUMBER n) = printf["  ", Real.toString n, "\n"]
	      | pr (NAME s) = printf["  ",  s, "\n"]
	      | pr (LITERAL s) = printf["  ", s, "\n"]
	      | pr (LIST l) = app pr l
	      | pr MARK = printf["  MARK\n"]
	      | pr (OPERATOR _) = printf["  <operator>\n"]
	      | pr TOP = printf["  TOP OF STACK\n"]
	      | pr _ = printf["  <object>\n"]
	    in
	      pr obj
	    end
    in

    exception Stop

    fun error opName stk = let
	  fun prStk ([], _) = ()
	    | prStk (_, 0) = ()
	    | prStk (obj::r, i) = (prObj TextIO.stdErr obj; prStk(r, i-1))
	  in
	    TextIO.output(TextIO.stdErr, "ERROR: "^opName^"\n");
	    prStk (stk, 10);
	    raise (Fail opName)
	  end

    fun installOperator (name, rator) =
	  dictInsert (NAME name, OPERATOR rator)

    fun ps_def (v::k::r) = (dictInsert(k, v); r)
      | ps_def stk = error "ps_def" stk

    local
      fun binOp (f, opName) = let
	    fun g ((NUMBER arg1)::(NUMBER arg2)::r) =
		  NUMBER(f(arg2, arg1)) :: r
	      | g stk = error opName stk
	    in
	      g
	    end
    in
    val ps_add = binOp (op +, "add")
    val ps_sub = binOp (op -, "sub")
    val ps_mul = binOp (op *, "mul")
    val ps_div = binOp (op /, "div")
    end

    fun ps_rand stk = (NUMBER 0.5)::stk (** ??? **)

    fun ps_print (obj::r) = (prObj TextIO.stdOut obj; r)
      | ps_print stk = error "print" stk

    fun ps_dup (obj::r) = (obj::obj::r)
      | ps_dup stk = error "dup" stk

    fun ps_stop _ = raise Stop

  (* initialize dictionary and begin parsing input *)
    fun parse inStrm = let
	  fun getc () = case TextIO.input1 inStrm of NONE => ""
                               | SOME c => Char.toString c
	  fun peek () = case TextIO.lookahead inStrm
                         of SOME x => Char.toString x
                          | _ => ""
	(* parse one token from inStrm *)
	  fun toke deferred = let
		fun doChar "" = exit OS.Process.success
		  | doChar "%" = let
		      fun lp "\n" = doChar(getc())
			| lp "" = exit OS.Process.success
			| lp _ = lp(getc())
		      in
			lp(getc())
		      end
		  | doChar "{" = (MARK, deferred+1)
		  | doChar "}" = (UNMARK, deferred-1)
		  | doChar c = if Char.isSpace (fromStr c)
		      then doChar(getc())
		      else let
			fun lp buf = (case peek()
			       of "{" => buf
				| "}" => buf
				| "%" => buf
				| c => if Char.isSpace(fromStr c)
				    then buf
				    else (getc(); lp(c::buf))
			      (* end case *))
			val tok = implode (rev (lp [c]))
			val hd = ordof(tok, 0)
			in
			  if (hd = ord (#"/"))
			    then (LITERAL(substring(tok, 1, size tok - 1)), deferred)
			  else 
                            if ((Char.isDigit (chr hd)) orelse (hd = ord (#"-")))
			    then (NUMBER(strToReal(tok)), deferred)
			    else (NAME tok, deferred)
			end
		in
		  doChar(getc())
		end
	(* execute a token (if not deferred) *)
	  fun exec (UNMARK, stk, _) = let
		fun lp ([], _) = raise Fail "MARK"
		  | lp (MARK::r, l) = (LIST l)::r
		  | lp (x::r, l) = lp (r, x::l)
		  in
		    lp (stk, [])
		  end
	    | exec (OPERATOR f, stk, 0) = f stk
	    | exec (LIST l, stk, 0) = let
		fun execBody ([], stk) = stk
		  | execBody (obj::r, stk) = (exec(obj, stk, 0); execBody(r, stk))
		in
		  execBody (l, stk)
		end
	    | exec (NAME s, stk, 0) = let
		fun find [] = raise Fail "undefined name"
		  | find ({key, value}::r) = if (key = s) then value else find r
		in
		  exec (find (!dict), stk, 0)
		end
	    | exec (obj, stk, _) = obj::stk
	  fun lp (stk, level) = let
		val (obj, level) = toke level
		val stk = exec (obj, stk, level)
		in
		  lp (stk, level)
		end
	  in
	    installOperator ("add", ps_add);
	    installOperator ("def", ps_def);
	    installOperator ("div", ps_div);
	    installOperator ("dup", ps_dup);
	    installOperator ("mul", ps_mul);
	    installOperator ("print", ps_print);
	    installOperator ("rand", ps_rand);
	    installOperator ("stop", ps_stop);
	    installOperator ("sub", ps_sub);
	    (lp ([], 0)) handle Stop => ()
	  end (* parse *)

    end (* local *)

  end (* Interp *)