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.