Implementing Exceptions, While-Do; Exceptions in Java
- In section 4.4, exception handling is added to the defined language.
The handler-exp evaluates to a function of one variable, which is installed as an exception handler continuation.[expression] ::= try [expression] handle [expression] (try-exp (body-exp expression?) (handler-exp expression?)) [epxression ::= raise [expression] (raise-exp (exp expression?))If body-exp finishes normally, its value is returned by the try. If a raise is encountered, its value is passed to the handler of the most recent try.
A handler can deal with the exception or can pass it up to the next nearest handler.
Exception handling is implemented in interp4-4exc.scm
- Examples
If strings are implemented --let x = read() in try if zero?(x) then raise x else *(x, x) handle proc(x) print(list(x, v))")Based on example from the text --let x = read('Enter pos num: ') in try if zero?(x) then raise 'Not positive!' else *(x, x) handle proc(x) print(x)With strings, expanded print, read -- two chances to make a mistakelet index = proc (n, l) letrec loop(l) = if null?(l) then raise sub1(0) else if equal?(n, car(l)) then 0 else add1((loop cdr(l))) in try (loop l) handle proc (x) x in begin print((index 1 list(2, 3))); print((index 2 list(2, 3))); print((index 3 list(2, 3))); (index 4 list(2, 3)) endlet excep = proc(x, y, z) print(x, ' not in [', y, ', ', z, ']') in let get = proc(a, b) let n = read('Enter num from ', a, ' to ', b, ': ') in if less?(n, a) then raise (excep n a b) else if greater?(n, b) then raise (excep n a b) else n in try (get 5 10) handle proc(x) try (get 5 10) handle proc(x) (get 5 10)")
- Implementation of
try/handleandraiseFor
eval-expression:For(try-exp (body-exp handler-exp) (eval-expression handler-exp env (handler-cont body-exp env cont))) (raise-exp (exp) (eval-expression exp env (raise-cont cont)))define-datatype continuation:For(handler-cont (body expression?) (env environment?) (cont continuation?)) (try-cont (handler expval?) (cont continuation?)) (raise-cont (cont continuation?))apply-cont:For(handler-cont (body-exp env cont) (if (procval? val) (eval-expression body-exp env (try-cont val cont)))) (try-cont (handler cont) (apply-cont cont val)) (raise-cont (cont) (find-handler val cont))find-handler:For the grammer:(define find-handler (lambda (val cont) (cases continuation cont (try-cont (handler cont) (apply-procval handler (list val) cont)) (halt-cont () (error 'find-handler "uncaught exception ~s" val)) (test-cont (true-exp false-exp env cont) (find-handler val cont)) (prim-args-cont (prim cont) (find-handler val cont)) (eval-first-cont (rands env cont) (find-handler val cont)) (eval-rest-cont (first-val cont) (find-handler val cont)) (varassign-exp-cont (id env cont) (find-handler val cont)) (let-exp-cont (ids env body cont) (find-handler val cont)) (eval-rator-cont (rands env cont) (find-handler val cont)) (app-exp-cont (proc cont) (find-handler val cont)) (begin-exp-cont (exps env cont) (find-handler val cont)) (handler-cont (body-exp env cont) (find-handler val cont)) (raise-cont (cont) (find-handler val cont)) (else (error 'find-handler "bad continuation ~s" cont)))))(expression ("try" expression "handle" expression) try-exp) (expression ("raise" expression) raise-exp)- Adding
while-doto the continuation-passing interpreter interp4-4exc.scmFor
eval-expression:For(while-do-exp (test exp) (eval-expression test env (while-test-cont test exp env cont)))define-datatype continuation:For(while-test-cont (test expression?) (exp expression?) (env environment?) (cont continuation?)) (while-exp-cont (test expression?) (exp expression?) (env environment?) (cont continuation?))apply-cont:For the grammar:(while-test-cont (test exp env cont) (if (true-value? val) (eval-expression exp env (while-exp-cont test exp env cont)) (apply-cont cont 1))) (while-exp-cont (test exp env cont) (eval-expression test env (while-test-cont test exp env cont)))An example that should work:(expression ("while" expression "do" expression) while-do-exp)Exception handling could be added by adding clauses for the while continuations tolet i = 0 s = 0 in begin while less?(i, 10) do begin set i = add1(i); set s = +(s, i) end; s endfind-handler.
- Examples of exceptions in
Scheme.java.
try/handlebecomestry/catch
System exceptions are raised implicitly.A user defined exception:public class Scheme { static void doFile(String fname) { try { File file = new File(fname); FileInputStream inFile = new FileInputStream(file); InputStreamReader inStream = new InputStreamReader(inFile); char[] cbuf = new char[(int)file.length()]; inStream.read( cbuf, 0, (int)file.length() ); String contents = new String(cbuf); Parser p = new Parser(contents); Exp e = p.parseExp(); Env env = Env.initEnv(); while (e != null) { e.eval(env).println(); e = p.parseExp(); } } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (EvalException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } catch (ParseException e) { System.out.println(e.getMessage()); } } public static void main(String argv[]) { if (argv.length==1) { doFile(argv[0]); return; } BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); Env env = Env.initEnv(); while (true) { System.out.print("> "); try { Parser p = new Parser(in.readLine()); p.parseExp().eval(env).println(); } catch (EvalException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } catch (ParseException e) { System.out.println(e.getMessage()); } } } }EvalExceptions are thrown in theclass EvalException extends RuntimeException { public EvalException(String msg) { super(msg); }applymethod in the classPrimProcand in the
evalmethods inandclass Varref extends Exp { private String var; public Varref(String _var) { var = _var; } public Value eval(Env env) { Vector v = env.apply(var); if (v == null) throw new EvalException("variable "+var+" undefined"); return (Value)v.firstElement(); } }The exception argument is printed and the program continues.class Set extends Exp { private String var; private Exp exp; public Set(String _var,Exp _exp) { var=_var;exp=_exp; } public Value eval(Env env) { Vector v = env.apply(var); if (v==null) throw new EvalException("variable "+var+" undefined"); v.setElementAt(exp.eval(env),0); return new VoidValue(); } }- School is coming.