try/catch
and throw
to SIMPLE
try/catch
and throw
Program | ::= |
Definition … Expression | a-program (defns exp1) |
Definition | ::= |
define Identifier = (
Identifier … ) Expression |
proc-definition (id bvars body) |
Expression | ::= |
Number | const-exp (num) |
::= |
Identifier | var-exp (var) |
|
::= |
Binop( Expression
, Expression) |
binop-exp (op exp1 exp2) |
|
::= |
if Expression
then Expression
else Expression |
if-exp (exp1 exp2 exp3) |
|
::= |
( Expression
Expression …
) |
call-exp (rator rands) |
|
::= |
try/catch Expression |
try-exp (exp1) |
|
::= |
throw Expression |
throw-exp (exp1) |
|
Binop | ::= |
+ |
op-plus () |
::= |
- |
op-minus () |
|
::= |
* |
op-times () |
|
::= |
< |
op-less() |
|
::= |
= |
op-equal () |
|
::= |
> |
op-greater () |
The following program computes the product of the first 20 primes.
define product = proc (f i j) if <(i,j) then *((f i),(product f +(i,1) j)) else 1 define prime = proc (i) if <(i,2) then +(i,2) else (primesearch +(2,(prime -(i,1)))) define primesearch = proc (n) if (primetest n) then n else (primesearch +(n,2)) define primetest = proc (n) if (divides 2 n) then false else (primetests 3 n) define primetests = proc (d n) if >(*(d,d),n) then true else if (divides d n) then false else (primetests +(d,2) n) define divides = proc (d n) (dividesloop 1 d n) define dividesloop = proc (q d n) if =(*(q,d),n) then true else if >(*(q,d),n) then false else (dividesloop +(q,1) d n) (product prime 0 20)
The following program computes the product of a million numbers, all but one of which are non-zero and take a very long time to compute. One of the very first numbers is zero, however. Wouldn't it be nice to return zero as soon as you see that one of the factors is zero?
define product = proc (f i j) if <(i,j) then (product2 f i j (f i)) else 1 define product2 = proc (f i j fi) if =(fi,0) then throw 0 else *(fi,(product f +(i,1) j)) define prime = proc (i) if <(i,2) then +(i,2) else (primesearch +(2,(prime -(i,1)))) define primesearch = proc (n) if (primetest n) then n else (primesearch +(n,2)) define primetest = proc (n) if (divides 2 n) then false else (primetests 3 n) define primetests = proc (d n) if >(*(d,d),n) then true else if (divides d n) then false else (primetests +(d,2) n) define divides = proc (d n) (dividesloop 1 d n) define dividesloop = proc (q d n) if =(*(q,d),n) then true else if >(*(q,d),n) then false else (dividesloop +(q,1) d n) define g = proc (i) if =(i,15) then 0 else (prime i) try/catch (product g 0 1000000)
We implement try/catch
and throw
by adding a second continuation to
value-of
.
choose
Expressions
Program | ::= |
Definition … Expression | a-program (defns exp1) |
Definition | ::= |
define Identifier = (
Identifier … ) Expression |
proc-definition (id bvars body) |
Expression | ::= |
Number | const-exp (num) |
::= |
Identifier | var-exp (var) |
|
::= |
Binop( Expression
, Expression) |
binop-exp (op exp1 exp2) |
|
::= |
if Expression
then Expression
else Expression |
if-exp (exp1 exp2 exp3) |
|
::= |
( Expression
Expression …
) |
call-exp (rator rands) |
|
::= |
choose ( Expression
, Expression) |
choose-exp (exp1 exp2) |
|
Binop | ::= |
+ |
op-plus () |
::= |
- |
op-minus () |
|
::= |
* |
op-times () |
|
::= |
< |
op-less() |
|
::= |
= |
op-equal () |
|
::= |
> |
op-greater () |
A choose
expression nondeterministically chooses
between the results of two expressions.
As we have implemented it, a choose
expression
always chooses a terminating computation over a non-terminating
computation:
choose (11,11) define loop = proc (n) if =(n,0) then 55 else (loop +(n,1)) choose ((loop -1), (loop 1)) define loop = proc (n) if =(n,0) then 55 else (loop +(n,1)) choose ((loop 1), (loop -1))
We implement this semantics by evaluating each expression in a separate thread:
This gives us the ability to express large-grained speculative parallelism:
define fail = proc () (fail) define primesearch = proc (n) choose (if (primetest n) then n else (fail), (primesearch +(n,1))) define primetest = proc (n) if (divides 2 n) then false else (primetests 3 n) define primetests = proc (d n) if >(*(d,d),n) then true else if (divides d n) then false else (primetests +(d,2) n) define divides = proc (d n) (dividesloop 1 d n) define dividesloop = proc (q d n) if =(*(q,d),n) then true else if >(*(q,d),n) then false else (dividesloop +(q,1) d n) (primesearch 8)
Somewhat surprisingly, our semantics is globally angelic:
define fail = proc () (fail) define primesearch = proc (n) choose (if (primetest n) then n else (fail), (primesearch +(n,1))) define primetest = proc (n) if (divides 2 n) then false else (primetests 3 n) define primetests = proc (d n) if >(*(d,d),n) then true else if (divides d n) then false else (primetests +(d,2) n) define divides = proc (d n) (dividesloop 1 d n) define dividesloop = proc (q d n) if =(*(q,d),n) then true else if >(*(q,d),n) then false else (dividesloop +(q,1) d n) define different = proc (n except) (different2 n except (primesearch n)) define different2 = proc (n except candidate) if =(except, candidate) then (fail) else candidate (different 8 11)
cut
and fail
choose
,
choose/cut
, and fail
Program | ::= |
Definition … Expression | a-program (defns exp1) |
Definition | ::= |
define Identifier = (
Identifier … ) Expression |
proc-definition (id bvars body) |
Expression | ::= |
Number | const-exp (num) |
::= |
Identifier | var-exp (var) |
|
::= |
Binop( Expression
, Expression) |
binop-exp (op exp1 exp2) |
|
::= |
if Expression
then Expression
else Expression |
if-exp (exp1 exp2 exp3) |
|
::= |
( Expression
Expression …
) |
call-exp (rator rands) |
|
::= |
choose ( Expression
, Expression) |
choose-exp (exp1 exp2) |
|
::= |
choose/cut ( Expression
, Expression) |
choose/cut-exp (exp1 exp2) |
|
::= |
fail |
fail-exp () |
|
Binop | ::= |
+ |
op-plus () |
::= |
- |
op-minus () |
|
::= |
* |
op-times () |
|
::= |
< |
op-less() |
|
::= |
= |
op-equal () |
|
::= |
> |
op-greater () |
define primesearch = proc (n) choose/cut (if (primetest n) then n else fail, (primesearch +(n,1))) define primetest = proc (n) if (divides 2 n) then false else (primetests 3 n) define primetests = proc (d n) if >(*(d,d),n) then true else if (divides d n) then false else (primetests +(d,2) n) define divides = proc (d n) (dividesloop 1 d n) define dividesloop = proc (q d n) if =(*(q,d),n) then true else if >(*(q,d),n) then false else (dividesloop +(q,1) d n) define different = proc (n except) (different2 n except (primesearch n)) define different2 = proc (n except candidate) if =(except, candidate) then fail else candidate (different 8 11)
We implement this semantics with some careful attention to how threads are killed:
Last updated 31 March 2008.