mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| module monadicSemantics
 | |
| 
 | |
| import StdEnv, StdGeneric, GenMap, GenHylo
 | |
| 
 | |
| /* For fun I implemented the recursive datastructre Exp and Stm as fixpoints
 | |
|    This helps us define recursive functions on them (only a little bit though)
 | |
|    However deriving gMap for Fix did not works out of the box
 | |
|    I had to remove some uniqueness typing in GenMap and GenHylo */
 | |
| :: Op      = Plus | Minus | Times | Rem | Equal | LessThan
 | |
| :: Var     :== String
 | |
| 
 | |
| :: ExpP a  = Int Int | Var Var | Op Op a a
 | |
| :: Exp     :== Fix ExpP
 | |
| 
 | |
| :: StmP a  = Assign Var Exp | If Exp a a | While Exp a | Seq a a | Cont
 | |
| :: Stm     :== Fix StmP
 | |
| 
 | |
| derive gMap ExpP, StmP, Fix
 | |
| 
 | |
| // Environment. Semantics is basically Env -> Env
 | |
| :: Env :== Var -> Int
 | |
| :: Sem :== Env -> (Int, Env)
 | |
| empty = \v . 0
 | |
| 
 | |
| // return
 | |
| rtn :: Int -> Sem
 | |
| rtn i = \e. (i, e)
 | |
| 
 | |
| // the usual bind
 | |
| (>>=) infixl 1 :: Sem (Int->Sem) -> Sem
 | |
| (>>=) x y = \e. (\(i,e2).y i e2) (x e)
 | |
| (>>|) infixl 1 :: Sem Sem -> Sem
 | |
| (>>|) x y = x >>= \_. y
 | |
| 
 | |
| // read variable from environment
 | |
| read :: Var -> Sem
 | |
| read v = \e. (e v, e)
 | |
| 
 | |
| // assign value to give variable in environment
 | |
| write :: Var Int -> Sem
 | |
| write v i = \e. (i, \w. if (w==v) i (e w))
 | |
| 
 | |
| // semantics
 | |
| class sem a :: a -> Sem
 | |
| 
 | |
| operator :: Op -> Int -> Int -> Int
 | |
| operator Plus     = (+)
 | |
| operator Minus    = (-)
 | |
| operator Times    = (*)
 | |
| operator Rem      = rem
 | |
| operator Equal    = \x y . if (x==y) 1 0
 | |
| operator LessThan = \x y . if (x< y)  1 0
 | |
| 
 | |
| // semantics of expressions
 | |
| instance sem Exp where
 | |
| 	sem x = cata phi x where
 | |
| 		phi (Int n)     = rtn n
 | |
| 		phi (Var v)     = read v
 | |
| 		phi (Op op x y) = x >>= \v1. y >>= return o (operator op v1)
 | |
| 
 | |
| // semantics of statments
 | |
| // NOTE: while will always return 0, as it might not even be executed
 | |
| instance sem Stm where
 | |
| 	sem x = cata phi x where
 | |
| 		phi (Assign v e)     = sem e >>= write v
 | |
| 		phi (If e s1 s2)     = sem e >>= \b . if (b<>0) s1 s2
 | |
| 		phi stm=:(While e s) = sem e >>= \b . if (b<>0) (s >>| phi stm) (phi Cont)
 | |
| 		phi (Seq s1 s2)      = s1 >>| s2    // Here the cata *finally* pays off :D
 | |
| 		phi Cont             = rtn 0
 | |
| 
 | |
| // convenience functions
 | |
| int    = In o Int
 | |
| var    = In o Var
 | |
| op o   = In o2 (Op o)
 | |
| assign = In o2 Assign
 | |
| ifte e = In o2 (If e)
 | |
| while  = In o2 While
 | |
| seq    = In o2 Seq
 | |
| cont   = In Cont
 | |
| 
 | |
| // test case, also testing the new operator <
 | |
| pEuclides =
 | |
| 	while (op LessThan (int 0) (var "b"))(
 | |
| 		seq (assign "r" (op Rem (var "a") (var "b")))
 | |
| 		(seq (assign "a" (var "b"))
 | |
| 		( (assign "b" (var "r")))
 | |
| 		)
 | |
| 	)
 | |
| 
 | |
| Start = fst (program start) where
 | |
| 	program = sem pEuclides >>| read "a"
 | |
| 	start "a" = 9
 | |
| 	start "b" = 12
 | |
| 	start _ = 0
 | |
| 
 | |
| // Helper
 | |
| (o2) infixr 9
 | |
| (o2) f g x :== f o (g x)
 | |
| 
 |