├── README.md ├── ex1 ├── Implementation.scala └── README.md ├── ex2 ├── Implementation.scala └── README.md ├── ex3 ├── Implementation.scala └── README.md ├── ex4 ├── README.md └── solution.md ├── ex5 ├── Implementation.scala └── README.md ├── ex6 ├── Implementation.scala └── README.md ├── ex7 ├── README.md └── solution.pdf ├── ex8 ├── README.md └── solution.md ├── hw1 ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg └── README.md ├── proj1 └── README.md ├── proj2 └── README.md └── proj3 └── README.md /README.md: -------------------------------------------------------------------------------- 1 | # KAIST CS320 Assignment Instructions 2 | 3 | The course has 5 coding exercises (no submission required) and 3 projects 4 | (submission required). 5 | 6 | * [Exercise #1: Scala Tutorial](/ex1) 7 | * [Exercise #2: Identifiers](/ex2) 8 | * [Exercise #3: MVAE](/ex3) 9 | * [Exercise #5: MRFVAE](/ex5) 10 | * [Exercise #6: SRBFAE](/ex6) 11 | * [Project #1: FIBER](/proj1) 12 | * [Project #2: X-FIBER](/proj2) 13 | * [Project #3: FABRIC](/proj3) 14 | 15 | ## Prerequisites 16 | 17 | * JDK >= 8 () 18 | * sbt () 19 | 20 | ## Download 21 | 22 | Run `sbt new kaist-plrg-cs320/[assignment name].g8` in your terminal. 23 | The project directory whose name is the same as the assignment will be created 24 | under the current directory. 25 | 26 | Below is an example. 27 | 28 | ``` 29 | $ sbt new kaist-plrg-cs320/scala-tutorial.g8 30 | ... 31 | name [Scala Tutorial]: 32 | Template applied in ./scala-tutorial 33 | ``` 34 | 35 | See the instructions for each assignment to find the exact assignment name. 36 | 37 | ## Directory Structure 38 | 39 | You can find the following directories and files in the project directory: 40 | 41 | ``` 42 | core/src 43 | - main/scala 44 | - cs320 45 | - Implementation.scala 46 | - Template.scala 47 | - package.scala 48 | - test/scala 49 | - cs320 50 | - Spec.scala 51 | ``` 52 | 53 | **DO NOT** edit files other than 54 | `core/src/main/scala/cs320/Implementation.scala` and 55 | `core/src/test/scala/cs320/Spec.scala`. 56 | 57 | * `core/src/main/scala/cs320/Implementation.scala`: 58 | You must fill this file to implement the required function(s). 59 | It is enough to edit only this file to finish the assignment. 60 | 61 | * `core/src/main/scala/cs320/Template.scala`: 62 | This file contains the definitions of functions that you must implement to 63 | complete the assignment. 64 | 65 | * `core/src/main/scala/package.scala`: 66 | This file defines `error` functions. You can throw an exception with an error 67 | message `s` by calling `error(s)`. To omit the message, you can use `error()`, 68 | instead of `error("")`. 69 | 70 | * `core/src/test/scala/cs320/Spec.scala` 71 | This file contains test cases. 72 | Passing all the provided tests does not guarantee that your implementation is correct. 73 | We highly recommend adding your own tests. 74 | 75 | ## Restrictions 76 | 77 | You must not use any of the following features in your implementation: 78 | 79 | * `asInstanceOf` 80 | * `isInstanceOf` 81 | * `null` 82 | * `return` 83 | * `throw` 84 | * `var` 85 | * `while` 86 | * `try-catch` 87 | * mutable data structures 88 | 89 | You can use any other features that are not explicitly forbidden. For example, 90 | 91 | * You can define helper functions and additional types. 92 | * You can use immutable data structures. 93 | * You can use `for`. 94 | * You can mutate mutable variables/fields already defined in the provided code. 95 | 96 | The use of the prohibited features will make your code not compile. If your code 97 | compiles successfully, you are not using any prohibited features. 98 | 99 | ## Testing Your Implementation 100 | 101 | Under the project directory, execute `sbt` to start an sbt console. 102 | 103 | ``` 104 | $ sbt 105 | [info] welcome to sbt 106 | ... 107 | sbt:...> 108 | ``` 109 | 110 | To run the test cases in `Spec.scala`, execute the `test` command. 111 | Every test case will fail at the beginning. 112 | 113 | ``` 114 | sbt:...> test 115 | ... 116 | [error] Failed tests: 117 | [error] cs320.Spec 118 | ``` 119 | 120 | After implementing every function correctly, every test will succeed. 121 | 122 | ``` 123 | sbt:...> test 124 | ... 125 | [info] All tests passed. 126 | ``` 127 | 128 | (If you are working on Exercise #1, stop reading here. The remaining parts are 129 | for the other assignments.) 130 | 131 | ### REPL 132 | 133 | Any assignments other than Exercise #1 provide REPL. 134 | REPL allows you to input an arbitrary expression into your implementation and see the result. 135 | Using REPL, you can quickly test your implementation without changing `Spec.scala`. 136 | 137 | Execute the `run` command to start REPL. 138 | Below is REPL of Exercise #3. 139 | 140 | ``` 141 | sbt:mvae > run 142 | [info] running cs320.Main 143 | Welcome to the MVAE REPL. 144 | Type in :q, :quit, or the EOF character to terminate the REPL. 145 | 146 | MVAE> 147 | ``` 148 | 149 | REPL will not work properly at the beginning. 150 | 151 | ``` 152 | MVAE> { val x = (1, 2); (x + x) } 153 | Parsed: Val(x,Num(List(1, 2)),Add(Id(x),Id(x))) 154 | scala.NotImplementedError: an implementation is missing 155 | at scala.Predef$.$qmark$qmark$qmark(Predef.scala:347) 156 | at cs320.Implementation$.interp(Implementation.scala:18) 157 | ``` 158 | 159 | After finishing the implementation, REPL will behave correctly. 160 | 161 | ``` 162 | MVAE> { val x = (1, 2); (x + x) } 163 | Parsed: Val(x,Num(List(1, 2)),Add(Id(x),Id(x))) 164 | Result: (2, 3, 3, 4) 165 | ``` 166 | 167 | (If you are working on an exercise, stop reading here. The remaining parts are 168 | for the projects.) 169 | 170 | ### Fuzzing 171 | 172 | Each project (but no exercise) provides a fuzzer. A fuzzer randomly generates 173 | expressions to test your interpreter. You need to install 174 | [Node.js](https://nodejs.org/en/download/) on your machine to use the fuzzer. 175 | 176 | Execute the `run fuzzer` command to use the fuzzer. 177 | 178 | ``` 179 | sbt:... > run fuzzer 180 | [info] running cs320.Main fuzzer 181 | 10000 182 | ``` 183 | 184 | The number shown on the screen is the number of expressions your interpreter 185 | correctly interpreted so far. The fuzzer runs forever until it finds a wrong 186 | behavior. Press `ctrl+c` to stop fuzzing. 187 | 188 | When the fuzzer finds a wrong behavior, it prints detailed information and 189 | terminates. 190 | 191 | ``` 192 | Incorrect behavior detected 193 | Expr: (1 + 2) 194 | Correct result: 3 195 | Your result: Unexpected Error 196 | an implementation is missing 197 | scala.Predef$.$qmark$qmark$qmark(Predef.scala:344) 198 | cs320.Implementation$.interp(Implementation.scala:7) 199 | cs320.Template.run(Template.scala:5) 200 | cs320.Template.run$(Template.scala:5) 201 | cs320.Implementation$.run(Implementation.scala:5) 202 | ``` 203 | 204 | If the fuzzer reports a failed case after you press `ctrl+c`, it is due to the 205 | abrupt termination, not a defect in your implementation, so you can ignore it. 206 | 207 | If your implementation correctly interprets a huge number of expressions, your 208 | implementation is highly likely to be correct. 209 | 210 | ## Grading 211 | 212 | You must submit your `Implementation.scala` of each project. 213 | See the instructions for each project to find the submission link. 214 | 215 | Violation of the honor code will give you F. 216 | You must work on each project by yourself without getting any help. 217 | You can refer to the lecture materials, including 218 | the lecture slides, the textbook, and the sample solutions to the exercises. 219 | 220 | We disallow late submissions. If you submit multiple times, only the last 221 | submission will be graded. 222 | 223 | You can get maximum 100 points. If your code uses a disallow feature or does not 224 | compile, you will get 0 points. 225 | 226 | * Test cases: 80 points (1 point per case) 227 | * Fuzzing: 20 points 228 | 229 | The test cases for the grading are similar to, but not the same as, those 230 | provided in `Spec.scala`. You get more points as you pass more test cases. The 231 | execution of each test case does not affect the others, e.g., the other test 232 | cases will be graded properly even when your implementation runs forever for a 233 | certain test case. 234 | 235 | If your implementation passes all the test cases, 236 | we test the implementation with the same fuzzer as the one you have. 237 | We use 10,000 expressions for each student. 238 | The expressions are the same for every student. 239 | If your implementation behaves correctly for every expression, you will get 20 240 | points for the Fuzzing part. Otherwise, you will get 0 points. 241 | 242 | ## FAQ 243 | 244 | ### My code does not terminate or emits stack overflow error 245 | 246 | Though not the only cause, this usually happens in student's implementation when student tries to call `error()` function with some string interpolation, for example 247 | 248 | ```scala 249 | error(s"not both number: $x, $y") 250 | ``` 251 | 252 | Maybe changing the code to use plain string might solve the issue, like 253 | 254 | ```scala 255 | error(s"not both number") 256 | ``` 257 | -------------------------------------------------------------------------------- /ex1/Implementation.scala: -------------------------------------------------------------------------------- 1 | package cs320 2 | 3 | object Implementation extends Template { 4 | 5 | def volumeOfCuboid(a: Int, b: Int, c: Int): Int = a * b * c 6 | 7 | def concat(x: String, y: String): String = x + y 8 | 9 | def addN(n: Int): Int => Int = _ + n 10 | 11 | def twice(f: Int => Int): Int => Int = x => f(f(x)) 12 | 13 | def compose(f: Int => Int, g: Int => Int): Int => Int = x => f(g(x)) 14 | 15 | def double(l: List[Int]): List[Int] = l.map(_ * 2) 16 | 17 | def sum(l: List[Int]): Int = l.foldLeft(0)(_ + _) 18 | 19 | def getKey(m: Map[String, Int], s: String): Int = m.getOrElse(s, error(s)) 20 | 21 | def countLeaves(t: Tree): Int = t match { 22 | case Branch(l, _, r) => countLeaves(l) + countLeaves(r) 23 | case _ => 1 24 | } 25 | 26 | def flatten(t: Tree): List[Int] = t match { 27 | case Branch(l, v, r) => flatten(l) ++ (v :: flatten(r)) 28 | case Leaf(v) => List(v) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ex1/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #1: Scala Tutorial 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | 5 | ## Download 6 | 7 | ```bash 8 | sbt new kaist-plrg-cs320/scala-tutorial.g8 9 | ``` 10 | 11 | ## Descriptions 12 | 13 | ### Primitives 14 | 15 | * `volumeOfCuboid` takes three non-negative integers `a`, `b`, and `c` 16 | denoting the lengths of three sides and returns the volume of the cuboid. 17 | ```scala 18 | test(volumeOfCuboid(1, 3, 5), 15) 19 | test(volumeOfCuboid(2, 3, 4), 24) 20 | ``` 21 | 22 | * `concat` takes two strings `x` and `y` 23 | and returns their concatenation. 24 | ```scala 25 | test(concat("x", "y"), "xy") 26 | test(concat("abc", "def"), "abcdef") 27 | ``` 28 | 29 | ### Functions 30 | 31 | * `addN` takes an integer `n` 32 | and returns a function that adds `n` to a given integer. 33 | ```scala 34 | test(addN(5)(3), 8) 35 | test(addN(5)(42), 47) 36 | ``` 37 | 38 | * `twice` takes a function `f` whose type is `Int => Int` 39 | and returns a function that applies `f` twice. 40 | ```scala 41 | test(twice(addN(3))(2), 8) 42 | test(twice(addN(3))(7), 13) 43 | ``` 44 | 45 | * `compose` takes two `Int => Int` functions `f` and `g` 46 | and returns their composition `f ∘ g`. 47 | ```scala 48 | test(compose(addN(3), addN(4))(5), 12) 49 | test(compose(addN(3), addN(4))(11), 18) 50 | ``` 51 | 52 | ### Lists 53 | 54 | * `double` takes an interger list `l` 55 | and returns a list whose elements are the doubles of the elements of `l`. 56 | ```scala 57 | test(double(List(1, 2, 3)), List(2, 4, 6)) 58 | test(double(double(List(1, 2, 3, 4, 5))), List(4, 8, 12, 16, 20)) 59 | ``` 60 | 61 | * `sum` takes an integer list `l` 62 | and returns the sum of the elements of `l`. 63 | ```scala 64 | test(sum(List(1, 2, 3)), 6) 65 | test(sum(List(4, 2, 3, 7, 5)), 21) 66 | ``` 67 | 68 | ### Maps 69 | 70 | * `getKey` takes a map `m` from strings to integers and a string `s` 71 | and returns the integer corresponding to `s` if `m` has such mapping 72 | and throws an exception with a message containing `s` otherwise. 73 | ```scala 74 | val m: Map[String, Int] = Map("Ryu" -> 42, "PL" -> 37) 75 | test(getKey(m, "Ryu"), 42) 76 | testExc(getKey(m, "CS320"), "CS320") 77 | ``` 78 | 79 | ### Algebraic Data Types 80 | 81 | The `Tree` type represents binary trees. 82 | A `Tree` is either `Branch` (a non-leaf node) or `Leaf` (a leaf node). 83 | A `Branch` consists of three fields: `left` and `right` denoting 84 | the left and right subtrees and `value` denoting its value. 85 | A `Leaf` has one field: `value` denoting its value. 86 | 87 | ```scala 88 | sealed trait Tree 89 | case class Branch(left: Tree, value: Int, right: Tree) extends Tree 90 | case class Leaf(value: Int) extends Tree 91 | ``` 92 | 93 | The `Tree` type is already defined in `Template.scala`. 94 | **DO NOT** define it again in `Implementation.scala`. 95 | 96 | * `countLeaves` takes a tree `t` and 97 | and returns the number of its leaf nodes. 98 | ```scala 99 | val t1: Tree = Branch(Leaf(1), 2, Leaf(3)) 100 | val t2: Tree = Branch(Leaf(1), 2, Branch(Leaf(3), 4, Leaf(5))) 101 | test(countLeaves(t1), 2) 102 | test(countLeaves(t2), 3) 103 | ``` 104 | 105 | * `flatten` takes a tree `t` 106 | and returns a list containing the value of each node in `t` with in-order traversal. 107 | ```scala 108 | val t1: Tree = Branch(Leaf(1), 2, Leaf(3)) 109 | val t2: Tree = Branch(Leaf(1), 2, Branch(Leaf(3), 4, Leaf(5))) 110 | test(flatten(t1), List(1, 2, 3)) 111 | test(flatten(t2), List(1, 2, 3, 4, 5)) 112 | ``` 113 | 114 | ## Sample Solution 115 | 116 | [`Implementation.scala`](./Implementation.scala) 117 | -------------------------------------------------------------------------------- /ex2/Implementation.scala: -------------------------------------------------------------------------------- 1 | package cs320 2 | 3 | object Implementation extends Template { 4 | 5 | def freeIds(expr: Expr): Set[String] = { 6 | def frees(e: Expr, ids: Set[String]): Set[String] = e match { 7 | case Num(n) => Set() 8 | case Add(left, right) => frees(left, ids) ++ frees(right, ids) 9 | case Sub(left, right) => frees(left, ids) ++ frees(right, ids) 10 | case Val(name, expr, body) => frees(expr, ids) ++ frees(body, ids + name) 11 | case Id(id) => if (ids contains id) Set() else Set(id) 12 | } 13 | frees(expr, Set()) 14 | } 15 | 16 | def bindingIds(expr: Expr): Set[String] = expr match { 17 | case Num(n) => Set() 18 | case Add(left, right) => bindingIds(left) ++ bindingIds(right) 19 | case Sub(left, right) => bindingIds(left) ++ bindingIds(right) 20 | case Val(name, expr, body) => bindingIds(expr) ++ bindingIds(body) + name 21 | case Id(id) => Set() 22 | } 23 | 24 | def boundIds(expr: Expr): Set[String] = { 25 | def bounds(e: Expr, ids: Set[String]): Set[String] = e match { 26 | case Num(n) => Set() 27 | case Add(left, right) => bounds(left, ids) ++ bounds(right, ids) 28 | case Sub(left, right) => bounds(left, ids) ++ bounds(right, ids) 29 | case Val(name, expr, body) => bounds(expr, ids) ++ bounds(body, ids + name) 30 | case Id(id) => if (ids contains id) Set(id) else Set() 31 | } 32 | bounds(expr, Set()) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ex2/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #2: Identifiers 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl) section.** 5 | 6 | ## Download 7 | 8 | ```bash 9 | sbt new kaist-plrg-cs320/identifiers.g8 10 | ``` 11 | 12 | ## Descriptions 13 | 14 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`: 15 | ``` 16 | e ::= n 17 | | e + e 18 | | e - e 19 | | val x = e; e 20 | | x 21 | ``` 22 | 23 | * `freeIds` takes an expression 24 | and returns the set of every free identifier in the expression. 25 | ```scala 26 | test(freeIds(Expr("{ val x = 1; (x + y) }")), Set("y")) 27 | test(freeIds(Expr("{ val z = 2; 1 }")), Set()) 28 | ``` 29 | 30 | * `bindingIds` takes an expression 31 | and returns the set of every binding identifier in the expression 32 | (whether or not the binding identifier is ever referenced by a bound identifier). 33 | ```scala 34 | test(bindingIds(Expr("{ val x = 1; (x + y) }")), Set("x")) 35 | test(bindingIds(Expr("{ val z = 2; 1 }")), Set("z")) 36 | ``` 37 | 38 | * `boundIds` takes an expression 39 | and returns the set of every bound identifier in the expression. 40 | ```scala 41 | test(boundIds(Expr("{ val x = 1; (x + y) }")), Set("x")) 42 | test(boundIds(Expr("{ val z = 2; 1 }")), Set()) 43 | ``` 44 | 45 | ## Sample Solution 46 | 47 | [`Implementation.scala`](./Implementation.scala) 48 | -------------------------------------------------------------------------------- /ex3/Implementation.scala: -------------------------------------------------------------------------------- 1 | package cs320 2 | 3 | object Implementation extends Template { 4 | 5 | def binOp( 6 | op: (Int, Int) => Int, 7 | ls: List[Int], 8 | rs: List[Int] 9 | ): List[Int] = ls match { 10 | case Nil => Nil 11 | case l :: rest => 12 | def f(r: Int): Int = op(l, r) 13 | rs.map(f) ++ binOp(op, rest, rs) 14 | } 15 | 16 | type Env = Map[String, List[Int]] 17 | 18 | def interp(expr: Expr, env: Env): List[Int] = expr match { 19 | case Num(ns) => ns 20 | case Add(l, r) => binOp(_ + _, interp(l, env), interp(r, env)) 21 | case Sub(l, r) => binOp(_ - _, interp(l, env), interp(r, env)) 22 | case Val(x, e, b) => interp(b, env + (x -> interp(e, env))) 23 | case Id(x) => env.getOrElse(x, error(s"free identifier: $x")) 24 | case Min(l, m, r) => 25 | val v = binOp(_ min _, interp(l, env), interp(m, env)) 26 | binOp(_ min _, v, interp(r, env)) 27 | case Max(l, m, r) => 28 | val v = binOp(_ max _, interp(l, env), interp(m, env)) 29 | binOp(_ max _, v, interp(r, env)) 30 | } 31 | 32 | def interp(expr: Expr): List[Int] = interp(expr, Map()) 33 | } 34 | -------------------------------------------------------------------------------- /ex3/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #3: MVAE 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl) section.** 5 | 6 | ## Download 7 | 8 | ```bash 9 | sbt new kaist-plrg-cs320/mvae.g8 10 | ``` 11 | 12 | ## Descriptions 13 | 14 | MVAE extends VAE with multi-integers. Implement an interpreter for MVAE. 15 | 16 | ### Overview 17 | 18 | A multi-integer is a value consisting of zero or more integers. For example, 19 | `()`, `(2)`, `(1, 42)`, and `(3, 4, 5)` are multi-integers. A multi-integer 20 | expression is defined as follows: 21 | 22 | ```scala 23 | case class Num(values: List[Int]) extends Expr 24 | ``` 25 | 26 | Addition and subtraction on multi-integers produce multi-integers by considering 27 | every possible combination. 28 | 29 | ```scala 30 | test(run("(3 + 7)"), List(10)) 31 | test(run("(10 - (3, 5))"), List(7, 5)) 32 | test(run("((1, 2) + (3, 4))"), List(4, 5, 5, 6)) 33 | ``` 34 | 35 | `((3) + (7))` is `(10)` because `3 + 7` is the only possible combination. 36 | `((10) - (3, 5))` is `(7, 5)` because both `10 - 3` and `10 - 5` are possible. 37 | `((1, 2) + (3, 4))` is `(4, 5, 5, 6)` because `1 + 3`, `1 + 4`, `2 + 3`, and `2 + 4` are possible. 38 | 39 | MVAE additionally supports two more arithmetic operators: `min` and `max`. 40 | Each of them takes three expressions and returns the minimum/maximum. 41 | 42 | ```scala 43 | test(run("min(3, 4, 5)"), List(3)) 44 | test(run("min((1, 4), (2, 9), 3)"), List(1, 1, 2, 3)) 45 | ``` 46 | 47 | `min((3), (4), (5))` is `(3)` because `min(3, 4, 5)` is the only possible combination. 48 | `min((1, 4), (2, 9), 3)` is `(1, 1, 2, 3)` because `min(1, 2, 3)`, `min(1, 9, 49 | 3)`, `min(4, 2, 3)`, and `min(4, 9 ,3)` are possible. 50 | 51 | ### Concrete Syntax 52 | 53 | We use the [extended Backus-Naur form](https://en.wikipedia.org/wiki/Extended_Backus\%E2\%80\%93Naur_form). 54 | Note that `{ }` denotes a repetition of zero or more times. 55 | 56 | ``` 57 | expr ::= ... 58 | | "(" ")" 59 | | "(" num {"," num} ")" 60 | | "min" "(" expr "," expr "," expr ")" 61 | | "max" "(" expr "," expr "," expr ")" 62 | ``` 63 | 64 | ### Abstract Syntax 65 | 66 | $e::=\cdots\ |\ (n,\cdots, n)\ |\ \min(e,e,e)\ |\ \max(e,e,e)$ 67 | 68 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`. 69 | 70 | ### Operational Semantics 71 | 72 | $\sigma\vdash (n_1,\cdots,n_i) \Rightarrow (n_1,\cdots,n_i)$ 73 | 74 | $\Large\frac{\sigma\vdash e_1\Rightarrow(n_1,\cdots,n_i)\quad\sigma\vdash e_2\Rightarrow(m_1,\cdots,m_j)}{\sigma\vdash e_1+e_2\Rightarrow(n_1+m_1,n_1+m_2,\cdots,n_i+m_{j-1},n_i+m_j)}$ 75 | 76 | $\Large\frac{\sigma\vdash e_1\Rightarrow(n_1,\cdots,n_i)\quad\sigma\vdash e_2\Rightarrow(m_1,\cdots,m_j)}{\sigma\vdash e_1-e_2\Rightarrow(n_1-m_1,n_1-m_2,\cdots,n_i-m_{j-1},n_i-m_j)}$ 77 | 78 | $\Large\frac{\sigma\vdash e_1\Rightarrow(n_1,\cdots,n_i)\quad\sigma\vdash e_2\Rightarrow(m_1,\cdots,m_j)\quad\sigma\vdash e_3\Rightarrow(l_1,\cdots,l_k)}{\sigma\vdash\min(e_1,e_2,e_3)\Rightarrow(\min(n_1,m_1,l_1),\min(n_1,m_1,l_2),\cdots,\min(n_i,m_j,l_k))}$ 79 | 80 | $\Large\frac{\sigma\vdash e_1\Rightarrow(n_1,\cdots,n_i)\quad\sigma\vdash e_2\Rightarrow(m_1,\cdots,m_j)\quad\sigma\vdash e_3\Rightarrow(l_1,\cdots,l_k)}{\sigma\vdash\max(e_1,e_2,e_3)\Rightarrow(\max(n_1,m_1,l_1),\max(n_1,m_1,l_2),\cdots,\max(n_i,m_j,l_k))}$ 81 | 82 | ## Sample Solution 83 | 84 | [`Implementation.scala`](./Implementation.scala) 85 | -------------------------------------------------------------------------------- /ex4/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #4: F1VAE 2 | 3 | Consider the following syntax of F1VAE: 4 | 5 | $d::={\sf def}\ x(x)=e$ 6 | 7 | $e::=n\ |\ e+e\ |\ {\sf val}\ x=e;e\ |\ x\ |\ x(e)$ 8 | 9 | $d\in{\it FunDef},\ x\in{\it Id},\ \sigma\in{\it Id}\rightarrow\mathbb{Z},\ \Lambda\in{\it Id}\rightarrow{\it FunDef}$ 10 | 11 | Write the operational semantics of the form $\sigma,\Lambda\vdash e\Rightarrow n$. 12 | 13 | ## Sample Solution 14 | 15 | [sample solution](./solution.md) 16 | -------------------------------------------------------------------------------- /ex4/solution.md: -------------------------------------------------------------------------------- 1 | $\sigma,\Lambda\vdash n\Rightarrow n$ 2 | 3 | $\Large\frac{\sigma,\Lambda\vdash e_1\Rightarrow n_1\quad\sigma,\Lambda\vdash e_2\Rightarrow n_2}{\sigma,\Lambda\vdash e_1+e_2\Rightarrow n_1+n_2}$ 4 | 5 | $\Large\frac{\sigma,\Lambda\vdash e_1\Rightarrow n_1\quad\sigma[x\mapsto n_1],\Lambda\vdash e_2\Rightarrow n_2}{\sigma,\Lambda\vdash {\sf val}\ x=e_1;e_2\Rightarrow n_2}$ 6 | 7 | $\Large\frac{x\in\mathit{Domain}(\sigma)}{\sigma,\Lambda\vdash x\Rightarrow\sigma(x)}$ 8 | 9 | $\Large\frac{\sigma,\Lambda\vdash e\Rightarrow n\quad x\in\mathit{Domain}(\Lambda)\quad\Lambda(x)=({\sf def}\ x(x_1)=e_1)\quad[x_1\mapsto n],\Lambda\vdash e_1\Rightarrow n_1}{\sigma,\Lambda\vdash x(e)\Rightarrow n_1}$ 10 | -------------------------------------------------------------------------------- /ex5/Implementation.scala: -------------------------------------------------------------------------------- 1 | package cs320 2 | 3 | import Value._ 4 | 5 | object Implementation extends Template { 6 | 7 | def numVop(op: (Int, Int) => Int): (Value, Value) => NumV = (_, _) match { 8 | case (NumV(x), NumV(y)) => NumV(op(x, y)) 9 | case (x, y) => error(s"not both numbers: $x, $y") 10 | } 11 | 12 | val numVAdd = numVop(_ + _) 13 | val numVSub = numVop(_ - _) 14 | 15 | def interp(expr: Expr, env: Env): Value = expr match { 16 | case Num(n) => NumV(n) 17 | case Add(l, r) => numVAdd(interp(l, env), interp(r, env)) 18 | case Sub(l, r) => numVSub(interp(l, env), interp(r, env)) 19 | case Val(x, e, b) => interp(b, env + (x -> interp(e, env))) 20 | case Id(x) => env.getOrElse(x, error(s"free identifier: $x")) 21 | case Fun(ps, b) => CloV(ps, b, env) 22 | case App(f, args) => interp(f, env) match { 23 | case CloV(params, b, fenv) => { 24 | val avals = args.map(interp(_, env)) 25 | if (args.length != params.length) error(s"wrong arity: $params, $args") 26 | interp(b, fenv ++ (params zip avals)) 27 | } 28 | case v => error(s"not a closure: $v") 29 | } 30 | case Rec(m) => RecV(m.map { case (f, e) => (f, interp(e, env)) }) 31 | case Acc(r, x) => interp(r, env) match { 32 | case RecV(m) => m.getOrElse(x, error(s"no such field: $x")) 33 | case v => error(s"not a record: $v") 34 | } 35 | } 36 | 37 | def interp(expr: Expr): Value = interp(expr, Map()) 38 | } 39 | -------------------------------------------------------------------------------- /ex5/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #5: MRFVAE 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl) section.** 5 | 6 | ## Download 7 | 8 | ```bash 9 | sbt new kaist-plrg-cs320/mrfvae.g8 10 | ``` 11 | 12 | ## Descriptions 13 | 14 | MRFVAE extends FVAE with multi-parameter functions and records. 15 | Implement an interpreter for MRFVAE. 16 | 17 | ### Overview 18 | 19 | #### Multi-Parameter Functions 20 | 21 | Functions have any number (including zero) of parameters. 22 | 23 | ```scala 24 | test(run("{ (x, y) => (x + y) }(1, 2)"), "3") 25 | test(run("{ () => (3 + 4) }()"), "7") 26 | ``` 27 | 28 | Function applications can cause two kinds of error: applying a non-function 29 | value to arguments and applying a function to a wrong number of arguments. In 30 | the first case, the interpreter must throw an exception whose message includes 31 | `"not a closure"`. In the second case, the interpreter must throw an exception 32 | whose message includes `"wrong arity"`. 33 | 34 | ```scala 35 | testExc(run("2((3 + 4))"), "not a closure") 36 | testExc(run("{ (x, y) => (x + y) }(1)"), "wrong arity") 37 | ``` 38 | 39 | #### Records 40 | 41 | A record is a value mapping fields to values. One can access a field of a record 42 | to obtain the value of the field. 43 | 44 | ```scala 45 | test(run("{ a = 10, b = (1 + 2) }"), "{ a = 10, b = 3 }") 46 | test(run("{ a = 10, b = (1 + 2) }.b"), "3") 47 | ``` 48 | 49 | Accessing the fields of records can cause two kinds of error: accessing a field 50 | of a non-record value and accessing a field not in a given record value. In the 51 | first case, the interpreter must throw an exception whose message includes `"not 52 | a record"`. In the second case, the interpreter must throw an exception whose 53 | message includes `"no such field"`. 54 | 55 | ```scala 56 | testExc(run("(1 + 2).a"), "not a record") 57 | testExc(run("{ z = { z = 0 }.y }"), "no such field") 58 | ``` 59 | 60 | ### Concrete Syntax 61 | 62 | We use the [extended Backus-Naur form](https://en.wikipedia.org/wiki/Extended_Backus\%E2\%80\%93Naur_form). 63 | Note that `{ }` denotes a repetition of zero or more times. 64 | 65 | ``` 66 | expr ::= ... 67 | | "{" "(" ")" "=>" expr "}" 68 | | "{" id "=>" expr "}" 69 | | "{" "(" id {"," id} ")" "=>" expr "}" 70 | | expr "(" ")" 71 | | expr "(" expr {"," expr} ")" 72 | | "{" "}" 73 | | "{" field "=" expr {"," field "=" expr} "}" 74 | | expr "." field 75 | ``` 76 | 77 | ### Abstract Syntax 78 | 79 | $e::=\cdots\ |\ \lambda x\cdots x.e\ |\ e(e,\cdots,e)\ |\ \lbrace f=e,\cdots,f=e\rbrace\ |\ e.f$ 80 | 81 | $v::=\cdots\ |\ \langle\lambda x\cdots x.e,\sigma\rangle\ |\ \lbrace f=v,\cdots,f=v\rbrace$ 82 | 83 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`, and values 84 | are defined in `core/src/main/scala/cs320/Value.scala`. 85 | 86 | ### Operational Semantics 87 | 88 | $\sigma\vdash\lambda x_1\cdots x_n.e\Rightarrow\langle\lambda x_1\cdots x_n.e,\sigma\rangle$ 89 | 90 | $\Large\frac{\sigma\vdash e\Rightarrow\langle\lambda x_1\cdots x_n.e',\sigma'\rangle\quad\sigma\vdash e_1\Rightarrow v_1\quad\cdots\quad\sigma\vdash e_n\Rightarrow v_n\quad\sigma'[x_1\mapsto v_1,\cdots,x_n\mapsto v_n]\vdash e'\Rightarrow v'}{\sigma\vdash e(e_1,\cdots,e_n)\Rightarrow v'}$ 91 | 92 | $\Large\frac{\sigma\vdash e_1\Rightarrow v_1\quad\cdots\quad\sigma\vdash e_n\Rightarrow v_n}{\sigma\vdash\lbrace f_1=e_1,\cdots,f_n=e_n\rbrace\Rightarrow\lbrace f_1=v_1,\cdots,f_n=v_n\rbrace}$ 93 | 94 | $\Large\frac{\sigma\vdash e\Rightarrow\lbrace\cdots,f=v,\cdots\rbrace}{\sigma\vdash e.f\Rightarrow v}$ 95 | 96 | ## Sample Solution 97 | 98 | [`Implementation.scala`](./Implementation.scala) 99 | -------------------------------------------------------------------------------- /ex6/Implementation.scala: -------------------------------------------------------------------------------- 1 | package cs320 2 | 3 | import Value._ 4 | 5 | object Implementation extends Template { 6 | 7 | type Sto = Map[Addr, Value] 8 | 9 | def interp(expr: Expr): Value = interp(expr, Map(), Map())._1 10 | 11 | private def interp(e: Expr, env: Env, sto: Sto): (Value, Sto) = e match { 12 | case Num(n) => (NumV(n), sto) 13 | case Add(l, r) => 14 | val (lv, ls) = interp(l, env, sto) 15 | val (rv, rs) = interp(r, env, ls) 16 | (numVAdd(lv, rv), rs) 17 | case Sub(l, r) => 18 | val (lv, ls) = interp(l, env, sto) 19 | val (rv, rs) = interp(r, env, ls) 20 | (numVSub(lv, rv), rs) 21 | case Id(x) => 22 | val v = env.getOrElse(x, error(s"free identifier: $x")) 23 | (v, sto) 24 | case Fun(p, b) => 25 | val cloV = CloV(p, b, env) 26 | (cloV, sto) 27 | case App(f, arg) => 28 | val (fv, fs) = interp(f, env, sto) 29 | fv match { 30 | case CloV(param, b, fenv) => 31 | val (av, as) = interp(arg, env, fs) 32 | interp(b, fenv + (param -> av), as) 33 | case v => error(s"not a closure: $v") 34 | } 35 | case NewBox(e) => 36 | val (v, s) = interp(e, env, sto) 37 | val addr = malloc(s) 38 | (BoxV(addr), s + (addr -> v)) 39 | case SetBox(b, e) => 40 | val (bv, bs) = interp(b, env, sto) 41 | bv match { 42 | case BoxV(addr) => 43 | val (v, s) = interp(e, env, bs) 44 | (v, s + (addr -> v)) 45 | case v => error(s"not a box: $v") 46 | } 47 | case OpenBox(b) => 48 | val (bv, bs) = interp(b, env, sto) 49 | bv match { 50 | case BoxV(addr) => 51 | val v = bs.getOrElse(addr, error(s"unallocated address: $addr")) 52 | (v, bs) 53 | case v => error(s"not a box: $v") 54 | } 55 | case Seqn(l, rs) => 56 | val initial = interp(l, env, sto) 57 | rs.foldLeft(initial) { 58 | case ((v, s), r) => interp(r, env, s) 59 | } 60 | case Rec(fs) => 61 | val (fields, s) = fs.foldLeft(Map[String, Addr](), sto) { 62 | case ((m0, s0), (f, e)) => 63 | val (v, s1) = interp(e, env, s0) 64 | val addr = malloc(s1) 65 | val s2 = s1 + (addr -> v) 66 | val m1 = m0 + (f -> addr) 67 | (m1, s2) 68 | } 69 | (RecV(fields), s) 70 | case Get(r, f) => 71 | val (rv, rs) = interp(r, env, sto) 72 | rv match { 73 | case RecV(fields) => 74 | val addr = fields.getOrElse(f, error(s"no such field: $f")) 75 | val v = rs.getOrElse(addr, error(s"unallocated address: $addr")) 76 | (v, rs) 77 | case v => error(s"not a record: $v") 78 | } 79 | case Set(r, f, e) => 80 | val (rv, rs) = interp(r, env, sto) 81 | rv match { 82 | case RecV(fields) => 83 | val addr = fields.getOrElse(f, error(s"no such field: $f")) 84 | val (v, s) = interp(e, env, rs) 85 | (v, s + (addr -> v)) 86 | case v => error(s"not a record: $v") 87 | } 88 | } 89 | 90 | private def numVop(op: (Int, Int) => Int): (Value, Value) => NumV = { 91 | case (NumV(x), NumV(y)) => NumV(op(x, y)) 92 | case (x, y) => error(s"not both numbers: $x, $y") 93 | } 94 | private val numVAdd = numVop(_ + _) 95 | private val numVSub = numVop(_ - _) 96 | 97 | private def malloc(sto: Sto): Addr = sto.keys.maxOption.map(_ + 1).getOrElse(0) 98 | } 99 | -------------------------------------------------------------------------------- /ex6/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #6: SRBFAE 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl) section.** 5 | 6 | ## Download 7 | 8 | ```bash 9 | sbt new kaist-plrg-cs320/srbfae.g8 10 | ``` 11 | 12 | ## Descriptions 13 | 14 | SRBFAE extends BFAE with generalized sequencing and mutable records. 15 | Implement an interpreter for SRBFAE. 16 | 17 | ### Overview 18 | 19 | #### Generalized Sequencing 20 | 21 | Generalized sequencing allows one or more subexpressions, 22 | instead of exactly two subexpressions. 23 | 24 | ```scala 25 | test(run("""{ 26 | b => { 27 | b.set((2 + b.get)); 28 | b.set((3 + b.get)); 29 | b.set((4 + b.get)); 30 | b.get 31 | } 32 | }(Box(1))"""), "10") 33 | ``` 34 | 35 | #### Mutable Records 36 | 37 | Unlike records in MRFVAE, records in SRBFAE are mutable. `{ e1.f = e2 }` 38 | changes the value of a field `f` in the record produced by `e1`. The value of 39 | `e2` determines the field's new value, and that value is also the result of the 40 | expression. 41 | 42 | ```scala 43 | test(run("""{ 44 | r => { 45 | { r.x = 5 }; 46 | r.x 47 | } 48 | }({ x = 1 })"""), "5") 49 | ``` 50 | 51 | As in MRFVAE, the interpreter must throw an exception whose message 52 | includes `"not a record"` when updating a field of a non-record value and `"no 53 | such field"` when updating a field not in a given record value. 54 | 55 | ### Concrete Syntax 56 | 57 | We use the [extended Backus-Naur form](https://en.wikipedia.org/wiki/Extended_Backus\%E2\%80\%93Naur_form). 58 | Note that `{ }` denotes a repetition of zero or more times. 59 | 60 | ``` 61 | expr ::= ... 62 | | "{" expr {";" expr} "}" 63 | | "{" "}" 64 | | "{" field "=" expr {"," field "=" expr} "}" 65 | | expr "." field 66 | | "{" expr "." field "=" expr "}" 67 | ``` 68 | 69 | ### Abstract Syntax 70 | 71 | $e::=\cdots\ |\ e;\cdots;e\ |\ \lbrace f=e,\cdots,f=e\rbrace\ |\ e.f\ |\ e.f:=e$ 72 | 73 | $v::=\cdots\ \| \lbrace f=a,\cdots,f=a\rbrace$ 74 | 75 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`, and values 76 | are defined in `core/src/main/scala/cs320/Value.scala`. 77 | 78 | ### Operational Semantics 79 | 80 | $\Large\frac{\sigma,M_0\vdash e_1\Rightarrow v_1,M_1\quad\cdots\quad\sigma,M_{n-1}\vdash e_n\Rightarrow v_n,M_n}{ \sigma,M_0\vdash e_1;\cdots;e_n\Rightarrow v_n,M_n}$ 81 | 82 | $\Large\frac{\sigma,M_0\vdash e_1\Rightarrow v_1,M_1'\quad\cdots\quad \sigma,M_{n-1}\vdash e_n\Rightarrow v_n,M_n'\quad a_1\not\in\mathit{Domain}(M_1')\quad\cdots\quad a_n\not\in\mathit{Domain}(M_n')\quad M_1=M_1'[a_1\mapsto v_1]\quad\cdots\quad M_n=M_n'[a_n\mapsto v_n]}{\sigma,M_0\vdash\lbrace f_1=e_1,\cdots,f_n=e_n\rbrace\Rightarrow\lbrace f_1=a_1,\cdots,f_n=a_n\rbrace,M_n}$ 83 | 84 | $\Large\frac{\sigma,M\vdash e\Rightarrow\lbrace\cdots,f=a,\cdots\rbrace,M_1\quad a\in\mathit{Domain}(M_1)}{\sigma,M\vdash e.f\Rightarrow M_1(a),M_1}$ 85 | 86 | $\Large\frac{\sigma,M\vdash e_1\Rightarrow\lbrace\cdots,f=a,\cdots\rbrace,M_1\quad\sigma,M_1\vdash e_2\Rightarrow v,M_2}{\sigma,M\vdash e_1.f:=e_2\Rightarrow v,M_2[a\mapsto v]}$ 87 | 88 | ## Sample Solution 89 | 90 | [`Implementation.scala`](./Implementation.scala) 91 | -------------------------------------------------------------------------------- /ex7/README.md: -------------------------------------------------------------------------------- 1 | # Exercise #7: TFAE 2 | 3 | Draw type derivations of the following expressions: 4 | 5 | 1. $(\lambda({\tt x}{:}{\sf num},{\tt y}{:}{\sf num}).{\tt x}+{\tt y})(8)$ 6 | 2. $({\sf if}\ {\sf false}\ (\lambda({\tt x}{:}{\sf num}).{\tt x})\ (\lambda({\tt y}{:}{\sf num}).2))(57)$ 7 | 3. $(\lambda({\tt x}{:}{\sf num},{\tt y}{:}{\sf num}\rightarrow{\sf bool}).{\tt y}({\tt x}+17))(42,\lambda({\tt x}{:}{\sf num}).{\tt x}>72)$ 8 | 9 | where the type of $e_1>e_2$ is $\sf bool$ if the types of $e_1$ and $e_2$ are $\sf num$. 10 | 11 | ## Sample Solution 12 | 13 | [sample solution](./solution.pdf) 14 | -------------------------------------------------------------------------------- /ex7/solution.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-plrg-cs320/assignment-docs/f4e963185b395e8050eb7f1970b74d4419e96d18/ex7/solution.pdf -------------------------------------------------------------------------------- /ex8/README.md: -------------------------------------------------------------------------------- 1 | # Exercise 8: TpolyFAE 2 | 3 | Consider TpolyFAE. 4 | 5 | $\Large\frac{\alpha\not\in{\it Domain}(\Gamma)\quad\Gamma[\alpha]\vdash e:\tau}{\Gamma\vdash\Lambda\alpha.e:\forall\alpha.\tau}$ 6 | 7 | $\Large\frac{\Gamma\vdash\tau_0\quad\Gamma\vdash e:\forall\alpha.\tau_1}{\Gamma\vdash e[\tau_0]:\tau_1[\alpha\leftarrow\tau_0]}$ 8 | 9 | $\Large\frac{\alpha\in{\it Domain}(\Gamma)}{\Gamma\vdash\alpha}$ 10 | 11 | $\Large\frac{\Gamma[\alpha]\vdash\tau}{\Gamma\vdash\forall\alpha.\tau}$ 12 | 13 | Rewrite the following expression using explicit annotations of polymorphic types 14 | with $\Lambda\alpha.$ and $[\tau]$ 15 | to replace all the occurrences of $?$ with types 16 | and to make function calls to take explicit type arguments. 17 | For example, if a given expression is $(\lambda {\tt x}{:}?.{\tt x})\ 1$, then the answer is 18 | $(\Lambda\alpha.\lambda {\tt x}{:}\alpha.{\tt x})[{\sf num}]\ 1$. 19 | 20 | ${\sf val}\ {\tt f}{:}?=(\lambda{\tt g}{:}?.\lambda{\tt v}{:}?.{\tt g}\ {\tt v});\ {\sf val}\ {\tt g}{:}?=(\lambda {\tt x}{:}?.{\tt x});\ {\tt f}\ {\tt g}\ 10$ 21 | 22 | ## Sample Solution 23 | 24 | [sample solution](./solution.md) 25 | -------------------------------------------------------------------------------- /ex8/solution.md: -------------------------------------------------------------------------------- 1 | ${\sf val}\ {\tt f}{:}\forall\alpha.\forall\beta.(\alpha\rightarrow\beta)\rightarrow(\alpha\rightarrow\beta)=(\Lambda\alpha.\Lambda\beta.\lambda{\tt g}{:}\alpha\rightarrow\beta.\lambda{\tt v}{:}\alpha.{\tt g}\ {\tt v});\ {\sf val}\ {\tt g}{:}\forall\gamma.\gamma\rightarrow\gamma=(\Lambda\gamma.\lambda{\tt x}{:}\gamma.{\tt x});\ ({\tt f}[{\sf num}][{\sf num}])\ ({\tt g}[{\sf num}])\ 10$ 2 | -------------------------------------------------------------------------------- /hw1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-plrg-cs320/assignment-docs/f4e963185b395e8050eb7f1970b74d4419e96d18/hw1/1.jpg -------------------------------------------------------------------------------- /hw1/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-plrg-cs320/assignment-docs/f4e963185b395e8050eb7f1970b74d4419e96d18/hw1/2.jpg -------------------------------------------------------------------------------- /hw1/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-plrg-cs320/assignment-docs/f4e963185b395e8050eb7f1970b74d4419e96d18/hw1/3.jpg -------------------------------------------------------------------------------- /hw1/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kaist-plrg-cs320/assignment-docs/f4e963185b395e8050eb7f1970b74d4419e96d18/hw1/4.jpg -------------------------------------------------------------------------------- /hw1/README.md: -------------------------------------------------------------------------------- 1 | # Homework #1: Growing a Language 2 | 3 | ## Descriptions 4 | 5 | Watch the [Growing a Language](https://youtu.be/_ahvzDzKdB0) video by Guy L. Steele Jr. 6 | The script of the video is available [online](https://link.springer.com/content/pdf/10.1023\%2FA\%3A1010085415024.pdf). 7 | If you are outside the campus, 8 | refer to the [Downloading the script outside the campus](#Downloading-the-script-outside-the-campus) section to access the script. 9 | 10 | Write an essay after watching the video. You must summarize the content of the 11 | video in your own words. In addition, you must include your own opinions on the 12 | video in the essay. You can write the essay both in Korean and English. There is 13 | no restriction on the format and length of the essay. 14 | 15 | ## Submission 16 | 17 | Submit your essay file at 18 | . 19 | 20 | Only `pdf` files are allowed to submit. You can freely choose the file name. 21 | 22 | ## Downloading the script outside the campus 23 | 24 | * Go to the [KAIST Library](https://library.kaist.ac.kr/main.do) website 25 | and sign in. 26 | * Click the "Remote Access (전자정보 교외접속)" button. 27 | ![1](1.jpg) 28 | * Click the "Direct Link (바로가기)" button. 29 | ![2](2.jpg) 30 | * Paste the link () 31 | in the box of the "Direct URL (직접 입력)" section at "Method 2 (방법 2)." 32 | ![3](3.jpg) 33 | * Click the "GO" button. 34 | ![4](4.jpg) 35 | * The script file will be downloaded. 36 | -------------------------------------------------------------------------------- /proj1/README.md: -------------------------------------------------------------------------------- 1 | # Project #1: FIBER 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the 5 | [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl), 6 | [Fuzzing](https://github.com/kaist-plrg-cs320/assignment-docs#fuzzing), and 7 | [Grading](https://github.com/kaist-plrg-cs320/assignment-docs#grading) 8 | sections.** 9 | 10 | ## Download 11 | 12 | ```bash 13 | sbt new kaist-plrg-cs320/fiber.g8 14 | ``` 15 | 16 | ## Descriptions 17 | 18 | Read the FIBER language specification (`fiber-spec.pdf`) in the project directory, 19 | and then implement an interpreter for FIBER. 20 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`, 21 | and values are defined in `core/src/main/scala/cs320/Value.scala`. 22 | 23 | ### Reference Interpreter 24 | 25 | The reference interpreter of FIBER is available at . 26 | Use the reference interpreter to find the correct result of a certain expression. 27 | 28 | ## Submission 29 | 30 | Submit your `Implementation.scala` at 31 | . 32 | -------------------------------------------------------------------------------- /proj2/README.md: -------------------------------------------------------------------------------- 1 | # Project #2: X-FIBER 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the 5 | [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl), 6 | [Fuzzing](https://github.com/kaist-plrg-cs320/assignment-docs#fuzzing), and 7 | [Grading](https://github.com/kaist-plrg-cs320/assignment-docs#grading) 8 | sections.** 9 | 10 | ## Download 11 | 12 | ```bash 13 | sbt new kaist-plrg-cs320/x-fiber.g8 14 | ``` 15 | 16 | ## Descriptions 17 | 18 | Read the X-FIBER language specification (`x-fiber-spec.pdf`) in the project directory, 19 | and then implement an interpreter for X-FIBER. 20 | Expressions are defined in `core/src/main/scala/cs320/Expr.scala`, 21 | and values are defined in `core/src/main/scala/cs320/Value.scala`. 22 | 23 | ### Reference Interpreter 24 | 25 | The reference interpreter of X-FIBER is available at . 26 | Use the reference interpreter to find the correct result of a certain expression. 27 | 28 | ## Submission 29 | 30 | Submit your `Implementation.scala` at 31 | . 32 | -------------------------------------------------------------------------------- /proj3/README.md: -------------------------------------------------------------------------------- 1 | # Project #3: FABRIC 2 | 3 | **Read the [common instructions](https://github.com/kaist-plrg-cs320/assignment-docs) first if you have not read them.** 4 | **Don't forget to read the 5 | [REPL](https://github.com/kaist-plrg-cs320/assignment-docs#repl), 6 | [Fuzzing](https://github.com/kaist-plrg-cs320/assignment-docs#fuzzing), and 7 | [Grading](https://github.com/kaist-plrg-cs320/assignment-docs#grading) 8 | sections.** 9 | 10 | ## Download 11 | 12 | ```bash 13 | sbt new kaist-plrg-cs320/fabric.g8 14 | ``` 15 | 16 | ## Descriptions 17 | 18 | Read the FABRIC language specification (`fabric.pdf`) in the project directory, 19 | and then implement a type checker and an interpreter for FABRIC. 20 | 21 | ### Important Files 22 | 23 | * `core/src/main/scala/cs320/Implementation.scala` 24 | 25 | You must fill this file to implement the type checker and the interpreter. 26 | More precisely, you must complete the `typeCheck` and `interp` functions. 27 | You will see the following code in the file: 28 | ```scala 29 | def typeCheck(e: Typed.Expr): Typed.Type = T.typeCheck(e) 30 | 31 | def interp(e: Untyped.Expr): Untyped.Value = U.interp(e) 32 | 33 | object T { 34 | import Typed._ 35 | 36 | def typeCheck(expr: Expr): Type = ??? 37 | } 38 | 39 | object U { 40 | import Untyped._ 41 | 42 | def interp(expr: Expr): Value = ??? 43 | } 44 | ``` 45 | We recommend you to implement everything related to type checking inside the 46 | object `T` and to implement everything related to interpretation inside the 47 | object `U`. 48 | 49 | * `core/src/main/scala/cs320/Template.scala` 50 | 51 | This file contains the 52 | definition of two functions that you must implement to complete the project. 53 | ```scala 54 | def typeCheck(expr: Typed.Expr): Typed.Type 55 | def interp(expr: Untyped.Expr): Untyped.Value 56 | ``` 57 | In addition, it defines two other functions: 58 | ```scala 59 | def run(str: String): String = { 60 | val expr = Typed.Expr(str) 61 | typeCheck(expr) 62 | val erased = Typed.erase(expr) 63 | Untyped.showValue(interp(erased)) 64 | } 65 | def runWithStdLib(str: String): String = 66 | run(StdLib.code + str) 67 | ``` 68 | The `run` function parses a given string to get a typed expression. It 69 | type-checks the expression with the `typeCheck` function. 70 | If the type checking succeeds, it erases types from 71 | the expression with the `erase` function to obtain an untyped expression. 72 | It evaluates the untyped expression with the `interp` function and returns 73 | the result after converting it to a string. 74 | 75 | The `runWithStdLib` function does a similar thing with `run`, but it 76 | prepends the source code of the standard library in front of a given string 77 | before running it. 78 | 79 | * `core/src/main/scala/cs320/Typed.scala` 80 | 81 | This file defines typed expressions, the parser, the desugarer, and the type 82 | erasure of the language. 83 | 84 | * `core/src/main/scala/cs320/Untyped.scala` 85 | 86 | This file defines untyped expression and values of the language. 87 | 88 | ### REPL 89 | 90 | If you give the `--lib` flag to the REPL, it will run a given expression with 91 | the standard library. In this case, it does not show the results of 92 | parsing and erasing. 93 | 94 | ``` 95 | sbt:fabric> run --lib 96 | [info] running cs320.Main 97 | Welcome to the FABRIC REPL. 98 | Type in :q, :quit, or the EOF character to terminate the REPL. 99 | 100 | FABRIC> listLength[Int](List5[Int](1, 2, 3, 4, 5)) 101 | Type: Int 102 | Result: 5 103 | ``` 104 | 105 | ### Fuzzing 106 | 107 | Note that fuzzing may take some time. It may not print anything for a minute 108 | after start-up. 109 | 110 | ### Reference Interpreter 111 | 112 | The reference interpreter of FABRIC is available at . 113 | Use the reference interpreter to find the correct result of a certain expression. 114 | 115 | ## Submission 116 | 117 | Submit your `Implementation.scala` at 118 | . 119 | --------------------------------------------------------------------------------