Interpreter for SIMPLE


Continuation-passing Interpreter for SIMPLE


Another Continuation-passing Interpreter for SIMPLE


Adding try/catch and throw to SIMPLE

Syntax for the SIMPLE language with try/catch and throw

Program ::= DefinitionExpression 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.


Globally Angelic Choice

Syntax for the SIMPLE language with choose Expressions

Program ::= DefinitionExpression 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)

Restricting Angelicism with cut and fail

Syntax for the SIMPLE language with choose, choose/cut, and fail

Program ::= DefinitionExpression 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.

Valid XHTML 1.0!