/exercise1/exercise1.lhs

http://sauce-code.googlecode.com/ · Haskell · 1133 lines · 786 code · 90 blank · 257 comment · 170 complexity · e9c759ede1181a1f5fcc222e4334c667 MD5 · raw file

  1. \documentclass[11pt]{article}
  2. %% Literate Haskell script intended for lhs2TeX.
  3. %include polycode.fmt
  4. %format `union` = "\cup"
  5. %format alpha = "\alpha"
  6. %format gamma "\gamma"
  7. %format capGamma = "\Gamma"
  8. %format tau = "\tau"
  9. %format tau1 = "\tau_{1}"
  10. %format tau2 = "\tau_{2}"
  11. %format t1 = "t_{1}"
  12. %format t2 = "t_{2}"
  13. %format t3 = "t_{3}"
  14. \usepackage{fullpage}
  15. \usepackage{verbatim}
  16. \usepackage{mathpazo}
  17. \usepackage{graphicx}
  18. \usepackage{color}
  19. \usepackage[centertags]{amsmath}
  20. \usepackage{amsfonts}
  21. \usepackage{amsthm}
  22. \usepackage{soul}
  23. \usepackage{listings}
  24. \usepackage{stmaryrd}
  25. \title{Exercise 1, CS 555}
  26. \author{\textbf{By:} Sauce Code Team (Dandan Mo, Qi Lu, Yiming Yang)}
  27. \date{\textbf{Due:} February 27th, 2012}
  28. \begin{document}
  29. \maketitle
  30. \thispagestyle{empty}
  31. \newpage
  32. \section{Concrete Lambda Language}
  33. We start the project with a small core lambda language, consisting of the lambda calculus with booleans
  34. and integers.
  35. Here is the concrete syntax in BNF:
  36. \begin{verbatim}
  37. Type --> arr lpar Type comma Type rpar
  38. | Bool_keyword
  39. | Int_keyword
  40. Term --> identifier
  41. | abs_keyword lpar identifier colon Type fullstop Term rpar
  42. | app_keyword lpar Term comma Term rpar
  43. | true_keyword
  44. | false_keyword
  45. | if_keyword Term then_keyword Term else_keyword Term fi_keyword
  46. | inliteral
  47. | plus lpar Term comma Term rpar
  48. | minus lpar Term comma Term rpar
  49. | div lpar Term comma Term rpar
  50. | nand lpar Term comma Term rpar
  51. | equal lpar Term comma Term rpar
  52. | lt lpar Term comma Term rpar
  53. | lpar Term rpar
  54. \end{verbatim}
  55. Here are the terminal symbols used in the grammar above:
  56. \newpage
  57. \begin{verbatim}
  58. arrow ->
  59. lpar (
  60. comma ,
  61. rpar )
  62. Bool_keyword Bool
  63. Int_keyword Int
  64. identifier an identifier, as in Haskell
  65. abs_keyword abs
  66. colon :
  67. fullstop .
  68. app_keyword app
  69. true_keyword true
  70. false_keyword false
  71. if_keyword if
  72. then_keyword then
  73. else_keyword else
  74. fi_keyword fi
  75. inliteral a non-negative decimal numeral
  76. plus +
  77. minus -
  78. mul *
  79. div /
  80. nand ^
  81. equal =
  82. lt <
  83. \end{verbatim}
  84. White space, such as space, tab, and newline characters, is permitted between tokens. White space is
  85. required between adjacent keyword tokens.
  86. Here are some example programs:
  87. \\ \\
  88. app (abs (x: Int . 1234), 10)
  89. -------------------------------------------------------------------------\\
  90. if true then true else false fi
  91. -------------------------------------------------------------------------\\
  92. if =(0,0) then 8 else 9 fi
  93. -------------------------------------------------------------------------\\
  94. /(4294967295,76)
  95. -------------------------------------------------------------------------\\
  96. \section{Lexer and Parser}
  97. 1):Lexer takes input string, returns a list of tokens. We define a data structure called Token as the followings,together with the show functions:\\
  98. \begin{code}
  99. data Token = ARROW
  100. | LPAR
  101. | COMMA
  102. | RPAR
  103. | BOOL
  104. | INT
  105. | ABS
  106. | COLON
  107. | FULLSTOP
  108. | APP
  109. | TRUE
  110. | FALSE
  111. | IF
  112. | THEN
  113. | ELSE
  114. | FI
  115. | PLUS
  116. | SUB
  117. | MUL
  118. | DIV
  119. | NAND
  120. | EQUAL
  121. | LT_keyword
  122. | ID String
  123. | NUM String
  124. deriving Eq
  125. instance Show Token where
  126. show ARROW = "->"
  127. show LPAR = "("
  128. show COMMA = ","
  129. show RPAR = ")"
  130. show BOOL = "Bool"
  131. show INT = "Int"
  132. show ABS = "abs"
  133. show COLON = ":"
  134. show FULLSTOP = "."
  135. show APP = "app"
  136. show TRUE = "true"
  137. show FALSE = "false"
  138. show IF = "if"
  139. show THEN = "then"
  140. show ELSE = "else"
  141. show FI = "fi"
  142. show PLUS = "+"
  143. show SUB = "-"
  144. show MUL = "*"
  145. show DIV = "/"
  146. show NAND = "^"
  147. show EQUAL = "="
  148. show LT_keyword = "<"
  149. show (ID id) = id
  150. show (NUM num) = num
  151. \end{code}
  152. For the Token identifier and decimal number, we use regular expression to recognize them, so we have two corresponding subscan function to deal with them.\\
  153. \begin{code}
  154. --reguar expresiion
  155. ex_num = mkRegex "(0|[1-9][0-9]*)"
  156. ex_id = mkRegex "([a-zA-Z][a-zA-Z0-9_]*)"
  157. --subscan for id
  158. subscan1 :: String -> Maybe ([Token],String)
  159. subscan1 str = case (matchRegexAll ex_id str) of
  160. Just (a1,a2,a3,a4) -> case a1 of
  161. "" -> Just ([ID a2],a3)
  162. _ -> Nothing
  163. Nothing -> Nothing
  164. --subscan for num
  165. subscan2 :: String -> Maybe ([Token],String)
  166. subscan2 str = case (matchRegexAll ex_num str) of
  167. Just (a1,a2,a3,a4) -> case a1 of
  168. "" -> Just ([NUM a2],a3)
  169. _ -> Nothing
  170. Nothing -> Nothing
  171. \end{code}
  172. Function scan takes an input string and returns a list tokens. If unexpected symbols exists,or the input string cannot mactch any defined token, the function reports errors and the program stops at the lexer level.\\
  173. \begin{code}
  174. --lexer
  175. scan :: String -> [Token]
  176. scan "" = []
  177. ----white spase
  178. scan (' ':xs) = scan xs
  179. scan ('\t':xs) = scan xs
  180. scan ('\n':xs) = scan xs
  181. ----keyword
  182. scan (':':xs) = [COLON] ++ scan xs
  183. scan ('-':'>':xs) = [ARROW] ++ scan xs
  184. scan ('(':xs) = [LPAR] ++ scan xs
  185. scan (',':xs) = [COMMA] ++ scan xs
  186. scan (')':xs) = [RPAR] ++ scan xs
  187. scan ('B':'o':'o':'l':xs) = [BOOL] ++ scan xs
  188. scan ('I':'n':'t':xs) = [INT] ++ scan xs
  189. scan ('a':'b':'s':xs) = [ABS] ++ scan xs
  190. scan ('a':'p':'p':xs) = [APP] ++ scan xs
  191. scan ('.':xs) = [FULLSTOP] ++ scan xs
  192. scan ('t':'r':'u':'e':xs) = [TRUE] ++ scan xs
  193. scan ('f':'a':'l':'s':'e':xs) = [FALSE] ++ scan xs
  194. scan ('i':'f':xs) = [IF] ++ scan xs
  195. scan ('t':'h':'e':'n':xs) = [THEN] ++ scan xs
  196. scan ('e':'l':'s':'e':xs) = [ELSE] ++ scan xs
  197. scan ('f':'i':xs) = [FI] ++ scan xs
  198. scan ('+':xs) = [PLUS] ++ scan xs
  199. scan ('-':xs) = [SUB] ++ scan xs
  200. scan ('*':xs) = [MUL] ++ scan xs
  201. scan ('/':xs) = [DIV] ++ scan xs
  202. scan ('^':xs) = [NAND] ++ scan xs
  203. scan ('=':xs) = [EQUAL] ++ scan xs
  204. scan ('<':xs) = [LT_keyword] ++ scan xs
  205. ----id and num
  206. scan str = case subscan1 str of
  207. Nothing -> case subscan2 str of
  208. Nothing -> error "[Scan]err: unexpected symbols!"
  209. Just (tok,xs) -> tok ++ scan xs
  210. Just (tok,xs) -> tok ++ scan xs
  211. str str = error "[Scan]err: unexpected symbols!"
  212. \end{code}
  213. 2):Parser takes a list of tokens, returns a term. We define the two data structures Type and Term, and two functions parseType and parseTerm to deal with them.\\
  214. parseType function returns a matched Type and the remaining tokens, parseTerm function returns a matched Term and the remaining tokens.\\
  215. Data structure:\\
  216. \begin{code}
  217. data Type = TypeArrow Type Type
  218. | TypeBool
  219. | TypeInt
  220. deriving Eq
  221. instance Show Type where
  222. show (TypeArrow tau1 tau2) = "->(" ++ show tau1 ++ "," ++ show tau2 ++ ")"
  223. show TypeBool = "Bool"
  224. show TypeInt = "Int"
  225. type Var = String
  226. data Term = Var Var
  227. | Abs Var Type Term
  228. | App Term Term
  229. | Tru
  230. | Fls
  231. | If Term Term Term
  232. | IntConst Integer
  233. | IntAdd Term Term
  234. | IntSub Term Term
  235. | IntMul Term Term
  236. | IntDiv Term Term
  237. | IntNand Term Term
  238. | IntEq Term Term
  239. | IntLt Term Term
  240. deriving Eq
  241. instance Show Term where
  242. show (Var x) = x
  243. show (Abs x tau t) = "abs(" ++ x ++ ":" ++ show tau ++ "." ++ show t ++ ")"
  244. show (App t1 t2) = "app(" ++ show t1 ++ "," ++ show t2 ++ ")"
  245. show Tru = "true"
  246. show Fls = "false"
  247. show (If t1 t2 t3) = "if " ++ show t1 ++ " then " ++ show t2 ++ " else " ++ show t3 ++ " fi"
  248. show (IntConst n) = show n
  249. show (IntAdd t1 t2) = "+(" ++ show t1 ++ "," ++ show t2 ++ ")"
  250. show (IntSub t1 t2) = "-(" ++ show t1 ++ "," ++ show t2 ++ ")"
  251. show (IntMul t1 t2) = "*(" ++ show t1 ++ "," ++ show t2 ++ ")"
  252. show (IntDiv t1 t2) = "/(" ++ show t1 ++ "," ++ show t2 ++ ")"
  253. show (IntNand t1 t2) = "^(" ++ show t1 ++ "," ++ show t2 ++ ")"
  254. show (IntEq t1 t2) = "=(" ++ show t1 ++ "," ++ show t2 ++ ")"
  255. show (IntLt t1 t2) = "<(" ++ show t1 ++ "," ++ show t2 ++ ")"
  256. \end{code}
  257. Function parseType, parseTerm and parse:\\
  258. \begin{code}
  259. --parser
  260. --type parser
  261. parseType :: [Token] -> Maybe (Type,[Token])
  262. parseType (BOOL:ty) = Just (TypeBool,ty)
  263. parseType (INT:ty) = Just (TypeInt,ty)
  264. parseType (RPAR:ty) = parseType ty
  265. parseType (COMMA:ty) = parseType ty
  266. parseType (ARROW:LPAR:ty) =
  267. case parseType ty of
  268. Just (t1,(COMMA:tl)) -> case parseType tl of
  269. Just (t2,(RPAR:tll)) -> Just ((TypeArrow t1 t2),tll)
  270. Nothing -> Nothing
  271. Nothing -> Nothing
  272. parseType tok = error "[P]err: type parsing error!"
  273. --term parser
  274. parseTerm :: [Token] -> Maybe (Term,[Token])
  275. ----id
  276. parseTerm ((ID id):ts) = Just ((Var id),ts)
  277. ----num
  278. parseTerm ((NUM num):ts) = Just ((IntConst (read num::Integer)),ts)
  279. ----symbol
  280. --parseTerm (COMMA:ts) = parseTerm ts
  281. --parseTerm (COLON:ts) = parseTerm ts
  282. --parseTerm (RPAR:ts) = parseTerm ts
  283. --parseTerm (FULLSTOP:ts) = parseTerm ts
  284. ----keyword
  285. parseTerm (THEN:ts) = parseTerm ts
  286. parseTerm (ELSE:ts) = parseTerm ts
  287. parseTerm (FI:ts) = parseTerm ts
  288. parseTerm (TRUE:ts) = Just (Tru,ts)
  289. parseTerm (FALSE:ts) = Just (Fls,ts)
  290. ----(term)
  291. parseTerm (LPAR:ts) = case parseTerm ts of
  292. Just (t,(RPAR:tl)) -> Just (t,tl)
  293. Nothing -> Nothing
  294. _ -> error "[P]err: t is not a term in the (t)"
  295. ----op
  296. parseTerm (PLUS:LPAR:ts) =
  297. case parseTerm ts of
  298. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  299. Just (t2,(RPAR:tll)) -> Just ((IntAdd t1 t2),tll)
  300. Nothing -> Nothing
  301. _ -> error "[P]err: plus term"
  302. Nothing -> Nothing
  303. _ -> error "[P]err: plus term"
  304. parseTerm (SUB:LPAR:ts) =
  305. case parseTerm ts of
  306. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  307. Just (t2,(RPAR:tll)) -> Just ((IntSub t1 t2),tll)
  308. Nothing -> Nothing
  309. _ -> error "[P]err: sub term"
  310. Nothing -> Nothing
  311. _ -> error "[P]err: sub term"
  312. parseTerm (MUL:LPAR:ts) =
  313. case parseTerm ts of
  314. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  315. Just (t2,(RPAR:tll)) -> Just ((IntMul t1 t2),tll)
  316. Nothing -> Nothing
  317. _ -> error "[P]err: mul term"
  318. Nothing -> Nothing
  319. _ -> error "[P]err: mul term"
  320. parseTerm (DIV:LPAR:ts) =
  321. case parseTerm ts of
  322. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  323. Just (t2,(RPAR:tll)) -> Just ((IntDiv t1 t2),tll)
  324. Nothing -> Nothing
  325. _ -> error "[P]err: div term"
  326. Nothing -> Nothing
  327. _ -> error "[P]err: div term"
  328. parseTerm (NAND:LPAR:ts) =
  329. case parseTerm ts of
  330. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  331. Just (t2,(RPAR:tll)) -> Just ((IntNand t1 t2),tll)
  332. Nothing -> Nothing
  333. _ -> error "[P]err: nand term"
  334. Nothing -> Nothing
  335. _ -> error "[P]err: nand term"
  336. parseTerm (EQUAL:LPAR:ts) =
  337. case parseTerm ts of
  338. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  339. Just (t2,(RPAR:tll)) -> Just ((IntEq t1 t2),tll)
  340. Nothing -> Nothing
  341. _ -> error "[P]err: eq term"
  342. Nothing -> Nothing
  343. _ -> error "[P]err: eq term"
  344. parseTerm (LT_keyword:LPAR:ts) =
  345. case parseTerm ts of
  346. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  347. Just (t2,(RPAR:tll)) -> Just ((IntLt t1 t2),tll)
  348. Nothing -> Nothing
  349. _ -> error "[P]err: lt term"
  350. Nothing -> Nothing
  351. _ -> error "[P]err: lt term"
  352. ----if-then-else
  353. parseTerm (IF:ts) =
  354. case parseTerm ts of
  355. Just (t1,(THEN:tl)) -> case parseTerm tl of
  356. Just (t2,(ELSE:tll)) -> case parseTerm tll of
  357. Just (t3,(FI:tn)) -> Just((If t1 t2 t3),tn)
  358. Nothing -> Nothing
  359. _ -> error "[P]err: if term"
  360. Nothing -> Nothing
  361. _ -> error "[P]err: if term"
  362. Nothing -> Nothing
  363. _ -> error "[P]err: if term"
  364. ----abs
  365. parseTerm (ABS:LPAR:(ID id):COLON:ts) =
  366. case parseType ts of
  367. Just (ty,(FULLSTOP:tl)) -> case parseTerm tl of
  368. Just (t,(RPAR:tll)) -> Just ((Abs id ty t),tll)
  369. Nothing -> Nothing
  370. _ -> error "[P]err: abs term"
  371. Nothing -> Nothing
  372. _ -> error "[P]err: abs term"
  373. ----app
  374. parseTerm (APP:LPAR:ts) = case parseTerm ts of
  375. Just (t1,(COMMA:tl)) -> case parseTerm tl of
  376. Just (t2,(RPAR:tll)) -> Just ((App t1 t2),tll)
  377. Nothing -> Nothing
  378. _ -> error "[P]err: app term"
  379. Nothing -> Nothing
  380. _ -> error "[P]err: app term"
  381. ----otherwise
  382. parseTerm tok = Nothing
  383. --parser
  384. parse :: [Token] -> Term
  385. parse t =
  386. case parseTerm t of
  387. Just (x,t) -> case t of
  388. [] -> x
  389. _ -> error "parsing error!"
  390. Nothing -> error "parsing error!"
  391. \end{code}
  392. If the input string can't match any defined Term, function parser reports an error and the program stops at the parser level.\\
  393. \section{Binding and Free Variables}
  394. Define functions to manipulate the abstract syntax. Place them together with the above type definitions
  395. in a module \textit{AbstractSyntax}.
  396. Enumerate the free variables of a term:
  397. \begin{code}
  398. fv :: Term -> [Var]
  399. fv (Var x) = [x]
  400. fv (Abs x _ t) = filter (/=x) (fv t)
  401. fv (App t1 t2) = (fv t1) ++ (fv t2)
  402. fv (If t1 t2 t3) = (fv t1) ++ (fv t2) ++ (fv t3)
  403. fv (IntAdd t1 t2) = (fv t1) ++ (fv t2)
  404. fv (IntSub t1 t2) = (fv t1) ++ (fv t2)
  405. fv (IntMul t1 t2) = (fv t1) ++ (fv t2)
  406. fv (IntDiv t1 t2) = (fv t1) ++ (fv t2)
  407. fv (IntNand t1 t2) = (fv t1) ++ (fv t2)
  408. fv (IntEq t1 t2) = (fv t1) ++ (fv t2)
  409. fv (IntLt t1 t2) = (fv t1) ++ (fv t2)
  410. fv _ = []
  411. \end{code}
  412. Substitution: subst $x$ $s$ $t$, or in writing $[x 7 \rightarrow s]t$, is the result of substituting $s$ for $x$ in $t$.
  413. \begin{code}
  414. subst :: Var -> Term -> Term -> Term
  415. subst x s (Var v) = if x == v then s else (Var v)
  416. subst x s (Abs y tau t1) =
  417. if x == y then
  418. Abs y tau t1
  419. else
  420. Abs y tau (subst x s t1)
  421. subst x s (App t1 t2) = App (subst x s t1) (subst x s t2)
  422. subst x s (If t1 t2 t3) = If (subst x s t1) (subst x s t2) (subst x s t3)
  423. subst x s (IntAdd t1 t2) = IntAdd (subst x s t1) (subst x s t2)
  424. subst x s (IntSub t1 t2) = IntSub (subst x s t1) (subst x s t2)
  425. subst x s (IntMul t1 t2) = IntMul (subst x s t1) (subst x s t2)
  426. subst x s (IntDiv t1 t2) = IntDiv (subst x s t1) (subst x s t2)
  427. subst x s (IntNand t1 t2) = IntNand (subst x s t1) (subst x s t2)
  428. subst x s (IntEq t1 t2) = IntEq (subst x s t1) (subst x s t2)
  429. subst x s (IntLt t1 t2) = IntLt (subst x s t1) (subst x s t2)
  430. subst x s t = t
  431. \end{code}
  432. Syntactic values: primitive constants and abstractions are values.
  433. \begin{code}
  434. isValue :: Term -> Bool
  435. isValue (Abs _ _ _) = True
  436. isValue Tru = True
  437. isValue Fls = True
  438. isValue (IntConst _) = True
  439. isValue _ = False
  440. \end{code}
  441. \section{Structural Operational Semantics}
  442. \paragraph{}
  443. Express the small-step semantics, as defined in class, in Haskell code. The completed source code is as follows:
  444. \begin{code}
  445. module StructuralOperationalSemantics where
  446. import List
  447. import qualified AbstractSyntax as S
  448. import qualified IntegerArithmetic as I
  449. eval1 :: S.Term -> Maybe S.Term
  450. -- E-IFTRUE
  451. eval1 (S.If S.Tru t2 t3) = Just t2
  452. -- E-IFFALSE
  453. eval1 (S.If S.Fls t2 t3) = Just t3
  454. -- E-IF
  455. eval1 (S.If t1 t2 t3) =
  456. case eval1 t1 of
  457. Just t1' -> Just (S.If t1' t2 t3)
  458. Nothing -> Nothing
  459. -- E-APPABS, E-APP1 and E-APP2
  460. eval1 (S.App t1 t2) =
  461. if S.isValue t1
  462. then if S.isValue t2
  463. then case t1 of
  464. S.Abs x tau11 t12 -> Just (S.subst x t2 t12) -- E-APPABS
  465. _ -> Nothing
  466. else case eval1 t2 of
  467. Just t2' -> Just (S.App t1 t2') -- E-APP2
  468. Nothing -> Nothing
  469. else case eval1 t1 of
  470. Just t1' -> Just (S.App t1' t2) -- E-APP1
  471. Nothing -> Nothing
  472. eval1 (S.IntAdd t1 t2) =
  473. if S.isValue t1
  474. then case t1 of
  475. S.IntConst n1 -> if S.isValue t2
  476. then case t2 of
  477. S.IntConst n2 -> Just (S.IntConst (I.intAdd n1 n2))
  478. _ -> Nothing
  479. else case eval1 t2 of
  480. Just t2' -> Just (S.IntAdd t1 t2')
  481. Nothing -> Nothing
  482. _ -> Nothing
  483. else case eval1 t1 of
  484. Just t1' -> Just (S.IntAdd t1' t2)
  485. Nothing -> Nothing
  486. eval1 (S.IntSub t1 t2) =
  487. if S.isValue t1
  488. then case t1 of
  489. S.IntConst n1 -> if S.isValue t2
  490. then case t2 of
  491. S.IntConst n2 -> Just (S.IntConst (I.intSub n1 n2))
  492. _ -> Nothing
  493. else case eval1 t2 of
  494. Just t2' -> Just (S.IntSub t1 t2')
  495. Nothing -> Nothing
  496. _ -> Nothing
  497. else case eval1 t1 of
  498. Just t1' -> Just (S.IntSub t1' t2)
  499. Nothing -> Nothing
  500. eval1 (S.IntMul t1 t2) =
  501. if S.isValue t1
  502. then case t1 of
  503. S.IntConst n1 -> if S.isValue t2
  504. then case t2 of
  505. S.IntConst n2 -> Just (S.IntConst (I.intMul n1 n2))
  506. _ -> Nothing
  507. else case eval1 t2 of
  508. Just t2' -> Just (S.IntMul t1 t2')
  509. Nothing -> Nothing
  510. _ -> Nothing
  511. else case eval1 t1 of
  512. Just t1' -> Just (S.IntMul t1' t2)
  513. Nothing -> Nothing
  514. eval1 (S.IntDiv t1 t2) =
  515. if S.isValue t1
  516. then case t1 of
  517. S.IntConst n1 -> if S.isValue t2
  518. then case t2 of
  519. S.IntConst n2 -> Just (S.IntConst (I.intDiv n1 n2))
  520. _ -> Nothing
  521. else case eval1 t2 of
  522. Just t2' -> Just (S.IntDiv t1 t2')
  523. Nothing -> Nothing
  524. _ -> Nothing
  525. else case eval1 t1 of
  526. Just t1' -> Just (S.IntDiv t1' t2)
  527. Nothing -> Nothing
  528. eval1 (S.IntNand t1 t2) =
  529. if S.isValue t1
  530. then case t1 of
  531. S.IntConst n1 -> if S.isValue t2
  532. then case t2 of
  533. S.IntConst n2 -> Just (S.IntConst (I.intNand n1 n2))
  534. _ -> Nothing
  535. else case eval1 t2 of
  536. Just t2' -> Just (S.IntNand t1 t2')
  537. Nothing -> Nothing
  538. _ -> Nothing
  539. else case eval1 t1 of
  540. Just t1' -> Just (S.IntNand t1' t2)
  541. Nothing -> Nothing
  542. eval1 (S.IntEq t1 t2) =
  543. if S.isValue t1
  544. then case t1 of
  545. S.IntConst n1 -> if S.isValue t2
  546. then case t2 of
  547. S.IntConst n2 -> case I.intEq n1 n2 of
  548. True -> Just S.Tru
  549. _ -> Just S.Fls
  550. _ -> Nothing
  551. else case eval1 t2 of
  552. Just t2' -> Just (S.IntEq t1 t2')
  553. Nothing -> Nothing
  554. _ -> Nothing
  555. else case eval1 t1 of
  556. Just t1' -> Just (S.IntEq t1' t2)
  557. Nothing -> Nothing
  558. eval1 (S.IntLt t1 t2) =
  559. if S.isValue t1
  560. then case t1 of
  561. S.IntConst n1 -> if S.isValue t2
  562. then case t2 of
  563. S.IntConst n2 -> case I.intLt n1 n2 of
  564. True -> Just S.Tru
  565. _ -> Just S.Fls
  566. _ -> Nothing
  567. else case eval1 t2 of
  568. Just t2' -> Just (S.IntLt t1 t2')
  569. Nothing -> Nothing
  570. _ -> Nothing
  571. else case eval1 t1 of
  572. Just t1' -> Just (S.IntLt t1' t2)
  573. Nothing -> Nothing
  574. -- All other cases
  575. eval1 _ = Nothing
  576. eval :: S.Term -> S.Term
  577. eval t =
  578. case eval1 t of
  579. Just t' -> eval t'
  580. Nothing -> t
  581. \end{code}
  582. \section{Arithmetic}
  583. The module $\mathit{IntegerArithmetic}$ formalizes the $\mathit{primitive}$ operators for integer arithmetic. In a nutshell, even though we use the Haskell infinite-precision type Integer to store integers, the numbers are really only using the 32-bit 2's complement range, and arithmetic operations must work accordingly. Roughly speaking, arithmetic is as in C on a 32-bit machine. Complete the code.
  584. \begin{code}
  585. module IntegerArithmetic where
  586. import Data.Bits
  587. intRestrictRangeAddMul :: Integer -> Integer
  588. intRestrictRangeAddMul m = m `mod` 4294967296
  589. intAdd :: Integer -> Integer -> Integer
  590. intAdd m n = intRestrictRangeAddMul (m + n)
  591. intSub :: Integer -> Integer -> Integer
  592. intSub m n = m - n
  593. intMul :: Integer -> Integer -> Integer
  594. intMul m n = intRestrictRangeAddMul (m * n)
  595. intDiv :: Integer -> Integer -> Integer
  596. intDiv m n = if n == 0 then error "integer division by zero" else m `div` n
  597. intNand :: Integer -> Integer -> Integer
  598. intNand m n = complement (m .&. n)
  599. intEq :: Integer -> Integer -> Bool
  600. intEq m n = m == n
  601. intLt :: Integer -> Integer -> Bool
  602. intLt m n = m < n
  603. \end{code}
  604. \section{Type Checker}
  605. It is always good to be sure a program is well-typed before we try to evaluate it. You can use the following type checker or write your own.
  606. \begin{code}
  607. module Typing where
  608. import qualified AbstractSyntax as S
  609. import List
  610. data Context = Empty
  611. | Bind Context S.Var S.Type
  612. deriving Eq
  613. instance Show Context where
  614. show Empty = "<>"
  615. show (Bind capGamma x tau) = show capGamma ++ "," ++ x ++ ":" ++ show tau
  616. contextLookup :: S.Var -> Context -> Maybe S.Type
  617. contextLookup x Empty = Nothing
  618. contextLookup x (Bind capGamma y tau)
  619. | x == y = Just tau
  620. | otherwise = contextLookup x capGamma
  621. typing :: Context -> S.Term -> Maybe S.Type
  622. --T-Var
  623. typing capGamma (S.Var x) = contextLookup x capGamma
  624. --T-Abs
  625. typing capGamma (S.Abs x tau_1 t2) = case typing (Bind capGamma x tau_1) t2 of
  626. Just(tp0) -> Just (S.TypeArrow tau_1 tp0)
  627. Nothing -> Nothing
  628. typing capGamma (S.App t0 t2)=
  629. case typing capGamma t0 of
  630. Just (S.TypeArrow tp tp0) -> case typing capGamma t2 of
  631. Just tp' -> if tp==tp'
  632. then Just tp0
  633. else Nothing
  634. Nothing -> Nothing
  635. _ -> Nothing
  636. --T-True
  637. typing capGamma S.Tru = Just S.TypeBool
  638. --T-False
  639. typing capGamma S.Fls = Just S.TypeBool
  640. --T-If
  641. typing capGamma (S.If t0 t2 t3)
  642. | (typing capGamma t2 == typing capGamma t3 && typing capGamma t0 == Just S.TypeBool) = typing capGamma t2
  643. | otherwise = Nothing
  644. typing capGamma (S.IntConst _) = Just S.TypeInt
  645. --T-IntAdd
  646. typing capGamma (S.IntAdd t1 t2) =
  647. case typing capGamma t1 of
  648. Just S.TypeInt -> case typing capGamma t1 of
  649. Just S.TypeInt -> Just S.TypeInt
  650. Nothing -> Nothing
  651. --T-IntSub
  652. typing capGamma (S.IntSub t1 t2) =
  653. case typing capGamma t1 of
  654. Just S.TypeInt -> case typing capGamma t1 of
  655. Just S.TypeInt -> Just S.TypeInt
  656. Nothing -> Nothing
  657. --T-IntMul
  658. typing capGamma (S.IntMul t1 t2) =
  659. case typing capGamma t1 of
  660. Just S.TypeInt -> case typing capGamma t1 of
  661. Just S.TypeInt -> Just S.TypeInt
  662. Nothing -> Nothing
  663. --T-IntDiv
  664. typing capGamma (S.IntDiv t1 t2) =
  665. case typing capGamma t1 of
  666. Just S.TypeInt -> case typing capGamma t1 of
  667. Just S.TypeInt -> Just S.TypeInt
  668. Nothing -> Nothing
  669. --T-IntNand
  670. typing capGamma (S.IntNand t1 t2) =
  671. case typing capGamma t1 of
  672. Just S.TypeInt -> case typing capGamma t1 of
  673. Just S.TypeInt -> Just S.TypeInt
  674. Nothing -> Nothing
  675. --T-IntEq
  676. typing capGamma (S.IntEq t1 t2) =
  677. case typing capGamma t1 of
  678. Just S.TypeBool -> case typing capGamma t1 of
  679. Just S.TypeBool -> Just S.TypeBool
  680. Nothing -> Nothing
  681. --T-IntLt
  682. typing capGamma (S.IntLt t1 t2) =
  683. case typing capGamma t1 of
  684. Just S.TypeBool -> case typing capGamma t1 of
  685. Just S.TypeBool -> Just S.TypeInt
  686. Nothing -> Nothing
  687. typeCheck :: S.Term -> S.Type
  688. typeCheck t =
  689. case typing Empty t of
  690. Just tau -> tau
  691. _ -> error "type error"
  692. \end{code}
  693. \section{Main Program}
  694. Write a main program which will (1) read the program text from a file into a string, (2) invoke the parser
  695. to produce an abstract syntax tree for the program, (3) type-check the program, and (4) evaluate the
  696. program using the small-step evaluation relation.
  697. \begin{code}
  698. module Main where
  699. import qualified System.Environment
  700. import Data.List
  701. import IO
  702. import qualified AbstractSyntax as S
  703. import qualified StructuralOperationalSemantics as E
  704. import qualified NaturalSemantics as N
  705. import qualified IntegerArithmetic as I
  706. import qualified Typing as T
  707. main :: IO()
  708. main =
  709. do
  710. args <- System.Environment.getArgs
  711. let [sourceFile] = args
  712. source <- readFile sourceFile
  713. let tokens = S.scan source
  714. let term = S.parse tokens
  715. putStrLn ("----Term----")
  716. putStrLn (show term)
  717. putStrLn ("----Type----")
  718. putStrLn (show (T.typeCheck term))
  719. putStrLn ("----Normal Form in Structureal Operational Semantics----")
  720. putStrLn (show (E.eval term))
  721. putStrLn ("----Normal Form of Natural Semantics----")
  722. putStrLn (show (N.eval term))
  723. \end{code}
  724. \section{Structural Operational Semantics}
  725. \paragraph{}
  726. Formally stating the rules that give the structural operational semantics of the core lambda language, the rules are listed below:
  727. \[
  728. \text{if true then } t_2 \text{ else } t_3 \rightarrow t_2 \text{\quad (\textsc{E-IfTrue})}
  729. \]
  730. \ \\
  731. \[
  732. \text{if false then } t_2 \text{ else } t_3 \rightarrow t_3 \text{(\quad \textsc{E-IfFalse})}
  733. \]
  734. \ \\
  735. \[
  736. \frac{t_1 \rightarrow t'_1}{\text{if } t_1 \text{ then } t_2 \text{ else } t_3 \rightarrow \text{if } t'_1 \text{ then } t_2 \text{ else} t_3} \text{\quad (\textsc{E-If})}
  737. \]
  738. \ \\
  739. \[
  740. \frac{t_1 \rightarrow t'_1}{t_1 \text{\ } t_2 \rightarrow t'_1 \text{\ } t_2}\text{\quad {\textsc{E-App1}}}
  741. \]
  742. \ \\
  743. \[
  744. \frac{t_2 \rightarrow t'_2}{t_1 \text{\ } t_2 \rightarrow t_1 \text{\ } t'_2}\text{\quad {\textsc{E-App2}}}
  745. \]
  746. \ \\
  747. \[
  748. (\lambda x: T_{11}.t_{12})v_2 \rightarrow [ x \mapsto v_2 ] _{12} \text{\quad (\textsc{E-AppAbs})}
  749. \]
  750. \ \\
  751. \[
  752. \frac{t_1 \rightarrow t'_1}{+(t_1, t_2) \rightarrow +(t'_1, t_2)} \text{\quad (\textsc{E-IntAdd1})}
  753. \]
  754. \ \\
  755. \[
  756. \frac{t_2 \rightarrow t'_2}{+(t_1, t_2) \rightarrow +(t_1, t'_2)} \text{\quad (\textsc{E-IntAdd2})}
  757. \]
  758. \ \\
  759. \[
  760. +(v_1, v_2) \rightarrow v_1 \widetilde{+} v_2 \text{\quad (\textsc{E-IntAppAdd})}
  761. \]
  762. \ \\
  763. \[
  764. \frac{t_1 \rightarrow t'_1}{-(t_1, t_2) \rightarrow -(t'_1, t_2)} \text{\quad (\textsc{E-IntSub1})}
  765. \]
  766. \ \\
  767. \[
  768. \frac{t_2 \rightarrow t'_2}{-(t_1, t_2) \rightarrow -(t_1, t'_2)} \text{\quad (\textsc{E-IntSub2})}
  769. \]
  770. \ \\
  771. \[
  772. -(v_1, v_2) \rightarrow v_1 \widetilde{-} v_2 \text{\quad (\textsc{E-AppIntSub})}
  773. \]
  774. \ \\
  775. \[
  776. \frac{t_1 \rightarrow t'_1}{*(t_1, t_2) \rightarrow *(t'_1, t_2)} \text{\quad (\textsc{E-IntMul1})}
  777. \]
  778. \ \\
  779. \[
  780. \frac{t_2 \rightarrow t'_2}{*(t_1, t_2) \rightarrow *(t_1, t'_2)} \text{\quad (\textsc{E-IntMul2})}
  781. \]
  782. \ \\
  783. \[
  784. *(v_1, v_2) \rightarrow v_1 \widetilde{*} v_2 \text{\quad (\textsc{E-AppIntMul})}
  785. \]
  786. \ \\
  787. \[
  788. \frac{t_1 \rightarrow t'_1}{/(t_1, t_2) \rightarrow /(t'_1, t_2)} \text{\quad (\textsc{E-IntDiv1})}
  789. \]
  790. \ \\
  791. \[
  792. \frac{t_2 \rightarrow t'_2}{/(t_1, t_2) \rightarrow /(t_1, t'_2)} \text{\quad (\textsc{E-IntDiv2})}
  793. \]
  794. \ \\
  795. \[
  796. /(v_1, v_2) \rightarrow v_1 \widetilde{/} v_2 \text{\quad (\textsc{E-AppIntDiv})}
  797. \]
  798. \ \\
  799. \[
  800. \frac{t_1 \rightarrow t'_1}{\wedge(t_1, t_2) \rightarrow \wedge(t'_1, t_2)} \text{\quad (\textsc{E-IntNand1})}
  801. \]
  802. \ \\
  803. \[
  804. \frac{t_2 \rightarrow t'_2}{\wedge(t_1, t_2) \rightarrow \wedge(t_1, t'_2)} \text{\quad (\textsc{E-IntNand2})}
  805. \]
  806. \ \\
  807. \[
  808. \wedge(v_1, v_2) \rightarrow v_1 \widetilde{\wedge} v_2 \text{\quad (\textsc{E-AppIntNand})}
  809. \]
  810. \ \\
  811. \[
  812. \frac{t_1 \rightarrow t'_1}{=(t_1, t_2) \rightarrow =(t'_1, t_2)} \text{\quad (\textsc{E-IntEq1})}
  813. \]
  814. \ \\
  815. \[
  816. \frac{t_2 \rightarrow t'_2}{=(t_1, t_2) \rightarrow =(t_1, t'_2)} \text{\quad (\textsc{E-IntEq2})}
  817. \]
  818. \ \\
  819. \[
  820. =(v_1, v_2) \rightarrow v_1 \widetilde{\equiv} v_2 \text{\quad (\textsc{E-AppIntEq})}
  821. \]
  822. \ \\
  823. \[
  824. \frac{t_1 \rightarrow t'_1}{<(t_1, t_2) \rightarrow <(t'_1, t_2)} \text{\quad (\textsc{E-IntLt1})}
  825. \]
  826. \ \\
  827. \[
  828. \frac{t_2 \rightarrow t'_2}{<(t_1, t_2) \rightarrow <(t_1, t'_2)} \text{\quad (\textsc{E-IntLt2})}
  829. \]
  830. \ \\
  831. \[
  832. <(v_1, v_2) \rightarrow v_1 \widetilde{<} v_2 \text{\quad (\textsc{E-AppIntLt})}
  833. \]
  834. \ \\
  835. where
  836. \begin{align*}
  837. \widetilde{+} &\text{\quad \quad is the funtion that adds the two arguments and returns an Integer result}\\
  838. \widetilde{-} &\text{\quad \quad is the function that subtracts the two arguments and returns an Integer result}\\
  839. \widetilde{*} &\text{\quad \quad is the function that times the two arguments and returns an Integer result}\\
  840. \widetilde{/} &\text{\quad \quad is the function that divides the two arguments and returns an Integer result}\\
  841. \widetilde{\wedge} &\text{\quad \quad is the function that gets the nand result of the two arguments and returns it }\\
  842. \widetilde{\equiv} &\text{\quad \quad is the function that judges whether the two values are equal. If so, returns \textbf{true}, otherwise \textbf{false}}\\
  843. \widetilde{<} &\text{\quad \quad is the function that judges whether the first value is less than the second one.} \\
  844. &\text{\quad \quad \ If so, returns \textbf{true}, otherwise \textbf{false}}
  845. \end{align*}
  846. \section{Natural Semantics}
  847. \paragraph{}
  848. Formally state the rules that give the natural semantics (big-step operational semantics) of the core lambda language. (Note: here we mean the version of natural semantics that operates on terms and performs substitutions, rather than the version with environments.)
  849. \paragraph{}
  850. The formal rules of the natural semantics for this programming language is as follows:
  851. \[
  852. a\Downarrow v \text{\quad (\textsc{B-ClosedForm})}
  853. \]
  854. for closed form $a$, and $a$ should have no free variable inside.
  855. \[
  856. v \Downarrow v \text{\quad (\textsc{B-Value})}
  857. \]
  858. \ \\
  859. \[
  860. \frac{a\Downarrow \lambda x.a'\text{\quad} b\Downarrow v'\text{\quad} [x\mapsto v']a'\Downarrow v}{a\text{\ }b \Downarrow v}\text{\quad (\textsc{B-App})}
  861. \]
  862. \ \\
  863. \[
  864. \frac{t_1 \Downarrow \text{ true\quad } t_2 \Downarrow v_2}{\text{if } t_1 \text{ then } t_2 \text{ else } t_3 \Downarrow v_2}\text{\quad (\textsc{B-IfTrue})}
  865. \]
  866. \ \\
  867. \[
  868. \frac{t_1 \Downarrow \text{ false\quad} t_3 \Downarrow v_3}{\text{if } t_1 \text{ then } t_2 \text{ else } t_3 \Downarrow v_3}\text{\quad (\textsc{B-IfFalse})}
  869. \]
  870. \ \\
  871. \[
  872. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{+}(v_1, v_2)}{+(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntAdd})}
  873. \]
  874. \ \\
  875. \[
  876. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{-}(v_1, v_2)}{-(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntSub})}
  877. \]
  878. \ \\
  879. \[
  880. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{*}(v_1, v_2)}{*(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntMul})}
  881. \]
  882. \ \\
  883. \[
  884. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{/}(v_1, v_2)}{/(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntDiv})}
  885. \]
  886. \ \\
  887. \[
  888. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{\wedge}(v_1, v_2)}{\wedge(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntNand})}
  889. \]
  890. \ \\
  891. \[
  892. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{=}(v_1, v_2)}{=(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntEq})}
  893. \]
  894. \ \\
  895. \[
  896. \frac{t_1 \Downarrow v_1\text{\quad} t_2 \Downarrow v_2\text{\quad} v = \widetilde{<}(v_1, v_2)}{<(t_1, t_2) \Downarrow v}\text{\quad (\textsc{B-IntLt})}
  897. \]
  898. \ \\
  899. \section{Natural Semantics}
  900. \paragraph{}
  901. Express the natural semantics in Haskell code, as an interpreter for lambda terms given by the Haskell function \textit{eval::Term $\rightarrow$ Term} in a module \textit{NaturalSemantics}. The completed module source code is as follows:
  902. \begin{code}
  903. module NaturalSemantics where
  904. import List
  905. import qualified AbstractSyntax as S
  906. import qualified IntegerArithmetic as I
  907. eval :: S.Term -> S.Term
  908. eval (S.If t1 t2 t3) =
  909. case eval t1 of
  910. S.Tru -> eval t2 -- B-IfTrue
  911. S.Fls -> eval t3 -- B-IfFalse
  912. _ -> S.If t1 t2 t3
  913. -- B-App
  914. eval (S.App t1 t2) =
  915. if (S.isValue $ eval t1)
  916. then case eval t1 of
  917. S.Abs x tau t11 -> if ((S.isValue $ eval t2) && ((S.fv (S.Abs x tau t11)) == []))
  918. then eval (S.subst x (eval t2) t11)
  919. else S.App t1 t2
  920. _ -> S.App t1 t2
  921. else S.App t1 t2
  922. -- B-IntAdd
  923. eval (S.IntAdd t1 t2) =
  924. case eval t1 of
  925. S.IntConst v1 -> case eval t2 of
  926. S.IntConst v2 -> S.IntConst (I.intAdd v1 v2)
  927. _ -> S.IntAdd t1 t2
  928. _ -> S.IntAdd t1 t2
  929. -- B-IntSub
  930. eval (S.IntSub t1 t2) =
  931. case eval t1 of
  932. S.IntConst v1 -> case eval t2 of
  933. S.IntConst v2 -> S.IntConst (I.intSub v1 v2)
  934. _ -> S.IntSub t1 t2
  935. _ -> S.IntSub t1 t2
  936. -- B-IntMul
  937. eval (S.IntMul t1 t2) =
  938. case eval t1 of
  939. S.IntConst v1 -> case eval t2 of
  940. S.IntConst v2 -> S.IntConst (I.intMul v1 v2)
  941. _ -> S.IntSub t1 t2
  942. _ -> S.IntSub t1 t2
  943. -- B-IntDiv
  944. eval (S.IntDiv t1 t2) =
  945. case eval t1 of
  946. S.IntConst v1 -> case eval t2 of
  947. S.IntConst v2 -> S.IntConst (I.intDiv v1 v2)
  948. _ -> S.IntDiv t1 t2
  949. _ -> S.IntDiv t1 t2
  950. -- B-IntNand
  951. eval (S.IntNand t1 t2) =
  952. case eval t1 of
  953. S.IntConst v1 -> case eval t2 of
  954. S.IntConst v2 -> S.IntConst (I.intNand v1 v2)
  955. _ -> S.IntNand t1 t2
  956. _ -> S.IntNand t1 t2
  957. -- B-IntEq
  958. eval (S.IntEq t1 t2) =
  959. case eval t1 of
  960. S.IntConst v1 -> case eval t2 of
  961. S.IntConst v2 -> case I.intEq v1 v2 of
  962. True -> S.Tru
  963. False -> S.Fls
  964. _ -> S.IntEq t1 t2
  965. _ -> S.IntEq t1 t2
  966. -- B-IntLt
  967. eval (S.IntLt t1 t2) =
  968. case eval t1 of
  969. S.IntConst v1 -> case eval t2 of
  970. S.IntConst v2 -> case I.intLt v1 v2 of
  971. True -> S.Tru
  972. False -> S.Fls
  973. _ -> S.IntLt t1 t2
  974. _ -> S.IntLt t1 t2
  975. -- B-Value and Exceptions
  976. eval t = t
  977. \end{code}
  978. \section{Test Cases}
  979. \subsection{Test 1}
  980. \verbatiminput{test1.TLBN}
  981. \verbatiminput{test1.out}
  982. \subsection{Test 2}
  983. \verbatiminput{test2.TLBN}
  984. \verbatiminput{test2.out}
  985. \subsection{Test 3}
  986. \verbatiminput{test3.TLBN}
  987. \verbatiminput{test3.out}
  988. \subsection{Test 4}
  989. \verbatiminput{test4.TLBN}
  990. \verbatiminput{test4.out}
  991. \subsection{Test 5}
  992. \verbatiminput{test5.TLBN}
  993. \verbatiminput{test5.out}
  994. \subsection{Test 6}
  995. \verbatiminput{test6.TLBN}
  996. \verbatiminput{test6.out}
  997. \subsection{Test 7}
  998. \verbatiminput{test7.TLBN}
  999. \verbatiminput{test7.out}
  1000. \subsection{Test 8}
  1001. \verbatiminput{test8.TLBN}
  1002. \verbatiminput{test8.out}
  1003. \subsection{Test 9}
  1004. \verbatiminput{test9.TLBN}
  1005. \verbatiminput{test9.out}
  1006. \subsection{Test 10}
  1007. \verbatiminput{test10.TLBN}
  1008. \verbatiminput{test10.out}
  1009. \end{document}