├── .github
└── ISSUE_TEMPLATE
│ └── question.md
├── .gitignore
├── README.md
├── exams
├── final-2023.pdf
├── mid-2023.pdf
└── mid-2024.pdf
├── homework
├── hw1
│ ├── README.md
│ ├── code
│ │ ├── _tags
│ │ ├── build
│ │ ├── dfa.ml
│ │ ├── dfa.mli
│ │ ├── hw.ml
│ │ ├── main.ml
│ │ ├── nfa.ml
│ │ ├── nfa.mli
│ │ └── regex.ml
│ └── hw1.pdf
├── hw2
│ ├── README.md
│ ├── code
│ │ ├── _tags
│ │ ├── absDom.ml
│ │ ├── build
│ │ ├── itvAnalysis.ml
│ │ ├── lang.ml
│ │ ├── lexer.mll
│ │ ├── main.ml
│ │ ├── options.ml
│ │ ├── parser.mly
│ │ ├── test
│ │ │ ├── array
│ │ │ ├── loop1
│ │ │ ├── loop2
│ │ │ └── loop3
│ │ └── vocab.ml
│ └── hw2.pdf
└── hw3
│ ├── README.md
│ ├── code
│ ├── Makefile
│ ├── lexer.mll
│ ├── main.ml
│ ├── optimizer.ml
│ ├── parser.mly
│ ├── s.ml
│ ├── t.ml
│ ├── test
│ │ ├── array.s
│ │ ├── fact.s
│ │ ├── fib.s
│ │ ├── loop1.s
│ │ ├── loop2.s
│ │ ├── t0.s
│ │ ├── t1.s
│ │ ├── t2.s
│ │ ├── t3.s
│ │ └── t4.s
│ └── translator.ml
│ └── hw3.pdf
├── ocaml-examples
├── ex1.ml
├── ex2.ml
├── ex3.ml
├── ex4.ml
├── ex5.ml
├── ex7.ml
├── lec12
│ └── signAnalysis.ml
└── lec9
│ ├── Makefile
│ ├── ast.ml
│ ├── lexer.mll
│ ├── main.ml
│ └── parser.mly
├── setup
├── install_ocaml_mac.sh
├── install_ocaml_ubuntu.sh
├── wsl-install-guideline.pdf
└── wsl_install.ps1
└── slides
├── lec-halting.pdf
├── lec-ocaml.pdf
├── lec0.pdf
├── lec1.pdf
├── lec10.pdf
├── lec11.pdf
├── lec12.pdf
├── lec13.pdf
├── lec14.pdf
├── lec15.pdf
├── lec16.pdf
├── lec17.pdf
├── lec18.pdf
├── lec2.pdf
├── lec3.pdf
├── lec4.pdf
├── lec5.pdf
├── lec6.pdf
├── lec7.pdf
├── lec8.pdf
└── lec9.pdf
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: 'ask your questions'
4 | title: "[Question]"
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 | **Name**: _write your name in here_
10 |
11 | **Question in one sentence**: _summarize your question in one sentence_
12 |
13 | **Detailed situtation** (optional)
14 |
15 | **Please delete the guidelines below when posting a question. If your issue does not follow the guidelines, it can be closed without responses.**
16 | - Please avoid burying your question in the middle of a lenghty text. Make sure your question is as specific and clear as possible. If necessary, you can attach relevant screenshots.
17 | - Please post a new question only if you cannot find an answer in the previous Q&A list.
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.native
2 | *.swp
3 | _build
4 | main.native
5 | *.cmo
6 | *.cmi
7 | a.out
8 | lexer.ml
9 | parser.ml
10 | parser.mli
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EC3204: Programming Languages and Compilers
(프로그래밍 언어 및 컴파일러)
2 | * Instuctor: [Sunbeom So](https://gist-pal.github.io)
3 | * TA: [Sunwoo Lee](https://sites.google.com/view/sunwoo-lee/)
4 | * Location: Haerim hall, EECS-B building
5 | * Time: Mon/Wed 16:00-17:30
6 |
7 | ## About The Course
8 | A compiler is a software system that translates a program written in one language (source language) into a semantically equivalent program written in another language (target language).
9 | The goal of this course is to learn principles of compiler construction and related programming language theories.
10 |
11 | ## Configuring the Programming Environment
12 | We will use [OCaml](https://ocaml.org/install) programming language for our programming exercises. This instruction assumes that you are using the Linux command line interface.
13 |
14 | ### macOS
15 | To install OCaml, simply copy and run the following commands in the terminal.
16 | ```
17 | $ chmod +x setup/install_ocaml_mac.sh; ./setup/install_ocaml_mac.sh; eval $(opam env)
18 | ```
19 |
20 | ### Ubuntu
21 | To install OCaml, simply copy and run the following commands in the terminal. I checked that the following commands successfully work for the clean docker image ``python:3.9.19-slim``.
22 | ```
23 | $ chmod +x setup/install_ocaml_ubuntu.sh; ./setup/install_ocaml_ubuntu.sh; eval $(opam env)
24 | ```
25 |
26 | ### Windows
27 | For Windows users, I recommend using [WSL](https://learn.microsoft.com/en-us/windows/wsl/install).
28 | * [WSL setup](setup/wsl-install-guideline.pdf): We provide a PDF guideline that explains how to install WSL and how to share files between the host OS and the guest OS.
29 | * [script](setup/wsl_install.ps1): For running this installation script, please refer to p.02 of the above PDF guideline.
30 |
31 | After setting up WSL, simply copy and run the following commands in the terminal to install OCaml.
32 | ```
33 | $ chmod +x setup/install_ocaml_ubuntu.sh; ./setup/install_ocaml_ubuntu.sh; eval $(opam env)
34 | ```
35 |
36 | ### Installation Verification
37 | For any OS, if the installation was successful, you should see the message ``The OCaml toplevel, version 5.1.1``
38 | by running the command ``ocaml --version`` in the terminal.
39 | ```
40 | $ ocaml --version
41 | The OCaml toplevel, version 5.1.1
42 | ```
43 |
44 | ## Textbook
45 | * [Compilers: Principles, Techniques, and Tools](https://www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811) (CPTT)
46 | * [Semantics with Applications: An Appetizer](https://link.springer.com/book/10.1007/978-1-84628-692-6) (SAA)
47 |
48 | ## Schedule
49 | |#|Date|Topics|Recommended Reading|
50 | |-|-|------|------|
51 | |0|9/2|[Course Overview](slides/lec0.pdf)|CPTT Ch.1|
52 | |1|9/2|[Overview of Compilers](slides/lec1.pdf)||
53 | |2|9/4|[Lexical Analysis (1)](slides/lec2.pdf)|CPTT Ch.3.3|
54 | |3|9/9|[Lexical Analysis (2)](slides/lec3.pdf)|CPTT Ch.3.4, 3.6, 3.7.5|
55 | |4|9/11,9/23|[Lexical Analysis (3)](slides/lec4.pdf)|CPTT Ch.3.7.4, 3.7.1|
56 | |-|9/25,9/30,10/2|[Functional Programming in OCaml](slides/lec-ocaml.pdf)|[Exercise solutions](ocaml-examples/)|
57 | |5|10/7|[Syntax Analysis (1)](slides/lec5.pdf)|CPTT Ch.4.2|
58 | |6|10/14,10/16|[Syntax Analysis (2)](slides/lec6.pdf)|CPTT Ch.2.2, 4.3, 4.4|
59 | |7|10/21,10/23|[Syntax Analysis (3)](slides/lec7.pdf)|CPTT Ch.4.5, 4.6|
60 | |-|10/28|Mid-term Exam||
61 | |8|11/4|[Syntax Analysis (4)](slides/lec8.pdf)|CPTT Ch.4.8|
62 | |9|11/6|[Lexer & Parser Generators](slides/lec9.pdf)|CPTT Ch.4.9, [Tutorial for ocamllex, ocamlyacc](https://ocaml.org/manual/5.2/lexyacc.html)|
63 | |10|11/11|[Semantic Analysis (1)](slides/lec10.pdf)||
64 | |-|11/13|[Undecidability, Halting Problem](slides/lec-halting.pdf)||
65 | |11|11/13,20|[Semantic Analysis (2)](slides/lec11.pdf)|SAA Ch.7.1|
66 | |12|11/25|[Semantic Analysis (3)](slides/lec12.pdf)||
67 | |13|11/25,27|[Semantic Analysis (4)](slides/lec13.pdf)||
68 | |14|12/2|[Intermediate Representation (1)](slides/lec14.pdf)||
69 | |15|12/4|[Intermediate Representation (2)](slides/lec15.pdf)|CPTT Ch.6.2, 8.4|
70 | |16|12/4|[Optimization (1)](slides/lec16.pdf)|CPTT Ch.9.1|
71 | |17|12/9|[Optimization (2)](slides/lec17.pdf)|CPTT Ch.9.2|
72 | |18|12/11|[Register Allocation](slides/lec18.pdf)||
73 | |-|12/16|Final Exam||
74 |
75 | ## Academic Integrity
76 | By registering for this course, I will assume you agree with the policy below.
77 | * All assignments (i.e., writing code) must be your own work. No discussions are allowed.
78 | * You should not share/show your code.
79 | * You should not post your code on public websites.
80 | * You should not modify other students’ code.
81 | * I will have a one-on-one meeting with each student under suspicion. If you fail to prove your integrity in the meeting (e.g., failing to answer my questions about the details of your submissions), I will consider that you cheated on your assignments, even if you do not admit to your cheating.
82 | * Cheating on assignments will result in an F.
83 |
84 | ## References & Acknowledgements
85 | My lecture slides are based on the slides from the following courses.
86 |
87 | * [COSE312: Compilers] course taught by Prof. Hakjoo Oh at Korea University
88 | * [[CS143: Compilers](https://web.stanford.edu/class/cs143/)] from Stanford University
89 |
--------------------------------------------------------------------------------
/exams/final-2023.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/exams/final-2023.pdf
--------------------------------------------------------------------------------
/exams/mid-2023.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/exams/mid-2023.pdf
--------------------------------------------------------------------------------
/exams/mid-2024.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/exams/mid-2024.pdf
--------------------------------------------------------------------------------
/homework/hw1/README.md:
--------------------------------------------------------------------------------
1 | # HW1 (Due: Nov 8)
2 | Complete ``hw.ml`` and submit it on GIST LMS.
3 | Read ``hw1.pdf`` for further details.
4 |
--------------------------------------------------------------------------------
/homework/hw1/code/_tags:
--------------------------------------------------------------------------------
1 | true: package(batteries), package(str)
2 |
--------------------------------------------------------------------------------
/homework/hw1/code/build:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TARGET=main.native
4 | INCLUDE_DIRS=lib
5 |
6 | function clean
7 | {
8 | ocamlbuild -clean
9 | exit 0
10 | }
11 |
12 | while [ $# -ne 0 ] && [ ! -z $1 ]; do
13 | case $1 in
14 | debug|clean|rebuild) "$1" ;;
15 | *) echo "build: invalid argument $1" && exit 1 ;;
16 | esac
17 | shift
18 | done
19 |
20 |
21 | time ocamlbuild $TARGET -use-ocamlfind -tag thread -Is $INCLUDE_DIRS
22 |
--------------------------------------------------------------------------------
/homework/hw1/code/dfa.ml:
--------------------------------------------------------------------------------
1 | open Regex
2 |
3 | type state = Nfa.states
4 | type states = state BatSet.t
5 | type delta = (state * symbol, state) BatMap.t
6 | type init = state
7 | type final = state BatSet.t
8 |
9 | type t = states * delta * init * final
10 |
11 | let mk_new_dfa : state -> t
12 | = fun is ->
13 | (BatSet.singleton is, BatMap.empty, is, BatSet.empty)
14 |
15 | let get_states : t -> states
16 | = fun (states,_,_,_) -> states
17 |
18 | let get_initial_state : t -> state
19 | = fun (_,_,s,_) -> s
20 |
21 | let get_next_state : t -> state -> symbol -> state
22 | = fun (_,delta,_,_) s x ->
23 | try BatMap.find (s,x) delta
24 | with Not_found -> failwith "Dfa.get_next_state: Not found"
25 |
26 | let is_final_state : t -> state -> bool
27 | = fun (_,_,_,final) s -> BatSet.mem s final
28 |
29 | let add_state : state -> t -> t
30 | = fun s (states, delta, is, final) ->
31 | (BatSet.add s states, delta, is, final)
32 |
33 | let add_final_state : state -> t -> t
34 | = fun s (states, delta, init, final) ->
35 | (BatSet.add s states, delta, init, BatSet.add s final)
36 |
37 | let add_edge : (state * symbol * state) -> t -> t
38 | = fun (s,x,s') (states, delta, init, final) ->
39 | if not (BatSet.mem s states) || not (BatSet.mem s' states)
40 | then failwith "Dfa.add_edge: states not found"
41 | else (states, BatMap.add (s,x) s' delta, init, final)
42 |
43 | let string_of_state = Nfa.string_of_states
44 |
45 | let string_of_states : states -> string
46 | = fun states ->
47 | "{ " ^
48 | BatSet.fold (fun s acc ->
49 | if acc = "" then string_of_state s
50 | else acc ^ ", " ^ string_of_state s
51 | ) states "" ^
52 | " }"
53 |
54 | let print : t -> unit
55 | = fun (states, delta, is, final) ->
56 | print_endline ("* States: " ^ string_of_states states);
57 | print_endline ("* Initial State : " ^ string_of_state is);
58 | print_endline ("* Final States : " ^ string_of_states final);
59 | prerr_endline "* Transition";
60 | BatMap.iter (fun (s,x) s' ->
61 | print_endline (string_of_state s ^ " --- " ^ string_of_symbol x ^ " ---> " ^ string_of_state s')
62 | ) delta
63 |
--------------------------------------------------------------------------------
/homework/hw1/code/dfa.mli:
--------------------------------------------------------------------------------
1 | open Regex
2 |
3 | (* a DFA state is a set of NFA states *)
4 | type state = Nfa.states
5 | type states = state BatSet.t
6 |
7 | type t
8 |
9 | (* create a new DFA with a start state *)
10 | val mk_new_dfa : state -> t
11 |
12 | (* return the set of all states of DFA *)
13 | val get_states : t -> states
14 |
15 | (* return the DFA's initial state *)
16 | val get_initial_state : t -> state
17 |
18 | (* get the next state that is directly reachable *)
19 | val get_next_state : t -> state -> symbol -> state
20 |
21 | (* check if a state is final *)
22 | val is_final_state : t -> state -> bool
23 |
24 | (* add a state to DFA *)
25 | val add_state : state -> t -> t
26 |
27 | (* add a state as a final state *)
28 | val add_final_state : state -> t -> t
29 |
30 | (* add a transition, i.e., update a transition function *)
31 | val add_edge : (state * symbol * state) -> t -> t
32 |
33 | (* string representation of a DFA state *)
34 | val string_of_state : state -> string
35 |
36 | (* string representation of DFA states *)
37 | val string_of_states : states -> string
38 |
39 | (* print DFA *)
40 | val print : t -> unit
41 |
--------------------------------------------------------------------------------
/homework/hw1/code/hw.ml:
--------------------------------------------------------------------------------
1 | open Regex
2 |
3 | exception NotImplemented
4 |
5 | let rec regex2nfa : Regex.t -> Nfa.t
6 | = fun regex -> raise NotImplemented (* TODO *)
7 |
8 | let nfa2dfa : Nfa.t -> Dfa.t
9 | = fun nfa -> raise NotImplemented (* TODO *)
10 |
11 | let run_nfa : Nfa.t -> symbol list -> bool
12 | = fun nfa str -> raise NotImplemented (* TODO *)
13 |
14 | let run_dfa : Dfa.t -> symbol list -> bool
15 | = fun dfa str -> raise NotImplemented (* TODO *)
16 |
--------------------------------------------------------------------------------
/homework/hw1/code/main.ml:
--------------------------------------------------------------------------------
1 | open Regex
2 | open Hw
3 |
4 | let testcases : (Regex.t * symbol list) list =
5 | [
6 | (Empty, []);
7 | (Epsilon, []);
8 | (Symbol 'a', ['a']);
9 | (Symbol 'b', ['b']);
10 | (OR (Symbol 'a', Symbol 'b'), ['b']);
11 | (CONCAT (STAR (Symbol 'a'), Symbol 'b'), ['b']);
12 | (CONCAT (STAR (Symbol 'a'), Symbol 'b'), ['a';'b']);
13 | (CONCAT (STAR (Symbol 'a'), Symbol 'b'), ['a';'a';'b']);
14 | (CONCAT (STAR (Symbol 'a'), Symbol 'b'), ['a';'b';'b']);
15 | (CONCAT (STAR (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['b']);
16 | (CONCAT (STAR (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'b']);
17 | (CONCAT (STAR (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'a';'b']);
18 | (CONCAT (STAR (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'a';'a';'b']);
19 | (CONCAT (POS (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['b']);
20 | (CONCAT (POS (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'b']);
21 | (CONCAT (POS (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'a';'b']);
22 | (CONCAT (POS (CONCAT (Symbol 'a', Symbol 'a')), Symbol 'b'), ['a';'a';'a';'a';'b']);
23 | (CONCAT (POS (OR (SymbolSet ('a','z'), SymbolSet ('A', 'Z'))), STAR (Symbol '_')), ['g';'i';'s';'t']);
24 | (CONCAT (POS (OR (SymbolSet ('a','z'), SymbolSet ('A', 'Z'))), STAR (Symbol '_')), ['G';'i';'S';'t']);
25 | (CONCAT (POS (OR (SymbolSet ('a','z'), SymbolSet ('A', 'Z'))), STAR (Symbol '_')), ['G';'i';'_';'s';'t']);
26 | ]
27 |
28 | let match_regex : Regex.t -> symbol list -> bool * bool
29 | = fun regex input ->
30 | let nfa = Hw.regex2nfa regex in
31 | let dfa = Hw.nfa2dfa nfa in
32 | (Hw.run_nfa nfa input, Hw.run_dfa dfa input)
33 |
34 | (* run testcases *)
35 | let _ =
36 | List.iter (fun (regex, str) ->
37 | let (b1,b2) = match_regex regex str in
38 | print_endline (string_of_bool b1 ^ ", " ^ string_of_bool b2)
39 | ) testcases
40 |
--------------------------------------------------------------------------------
/homework/hw1/code/nfa.ml:
--------------------------------------------------------------------------------
1 | open Regex
2 |
3 | type state = int
4 | type states = state BatSet.t
5 | type delta = (state * symbol option, states) BatMap.t
6 | type init = state
7 | type final = state BatSet.t
8 |
9 | type t = states * delta * init * final
10 | and nfa = t
11 |
12 | let sid = ref 0
13 |
14 | let mk_new_state : unit -> state
15 | = fun () -> sid := !sid + 1; !sid
16 |
17 | let mk_new_nfa : unit -> nfa
18 | = fun () ->
19 | let is = mk_new_state () in
20 | (BatSet.singleton is, BatMap.empty, is, BatSet.empty)
21 |
22 | let get_states : t -> states
23 | = fun (states,_,_,_) -> states
24 |
25 | let get_delta : t -> delta
26 | = fun (_,delta,_,_) -> delta
27 |
28 | let get_initial_state : t -> state
29 | = fun (_,_,is,_) -> is
30 |
31 | let get_final_states : t -> states
32 | = fun (_,_,_,final) -> final
33 |
34 | let get_next_states : t -> state -> symbol option -> states
35 | = fun (_,delta,_,_) s x ->
36 | try BatMap.find (s,x) delta
37 | with Not_found -> BatSet.empty
38 |
39 | let is_final_state : t -> state -> bool
40 | = fun (_,_,_,final) s -> BatSet.mem s final
41 |
42 | let add_states : states -> t -> t
43 | = fun states' (states,delta,is,fs) ->
44 | (BatSet.union states states', delta, is, fs)
45 |
46 | let add_final_state : state -> t -> t
47 | = fun s (states, delta, init, final) ->
48 | (BatSet.add s states, delta, init, BatSet.add s final)
49 |
50 | let add_edge : (state * symbol option * state) -> t -> t
51 | = fun (s,x,s') ((states, delta, init, final) as nfa) ->
52 | if not (BatSet.mem s states) || not (BatSet.mem s' states)
53 | then failwith "Nfa.add_edge: states not found"
54 | else
55 | let nexts = BatSet.add s' (get_next_states nfa s x) in
56 | let delta' = BatMap.add (s,x) nexts delta in
57 | (states, delta', init, final)
58 |
59 | let add_delta : delta -> t -> t
60 | = fun delta' (states,delta,is,fs) ->
61 | (states, BatMap.union delta delta', is, fs)
62 |
63 | let string_of_states : states -> string
64 | = fun states ->
65 | "{" ^
66 | BatSet.fold (fun s acc ->
67 | if acc = "" then string_of_int s
68 | else acc ^ "," ^ string_of_int s
69 | ) states "" ^
70 | "}"
71 |
72 | let string_of_symbol_op : symbol option -> string
73 | = fun x ->
74 | match x with
75 | | None -> "epsilon"
76 | | Some x'-> string_of_symbol x'
77 |
78 | let print : t -> unit
79 | = fun (states, delta, is, final) ->
80 | print_endline ("* States: " ^ string_of_states states);
81 | print_endline ("* Initial State : " ^ string_of_int is);
82 | print_endline ("* Final States: " ^ string_of_states final);
83 | print_endline "* Transition";
84 | BatMap.iter (fun (s,x) nexts ->
85 | print_endline (string_of_int s ^ " ----- " ^ string_of_symbol_op x ^ " -----> " ^ string_of_states nexts)
86 | ) delta
87 |
--------------------------------------------------------------------------------
/homework/hw1/code/nfa.mli:
--------------------------------------------------------------------------------
1 | open Regex
2 |
3 | type state = int
4 | type states = state BatSet.t
5 | type delta = (state * symbol option, states) BatMap.t
6 |
7 | type t
8 |
9 | (* create a new NFA state *)
10 | val mk_new_state : unit -> state
11 |
12 | (* create a new NFA containing a single start state *)
13 | val mk_new_nfa : unit -> t
14 |
15 | (* return the set of all states of NFA *)
16 | val get_states : t -> states
17 |
18 | (* return the transition function *)
19 | val get_delta : t -> delta
20 |
21 | (* return the NFA's initial state *)
22 | val get_initial_state : t -> state
23 |
24 | (* return the set of final states *)
25 | val get_final_states : t -> states
26 |
27 | (* get the next states that are directly reachable *)
28 | val get_next_states : t -> state -> symbol option -> states
29 |
30 | (* check if a state is final *)
31 | val is_final_state : t -> state -> bool
32 |
33 | (* add a set of states into NFA *)
34 | val add_states : states -> t -> t
35 |
36 | (* add a state as a final state *)
37 | val add_final_state : state -> t -> t
38 |
39 | (* add a transition, i.e., update a transition function *)
40 | val add_edge : (state * symbol option * state) -> t -> t
41 |
42 | (* add a transition function into NFA *)
43 | val add_delta : delta -> t -> t
44 |
45 | (* string representation of NFA states *)
46 | val string_of_states : states -> string
47 |
48 | (* print NFA *)
49 | val print : t -> unit
50 |
--------------------------------------------------------------------------------
/homework/hw1/code/regex.ml:
--------------------------------------------------------------------------------
1 | type t =
2 | | Empty
3 | | Epsilon
4 | | Symbol of symbol
5 | | SymbolSet of symbol * symbol (* regex shorthand. SymbolSet (c1,c2) = [c1-c2] *)
6 | | OR of t * t
7 | | CONCAT of t * t
8 | | STAR of t
9 | | POS of t
10 |
11 | and symbol = char
12 |
13 | let string_of_symbol = Char.escaped
14 |
15 | (* enumerate symbols within a range *)
16 | (* e.g., range 'a' 'd' = ['a';'b';'c';'d'] *)
17 | let range : symbol -> symbol -> symbol list
18 | = fun a b ->
19 | List.init (Char.code b - Char.code a + 1) (fun i -> Char.chr (Char.code a + i))
20 |
21 | (* a set of input symbols: a-z, A-Z, 0-9, _ *)
22 | let alphabet : symbol list =
23 | range 'a' 'z' @ range 'A' 'Z' @ range '0' '9' @ ['_']
24 |
--------------------------------------------------------------------------------
/homework/hw1/hw1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/homework/hw1/hw1.pdf
--------------------------------------------------------------------------------
/homework/hw2/README.md:
--------------------------------------------------------------------------------
1 | # HW2 (Due: Dec 11)
2 | Complete ``parser.mly``, ``absDom.ml``, and ``itvAnalysis.ml``. Submit the three files on GIST LMS.
3 | Read ``hw2.pdf`` for further details.
4 |
--------------------------------------------------------------------------------
/homework/hw2/code/_tags:
--------------------------------------------------------------------------------
1 | true: package(batteries), package(str)
2 |
--------------------------------------------------------------------------------
/homework/hw2/code/absDom.ml:
--------------------------------------------------------------------------------
1 | open Lang
2 | open Vocab
3 |
4 | module AbsBool = struct
5 | type t = Top | Bot | True | False
6 |
7 | let porder : t -> t -> bool
8 | = fun b1 b2 ->
9 | if b1 = b2 then true
10 | else
11 | match b1,b2 with
12 | | Bot,_ -> true
13 | | _,Top -> true
14 | | _ -> false
15 |
16 | let join : t -> t -> t
17 | = fun b1 b2 ->
18 | if porder b1 b2 then b2
19 | else if porder b2 b1 then b1
20 | else
21 | match b1,b2 with
22 | | True,False
23 | | False,True -> Top
24 | | _ -> assert false
25 |
26 | let alpha : bool -> t
27 | = fun b -> if b then True else False
28 |
29 | let to_string : t -> string
30 | = fun t ->
31 | match t with
32 | | Bot -> "bot"
33 | | False -> "false"
34 | | True -> "true"
35 | | Top -> "top"
36 |
37 | let bnot : t -> t
38 | = fun b ->
39 | match b with
40 | | Bot -> Bot
41 | | True -> False
42 | | False -> True
43 | | Top -> Top
44 |
45 | let eq : t -> t -> t
46 | = fun b1 b2 ->
47 | match b1,b2 with
48 | | Bot,_
49 | | _,Bot -> Bot
50 | | True,True -> True
51 | | False,False -> False
52 | | _ -> Top
53 |
54 | let neq : t -> t -> t
55 | = fun b1 b2 -> bnot (eq b1 b2)
56 |
57 | let bor : t -> t -> t
58 | = fun b1 b2 -> raise NotImplemented (* TODO *)
59 |
60 | let band : t -> t -> t
61 | = fun b1 b2 ->
62 | match b1,b2 with
63 | | Bot,_
64 | | _,Bot -> Bot
65 | | True,True -> True
66 | | False,_
67 | | _,False -> False
68 | | _ -> Top
69 | end
70 |
71 | module Itv = struct
72 | type t' =
73 | | V of int
74 | | PInf
75 | | NInf
76 |
77 | type t = Itv of t' * t' | Bot
78 |
79 | let top = Itv (NInf, PInf)
80 | let bot = Bot
81 |
82 | let alpha : int -> t
83 | = fun n -> Itv (V n, V n)
84 |
85 | let to_string' : t' -> string
86 | = fun v ->
87 | match v with
88 | | V n -> string_of_int n
89 | | PInf -> "+oo"
90 | | NInf -> "-oo"
91 |
92 | let to_string : t -> string
93 | = fun itv ->
94 | match itv with
95 | | Itv (l,u) -> "[" ^ (to_string' l) ^ ", " ^ (to_string' u) ^"]"
96 | | Bot -> "bot"
97 |
98 | let leq' : t' -> t' -> bool
99 | = fun v1 v2 ->
100 | match v1,v2 with
101 | | NInf,_ -> true
102 | | _,PInf -> true
103 | | V n1,V n2 -> n1<=n2
104 | | _,_ -> false
105 |
106 | let eq' : t' -> t' -> bool
107 | = fun v1 v2 ->
108 | match v1,v2 with
109 | | NInf,NInf
110 | | PInf,PInf -> true
111 | | V n1,V n2 -> n1=n2
112 | | _,_ -> false
113 |
114 | let lt' : t' -> t' -> bool
115 | = fun v1 v2 -> leq' v1 v2 && not (eq' v1 v2)
116 |
117 | let gt' : t' -> t' -> bool
118 | = fun v1 v2 -> not (leq' v1 v2)
119 |
120 | let ge' : t' -> t' -> bool
121 | = fun v1 v2 -> not (lt' v1 v2)
122 |
123 | let min' : t' -> t' -> t'
124 | = fun v1 v2 -> if leq' v1 v2 then v1 else v2
125 |
126 | let max' : t' -> t' -> t'
127 | = fun v1 v2 -> if leq' v1 v2 then v2 else v1
128 |
129 | let plus' : t' -> t' -> t'
130 | = fun v1 v2 ->
131 | match v1,v2 with
132 | | V n1,V n2 -> V (n1+n2)
133 | | PInf,NInf
134 | | NInf,PInf -> assert false
135 | | PInf,_ -> PInf
136 | | NInf,_ -> NInf
137 | | _,PInf -> PInf
138 | | _,NInf -> NInf
139 |
140 | let minus' : t' -> t' -> t'
141 | = fun v1 v2 ->
142 | match v1,v2 with
143 | | V n1,V n2 -> V (n1-n2)
144 | | PInf,PInf
145 | | NInf,NInf -> assert false
146 | | PInf,_ -> PInf
147 | | NInf,_ -> NInf
148 | | _,PInf -> NInf
149 | | _,NInf -> PInf
150 |
151 | let mul' : t' -> t' -> t'
152 | = fun v1 v2 ->
153 | match v1,v2 with
154 | | V n1,V n2 -> V (n1*n2)
155 | | PInf,PInf
156 | | NInf,NInf -> PInf
157 | | PInf,NInf
158 | | NInf,PInf -> NInf
159 | | PInf,V n
160 | | V n,PInf ->
161 | if n>0 then PInf
162 | else if n<0 then NInf
163 | else V 0
164 | | NInf,V n
165 | | V n,NInf ->
166 | if n>0 then NInf
167 | else if n<0 then PInf
168 | else V 0
169 |
170 | let is_bot : t -> bool
171 | = fun itv ->
172 | match itv with
173 | | Bot -> true
174 | | Itv (l,u) -> l = PInf || u = NInf || not (leq' l u)
175 |
176 | let porder : t -> t -> bool
177 | = fun itv1 itv2 ->
178 | if is_bot itv1 then true
179 | else if is_bot itv2 then false
180 | else
181 | match itv1,itv2 with
182 | | Itv (l1,u1),Itv (l2,u2) -> leq' l2 l1 && leq' u1 u2
183 | | _ -> assert false
184 |
185 | (* binary least upper bound *)
186 | let join : t -> t -> t
187 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
188 |
189 | let widen : t -> t -> t
190 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
191 |
192 | let narrow : t -> t -> t
193 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
194 |
195 | (*************************************)
196 | (*** Abstract Arithmetic Operators ***)
197 | (*************************************)
198 | let plus : t -> t -> t
199 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
200 |
201 | let minus : t -> t -> t
202 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
203 |
204 | let mul : t -> t -> t
205 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
206 |
207 | (*********************************)
208 | (*** Abstract Binary Relations ***)
209 | (*********************************)
210 | let eq : t -> t -> AbsBool.t
211 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
212 |
213 | let neq : t -> t -> AbsBool.t
214 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
215 |
216 | let leq : t -> t -> AbsBool.t
217 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
218 |
219 | let lt : t -> t -> AbsBool.t
220 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
221 |
222 | let geq : t -> t -> AbsBool.t
223 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
224 |
225 | let gt : t -> t -> AbsBool.t
226 | = fun itv1 itv2 -> raise NotImplemented (* TODO *)
227 |
228 | end
229 |
230 | module AbsMem = struct
231 | module Variable = struct type t = var let compare = Stdlib.compare end
232 | module Map = Map.Make(Variable) (* key domain: variable *)
233 | type t = Itv.t Map.t (* map domain: var -> Itv.t *)
234 |
235 | let empty = Map.empty
236 | let add = Map.add
237 | let find x m = try Map.find x m with _ -> Itv.bot
238 |
239 | let join : t -> t -> t
240 | = fun m1 m2 ->
241 | let f k v1 v2 =
242 | match v1,v2 with
243 | | None,None -> None
244 | | Some v,None -> Some v
245 | | None,Some v -> Some v
246 | | Some v1,Some v2 -> Some (Itv.join v1 v2)
247 | in
248 | Map.merge f m1 m2
249 |
250 | let widen : t -> t -> t
251 | = fun m1 m2 ->
252 | let f k v1 v2 =
253 | match v1,v2 with
254 | | None,None -> None
255 | | Some v,None -> Some v
256 | | None,Some v -> Some v
257 | | Some v1,Some v2 -> Some (Itv.widen v1 v2)
258 | in
259 | Map.merge f m1 m2
260 |
261 | let narrow : t -> t -> t
262 | = fun m1 m2 ->
263 | let f k v1 v2 =
264 | match v1,v2 with
265 | | None,None -> None
266 | | Some v,None -> Some v
267 | | None,Some v -> Some v
268 | | Some v1,Some v2 -> Some (Itv.narrow v1 v2)
269 | in
270 | Map.merge f m1 m2
271 |
272 | let porder : t -> t -> bool
273 | = fun m1 m2 -> Map.for_all (fun x v -> Itv.porder v (find x m2)) m1
274 |
275 | let print : t -> unit
276 | = fun m ->
277 | if Map.is_empty m then print_endline "empty"
278 | else
279 | Map.iter (fun x v -> print_endline (x ^ " |-> " ^ Itv.to_string v)) m
280 | end
281 |
--------------------------------------------------------------------------------
/homework/hw2/code/build:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TARGET=main.native
4 | INCLUDE_DIRS=lib
5 |
6 | function clean
7 | {
8 | ocamlbuild -clean
9 | exit 0
10 | }
11 |
12 | while [ $# -ne 0 ] && [ ! -z $1 ]; do
13 | case $1 in
14 | debug|clean|rebuild) "$1" ;;
15 | *) echo "build: invalid argument $1" && exit 1 ;;
16 | esac
17 | shift
18 | done
19 |
20 |
21 | time ocamlbuild $TARGET -use-ocamlfind -Is $INCLUDE_DIRS -tag thread
22 |
--------------------------------------------------------------------------------
/homework/hw2/code/itvAnalysis.ml:
--------------------------------------------------------------------------------
1 | open Vocab
2 | open Lang
3 | open AbsDom
4 | open AbsDom.Itv
5 |
6 | let rec eval_c : cmd -> AbsMem.t * int -> AbsMem.t * int
7 | = fun cmd (m,proven) -> raise NotImplemented (* TODO *)
8 |
9 | let init_param m (typ,x) =
10 | match typ with
11 | | T_Int -> AbsMem.add x Itv.top m
12 | | T_Array n ->
13 | m |> AbsMem.add x Itv.top
14 | |> AbsMem.add ("len_" ^ x) (Itv.alpha n)
15 |
16 | let run : pgm -> int
17 | = fun (fid,params,cmd) ->
18 | let m0 = List.fold_left init_param AbsMem.empty params in
19 | print_endline "[INFO] initial memory state";
20 | AbsMem.print m0;
21 | snd (eval_c cmd (m0,0))
22 |
--------------------------------------------------------------------------------
/homework/hw2/code/lang.ml:
--------------------------------------------------------------------------------
1 | open Vocab
2 |
3 | type pgm = fid * param list * cmd
4 | and fid = string
5 | and param = typ * var
6 | and var = string
7 |
8 | and typ =
9 | | T_Int
10 | | T_Array of int
11 |
12 | and lv =
13 | | Var of var
14 | | Arr of var * aexp
15 |
16 | and aexp =
17 | | Int of int
18 | | Len of var
19 | | Lv of lv
20 | | Plus of aexp * aexp
21 | | Minus of aexp * aexp
22 | | Mul of aexp * aexp
23 |
24 | and bexp =
25 | | True
26 | | False
27 | | Eq of aexp * aexp
28 | | Neq of aexp * aexp
29 | | Leq of aexp * aexp
30 | | Lt of aexp * aexp
31 | | Geq of aexp * aexp
32 | | Gt of aexp * aexp
33 | | Not of bexp
34 | | Or of bexp * bexp
35 | | And of bexp * bexp
36 |
37 | and cmd =
38 | | Decl of typ * var
39 | | Assign of lv * aexp
40 | | Skip
41 | | Seq of cmd * cmd
42 | | If of bexp * cmd * cmd
43 | | While of bexp * cmd
44 | | Assert of bexp
45 |
46 | let rec to_string_typ : typ -> string
47 | = fun t ->
48 | match t with
49 | | T_Int -> "int"
50 | | T_Array n -> "int" ^ "[" ^ string_of_int n ^ "]"
51 |
52 | let rec to_string_cmd ?(indent="") : cmd -> string
53 | = fun cmd ->
54 | match cmd with
55 | | Decl (t,x) -> indent ^ to_string_typ t ^ " " ^ x ^ ";"
56 | | Assign (lv,a) -> indent ^ to_string_lv lv ^ " = " ^ to_string_aexp a ^ ";"
57 | | Skip -> indent ^ "skip;"
58 | | Assert b -> indent ^ "assert" ^ "(" ^ to_string_bexp b ^ ")" ^ ";"
59 | | Seq (c1,c2) -> to_string_cmd ~indent c1 ^ "\n" ^ to_string_cmd ~indent c2
60 | | If (b,c1,c2) ->
61 | indent ^
62 | "if" ^ "(" ^ to_string_bexp b ^ ")" ^ "{" ^ "\n" ^
63 | to_string_cmd ~indent:(" " ^ indent) c1 ^ "\n" ^
64 | indent ^ "}" ^ "\n" ^
65 | indent ^
66 | "else" ^ "{" ^ "\n" ^
67 | to_string_cmd ~indent:(" " ^ indent) c2 ^ "\n" ^
68 | indent ^ "}"
69 | | While (b,c) ->
70 | indent ^ "while" ^ " " ^ "(" ^ to_string_bexp b ^ ")" ^ " " ^ "{\n" ^
71 | to_string_cmd ~indent:(" " ^ indent) c ^ "\n" ^
72 | indent ^ "}"
73 |
74 | and to_string_aexp : aexp -> string
75 | = fun ae ->
76 | match ae with
77 | | Int n -> string_of_int n
78 | | Len x -> "len(" ^ x ^ ")"
79 | | Lv lv -> to_string_lv lv
80 | | Plus (a1,a2) -> to_string_aexp a1 ^ " + " ^ to_string_aexp a2
81 | | Minus (a1,a2) -> to_string_aexp a1 ^ " - " ^ to_string_aexp a2
82 | | Mul (a1,a2) -> to_string_aexp a1 ^ " * " ^ to_string_aexp a2
83 |
84 | and to_string_bexp : bexp -> string
85 | = fun be ->
86 | match be with
87 | | True -> "true"
88 | | False -> "false"
89 | | Eq (a1,a2) -> to_string_aexp a1 ^ " == " ^ to_string_aexp a2
90 | | Neq (a1,a2) -> to_string_aexp a1 ^ " != " ^ to_string_aexp a2
91 | | Leq (a1,a2) -> to_string_aexp a1 ^ " <= " ^ to_string_aexp a2
92 | | Lt (a1,a2) -> to_string_aexp a1 ^ " < " ^ to_string_aexp a2
93 | | Geq (a1,a2) -> to_string_aexp a1 ^ " >= " ^ to_string_aexp a2
94 | | Gt (a1,a2) -> to_string_aexp a1 ^ " > " ^ to_string_aexp a2
95 | | Not b -> "!" ^ "(" ^ to_string_bexp b ^ ")"
96 | | Or (b1,b2) -> "(" ^ to_string_bexp b1 ^ " || " ^ to_string_bexp b2 ^ ")"
97 | | And (b1,b2) -> "(" ^ to_string_bexp b1 ^ " && " ^ to_string_bexp b2 ^ ")"
98 |
99 | and to_string_lv : lv -> string
100 | = fun lv ->
101 | match lv with
102 | | Var x -> x
103 | | Arr (x,a) -> x ^ "[" ^ to_string_aexp a ^ "]"
104 |
105 | let to_string_param (typ,var) = to_string_typ typ ^ " " ^ var
106 |
107 | let to_string_params params =
108 | string_of_list ~first:"(" ~sep:", " ~last:")" to_string_param params
109 |
110 | let to_string_pgm (fname,params,cmd) =
111 | fname ^ " " ^ to_string_params params ^ " " ^ "{\n" ^
112 | to_string_cmd ~indent:" " cmd ^ "\n" ^
113 | "}\n"
114 |
--------------------------------------------------------------------------------
/homework/hw2/code/lexer.mll:
--------------------------------------------------------------------------------
1 | {
2 | open Parser
3 | exception Eof
4 | exception LexicalError
5 | let comment_depth = ref 0
6 | let keyword_tbl = Hashtbl.create 31
7 | let _ = List.iter (fun (keyword,tok) -> Hashtbl.add keyword_tbl keyword tok)
8 | [
9 | ("true", TRUE);
10 | ("false", FALSE);
11 | ("if", IF);
12 | ("else", ELSE);
13 | ("while", WHILE);
14 | ("assert", ASSERT);
15 | ("int", INT);
16 | ("len", LEN);
17 | ]
18 | }
19 |
20 | let blank = [' ' '\n' '\t' '\r']+
21 | let id = ['a'-'z' 'A'-'Z']['a'-'z' 'A'-'Z' '\'' '0'-'9' '_']*
22 | let number = ['0'-'9']+
23 |
24 | rule start = parse
25 | | blank { start lexbuf }
26 | | "(*" { comment_depth :=1;
27 | comment lexbuf;
28 | start lexbuf }
29 | | "+" {PLUS} | "-" {MINUS} | "*" {MUL}
30 | | "=" {EQ} | "==" {EQEQ} | "!=" {NEQ}
31 | | "<" {LT} | "<=" {LE} | ">" {GT} | ">=" {GE}
32 | | "!" {NOT} | "&&" {AND} | "||" {OR}
33 | | "," {COMMA} | ";" {SEMICOLON}
34 | | "(" {LPAREN} | ")" {RPAREN}
35 | | "{" {LBRACE} | "}" {RBRACE}
36 | | "[" {LBRACKET} | "]" {RBRACKET}
37 | | number {NUM (int_of_string (Lexing.lexeme lexbuf))}
38 | | id {let id = Lexing.lexeme lexbuf in
39 | try Hashtbl.find keyword_tbl id
40 | with _ -> ID id}
41 | | eof {EOF}
42 | | _ { print_endline (Lexing.lexeme lexbuf); raise LexicalError }
43 |
44 | and comment = parse
45 | | "(*" {comment_depth := !comment_depth+1; comment lexbuf}
46 | | "*)" {comment_depth := !comment_depth-1;
47 | if !comment_depth > 0 then comment lexbuf }
48 | | eof {raise Eof}
49 | | _ {comment lexbuf}
50 |
--------------------------------------------------------------------------------
/homework/hw2/code/main.ml:
--------------------------------------------------------------------------------
1 | open Lang
2 | open Vocab
3 | open Options
4 |
5 | let main () =
6 | let usageMsg = "./main.native -input filename" in
7 | let _ = Arg.parse options (fun s->()) usageMsg in
8 | let file_channel = open_in !inputfile in
9 | let lexbuf = Lexing.from_channel file_channel in
10 | let pgm = Parser.program Lexer.start lexbuf in
11 | let _ = print_endline "========== Program ==========" in
12 | let _ = print_endline (to_string_pgm pgm) in
13 | let t0 = Sys.time () in
14 | let _ =
15 | print_endline "========== Processing ==========";
16 | let proven = ItvAnalysis.run pgm in
17 | print_endline "========== Result ==========";
18 | print_endline ("- # Proven : " ^ string_of_int proven) in
19 | let t1 = Sys.time () in
20 | print_endline ("- Time : " ^ string_of_float (t1 -. t0) ^ "seconds")
21 |
22 | let _ = main ()
23 |
--------------------------------------------------------------------------------
/homework/hw2/code/options.ml:
--------------------------------------------------------------------------------
1 | let inputfile = ref ""
2 |
3 | let options =
4 | [
5 | ("-input", (Arg.String (fun s -> inputfile := s)), "inputfile containing your examples");
6 | ]
7 |
--------------------------------------------------------------------------------
/homework/hw2/code/parser.mly:
--------------------------------------------------------------------------------
1 | %{
2 | open Lang
3 | module L = Lang
4 | %}
5 |
6 | %token NUM
7 | %token ID
8 | %token TRUE FALSE
9 |
10 | %token LEN
11 | %token INT
12 | %token PLUS MINUS MUL EQ EQEQ NEQ
13 | %token LE LT GE GT NOT OR AND
14 | %token IF WHILE COMMA ELSE ASSERT SEMICOLON
15 | %token LBRACE RBRACE LBRACKET RBRACKET LPAREN RPAREN EOF
16 |
17 | %left SEMICOLON
18 | %right OR
19 | %right AND
20 | %nonassoc LT LE GT GE EQEQ NEQ
21 | %left PLUS MINUS
22 | %left MUL
23 | %right NOT
24 |
25 | %start program
26 | %type program
27 |
28 | %%
29 |
30 | program:
31 | ID LPAREN params RPAREN
32 | LBRACE cmd RBRACE EOF
33 | {($1,$3,$6)}
34 |
35 | params:
36 | | param COMMA params {$1::$3}
37 | | param {[$1]}
38 |
39 | param:
40 | | typ ID { ($1,$2) }
41 |
42 | typ:
43 | | INT { T_Int }
44 | | INT LBRACKET NUM RBRACKET { T_Array $3 }
45 |
46 | cmd:
47 | | atom_cmd SEMICOLON { $1 }
48 | | atom_cmd SEMICOLON cmd {L.Seq ($1, $3)}
49 | | compound_cmd { $1 }
50 | | compound_cmd cmd {L.Seq ($1,$2)}
51 |
52 | atom_cmd:
53 | | typ ID { L.Decl ($1, $2) }
54 | | lv EQ aexp { L.Assign ($1, $3) }
55 | | ASSERT LPAREN bexp RPAREN {L.Assert ($3)}
56 |
57 | compound_cmd:
58 | | IF LPAREN bexp RPAREN LBRACE cmd RBRACE ELSE LBRACE cmd RBRACE {L.If ($3,$6,$10)}
59 | | IF LPAREN bexp RPAREN LBRACE cmd RBRACE {L.If ($3,$6,L.Skip)}
60 | | WHILE
61 | LPAREN bexp RPAREN
62 | LBRACE cmd RBRACE {L.While ($3,$6)}
63 |
64 | aexp: (* TODO *)
65 | | MINUS NUM {L.Int ($2* (-1))}
66 | | NUM {L.Int $1}
67 |
68 | bexp: (* TODO *)
69 | | TRUE {L.True}
70 |
71 | lv:
72 | | ID {L.Var $1}
73 | | ID LBRACKET aexp RBRACKET {L.Arr ($1,$3)}
74 |
75 | %%
76 |
--------------------------------------------------------------------------------
/homework/hw2/code/test/array:
--------------------------------------------------------------------------------
1 | (* expected output: 4 *)
2 |
3 | array (int n) {
4 | int i;
5 | int j;
6 | int[10] a;
7 | int[10] b;
8 |
9 | assert (len(a) == 10); (* safe, provable *)
10 |
11 | i = 0;
12 | while (i < 10) {
13 | assert(i < len(a)); (* safe, provable *)
14 | a[i] = i;
15 | assert(i < len(b)); (* safe, provable *)
16 | b[i] = i;
17 | i = i+1;
18 | j = j+1;
19 | }
20 |
21 | assert(i-1 < len(a)); (* safe, provable *)
22 | a[i-1] = 10;
23 |
24 | assert(i < len(a)); (* unsafe *)
25 | a[i] = 10;
26 |
27 | assert(j < len(a)); (* unsafe *)
28 | a[j] = 5;
29 | }
30 |
--------------------------------------------------------------------------------
/homework/hw2/code/test/loop1:
--------------------------------------------------------------------------------
1 | (* expected output: 2 *)
2 |
3 | loop1 (int n) {
4 | int i;
5 | int j;
6 |
7 | i = 0;
8 | j = 0;
9 |
10 | while (i!=n) {
11 | i = i+1;
12 | j = j+1;
13 | assert(1<=i); (* safe, provable *)
14 | assert(1<=j); (* safe, provable *)
15 | }
16 |
17 | assert (i==n); (* safe, but cannot be proven using our interval analysis *)
18 | assert (i==j); (* safe, but cannot be proven using our interval analysis *)
19 | }
20 |
--------------------------------------------------------------------------------
/homework/hw2/code/test/loop2:
--------------------------------------------------------------------------------
1 | (* expected output: 1 *)
2 |
3 | loop2 (int n) {
4 | int i;
5 | int j;
6 |
7 | i = 1;
8 | j = 1;
9 |
10 | while (i int
8 | = fun lst ->
9 | let fst = List.hd lst in
10 | List.fold_left (fun min n -> if min>n then n else min) fst lst
11 |
12 | let max : int list -> int
13 | = fun lst ->
14 | let fst = List.hd lst in
15 | List.fold_left (fun max n -> if max f (g x)
23 | let (>>>) f g = fun x -> g (f x)
24 |
25 | let id x = x
26 | let flip f = fun y x -> f x y
27 |
28 | let domof m = BatMap.foldi (fun k _ set -> BatSet.add k set) m BatSet.empty
29 |
30 | (** This applies [List.fold_left], but the argument type is the same with
31 | [PSet.fold]. *)
32 | let list_fold : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b
33 | = fun f list init ->
34 | List.fold_left (flip f) init list
35 |
36 | let list_fold2 : ('a -> 'b -> 'c -> 'c) -> 'a list -> 'b list -> 'c -> 'c
37 | = fun f list1 list2 init ->
38 | let f' acc a b = f a b acc in
39 | List.fold_left2 f' init list1 list2
40 |
41 | let list_rev : 'a list -> 'a list
42 | = fun l ->
43 | let rec list_rev_rec l1 l2 =
44 | match l1 with
45 | | [] -> l2
46 | | a :: b -> list_rev_rec b (a :: l2) in
47 | list_rev_rec l []
48 |
49 | let find_opt : 'a -> ('a, 'b) BatMap.t -> 'b option
50 | = fun k m ->
51 | try Some (BatMap.find k m) with
52 | | Not_found -> None
53 |
54 | let find_def : 'a -> ('a, 'b) BatMap.t -> 'b -> 'b
55 | = fun k m default ->
56 | BatOption.default default (find_opt k m)
57 |
58 | let link_by_sep sep s acc = if acc = "" then s else acc ^ sep ^ s
59 |
60 | let string_of_list ?(first="[") ?(last="]") ?(sep=",") : ('a -> string)
61 | -> ('a list) -> string
62 | = fun string_of_v list ->
63 | let add_string_of_v v acc = link_by_sep sep (string_of_v v) acc in
64 | first ^ list_fold add_string_of_v list "" ^ last
65 |
66 | let string_of_array ?(first="{") ?(last="}") ?(sep=",") : ('a -> string)
67 | -> ('a list) -> string
68 | = fun string_of_v list ->
69 | let add_string_of_v v acc = link_by_sep sep (string_of_v v) acc in
70 | first ^ list_fold add_string_of_v list "" ^ last
71 |
72 | let string_of_set ?(first="{") ?(last="}") ?(sep=",") : ('a -> string)
73 | -> ('a BatSet.t) -> string
74 | = fun string_of_v set ->
75 | let add_string_of_v v acc = link_by_sep sep (string_of_v v) acc in
76 | first ^ BatSet.fold add_string_of_v set "" ^ last
77 |
78 | let string_of_map ?(first="{") ?(last="}") ?(sep=",\n") : ('a -> string)
79 | -> ('b -> string) -> (('a, 'b) BatMap.t) -> string
80 | = fun string_of_k string_of_v map ->
81 | let add_string_of_k_v k v acc =
82 | let str = string_of_k k ^ " -> " ^ string_of_v v in
83 | link_by_sep sep str acc in
84 | if BatMap.is_empty map then "empty"
85 | else first ^ BatMap.foldi add_string_of_k_v map "" ^ last
86 |
87 | let list2set l = list_fold BatSet.add l BatSet.empty
88 | let set2list s = BatSet.fold (fun x l -> x::l) s []
89 |
90 | let set_union_small_big small big = BatSet.fold BatSet.add small big
91 |
92 | (* fixpoint operator for set *)
93 | let rec fix : ('a BatSet.t -> 'a BatSet.t) -> 'a BatSet.t -> 'a BatSet.t
94 | = fun f init ->
95 | let next = f init in
96 | if BatSet.subset next init then init
97 | else fix f next
98 |
--------------------------------------------------------------------------------
/homework/hw2/hw2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/homework/hw2/hw2.pdf
--------------------------------------------------------------------------------
/homework/hw3/README.md:
--------------------------------------------------------------------------------
1 | # HW3 (Due: 14:00, Dec 28)
2 | Complete ``translator.ml`` and ``optimizer.ml``. Submit the two files on GIST LMS.
3 | Read ``hw3.pdf`` for details.
4 |
--------------------------------------------------------------------------------
/homework/hw3/code/Makefile:
--------------------------------------------------------------------------------
1 | all: run
2 |
3 | run: lexer.cmo parser.cmo s.cmo t.cmo translator.cmo optimizer.cmo main.cmo
4 | ocamlfind ocamlc -thread -package batteries -linkpkg -o run lexer.cmo parser.cmo s.cmo t.cmo translator.cmo optimizer.cmo main.cmo
5 |
6 | s.cmo : s.ml
7 | ocamlfind ocamlc -thread -package batteries -linkpkg -c s.ml
8 |
9 | t.cmo : t.ml
10 | ocamlfind ocamlc -thread -package batteries -linkpkg -c t.ml
11 |
12 | translator.cmo : s.cmo t.cmo translator.ml
13 | ocamlc -c translator.ml
14 |
15 | optimizer.cmo : t.cmo
16 | ocamlfind ocamlc -thread -package batteries -linkpkg -c optimizer.ml
17 |
18 | parser.ml: parser.mly s.cmo
19 | ocamlyacc parser.mly
20 |
21 | parser.mli: parser.mly
22 | ocamlyacc parser.mly
23 |
24 | parser.cmi: parser.mli
25 | ocamlc -c parser.mli
26 |
27 | parser.cmo: parser.ml parser.cmi
28 | ocamlc -c parser.ml
29 |
30 | main.cmo : s.cmo t.cmo translator.cmo optimizer.cmo main.ml
31 | ocamlc -c main.ml
32 |
33 | lexer.cmo: lexer.ml
34 | ocamlc -c lexer.ml
35 |
36 | lexer.ml: lexer.mll parser.cmo
37 | ocamllex lexer.mll
38 |
39 | clean:
40 | rm -f *.cmx *.cmi parser.mli parser.ml lexer.ml run *.o *.cmo
41 |
--------------------------------------------------------------------------------
/homework/hw3/code/lexer.mll:
--------------------------------------------------------------------------------
1 | {
2 | open Parser
3 | exception Eof
4 | exception LexicalError
5 | let comment_depth = ref 0
6 | }
7 |
8 | let blank = [' ' '\n' '\t' '\r']+
9 | let id = ['a'-'z' 'A'-'Z']['a'-'z' 'A'-'Z' '0'-'9' '_']*
10 | let number = ['0'-'9']+
11 |
12 | rule start =
13 | parse blank { start lexbuf }
14 | | "/*" { comment_depth :=1; comment lexbuf; start lexbuf }
15 | | number { NUM (int_of_string (Lexing.lexeme lexbuf)) }
16 | | "int" { INT }
17 | | "if" { IF }
18 | | "else" { ELSE }
19 | | "while" { WHILE }
20 | | "do" { DO }
21 | | "read" { READ }
22 | | "print" { PRINT }
23 | | id { ID (Lexing.lexeme lexbuf) }
24 | | "+" { PLUS }
25 | | "-" { MINUS }
26 | | "*" { STAR }
27 | | "/" { SLASH }
28 | | "!" { NOT }
29 | | "==" { EQUALEQUAL }
30 | | "=" { EQUAL }
31 | | "<=" { LE }
32 | | "<" { LT }
33 | | ">=" { GE }
34 | | ">" { GT }
35 | | "{" { LBRACE }
36 | | "}" { RBRACE }
37 | | "]" { RBLOCK }
38 | | "[" { LBLOCK }
39 | | "(" { LPAREN }
40 | | ")" { RPAREN }
41 | | "&&" { AND }
42 | | "||" { OR }
43 | | ";" { SEMICOLON }
44 | | eof { EOF }
45 | | _ { raise LexicalError }
46 |
47 | and comment = parse
48 | "/*" {comment_depth := !comment_depth+1; comment lexbuf}
49 | | "*/" {comment_depth := !comment_depth-1;
50 | if !comment_depth > 0 then comment lexbuf }
51 | | eof {raise Eof}
52 | | _ {comment lexbuf}
53 |
--------------------------------------------------------------------------------
/homework/hw3/code/main.ml:
--------------------------------------------------------------------------------
1 | let main () =
2 | let print_code = ref false in
3 | let src = ref "" in
4 | let spec = [("-pp", Arg.Set print_code, "pretty print the input program")] in
5 | let usage = "Usage: run " in
6 | let _ = Arg.parse spec
7 | (fun
8 | x ->
9 | if Sys.file_exists x then src := x
10 | else raise (Arg.Bad (x ^ ": No files given")))
11 | usage
12 | in
13 |
14 | if !src = "" then Arg.usage spec usage
15 | else
16 | try
17 | let file_channel = open_in !src in
18 | let lexbuf = Lexing.from_channel file_channel in
19 | let s_pgm = Parser.program Lexer.start lexbuf in
20 | let _ = print_endline "== source program ==" in
21 | let _ = S.pp s_pgm in
22 | let _ = print_endline "== execution result (source) ==" in
23 | let _ = try S.execute s_pgm with (Failure s) -> print_endline ("Error: "^s) in
24 |
25 | let t_pgm = Translator.translate s_pgm in
26 | let _ = print_endline "== translated target program ==" in
27 | let _ = T.pp t_pgm in
28 | let _ = print_endline "== execution result (translated) ==" in
29 | let _ = try T.execute t_pgm with (Failure s) -> print_endline ("Error: "^s) in
30 | let t_pgm_opt = Optimizer.optimize t_pgm in
31 | let _ = print_endline "== optimized target program ==" in
32 | let _ = T.pp t_pgm_opt in
33 | let _ = print_endline "== execution result (optimized) ==" in
34 | try T.execute t_pgm_opt with (Failure s) -> print_endline ("Error: "^s)
35 |
36 | with (Failure s) -> print_endline (!src ^ ": " ^ s)
37 |
38 | let _ = main ()
39 |
--------------------------------------------------------------------------------
/homework/hw3/code/optimizer.ml:
--------------------------------------------------------------------------------
1 | exception NotImplemented
2 |
3 | let optimize : T.program -> T.program
4 | = fun t -> raise NotImplemented (* TODO *)
5 |
--------------------------------------------------------------------------------
/homework/hw3/code/parser.mly:
--------------------------------------------------------------------------------
1 | %{
2 |
3 | %}
4 |
5 | %token NUM
6 | %token ID
7 | %token INT PLUS MINUS STAR SLASH EQUAL EQUALEQUAL LE LT GE GT NOT AND OR IF ELSE WHILE DO READ PRINT SEMICOLON
8 | %token LBRACE RBRACE LBLOCK RBLOCK LPAREN RPAREN EOF
9 |
10 | %left SEMICOLON
11 | %left OR
12 | %left AND
13 | %left EQUALEQUAL
14 | %left LT LE GT GE
15 | %left PLUS MINUS
16 | %left STAR SLASH
17 | %right NOT
18 | %nonassoc LBRACE RBRACE LBLOCK RBLOCK LPAREN RPAREN
19 | %nonassoc ELSE
20 |
21 | %start program
22 | %type program
23 | %%
24 |
25 | program:
26 | block EOF { $1 }
27 |
28 | block:
29 | LBRACE decls stmts RBRACE { ($2,$3) }
30 |
31 | decls:
32 | | decls decl { $1@[$2] }
33 | | { [] }
34 |
35 | decl:
36 | | typ ID SEMICOLON { ($1,$2) }
37 |
38 | typ:
39 | | INT LBLOCK NUM RBLOCK { S.TARR ($3) }
40 | | INT { S.TINT }
41 |
42 | stmts:
43 | | stmts stmt { $1@[$2] }
44 | | { [] }
45 |
46 | stmt:
47 | | lv EQUAL exp SEMICOLON { S.ASSIGN ($1,$3) }
48 | | lv PLUS PLUS SEMICOLON { S.ASSIGN ($1,S.ADD(S.LV $1, S.ICONST 1)) }
49 | | IF LPAREN exp RPAREN stmt ELSE stmt { S.IF ($3,$5,$7) }
50 | | IF LPAREN exp RPAREN stmt { S.IF ($3,$5,S.BLOCK ([],[])) }
51 | | WHILE LPAREN exp RPAREN stmt { S.WHILE ($3,$5) }
52 | | DO stmt WHILE LPAREN exp RPAREN SEMICOLON { S.DOWHILE ($2,$5) }
53 | | READ LPAREN ID RPAREN SEMICOLON { S.READ $3 }
54 | | PRINT LPAREN exp RPAREN SEMICOLON { S.PRINT $3 }
55 | | block { S.BLOCK $1 }
56 |
57 | lv:
58 | | ID { S.ID $1 }
59 | | ID LBLOCK exp RBLOCK { S.ARR ($1, $3) }
60 |
61 | exp:
62 | | exp PLUS exp { S.ADD ($1,$3) }
63 | | exp MINUS exp { S.SUB ($1,$3) }
64 | | exp STAR exp { S.MUL ($1,$3) }
65 | | exp SLASH exp { S.DIV ($1,$3) }
66 | | MINUS exp { S.UMINUS $2 }
67 | | lv { S.LV $1 }
68 | | NUM { S.ICONST $1 }
69 | | NOT exp { S.NOT $2 }
70 | | exp EQUALEQUAL exp { S.EQ ($1,$3) }
71 | | exp LT exp { S.LT ($1,$3) }
72 | | exp LE exp { S.LE ($1,$3) }
73 | | exp GT exp { S.GT ($1,$3) }
74 | | exp GE exp { S.GE ($1,$3) }
75 | | exp OR exp { S.OR ($1,$3) }
76 | | exp AND exp { S.AND ($1,$3) }
77 | | LPAREN exp RPAREN { $2 }
78 |
--------------------------------------------------------------------------------
/homework/hw3/code/s.ml:
--------------------------------------------------------------------------------
1 | (****************************)
2 | (*** abstract syntax of S ***)
3 | (****************************)
4 |
5 | type program = block
6 | and block = decls * stmts
7 | and decls = decl list
8 | and decl = typ * id
9 | and typ = TINT | TARR of int
10 | and stmts = stmt list
11 | and id = string
12 | and stmt = ASSIGN of lv * exp
13 | | IF of exp * stmt * stmt
14 | | WHILE of exp * stmt
15 | | DOWHILE of stmt * exp
16 | | READ of id
17 | | PRINT of exp
18 | | BLOCK of block
19 | and lv = ID of id | ARR of id * exp
20 | and exp = ICONST of int (* integer constant *)
21 | | LV of lv
22 | | ADD of exp * exp
23 | | SUB of exp * exp
24 | | MUL of exp * exp
25 | | DIV of exp * exp
26 | | UMINUS of exp
27 | | NOT of exp
28 | | LT of exp * exp
29 | | LE of exp * exp
30 | | GT of exp * exp
31 | | GE of exp * exp
32 | | EQ of exp * exp
33 | | AND of exp * exp
34 | | OR of exp * exp
35 |
36 | (*************************************)
37 | (* interpreter for S *)
38 | (*************************************)
39 |
40 | type loc = VAR of string | ADDR of base * offset
41 | and base = int
42 | and offset = int
43 | type value = INT of int | ARRAY of base * size
44 | and size = int
45 |
46 | let str_of_loc l =
47 | match l with
48 | | VAR x -> x
49 | | ADDR (x,n) -> "(l"^(string_of_int x)^","^(string_of_int n)^")"
50 |
51 | let new_loc = ref 1
52 | module Memory = struct
53 | type t = (loc, value) BatMap.t
54 | let empty = BatMap.empty
55 | let bind l v m = BatMap.add l v m
56 | let lookup l m = try BatMap.find l m
57 | with _ -> raise (Failure ("Memory error: " ^ (str_of_loc l)))
58 | let alloc x size m =
59 | if size <= 0 then raise (Failure "alloc with non-positive size")
60 | else begin
61 | new_loc := !new_loc + 1;
62 | let rec helper offset m =
63 | if offset = size then m
64 | else helper (offset+1) (bind (ADDR (!new_loc,offset)) (INT 0) m) in
65 | bind (VAR x) (ARRAY (!new_loc, size)) (helper 0 m)
66 | end
67 | end
68 |
69 | type mem = Memory.t
70 |
71 | let list_fold f l a = List.fold_left (fun a e -> f e a) a l
72 |
73 | let rec run_block :block -> mem -> mem
74 | = fun (decls,stmts) m ->
75 | let m' = run_decls decls m in
76 | let m'' = run_stmts stmts m' in
77 | m''
78 |
79 | and run_decls : decls -> mem -> mem
80 | = fun decls m -> list_fold run_decl decls m
81 |
82 | and run_decl : decl -> mem -> mem
83 | = fun (typ,x) m ->
84 | match typ with
85 | | TINT -> Memory.bind (VAR x) (INT 0) m
86 | | TARR n -> Memory.alloc x n m
87 |
88 | and run_stmts : stmts -> mem -> mem
89 | = fun stmts m -> list_fold run_stmt stmts m
90 |
91 | and run_stmt : stmt -> mem -> mem
92 | = fun stmt m ->
93 | match stmt with
94 | | ASSIGN (lv, e) -> Memory.bind (eval_lv lv m) (eval e m) m
95 | | IF (e,stmt1,stmt2) ->
96 | (match eval e m with
97 | | INT 0 -> run_stmt stmt2 m
98 | | INT _ -> run_stmt stmt1 m
99 | | _ -> failwith "Error: IF")
100 | | WHILE (e,stmt) ->
101 | (match eval e m with
102 | | INT 0 -> m
103 | | INT _ ->
104 | let m1 = run_stmt stmt m in
105 | run_stmt (WHILE (e,stmt)) m1
106 | | _ -> failwith "Error : while")
107 | | DOWHILE (stmt,e) ->
108 | let m1 = run_stmt stmt m in
109 | (match eval e m1 with
110 | | INT 0 -> m1
111 | | INT _ -> run_stmt (DOWHILE (stmt,e)) m1
112 | | _ -> failwith "Error: dowhile")
113 | | READ x -> Memory.bind (VAR x) (INT (read_int ())) m
114 | | PRINT e ->
115 | (match eval e m with
116 | | INT n -> print_endline (string_of_int n); m
117 | | _ -> failwith "print: not an integer")
118 | | BLOCK b -> run_block b m
119 |
120 | and eval_int : exp -> mem -> int
121 | = fun e m ->
122 | match eval e m with
123 | | INT n -> n
124 | | _ -> failwith "Expression must evaluate to integer"
125 |
126 | and eval : exp -> mem -> value
127 | = fun e m ->
128 | match e with
129 | | ICONST n -> INT n
130 | | LV lv -> Memory.lookup (eval_lv lv m) m
131 | | ADD (e1,e2) -> INT ((eval_int e1 m) + (eval_int e2 m))
132 | | SUB (e1,e2) -> INT ((eval_int e1 m) - (eval_int e2 m))
133 | | MUL (e1,e2) -> INT ((eval_int e1 m) * (eval_int e2 m))
134 | | DIV (e1,e2) -> INT ((eval_int e1 m) / (eval_int e2 m))
135 | | UMINUS e -> INT (-(eval_int e m))
136 | | NOT e ->
137 | (match eval_int e m with
138 | | 0 -> INT 1
139 | | _ -> INT 0)
140 | | LT (e1,e2) -> if eval_int e1 m < eval_int e2 m then INT 1 else INT 0
141 | | LE (e1,e2) -> if eval_int e1 m <= eval_int e2 m then INT 1 else INT 0
142 | | GT (e1,e2) -> if eval_int e1 m > eval_int e2 m then INT 1 else INT 0
143 | | GE (e1,e2) -> if eval_int e1 m >= eval_int e2 m then INT 1 else INT 0
144 | | EQ (e1,e2) -> if eval_int e1 m = eval_int e2 m then INT 1 else INT 0
145 | | AND (e1,e2) ->
146 | (match eval_int e1 m, eval_int e2 m with
147 | |0,_
148 | |_,0 -> INT 0
149 | |_,_ -> INT 1)
150 | | OR (e1,e2) ->
151 | (match eval_int e1 m, eval_int e2 m with
152 | |0,0 -> INT 0
153 | |_,_ -> INT 1)
154 |
155 | and eval_lv : lv -> mem -> loc
156 | = fun lv m ->
157 | match lv with
158 | | ID x -> VAR x
159 | | ARR (x,e) ->
160 | (match Memory.lookup (VAR x) m with
161 | | ARRAY (base,size) ->
162 | (match eval e m with
163 | | INT idx ->
164 | if idx < 0 || idx >= size then raise (Failure ("Array out of bounds: offset: " ^
165 | string_of_int idx ^ " size: " ^ string_of_int size))
166 | else ADDR (base, idx)
167 | | _ -> raise (Failure ("index must be an integer")))
168 | | _ -> raise (Failure (x ^ " must be an array")))
169 |
170 |
171 | let execute : program -> unit
172 | = fun pgm -> ignore (run_block pgm Memory.empty)
173 |
174 | (*************************************)
175 | (* pretty printer for the S langauge *)
176 | (*************************************)
177 |
178 | let p x = print_string (x)
179 |
180 | let rec p_indent n = if n = 0 then () else (p " "; p_indent (n-1))
181 |
182 | let rec p_typ t =
183 | match t with
184 | | TINT -> p "int"
185 | | TARR (n) -> p "int"; p"[";print_int n; p"]"
186 |
187 | and p_lv lv =
188 | match lv with
189 | | ID x -> p x
190 | | ARR (x, e) -> p x; p "["; p_exp e; p "]"
191 |
192 | and p_exp e =
193 | begin
194 | match e with
195 | | ADD (e1,e2) -> p_exp e1; p "+"; p_exp e2
196 | | SUB (e1,e2) -> p_exp e1; p "-"; p_exp e2
197 | | MUL (e1,e2) -> p_exp e1; p "*"; p_exp e2
198 | | DIV (e1,e2) -> p_exp e1; p "/"; p_exp e2
199 | | UMINUS e -> p "-"; p_exp e
200 | | LV lv -> p_lv lv;
201 | | ICONST i -> print_int i
202 | | LT (e1,e2) -> p_exp e1; p "<"; p_exp e2
203 | | LE (e1,e2) -> p_exp e1; p "<="; p_exp e2
204 | | GT (e1,e2) -> p_exp e1; p ">"; p_exp e2
205 | | GE (e1,e2) -> p_exp e1; p ">="; p_exp e2
206 | | EQ (e1,e2) -> p_exp e1; p "=="; p_exp e2
207 | | NOT e -> p "!"; p_exp e
208 | | AND (e1,e2) -> p_exp e1; p"&&"; p_exp e2
209 | | OR (e1,e2) -> p_exp e1; p"||"; p_exp e2
210 | end
211 |
212 | and p_decl : int -> decl -> unit
213 | = fun indent (typ,var) ->
214 | p_indent indent;
215 | p_typ typ; p " "; p var; p ";"
216 |
217 | and p_stmt : int -> stmt -> unit
218 | = fun indent stmt ->
219 | p_indent indent;
220 | begin
221 | match stmt with
222 | | ASSIGN (lv, exp) -> p_lv lv; p " = "; p_exp exp; p ";"
223 | | IF (bexp,stmt1,stmt2) -> p "if "; p_exp bexp; p ""; p_stmt indent stmt1; p "else"; p_stmt indent stmt2
224 | | WHILE (b, s) -> p "while "; p_exp b; p ""; p_stmt indent s
225 | | DOWHILE (s,b) -> p "do"; p_stmt (indent+1) s; p_indent indent; p "while"; p_exp b; p";"
226 | | PRINT e -> p "print "; p_exp e; p ""; p";"
227 | | READ x -> p "read "; p x; p ""; p";"
228 | | BLOCK b -> p_block indent b
229 | end;
230 |
231 | and p_decls : int -> decls -> unit
232 | = fun indent decls -> List.iter (fun decl -> p_decl indent decl; p "\n") decls
233 |
234 | and p_stmts : int -> stmts -> unit
235 | = fun indent stmts -> List.iter (fun stmt -> p_stmt indent stmt; p "\n") stmts
236 |
237 | and p_block : int -> block -> unit
238 | = fun indent (decls,stmts) ->
239 | p_indent indent; p "{\n";
240 | p_decls (indent + 1) decls;
241 | p_stmts (indent + 1) stmts;
242 | p_indent indent; p "}\n"
243 |
244 | let pp : program -> unit
245 | = fun b -> p_block 0 b
246 |
--------------------------------------------------------------------------------
/homework/hw3/code/t.ml:
--------------------------------------------------------------------------------
1 | (***********************************)
2 | (* abstract syntax definition of T *)
3 | (***********************************)
4 |
5 | type program = linstr list
6 | and linstr = label * instr (* labeled instruction *)
7 | and instr =
8 | | SKIP
9 | | ALLOC of var * int (* x = alloc(n) *)
10 | | ASSIGNV of var * bop * var * var (* x = y bop z *)
11 | | ASSIGNC of var * bop * var * int (* x = y bop n *)
12 | | ASSIGNU of var * uop * var (* x = uop y *)
13 | | COPY of var * var (* x = y *)
14 | | COPYC of var * int (* x = n *)
15 | | UJUMP of label (* goto L *)
16 | | CJUMP of var * label (* if x goto L *)
17 | | CJUMPF of var * label (* ifFalse x goto L *)
18 | | LOAD of var * arr (* x = a[i] *)
19 | | STORE of arr * var (* a[i] = x *)
20 | | READ of var (* read x *)
21 | | WRITE of var (* write x *)
22 | | HALT
23 | and var = string
24 | and label = int
25 | and arr = var * var
26 | and bop = ADD | SUB | MUL | DIV | LT | LE | GT | GE | EQ | AND | OR
27 | and uop = MINUS | NOT
28 |
29 | let dummy_label = 0
30 |
31 | (*************************************)
32 | (* Interpreter for T *)
33 | (*************************************)
34 | type loc = VAR of var | ADDR of base * offset
35 | and value = INT of int | ARRAY of base * size
36 | and offset = int
37 | and size = int
38 | and base = int
39 |
40 | let string_of_value v =
41 | match v with
42 | | INT n -> string_of_int n
43 | | ARRAY (b,s) -> "array of size " ^ string_of_int s
44 |
45 | let rec range b e = if b = e then [b] else b::(range (b+1) e)
46 |
47 | let new_loc = ref 1
48 | module Memory = struct
49 | type t = (loc, value) BatMap.t
50 | let empty = BatMap.empty
51 | let alloc : t -> int -> t * (base * size)
52 | = fun mem n ->
53 | new_loc := !new_loc + 1;
54 | (List.fold_left (fun m offset ->
55 | BatMap.add (ADDR (!new_loc, offset)) (INT 0) m
56 | ) mem (range 0 (n-1)), (!new_loc,n))
57 | let bind = BatMap.add
58 | let lookup a m = try BatMap.find a m with _ -> raise (Failure "Memory error")
59 | end
60 |
61 | type state = pc * Memory.t
62 | and pc = int
63 | and l2pc = (label,pc) BatMap.t
64 | and global = program * l2pc
65 |
66 | let eval_binary : value -> bop -> value -> value
67 | = fun v1 op v2 ->
68 | match v1,op,v2 with
69 | | INT n1, ADD, INT n2 -> INT (n1+n2)
70 | | INT n1, SUB, INT n2 -> INT (n1-n2)
71 | | INT n1, MUL, INT n2 -> INT (n1*n2)
72 | | INT n1, DIV, INT n2 -> INT (n1/n2)
73 | | INT n1, LT, INT n2 -> if n1 < n2 then INT 1 else INT 0
74 | | INT n1, LE, INT n2 -> if n1 <= n2 then INT 1 else INT 0
75 | | INT n1, GT, INT n2 -> if n1 > n2 then INT 1 else INT 0
76 | | INT n1, GE, INT n2 -> if n1 >= n2 then INT 1 else INT 0
77 | | INT n1, EQ, INT n2 -> if n1 = n2 then INT 1 else INT 0
78 | | INT n1, AND, INT n2 -> if n1 != 0 && n2 != 0 then INT 1 else INT 0
79 | | INT n1, OR, INT n2 -> if n1 != 0 || n2 != 0 then INT 1 else INT 0
80 | | _ -> raise (Failure "T.eval_binary : invalid operands")
81 |
82 | let eval_unary : uop -> value -> value
83 | = fun op v ->
84 | match op, v with
85 | | MINUS, INT n -> INT (-n)
86 | | NOT, INT n -> if n = 0 then INT 1 else INT 0
87 | | _ -> raise (Failure "T.eval_unary: invalid operands")
88 |
89 | let get_array_location : arr -> Memory.t -> loc
90 | = fun (a,x) mem ->
91 | match Memory.lookup (VAR a) mem with
92 | | ARRAY (base, size) ->
93 | begin
94 | match Memory.lookup (VAR x) mem with
95 | | INT offset ->
96 | if offset < 0 || offset >= size then raise (Failure "T: invalid array index")
97 | else ADDR (base, offset)
98 | | _ -> raise (Failure "T: invalid array index")
99 | end
100 | | _ -> raise (Failure "T: invalid array")
101 |
102 | let get_instr : program -> pc -> instr
103 | = fun pgm pc ->
104 | let (_,instr) = List.nth pgm pc in
105 | instr
106 |
107 | let get_next_mem : instr -> Memory.t -> Memory.t
108 | = fun instr mem ->
109 | match instr with
110 | | ALLOC (x,n) ->
111 | let mem, (b,s) = Memory.alloc mem n in
112 | Memory.bind (VAR x) (ARRAY (b,s)) mem
113 | | ASSIGNV (x,o,y,z) ->
114 | let v_y = Memory.lookup (VAR y) mem in
115 | let v_z = Memory.lookup (VAR z) mem in
116 | let v_x = eval_binary v_y o v_z in
117 | Memory.bind (VAR x) v_x mem
118 | | ASSIGNC (x,o,y,n) ->
119 | let v_y = Memory.lookup (VAR y) mem in
120 | let v_x = eval_binary v_y o (INT n) in
121 | Memory.bind (VAR x) v_x mem
122 | | ASSIGNU (x,o,y) ->
123 | let v_y = Memory.lookup (VAR y) mem in
124 | let v_x = eval_unary o v_y in
125 | Memory.bind (VAR x) v_x mem
126 | | COPY (x,y) -> Memory.bind (VAR x) (Memory.lookup (VAR y) mem) mem
127 | | COPYC (x,c) -> Memory.bind (VAR x) (INT c) mem
128 | | LOAD (x,arr) ->
129 | let arrloc = get_array_location arr mem in
130 | let v_x = Memory.lookup arrloc mem in
131 | Memory.bind (VAR x) v_x mem
132 | | STORE (arr,x) ->
133 | let v_x = Memory.lookup (VAR x) mem in
134 | let arrloc = get_array_location arr mem in
135 | Memory.bind arrloc v_x mem
136 | | READ x ->
137 | let v = read_int () in
138 | Memory.bind (VAR x) (INT v) mem
139 | | WRITE x ->
140 | let v_x = Memory.lookup (VAR x) mem in
141 | (match v_x with
142 | | INT n -> print_endline (string_of_int n)
143 | | _ -> raise (Failure "WRITE: not an integer")
144 | );
145 | mem
146 | | _ -> mem
147 |
148 | let get_pc_of_label : global -> label -> pc
149 | = fun (_,l2pc) l -> try BatMap.find l l2pc with _ -> raise (Failure ("T: Label not found :"^ string_of_int l))
150 |
151 | let get_next_pc : global -> instr -> state -> pc
152 | = fun global instr (pc,mem) ->
153 | match instr with
154 | | UJUMP l -> get_pc_of_label global l
155 | | CJUMP (x,l) ->
156 | let v = Memory.lookup (VAR x) mem in
157 | begin
158 | match v with
159 | | INT n -> if n != 0 then get_pc_of_label global l else pc+1
160 | | _ -> raise (Failure "T: invalid operands for CJUMP")
161 | end
162 | | CJUMPF (x,l) ->
163 | let v = Memory.lookup (VAR x) mem in
164 | begin
165 | match v with
166 | | INT n -> if n = 0 then get_pc_of_label global l else pc+1
167 | | _ -> raise (Failure "T: invalid operands for CJUMP")
168 | end
169 | | _ -> pc+1
170 |
171 | let run : global -> state -> state
172 | = fun (pgm,l2pc) (pc,mem) ->
173 | let instr = get_instr pgm pc in
174 | let mem' = get_next_mem instr mem in
175 | let pc' = get_next_pc (pgm,l2pc) instr (pc,mem) in
176 | (pc',mem')
177 |
178 | let rec loop : global -> state -> int -> unit
179 | = fun (pgm,l2pc) (pc,mem) k ->
180 | if get_instr pgm pc = HALT then print_endline ("#instructions executed : " ^ string_of_int k)
181 | else loop (pgm,l2pc) (run (pgm,l2pc) (pc,mem)) (k+1)
182 |
183 | let get_label2pc : program -> l2pc
184 | = fun pgm ->
185 | let _,map =
186 | List.fold_left (fun (pc,map) (l,_) ->
187 | if l = dummy_label then (pc+1,map) else (pc+1,BatMap.add l pc map)
188 | ) (0,BatMap.empty) pgm in
189 | map
190 |
191 | let execute : program -> unit
192 | = fun pgm ->
193 | let l2pc = get_label2pc pgm in
194 | loop (pgm,l2pc) (0,Memory.empty) 0
195 |
196 | (*************************************)
197 | (* pretty printer for the T language *)
198 | (*************************************)
199 | let pp : program -> unit
200 | = fun pgm ->
201 | let ps = print_string in
202 | let pn = print_endline in
203 | let s_bop o = match o with ADD -> "+" | SUB -> "-" | MUL -> "*" | DIV -> "/"
204 | | LT -> "<" | LE -> "<=" | GT -> ">" | GE -> ">=" | EQ -> "==" | AND -> "&&" |
205 | OR -> "||" in
206 | let s_uop o = match o with MINUS -> "-" | NOT -> "!" in
207 | let s_arr (x,y) = x ^ "[" ^ y ^ "]" in
208 | List.iter (fun (label, instr) ->
209 | ps (string_of_int label ^ " : ");
210 | match instr with
211 | | HALT -> pn "HALT"
212 | | SKIP -> pn "SKIP"
213 | | ALLOC (x,n) -> pn (x ^ " = alloc (" ^ string_of_int n ^ ")")
214 | | ASSIGNV (x,o,y,z) -> pn (x ^ " = " ^ y ^ " " ^ s_bop o ^ " " ^ z)
215 | | ASSIGNC (x,o,y,n) -> pn (x ^ " = " ^ y ^ " " ^ s_bop o ^ " " ^ string_of_int n)
216 | | ASSIGNU (x,o,y) -> pn (x ^ " = " ^ s_uop o ^ y)
217 | | COPY (x,y) -> pn (x ^ " = " ^ y)
218 | | COPYC (x,n) -> pn (x ^ " = " ^ string_of_int n)
219 | | UJUMP label -> pn ("goto " ^ string_of_int label)
220 | | CJUMP (x,l) -> pn ("if " ^ x ^ " goto " ^ string_of_int l)
221 | | CJUMPF (x,l) -> pn ("iffalse " ^ x ^ " goto " ^ string_of_int l)
222 | | LOAD (x,a) -> pn (x ^ " = " ^ s_arr a)
223 | | STORE (a,x) -> pn (s_arr a ^ " = " ^ x)
224 | | READ x -> pn ("read " ^ x)
225 | | WRITE x -> pn ("write " ^ x)
226 | ) pgm
227 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/array.s:
--------------------------------------------------------------------------------
1 | {
2 | int[10] arr;
3 | int i;
4 |
5 | i = 0;
6 | while (i < 10) {
7 | arr[i] = i;
8 | i++;
9 | }
10 | print (i);
11 | }
12 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/fact.s:
--------------------------------------------------------------------------------
1 | {
2 | int n;
3 | int i;
4 | int s;
5 | int[10] a;
6 |
7 | i = 1;
8 | s = 1;
9 | read (n);
10 | while (i <= n) {
11 | s = s * i;
12 | i++;
13 | }
14 | print (s);
15 | }
16 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/fib.s:
--------------------------------------------------------------------------------
1 | /* Fibonacci number */
2 | {
3 | int x;
4 | int y;
5 | int z;
6 | int n;
7 | int i;
8 | x = 0;
9 | y = 1;
10 | z = 0;
11 | i = 0;
12 | read (n);
13 | while (i < n) {
14 | y = z + y;
15 | z = x;
16 | x = y;
17 | i++;
18 | }
19 | print (y);
20 | }
21 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/loop1.s:
--------------------------------------------------------------------------------
1 | /* Fibonacci number */
2 | {
3 | int x;
4 | int y;
5 | int n;
6 | int z;
7 | int i;
8 | int[10] fib;
9 | x = 0;
10 | y = 1;
11 | z = 0;
12 | i = 0;
13 | n = 10;
14 | while (i < n) {
15 | y = z + y;
16 | z = x;
17 | x = y;
18 | fib[i] = y;
19 | i++;
20 | }
21 | i = 0;
22 | while (i < n) {
23 | print (fib[i]);
24 | i++;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/loop2.s:
--------------------------------------------------------------------------------
1 | {
2 | int size;
3 | int[100] a;
4 | int i;
5 | int j;
6 | int cnt;
7 |
8 | i = 0;
9 | cnt = 0;
10 | while (i<10) {
11 | j = 0;
12 | while (j<10) {
13 | a[i*10+j] = cnt;
14 | j++;
15 | cnt++;
16 | }
17 | i++;
18 | }
19 | print (a[10]);
20 | print (a[20]);
21 | }
22 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/t0.s:
--------------------------------------------------------------------------------
1 | {
2 | int x;
3 | x = 0;
4 | print (x+1);
5 | }
6 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/t1.s:
--------------------------------------------------------------------------------
1 | {
2 | int x;
3 | x = -1; /* /* com */ ment */
4 |
5 | if (!x) {
6 | print (-1);
7 | } else {
8 | print (2);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/t2.s:
--------------------------------------------------------------------------------
1 | {
2 | int x; int y;
3 |
4 | x = 0;
5 | y = 0;
6 | while (x < 10) {
7 | x++;
8 | print (x);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/t3.s:
--------------------------------------------------------------------------------
1 | {
2 | int sum;
3 | int i;
4 |
5 | i = 0;
6 | sum = 0;
7 | while (i < 10) {
8 | sum = sum + i;
9 | i++;
10 | }
11 |
12 | print (sum);
13 | }
14 |
--------------------------------------------------------------------------------
/homework/hw3/code/test/t4.s:
--------------------------------------------------------------------------------
1 | {
2 | int x;
3 | read (x);
4 |
5 | if (x == 1 || x == 2) print (x); else print (x+1);
6 | }
7 |
--------------------------------------------------------------------------------
/homework/hw3/code/translator.ml:
--------------------------------------------------------------------------------
1 | exception NotImplemented
2 |
3 | let translate : S.program -> T.program
4 | = fun s -> raise NotImplemented (* TODO *)
5 |
--------------------------------------------------------------------------------
/homework/hw3/hw3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/homework/hw3/hw3.pdf
--------------------------------------------------------------------------------
/ocaml-examples/ex1.ml:
--------------------------------------------------------------------------------
1 | let rec append l1 l2 =
2 | match l1 with
3 | | [] -> l2
4 | | h::t -> h::(append t l2)
5 |
--------------------------------------------------------------------------------
/ocaml-examples/ex2.ml:
--------------------------------------------------------------------------------
1 | let rec reverse l =
2 | match l with
3 | | [] -> []
4 | | h::t -> (reverse t) @ [h]
5 |
--------------------------------------------------------------------------------
/ocaml-examples/ex3.ml:
--------------------------------------------------------------------------------
1 | let rec nth l n =
2 | match l with
3 | | [] -> raise (Failure "list is too short")
4 | | hd::tl -> if n = 0 then hd else nth tl (n-1)
5 |
6 | let tc = (([1;2;3], 2), 3)
7 |
8 | let run f ((l,n),out) = (f l n = out)
9 |
10 | let _ = print_endline (string_of_bool (run nth tc))
11 |
--------------------------------------------------------------------------------
/ocaml-examples/ex4.ml:
--------------------------------------------------------------------------------
1 | let rec remove_first a l =
2 | match l with
3 | | [] -> []
4 | | hd::tl ->
5 | if a=hd then tl
6 | else hd::(remove_first a tl)
7 |
--------------------------------------------------------------------------------
/ocaml-examples/ex5.ml:
--------------------------------------------------------------------------------
1 | let rec insert a l = (* assume increasing order *)
2 | match l with
3 | | [] -> [a]
4 | | hd::tl ->
5 | if a <= hd then a::hd::tl
6 | else hd::(insert a tl)
7 |
--------------------------------------------------------------------------------
/ocaml-examples/ex7.ml:
--------------------------------------------------------------------------------
1 | type exp =
2 | | Int of int
3 | | Minus of exp * exp
4 | | Plus of exp * exp
5 | | Mult of exp * exp
6 | | Div of exp * exp
7 |
8 | let rec eval : exp -> int
9 | = fun exp ->
10 | match exp with
11 | | Int n -> n
12 | | Minus (e1,e2) -> eval e1 - eval e2
13 | | Plus (e1,e2) -> eval e1 + eval e2
14 | | Mult (e1,e2) -> eval e1 * eval e2
15 | | Div (e1,e2) ->
16 | try eval e1 / eval e2
17 | with Division_by_zero -> failwith "eval e2 is zero"
18 |
19 | let exp1 = Int 3
20 | let exp2 = Plus (Int 3, Plus (Int 5, Mult (Int 2, Int 3)))
21 | let exp3 = Div (Plus (Int 1, Int 4), Minus (Int 3, Mult (Int 1, Int 3)))
22 |
23 | let _ = print_endline (string_of_int (eval exp1))
24 | let _ = print_endline (string_of_int (eval exp2))
25 | let _ = print_endline (string_of_int (eval exp3))
26 |
--------------------------------------------------------------------------------
/ocaml-examples/lec12/signAnalysis.ml:
--------------------------------------------------------------------------------
1 | exception NotImplemented
2 |
3 | (********************)
4 | (***** Language *****)
5 | (********************)
6 |
7 | type aexp =
8 | | Int of int
9 | | Var of var
10 | | Plus of aexp * aexp
11 | | Mul of aexp * aexp
12 | | Sub of aexp * aexp
13 |
14 | and var = string
15 |
16 | type bexp =
17 | | True | False
18 | | Eq of aexp * aexp
19 | | Leq of aexp * aexp
20 | | Not of bexp
21 | | And of bexp * bexp
22 |
23 | type cmd =
24 | | Assign of var * aexp
25 | | Skip
26 | | Seq of cmd * cmd
27 | | If of bexp * cmd * cmd
28 | | While of bexp * cmd
29 |
30 | (***************************)
31 | (***** Abstract Domain *****)
32 | (***************************)
33 |
34 | module Sign = struct
35 | type t = Top | Bot | Pos | Neg | Zero | NonPos | NonNeg | NonZero
36 |
37 | let porder : t -> t -> bool
38 | = fun s1 s2 ->
39 | match s1,s2 with
40 | | _ when s1 = s2 -> true
41 | | Bot,_ -> true
42 | | _,Top -> true
43 | | Neg,NonPos -> true
44 | | Neg,NonZero -> true
45 | | Zero,NonPos -> true
46 | | Zero,NonNeg -> true
47 | | Pos,NonZero -> true
48 | | Pos,NonNeg -> true
49 | | _ -> false
50 |
51 | let to_string : t -> string
52 | = fun t ->
53 | match t with
54 | | Top -> "top"
55 | | Bot -> "bot"
56 | | Pos -> "pos"
57 | | Neg -> "neg"
58 | | Zero -> "zero"
59 | | NonPos -> "nonpos"
60 | | NonNeg -> "nonneg"
61 | | NonZero -> "nonzero"
62 |
63 |
64 | let alpha' : int -> t
65 | = fun n ->
66 | if n>0 then Pos
67 | else if n=0 then Zero
68 | else Neg
69 |
70 | let join : t -> t -> t
71 | = fun s1 s2 ->
72 | if porder s1 s2 then s2
73 | else if porder s2 s1 then s1
74 | else
75 | match s1,s2 with
76 | | Neg,Pos
77 | | Pos,Neg -> NonZero
78 | | Neg,Zero
79 | | Zero,Neg -> NonPos
80 | | Zero,Pos
81 | | Pos,Zero -> NonNeg
82 | | _ -> Top
83 |
84 | let add : t -> t -> t
85 | = fun s1 s2 ->
86 | match s1,s2 with
87 | | Bot,_
88 | | _,Bot -> Bot
89 | | Top,_
90 | | _,Top -> Top
91 | | Neg,Neg -> Neg
92 | | Neg,Zero -> Neg
93 | | Neg,NonPos -> Neg
94 | | Neg,_ -> Top
95 | | Zero,_ -> s2
96 | | Pos,Zero
97 | | Pos,Pos
98 | | Pos,NonNeg -> Pos
99 | | Pos,_ -> Top
100 | | NonPos,Neg -> Neg
101 | | NonPos,Zero -> NonPos
102 | | NonPos,NonPos -> NonPos
103 | | NonPos,_ -> Top
104 | | NonZero,Zero -> NonZero
105 | | NonZero,_ -> Top
106 | | NonNeg,Zero -> NonNeg
107 | | NonNeg,Pos -> Pos
108 | | NonNeg,NonNeg -> NonNeg
109 | | NonNeg,_ -> Top
110 |
111 | let sub s1 s2 = raise NotImplemented (* TODO: exercise *)
112 | let mul s1 s2 = raise NotImplemented (* TODO: exercise *)
113 | end
114 |
115 | module AbsBool = struct
116 | open Sign
117 | type t = Top | Bot | True | False
118 |
119 | let porder : t -> t -> bool
120 | = fun b1 b2 ->
121 | if b1 = b2 then true
122 | else
123 | match b1,b2 with
124 | | Bot,_ -> true
125 | | _,Top -> true
126 | | _ -> false
127 |
128 | let to_string : t -> string
129 | = fun t ->
130 | match t with
131 | | Bot -> "bot"
132 | | False -> "false"
133 | | True -> "true"
134 | | Top -> "top"
135 |
136 | let not : t -> t
137 | = fun b ->
138 | match b with
139 | | Bot -> Bot
140 | | True -> False
141 | | False -> True
142 | | Top -> Top
143 |
144 | let band : t -> t -> t
145 | = fun b1 b2 ->
146 | match b1,b2 with
147 | | Bot,_
148 | | _,Bot -> Bot
149 | | True,True -> True
150 | | False,_
151 | | _,False -> False
152 | | _ -> Top
153 |
154 | let leq : Sign.t -> Sign.t -> t
155 | = fun s1 s2 ->
156 | match s1,s2 with
157 | | Bot,_ -> Bot
158 | | _,Bot -> Bot
159 | | Neg,_ when List.mem s2 [Zero;Pos;NonNeg] -> True
160 | | Zero,_ when List.mem s2 [Zero;Pos;NonNeg] -> True
161 | | Pos,_ -> Top
162 | | NonPos,_ when List.mem s2 [Pos] -> True
163 | | NonZero,_ -> Top
164 | | NonNeg,_ -> Top
165 | | _ -> Top
166 |
167 | let eq : Sign.t -> Sign.t -> t
168 | = fun s1 s2 ->
169 | match s1,s2 with
170 | | Bot,_ -> Bot
171 | | _,Bot -> Bot
172 | | Zero,_ when List.mem s2 [Neg;Pos;NonZero] -> False
173 | | Zero,Zero -> True
174 | | Pos,_ when List.mem s2 [Neg;Zero;NonPos] -> False
175 | | NonPos,Pos -> False
176 | | NonZero,Zero -> False
177 | | NonNeg,Neg -> False
178 | | _ -> Top
179 | end
180 |
181 | module AbsMem = struct
182 | (* reference : https://ocaml.org/manual/5.2/api/Map.Make.html *)
183 | module Map = Map.Make(String) (* key domain: variable *)
184 | type t = Sign.t Map.t (* map domain: string(var) -> Sign.t *)
185 |
186 | let empty = Map.empty
187 | let add = Map.add
188 | let find x m = try Map.find x m with _ -> Sign.Bot
189 |
190 | let join m1 m2 =
191 | let f k v1 v2 =
192 | match v1,v2 with
193 | | None,None -> None
194 | | Some v,None -> Some v
195 | | None,Some v -> Some v
196 | | Some v1,Some v2 -> Some (Sign.join v1 v2)
197 | in
198 | Map.merge f m1 m2
199 |
200 | let porder : t -> t -> bool
201 | = fun m1 m2 ->
202 | Map.for_all (fun x v -> Sign.porder v (find x m2)) m1
203 |
204 | let print : t -> unit
205 | = fun m ->
206 | if Map.is_empty m then print_endline "empty"
207 | else
208 | Map.iter (fun x v -> print_endline (x ^ " |-> " ^ Sign.to_string v)) m
209 | end
210 |
211 | (******************************)
212 | (***** Abstract Semantics *****)
213 | (******************************)
214 |
215 | let rec eval_a : aexp -> AbsMem.t -> Sign.t
216 | = fun a m ->
217 | match a with
218 | | Int n -> Sign.alpha' n
219 | | Var x -> AbsMem.find x m
220 | | Plus (a1, a2) -> Sign.add (eval_a a1 m) (eval_a a2 m)
221 | | Mul (a1, a2) -> Sign.mul (eval_a a1 m) (eval_a a2 m)
222 | | Sub (a1, a2) -> Sign.sub (eval_a a1 m) (eval_a a2 m)
223 |
224 | let rec eval_b : bexp -> AbsMem.t -> AbsBool.t
225 | = fun b m ->
226 | match b with
227 | | True -> AbsBool.True
228 | | False -> AbsBool.False
229 | | Eq (a1, a2) -> AbsBool.eq (eval_a a1 m) (eval_a a2 m)
230 | | Leq (a1, a2) -> AbsBool.leq (eval_a a1 m) (eval_a a2 m)
231 | | Not b -> AbsBool.not (eval_b b m)
232 | | And (b1, b2) -> AbsBool.band (eval_b b1 m) (eval_b b2 m)
233 |
234 | let rec eval_c : cmd -> AbsMem.t -> AbsMem.t
235 | = fun c m ->
236 | match c with
237 | | Assign (x,a) -> AbsMem.add x (eval_a a m) m
238 | | Skip -> m
239 | | Seq (c1,c2) -> eval_c c2 (eval_c c1 m)
240 | | If (b, c1, c2) -> cond (eval_b b, eval_c c1, eval_c c2) m
241 | | While (b, c) ->
242 | let onestep x = AbsMem.join m (eval_c c x) in
243 | let rec fix f x i =
244 | let x' = f x in
245 | if AbsMem.porder x' x then x
246 | else fix f x' (i+1)
247 | in
248 | fix onestep m 1
249 |
250 | and cond (f,g,h) m =
251 | match f m with
252 | | AbsBool.Bot -> AbsMem.empty
253 | | AbsBool.True -> g m
254 | | AbsBool.False -> h m
255 | | AbsBool.Top -> AbsMem.join (g m) (h m)
256 |
257 | (****************)
258 | (***** Test *****)
259 | (****************)
260 |
261 | let pgm =
262 | let l1 = Assign ("x", Int 0) in
263 | let l2 = Assign ("y", Int 0) in
264 | let l5 = Assign ("x", Plus (Var "x", Int 1)) in
265 | let l8 = Assign ("x", Plus (Var "x", Var "y")) in
266 | let l10 = Assign ("y", Plus (Var "y", Int 1)) in
267 | let loop =
268 | While (Leq (Var "y", Var "n"),
269 | Seq (If (Eq (Var "z", Int 0), l5, l8), l10)
270 | )
271 | in
272 | Seq (l1, Seq (l2, loop))
273 |
274 | let mem = (AbsMem.add "z" Sign.Top (AbsMem.add "n" Sign.Top AbsMem.empty))
275 | let _ =
276 | let mem' = eval_c pgm mem in
277 | print_endline "=== final memory ===";
278 | AbsMem.print mem'
279 |
--------------------------------------------------------------------------------
/ocaml-examples/lec9/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | ocamlc -c ast.ml
3 | ocamlyacc parser.mly
4 | ocamlc -c parser.mli
5 | ocamllex lexer.mll
6 | ocamlc -c lexer.ml
7 | ocamlc -c parser.ml
8 | ocamlc -c main.ml
9 | ocamlc ast.cmo lexer.cmo parser.cmo main.cmo
10 |
11 | clean:
12 | rm -f *.cmo *.cmi a.out lexer.ml parser.ml parser.mli
13 |
--------------------------------------------------------------------------------
/ocaml-examples/lec9/ast.ml:
--------------------------------------------------------------------------------
1 | type expr =
2 | | Num of int
3 | | Add of expr * expr
4 | | Mul of expr * expr
5 |
6 | let rec eval : expr -> int
7 | = fun e ->
8 | match e with
9 | | Num n -> n
10 | | Add (e1, e2) -> (eval e1) + (eval e2)
11 | | Mul (e1, e2) -> (eval e1) * (eval e2)
12 |
--------------------------------------------------------------------------------
/ocaml-examples/lec9/lexer.mll:
--------------------------------------------------------------------------------
1 | {
2 | open Parser
3 | exception LexicalError
4 | }
5 |
6 | let number = ['0'-'9']+
7 | let blank = [' ' '\t']
8 |
9 | rule token = parse
10 | | blank { token lexbuf }
11 | | '\n' { NEWLINE }
12 | | number { NUM (int_of_string (Lexing.lexeme lexbuf)) }
13 | | '+' { PLUS }
14 | | '-' { MINUS }
15 | | '*' { MULTIPLY }
16 | | '(' { LPAREN }
17 | | ')' { RPAREN }
18 | | _ { raise LexicalError }
19 |
--------------------------------------------------------------------------------
/ocaml-examples/lec9/main.ml:
--------------------------------------------------------------------------------
1 | let main () =
2 | let lexbuf = Lexing.from_channel stdin in
3 | let ast = Parser.program Lexer.token lexbuf in
4 | let num = Ast.eval ast in
5 | print_endline (string_of_int num)
6 |
7 | let _ = main ()
8 |
--------------------------------------------------------------------------------
/ocaml-examples/lec9/parser.mly:
--------------------------------------------------------------------------------
1 | %{
2 |
3 | %}
4 |
5 | %token NEWLINE LPAREN RPAREN PLUS MINUS MULTIPLY
6 | %token NUM
7 |
8 | %start program
9 | %type program
10 |
11 | %%
12 |
13 | program : exp NEWLINE { $1 }
14 |
15 | exp :
16 | | NUM { Ast.Num ($1) }
17 | | exp PLUS exp { Ast.Add ($1, $3) }
18 | | exp MULTIPLY exp { Ast.Mul ($1, $3) }
19 | | LPAREN exp RPAREN { $2 }
20 |
--------------------------------------------------------------------------------
/setup/install_ocaml_mac.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sudo rm -rf ~/.opam
4 | sudo rm -rf $(which opam)
5 | sudo rm -rf $(which ocaml)
6 |
7 | sudo yes '' | bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
8 | opam init -y
9 | eval $(opam env --switch=default)
10 | opam switch create 5.1.1
11 | eval $(opam env --switch=5.1.1)
12 | brew reinstall gmp pkg-config
13 | opam install -y conf-m4.1 ocamlfind ocamlbuild zarith batteries
14 | eval $(opam env)
15 |
--------------------------------------------------------------------------------
/setup/install_ocaml_ubuntu.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # check if sudo is installed
4 | if ! command -v sudo &> /dev/null; then
5 | apt-get update && apt-get upgrade -y
6 | apt-get install -y --no-install-recommends sudo
7 | fi
8 |
9 | sudo rm -rf ~/.opam && sudo rm -rf $(which opam) && sudo rm -rf $(which ocaml)
10 |
11 | sudo apt-get install -y --no-install-recommends wget gcc build-essential curl unzip bubblewrap ocaml-findlib vim libgmp-dev m4 pkg-config
12 | yes '' | bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
13 | opam init -y
14 | eval $(opam env --switch=default)
15 | opam switch create 5.1.1
16 | eval $(opam env --switch=5.1.1)
17 | opam install -y conf-m4.1 ocamlfind ocamlbuild zarith batteries
18 | eval $(opam env)
19 |
--------------------------------------------------------------------------------
/setup/wsl-install-guideline.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/setup/wsl-install-guideline.pdf
--------------------------------------------------------------------------------
/setup/wsl_install.ps1:
--------------------------------------------------------------------------------
1 | function Main {
2 | try {
3 | # Windows 버전 및 빌드 번호 확인
4 | $osInfo = Get-WmiObject -Class Win32_OperatingSystem
5 | $windowsVersion = [System.Version]$osInfo.Version
6 | $windowsBuild = $osInfo.BuildNumber
7 |
8 | if ($windowsVersion.Major -ge 10 -and $windowsVersion.Minor -ge 0 -and $windowsBuild -ge 19041) {
9 | Write-Host "Compatible Windows version detected (Windows 10 version 2004 or later, or Windows 11)."
10 | Write-Host "Activating WSL and Virtual Machine Platform features..."
11 | dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
12 | dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
13 |
14 | Write-Host "Installing WSL with Ubuntu..."
15 | wsl --install
16 |
17 | Write-Host "WSL and default Ubuntu distribution have been successfully installed."
18 | Write-Host "A system restart is required to complete the installation."
19 |
20 | $restart = Read-Host "Do you want to restart now? (Y/N)"
21 | if ($restart -eq 'Y' -or $restart -eq 'y') {
22 | Restart-Computer
23 | }
24 | } else {
25 | # 호환되지 않는 버전인 경우
26 | Write-Host "Incompatible Windows version detected. Proceeding with WSL installation and kernel update."
27 |
28 | Write-Host "Activating WSL and Virtual Machine Platform features..."
29 | dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
30 | dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
31 |
32 | Write-Host "WSL is already installed. Proceeding with WSL2 kernel update..."
33 |
34 | # WSL2 커널 업데이트
35 | Write-Host "Downloading and installing WSL2 Linux kernel update package..."
36 | $url = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi"
37 | if ($env:PROCESSOR_ARCHITECTURE -like "*ARM*") {
38 | $url = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_arm64.msi"
39 | }
40 |
41 | $outPath = "$env:TEMP\wsl_update.msi"
42 | try {
43 | Invoke-WebRequest -Uri $url -OutFile $outPath -ErrorAction Stop
44 | Write-Host "WSL2 Linux kernel update package downloaded successfully."
45 | } catch {
46 | Write-Warning "Failed to download WSL2 Linux kernel update package: $_"
47 | Write-Host "Please download and install the WSL2 Linux kernel update package manually from: $url"
48 | return
49 | }
50 |
51 | try {
52 | $installProcess = Start-Process msiexec.exe -Wait -ArgumentList "/I `$outPath /quiet" -PassThru -Verb RunAs
53 | if ($installProcess.ExitCode -eq 0) {
54 | Write-Host "WSL2 Linux kernel update package installed successfully."
55 | } else {
56 | Write-Warning "WSL2 Linux kernel update package installation might have failed. Exit code: $($installProcess.ExitCode)"
57 | }
58 | } catch {
59 | Write-Warning "An error occurred during WSL2 Linux kernel update package installation: $_"
60 | }
61 |
62 | # Ubuntu 설치 여부 확인 및 설치
63 | if (-not (wsl --list --online | Select-String -Pattern "Ubuntu")) {
64 | try {
65 | Write-Host "Attempting to install Ubuntu 22.04.3 LTS..."
66 | $installProcess = Start-Process -FilePath "winget" -ArgumentList "install --id 9PN20MSR04DW --source msstore --accept-package-agreements --accept-source-agreements" -NoNewWindow -PassThru -Wait
67 |
68 | if ($installProcess.ExitCode -eq 0) {
69 | Write-Host "Ubuntu 22.04.3 LTS has been successfully installed."
70 | } else {
71 | Write-Warning "Installation might have failed. Exit code: $($installProcess.ExitCode)"
72 | Write-Host "If the installation failed, please try to install Ubuntu 22.04.3 LTS manually from the Microsoft Store."
73 | }
74 | } catch {
75 | Write-Warning "An error occurred during installation: $_"
76 | Write-Host "Please try to install Ubuntu 22.04.3 LTS manually from the Microsoft Store."
77 | }
78 | } else {
79 | Write-Host "Ubuntu is already installed."
80 | }
81 |
82 | Write-Host "To run Ubuntu, search for 'Ubuntu' in the Start menu."
83 |
84 | # 재시작 요청
85 | $restart = Read-Host "A system restart is recommended to complete the update. Do you want to restart now? (Y/N)"
86 | if ($restart -eq 'Y' -or $restart -eq 'y') {
87 | Restart-Computer
88 | }
89 | }
90 | } catch {
91 | Write-Host "An error occurred: $_"
92 | Write-Host "Please check the error and try again."
93 | }
94 | }
95 |
96 | # 스크립트 실행
97 | Main
98 |
--------------------------------------------------------------------------------
/slides/lec-halting.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec-halting.pdf
--------------------------------------------------------------------------------
/slides/lec-ocaml.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec-ocaml.pdf
--------------------------------------------------------------------------------
/slides/lec0.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec0.pdf
--------------------------------------------------------------------------------
/slides/lec1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec1.pdf
--------------------------------------------------------------------------------
/slides/lec10.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec10.pdf
--------------------------------------------------------------------------------
/slides/lec11.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec11.pdf
--------------------------------------------------------------------------------
/slides/lec12.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec12.pdf
--------------------------------------------------------------------------------
/slides/lec13.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec13.pdf
--------------------------------------------------------------------------------
/slides/lec14.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec14.pdf
--------------------------------------------------------------------------------
/slides/lec15.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec15.pdf
--------------------------------------------------------------------------------
/slides/lec16.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec16.pdf
--------------------------------------------------------------------------------
/slides/lec17.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec17.pdf
--------------------------------------------------------------------------------
/slides/lec18.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec18.pdf
--------------------------------------------------------------------------------
/slides/lec2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec2.pdf
--------------------------------------------------------------------------------
/slides/lec3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec3.pdf
--------------------------------------------------------------------------------
/slides/lec4.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec4.pdf
--------------------------------------------------------------------------------
/slides/lec5.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec5.pdf
--------------------------------------------------------------------------------
/slides/lec6.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec6.pdf
--------------------------------------------------------------------------------
/slides/lec7.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec7.pdf
--------------------------------------------------------------------------------
/slides/lec8.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec8.pdf
--------------------------------------------------------------------------------
/slides/lec9.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gist-pal/ec3204-pl-and-compilers/bbe68779f45f615c5780bc1d3d4accd1455baade/slides/lec9.pdf
--------------------------------------------------------------------------------