2. Syntax and Semantics
Names, Bindings, and Scopes
Storage
Data Types
Functional Programming
First-class Functions
Polymorphism
Traits & Type Parameterization
Parsing and Interpretation
Data Abstraction / Modular Programming
Functional Programming Redux
Concurrency
Concurrent Programming
Domain-Specific Languages
Quarter 3
Quarter 4
Basics of
Scala
JavaScript
C
32. sealed abstract class ParseResult[+T]
case class Success[T](result: T, in: Input)
extends ParseResult[T]
case class Failure(msg: String, in: Input)
extends ParseResult[Nothing]
Parse Result
33. abstract class Parser[+T] extends (Input => ParseResult[T])
{ p =>
// An unspecified method that defines
// the behavior of this parser.
def apply(in: Input): ParseResult[T]
def ~ // ...
def | // ...
// ...
}
Parser
34. def elem(kind: String, p: Elem => Boolean) =
new Parser[Elem] {
def apply(in: Input) =
if (p(in.first)) Success(in.first, in.rest)
else Failure(kind + " expected", in)
}
Single Element Parser
35. abstract class Parser[+T] //...
{ p =>
//...
def ~ [U](q: => Parser[U]) = new Parser[T~U] {
def apply(in: Input) = p(in) match {
case Success(x, in1) =>
q(in1) match {
case Success(y, in2) => Success(new ~(x, y), in2)
case failure => failure
}
case failure => failure
}
}
Sequential Composition
36. def | (q: => Parser[T]) = new Parser[T] {
def apply(in: Input) = p(in) match {
case s1 @ Success(_, _) => s1
case failure => q(in)
}
}
Alternative Composition
37. def ^^ [U](f: T => U): Parser[U] = new Parser[U] {
def apply(in: Input) = p(in) match {
case Success(x, in1) => Success(f(x), in1)
case failure => failure
}
}
Result Conversion
44. sealed abstract class Exp
case class Num(n: Int) extends Exp
case class Add(lhs: Exp, rhs: Exp) extends Exp
sealed abstract class Value
case class numV(n: Int) extends Value
def plus(l: Value, r: Value) = l match {
case numV(n) => r match {
case numV(m) => numV(n + m)
case _ => sys.error("Cannot add non-number")
}
}
def eval(exp: Exp): Value = exp match {
case Num(v) => numV(v)
case Add(l, r) => plus(eval(l), eval(r))
}
Calculator
45. Let Bindingdef testLet {
expect(numV(42)) {
eval(parse("""
let x = 40
in (x + 2)
"""))
}
}
def testLetShadow {
expect(numV(?)) {
eval(parse("""
let x = 40
in (let y = 4
in (let x = 3 in (x + y)))
"""))
}
}
46. sealed abstract class Env
case class mtEnv() extends Env
case class bind(boundName: Symbol, boundValue: Value, rest: Env)
extends Env
def lookup(name: Symbol, env: Env): Value = env match {
case mtEnv() =>
sys.error("Lookup of " + name + " in empty environment")
case bind(boundName, boundValue, rest) =>
if(boundName == name) boundValue else lookup(name, rest)
}
Environment
47. def eval(exp: Exp): Value = eval(exp, mtEnv())
def eval(exp: Exp, env: Env): Value = exp match {
case Num(v) => numV(v)
case Add(l, r) => plus(eval(l, env), eval(r, env))
case Id(name) => lookup(name, env)
case Let(name, e1, e2) =>
eval(e2, bind(name, eval(e1, env), env))
}
Evaluating Let Bindings
48. def testFun1 {
expect(numV(5)) {
eval(parse("""
let inc = fun(x){ x + 1 }
in (inc 4)
"""))
}
}
def testFun2 {
expect(numV(5)) {
eval(parse("""
let y = 3
in (let inc = fun(x){ x + y }
in (let y = 11 in (inc 2)))
"""))
}
}
Functions
49. sealed abstract class Value
case class numV(n: Int) extends Value
case class funV(param: Symbol, body: Exp) extends Value
def eval(exp: Exp, env: Env): Value = exp match {
case Num(v) => numV(v)
case Add(l, r) => plus(eval(l, env), eval(r, env))
case Id(name) => lookup(name, env)
case Let(name, e1, e2) =>
eval(e2, bind(name, eval(e1, env), env))
case Fun(name, body) => funV(name, body)
case App(fun, arg) => eval(fun, env) match {
case funV(name, body) =>
eval(body, bind(name, eval(arg, env), env))
case _ => sys.error("Function expected")
}
}
Functions
50. sealed abstract class Value
case class numV(n: Int) extends Value
case class funV(param: Symbol, body: Exp) extends Value
def eval(exp: Exp, env: Env): Value = exp match {
case Num(v) => numV(v)
case Add(l, r) => plus(eval(l, env), eval(r, env))
case Id(name) => lookup(name, env)
case Let(name, e1, e2) =>
eval(e2, bind(name, eval(e1, env), env))
case Fun(name, body) => funV(name, body)
case App(fun, arg) => eval(fun, env) match {
case funV(name, body) =>
eval(body, bind(name, eval(arg, env), env))
case _ => sys.error("Function expected")
}
}
FunctionsDynamic Scoping
51. sealed abstract class Value
case class numV(n: Int) extends Value
case class closureV(param: Symbol, body: Exp, env: Env)
extends Value
def eval(exp: Exp, env: Env): Value = exp match {
case Num(v) => numV(v)
case Add(l, r) => plus(eval(l, env), eval(r, env))
case Id(name) => lookup(name, env)
case Let(name, e1, e2) =>
eval(e2, bind(name, eval(e1, env), env))
case Fun(name, body) => closureV(name, body, env)
case App(fun, arg) => eval(fun, env) match {
case closureV(name, body, env2) =>
eval(body, bind(name, eval(arg, env), env2))
case _ => sys.error("Closure expected")
}
}
Functions with Closures
52. Reading & Programming in Week 9
Reading
Sebesta Chapter 4: Lexical and Syntactic Analysis
Scala Chapter 33: Combinator Parsing
Week 10: Components
WebLab:
Graded Assignment 2: (deadline 14 May 2013, 23:59)
Graded Assignment 3: (deadline 31 May 2013, 23:59)