module skeleton11 //Mart Lubbers s4109503 //Charlie Gerhardus s3050009 import StdEnv :: Prog :== [Instr] :: Instr = Write Expr | Atomic [Instr] :: Expr = Int Int | Plus Expr Expr | Times Expr Expr | Read possibleResults :: [Prog] -> [Int] possibleResults x = produce x 0 produce :: [Prog] Int -> [Int] produce x i | all (isEmpty) x = [i] = flatten [produce (updateAt idx ys x) (eval y i)\\(idx, [y:ys])<-zip2 [0..] x] eval :: Instr Int -> Int eval (Write (Int i)) s = i eval (Write (Plus e1 e2)) s = eval (Write e1) s + eval (Write e2) s eval (Write (Times e1 e2)) s = eval (Write e1) s * eval (Write e2) s eval (Write Read) s = s eval (Atomic x) s = hd (produce [x] s) prog0 = [Write (Int 12), Write (Plus Read (Int 1))] prog1 = [Write (Times Read (Int 2))] test0 = [prog0] test1 = [prog0, prog1] Start = 0 /* Writing the semantics in clean is advantageous because you can execute the * code, have it type checked and it is very readable for a programmer. * * Disadvantages might be that it might be harder to prove stuff. Also * mathematic notation is generally more concise. * * Some things are modelled very difficultly in a functional language. For * example file io, parallel processes or user interaction. */