├── .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 --------------------------------------------------------------------------------