diff options
author | Camil Staps | 2016-03-30 10:54:45 +0200 |
---|---|---|
committer | Camil Staps | 2016-03-30 11:25:31 +0200 |
commit | 25681f822f4a965ca38efa47eed9927b0edc75c7 (patch) | |
tree | 3d7b1bd603f83f5a5f4faff85939dd397beb67c2 | |
parent | Readme: features, headings (diff) |
Overloaded state, more boolean ops, unaliased Var
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.md | 27 | ||||
-rw-r--r-- | While.dcl | 25 | ||||
-rw-r--r-- | While.icl | 107 | ||||
-rw-r--r-- | WhileVars.dcl | 11 | ||||
-rw-r--r-- | WhileVars.icl | 2 | ||||
-rw-r--r-- | test.icl | 23 |
7 files changed, 128 insertions, 71 deletions
@@ -1,7 +1,7 @@ CLM=clm -CLMFLAGS=-b -nt +CLMFLAGS=-nt TEST=test -DEPS=While.dcl While.icl +DEPS=While.dcl While.icl WhileVars.dcl WhileVars.icl all: $(TEST) @@ -17,23 +17,26 @@ For example, the [following program][sqrt] is a rounded down square root function (if `x=n` at the start and `n` is a natural number, then `z` is the square root of `n`, rounded down, after execution): + import While + from WhileVars import o, s, x, z // o :== Var 'o'; etc. + sqrt :: Stm - sqrt = 'z' := 0 :. - 'o' := 1 :. - 's' := 1 :. - While ('s' <= 'x') - ( 'z' := 'z' + 1 :. - 'o' := 'o' + 2 :. - 's' := 's' + 'o' ) + sqrt = z := 0 :. + o := 1 :. + s := 1 :. + While (s <= x) + ( z := z + 1 :. + o := o + 2 :. + s := s + o ) ### Evaluation -We can now execute this code on a `State`, which maps `Var` (`Char`) to `Int`: +We can now execute this code on a `State`, which maps `Var` to `Int`: Start :: Int - Start = eval NS sqrt st 'z' + Start = eval NS sqrt st z where - st :: Var -> Int - st 'x' = 36 + st :: Char -> Int // Or: st :: Var -> Int // st :: CharState + st 'x' = 9 // st (Var 'x') = 9 // st = \'x' -> 9 `eval NS sqrt st` is a `State` itself (the state that results from execution of `sqrt` in `st`), so we apply that to `z` to get the result. Other than the @@ -135,8 +138,6 @@ qualified imports where needed. ## Todo - Gast testing - - More boolean operators for testing integers besides `==` and `<=` - - Can boolean operators be made functions rather than type constructors? - Prettyprint for `DerivTree` - Parser - Add the state to the `toString` of `DerivTree` and `DerivSeq` @@ -5,9 +5,8 @@ from StdOverloaded import class toString :: Semantics = NS // Natural Semantics | SOS // Structural Operational Semantics -// evaluate @arg2 in state @arg3 according to @arg1 -class eval a b :: Semantics a State -> b - +// evaluate @2 in state @3 according to @1 +class eval a b :: Semantics a st -> b | toState st instance eval Stm State instance eval Int Int instance eval Var Int @@ -15,9 +14,14 @@ instance eval ArithExpr Int instance eval Bool Bool instance eval BoolExpr Bool +class toState a :: a -> State +instance toState State +instance toState CharState + instance toString ArithExpr instance toString BoolExpr instance toString Stm +instance toString Var instance toString DerivTree instance toString DerivSeq @@ -32,7 +36,7 @@ instance toString DerivSeq | E.a: While a Stm // While & eval a Bool & toString a -:: Var :== Char // Variable +:: Var = Var Char // Variable :: ArithExpr = E.a b: (+) infixl 6 a b // Addition & eval a Int & toString a & eval b Int & toString b @@ -45,12 +49,21 @@ instance toString DerivSeq & eval a Int & toString a & eval b Int & toString b | E.a b: (<=) infix 4 a b // Ord & eval a Int & toString a & eval b Int & toString b + | E.a b: (>=) infix 4 a b + & eval a Int & toString a & eval b Int & toString b + | E.a b: (<) infix 4 a b + & eval a Int & toString a & eval b Int & toString b + | E.a b: (>) infix 4 a b + & eval a Int & toString a & eval b Int & toString b | E.a: ~ a // Negation & eval a Bool & toString a + | E.a b: (\/) infixr 4 a b // Disjunction + & eval a Bool & toString a & eval b Bool & toString b | E.a b: (/\) infixr 3 a b // Conjunction & eval a Bool & toString a & eval b Bool & toString b :: State :== Var -> Int +:: CharState :== Char -> Int // Natural Semantics @@ -60,7 +73,7 @@ instance toString DerivSeq , result :: State } -tree :: Stm State -> DerivTree // The derivation tree for @arg1 in state @arg2 +tree :: Stm st -> DerivTree | toState st // The deriv. tree for @1 in state @2 // Structural Operational Semantics @@ -69,5 +82,5 @@ tree :: Stm State -> DerivTree // The derivation tree for @arg1 in state @arg2 :: DerivSeq :== [DerivSeqNode] -seq :: Stm State -> DerivSeq // The derivation seq. for @arg1 in state @arg2 +seq :: Stm st -> DerivSeq | toState st // The deriv. seq. for @1 in state @2 @@ -4,14 +4,14 @@ from StdBool import not, &&, || from StdList import hd, last, map, take from StdMisc import abort from StdOverloaded import class +++(..), class toString(..) -from StdString import instance +++ {#Char}, +from StdString import instance +++ {#Char}, instance toString {#Char}, instance toString Int, instance toString Bool, instance toString Char import _SystemArray // Evaluation utilities instance eval Int Int where eval _ i _ = i -instance eval Var Int where eval _ v st = st v +instance eval Var Int where eval _ v st = (toState st) v instance eval ArithExpr Int where eval m (a1 + a2) st = addI (eval m a1 st) (eval m a2 st) @@ -23,28 +23,36 @@ instance eval BoolExpr Bool where eval m (a1 == a2) st = eqI (eval m a1 st) (eval m a2 st) eval m (a1 <= a2) st = ltI (eval m a1 st) (eval m a2 st) - || eqI (eval m a1 st) (eval m a2 st) - eval m (~ b) st = not (eval m b st) + || eqI (eval m a1 st) (eval m a2 st) + eval m (a1 >= a2) st = eval m (a2 <= a1) st + eval m (a1 < a2) st = ltI (eval m a1 st) (eval m a2 st) + eval m (a1 > a2) st = eval m (a2 < a1) st + eval m (~ b) st = not (eval m b st) eval m (b1 /\ b2) st = eval m b1 st && eval m b2 st + eval m (b1 \/ b2) st = eval m b1 st || eval m b2 st instance eval Stm State where - eval SOS stm st = let (Done st`) = last (seq stm st) in st` - eval NS stm st = (tree stm st).result + eval SOS stm st = let (Done st`) = last (seq stm (toState st)) in st` + eval NS stm st = (tree stm (toState st)).result // Natural Semantics -tree :: Stm State -> DerivTree -tree stm=:Skip st = dTree stm st [] st -tree stm=:(v:=a) st = dTree stm st [] (\w->if (eqC v w) (eval NS a st) (st w)) -tree stm=:(s1 :. s2) st = dTree stm st [t1,t2] t2.result -where t1 = tree s1 st; t2 = tree s2 t1.result -tree stm=:(If b s1 s2) st = dTree stm st [t] t.result -where t = tree (if (eval NS b st) s1 s2) st -tree stm=:(While b s) st -| eval NS b st = dTree stm st [t1,t2] t2.result -| otherwise = dTree stm st [] st -where t1 = tree s st; t2 = tree stm t1.result +tree :: Stm st -> DerivTree | toState st +tree stm stv = tree` stm (toState stv) +where + tree` :: Stm State -> DerivTree + tree` stm=:Skip st = dTree stm st [] st + tree` stm=:(v:=a) st + = let e = eval NS a st in dTree stm st [] (\w->if (eqV v w) e (st w)) + tree` stm=:(s1 :. s2) st = dTree stm st [t1,t2] t2.result + where t1 = tree` s1 st; t2 = tree` s2 t1.result + tree` stm=:(If b s1 s2) st = dTree stm st [t] t.result + where t = tree` (if (eval NS b st) s1 s2) st + tree` stm=:(While b s) st + | eval NS b st = dTree stm st [t1,t2] t2.result + | otherwise = dTree stm st [] st + where t1 = tree` s st; t2 = tree` stm t1.result // Records are too much typing dTree :: Stm State [DerivTree] State -> DerivTree @@ -52,54 +60,70 @@ dTree stm st ts r = {stm=stm, state=st, children=ts, result=r} // Structural Operational Semantics -seq :: Stm State -> DerivSeq -seq stm st = case step stm st of (Done st`) = [NDone stm st, Done st`] - (NDone stm` st`) = [NDone stm st:seq stm` st`] +seq :: Stm st -> DerivSeq | toState st +seq stm stv = let st = toState stv in case step stm st of + (Done st`) = [NDone stm st, Done st`] + (NDone stm` st`) = [NDone stm st:seq stm` st`] where step :: Stm State -> DerivSeqNode step Skip st = Done st - step (v := a) st = Done (\w->if (eqC v w) (eval SOS a st) (st w)) + step (v:=a) st = let e = eval SOS a st in Done (\w->if (eqV v w) e (st w)) step (s1 :. s2) st = case step s1 st of seqe=:(NDone s1` st`) = NDone (s1` :. s2) st` (Done st`) = NDone s2 st` step (If b s1 s2) st = NDone (if (eval SOS b st) s1 s2) st step stm=:(While b s) st = NDone (If b (s:.stm) Skip) st +// State utilities + +instance toState State where toState st = st +instance toState CharState where toState cst = \(Var v) -> cst v +instance toState (Var -> Int) where toState st = st + // String utilities +(<+) infixr 5 :: a b -> String | toString a & toString b +(<+) a b = toString a +++ toString b + instance toString ArithExpr where - toString (a1 + a2) = toString a1 +++ "+" +++ toString a2 - toString (a1 - a2) = toString a1 +++ "-" +++ toString a2 - toString (a1 * a2) = toString a1 +++ "*" +++ toString a2 + toString (a1 + a2) = a1 <+ "+" <+ a2 + toString (a1 - a2) = a1 <+ "-" <+ a2 + toString (a1 * a2) = a1 <+ "*" <+ a2 instance toString BoolExpr where - toString (a1 == a2) = toString a1 +++ "=" +++ toString a2 - toString (a1 <= a2) = toString a1 +++ "<=" +++ toString a2 - toString (~ b) = "~" +++ toString b - toString (b1 /\ b2) = toString b1 +++ "/\\" +++ toString b2 + toString (a1 == a2) = a1 <+ "=" <+ a2 + toString (a1 <= a2) = a1 <+ "<=" <+ a2 + toString (a1 >= a2) = a1 <+ ">=" <+ a2 + toString (a1 < a2) = a1 <+ "<" <+ a2 + toString (a1 > a2) = a1 <+ ">" <+ a2 + toString (~ b) = "~" <+ toString b + toString (b1 /\ b2) = b1 <+ "/\\" <+ b2 + toString (b1 \/ b2) = b1 <+ "\\/" <+ b2 instance toString Stm where toString Skip = "skip" - toString (s1 :. s2) = toString s1 +++ "; " +++ toString s2 - toString (v := a) = {v} +++ ":=" +++ toString a - toString (If b s1 s2) = "if " +++ toString b +++ " then " +++ toString s1 +++ " else " +++ toString s2 - toString (While b s) = "while " +++ toString b +++ " do " +++ toString s +++ " done" + toString (s1 :. s2) = s1 <+ "; " <+ s2 + toString (v := a) = v <+ ":=" <+ a + toString (If b s1 s2) = "if " <+ b <+ " then " <+ s1 <+ " else " <+ s2 + toString (While b s) = "while " <+ b <+ " do " <+ s <+ " done" + +instance toString Var where toString (Var v) = {v} instance toString DerivTree where toString t = toS 0 t where toS :: Int DerivTree -> String - toS i {stm,children=[]} = pad i +++ toString stm +++ "\n" - toS i {stm,children} = pad i +++ "(" +++ toString stm +++ "\n" +++ - concat (map (toS (addI i 1)) children) +++ pad i +++ ")\n" + toS i {stm,children=[]} = pad i <+ stm <+ "\n" + toS i {stm,children} = pad i <+ "(" <+ stm <+ "\n" <+ + concat (map (toS (addI i 1)) children) <+ pad i <+ ")\n" - concat :: [String] -> String + concat :: [a] -> String | toString a concat [] = "" - concat [s:ss] = s +++ concat ss + concat [s:ss] = s <+ concat ss pad :: Int -> String pad 0 = "" @@ -107,11 +131,11 @@ where instance toString DerivSeq where - toString seq = join "\n" (map toString [stm \\ (NDone stm _) <- seq]) + toString seq = join "\n" [stm \\ (NDone stm _) <- seq] where - join :: String [String] -> String + join :: a [b] -> String | toString a & toString b join _ [] = "" - join g [s:ss] = s +++ g +++ join g ss + join g [s:ss] = s <+ g <+ join g ss // Low end addI :: !Int !Int -> Int @@ -144,3 +168,6 @@ eqC a b = code inline { eqC } +eqV :: !Var !Var -> Bool +eqV (Var a) (Var b) = eqC a b + diff --git a/WhileVars.dcl b/WhileVars.dcl new file mode 100644 index 0000000..4db8197 --- /dev/null +++ b/WhileVars.dcl @@ -0,0 +1,11 @@ +definition module WhileVars + +from While import ::Var(..) + +a :== Var 'a'; b :== Var 'b'; c :== Var 'c'; d :== Var 'd'; e :== Var 'e' +f :== Var 'f'; g :== Var 'g'; h :== Var 'h'; i :== Var 'i'; j :== Var 'j' +k :== Var 'k'; l :== Var 'l'; m :== Var 'm'; n :== Var 'n'; o :== Var 'o' +p :== Var 'p'; q :== Var 'q'; r :== Var 'r'; s :== Var 's'; t :== Var 't' +u :== Var 'u'; v :== Var 'v'; w :== Var 'w'; x :== Var 'x'; y :== Var 'y' +z :== Var 'z' + diff --git a/WhileVars.icl b/WhileVars.icl new file mode 100644 index 0000000..1540a10 --- /dev/null +++ b/WhileVars.icl @@ -0,0 +1,2 @@ +implementation module WhileVars + @@ -1,6 +1,7 @@ module test import While +from WhileVars import o, s, x, z from StdMisc import abort from StdOverloaded import class +++(..), class toString(..) @@ -12,18 +13,20 @@ import _SystemArray // The rounded down square root function: // { x=n /\ n >= 0 } sqrt { z^2 <= n /\ (z+1)^2 > n } sqrt :: Stm -sqrt = 'z' := 0 :. - 'o' := 1 :. - 's' := 1 :. - While ('s' <= 'x') - ( 'z' := 'z' + 1 :. - 'o' := 'o' + 2 :. - 's' := 's' + 'o' ) +sqrt = z := 0 :. + o := 1 :. + s := 1 :. + While (s <= x) + ( z := z + 1 :. + o := o + 2 :. + s := s + o ) -//Start = toString (seq sqrt st) -Start = toString (tree sqrt st) +Start :: Int // Value of z after execution of sqrt in st +Start = eval NS sqrt st z +//Start = toString (seq sqrt st) // Derivation sequence of sqrt in st +//Start = toString (tree sqrt st) // Derivation tree of sqrt in st where - st :: Var -> Int + st :: Char -> Int st 'x' = 9 |