| 1 | (******************************************************************************* |
|---|
| 2 | Copyright 2009 Sun Microsystems, Inc., |
|---|
| 3 | 4150 Network Circle, Santa Clara, California 95054, U.S.A. |
|---|
| 4 | All rights reserved. |
|---|
| 5 | |
|---|
| 6 | U.S. Government Rights - Commercial software. |
|---|
| 7 | Government users are subject to the Sun Microsystems, Inc. standard |
|---|
| 8 | license agreement and applicable provisions of the FAR and its supplements. |
|---|
| 9 | |
|---|
| 10 | Use is subject to license terms. |
|---|
| 11 | |
|---|
| 12 | This distribution may include materials developed by third parties. |
|---|
| 13 | |
|---|
| 14 | Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered |
|---|
| 15 | trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|---|
| 16 | ******************************************************************************) |
|---|
| 17 | |
|---|
| 18 | (* |
|---|
| 19 | Implementation in the Fortress Programming Language of an Interpreter for the |
|---|
| 20 | dynamic semantics of Featherweight Java, as defined in: |
|---|
| 21 | |
|---|
| 22 | Featherweight Java: A Minimal Core Calculus for Java and GJ, |
|---|
| 23 | Atsushi Igarashi and Benjamin C. Pierce, |
|---|
| 24 | ACM Transactions on Programming Languages and Systems, Vol. 23, No. 3, |
|---|
| 25 | May 2001, Pages 396-450. |
|---|
| 26 | |
|---|
| 27 | Author: Eric Allen, January 2008. |
|---|
| 28 | *) |
|---|
| 29 | |
|---|
| 30 | component FeatherweightJava |
|---|
| 31 | import List.{...} |
|---|
| 32 | import Map.{...} |
|---|
| 33 | export Executable |
|---|
| 34 | |
|---|
| 35 | (* Classes and Class tables *) |
|---|
| 36 | |
|---|
| 37 | object ClassTable(defs: Map[\String, Class\]) |
|---|
| 38 | lookup(typ: Type) = defs[typ.name] |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | subtype(s: Type, t: Type) = |
|---|
| 42 | (s = t) OR: ((s.name =/= "Object") AND: (subtype(lookup(s).ext, t))) |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | field(v: New, n: String) requires {v.isVal()} = do |
|---|
| 46 | fields_v: List[\Decl\] = fields(v.tag) |
|---|
| 47 | |
|---|
| 48 | label find |
|---|
| 49 | for i <- fields_v.indices do |
|---|
| 50 | if n = fields_v[i].name then |
|---|
| 51 | exit find with v.args[i] |
|---|
| 52 | end |
|---|
| 53 | end |
|---|
| 54 | fail("Field " n " not found in class " v.tag.name ".") |
|---|
| 55 | end find |
|---|
| 56 | end |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | fields(c: Type): List[\Decl\] = do |
|---|
| 60 | if c.name = "Object" then <|[\Decl\] |> |
|---|
| 61 | else |
|---|
| 62 | c_def: Class = defs[c.name] |
|---|
| 63 | c_def.fields.appendR[\Decl\](fields(c_def.ext)) |
|---|
| 64 | end |
|---|
| 65 | end |
|---|
| 66 | |
|---|
| 67 | mbody(typ: Type, m_name: String): Meth = do |
|---|
| 68 | if typ.name = "Object" then |
|---|
| 69 | fail("Method " m_name " not found.") |
|---|
| 70 | else |
|---|
| 71 | class: Class = defs[typ.name] |
|---|
| 72 | |
|---|
| 73 | label find |
|---|
| 74 | for meth <- class.meths do |
|---|
| 75 | if m_name = meth.name then |
|---|
| 76 | exit find with meth |
|---|
| 77 | end |
|---|
| 78 | end |
|---|
| 79 | mbody(class.ext, m_name) |
|---|
| 80 | end find |
|---|
| 81 | end |
|---|
| 82 | end |
|---|
| 83 | end |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | object Class(name: String, ext: Type, |
|---|
| 87 | fields: List[\Decl\], cons: Cons, meths: List[\Meth\]) |
|---|
| 88 | end |
|---|
| 89 | |
|---|
| 90 | (* Exprs *) |
|---|
| 91 | trait Expr |
|---|
| 92 | getter asString(): String |
|---|
| 93 | isVal(): Boolean = false |
|---|
| 94 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr |
|---|
| 95 | ensures { outcome.isVal() } |
|---|
| 96 | end |
|---|
| 97 | |
|---|
| 98 | object Var(x: String) extends Expr |
|---|
| 99 | getter asString(): String = x |
|---|
| 100 | opr =(self, other: Var) = (x = other.x) |
|---|
| 101 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr = theta[x] |
|---|
| 102 | end |
|---|
| 103 | |
|---|
| 104 | object New(tag: Type, args: List[\Expr\]) extends Expr |
|---|
| 105 | getter asString() = "new " tag.asString <|[\String\] a.asString | a <- args|> |
|---|
| 106 | |
|---|
| 107 | isVal() = BIG AND[arg <- args] arg.isVal() |
|---|
| 108 | |
|---|
| 109 | opr =(self, other: New) = |
|---|
| 110 | (tag = other.tag) AND (BIG AND[i <- args.indices] args[i] = other.args[i]) |
|---|
| 111 | |
|---|
| 112 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr = |
|---|
| 113 | New(tag, <|[\Expr\] arg.eval(CT_, theta) | arg <- args |>) |
|---|
| 114 | end |
|---|
| 115 | |
|---|
| 116 | object Proj(receiver: Expr, field: String) extends Expr |
|---|
| 117 | getter asString() = (receiver.asString "." field) |
|---|
| 118 | |
|---|
| 119 | opr =(self, other: Proj) = |
|---|
| 120 | (receiver = other.receiver) AND (field = other.field) |
|---|
| 121 | |
|---|
| 122 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr = |
|---|
| 123 | CT_.field(cast[\New\](receiver.eval(CT_, theta)), field) |
|---|
| 124 | end |
|---|
| 125 | |
|---|
| 126 | object Invk(receiver: Expr, m_name: String, args: List[\Expr\]) extends Expr |
|---|
| 127 | getter asString() = (receiver.asString "." m_name args) |
|---|
| 128 | |
|---|
| 129 | opr =(self, other: Invk) = |
|---|
| 130 | (receiver = other.receiver) AND (m_name = other.m_name) AND (args = other.args) |
|---|
| 131 | |
|---|
| 132 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr = do |
|---|
| 133 | rec_v = cast[\New\](receiver.eval(CT_, theta)) |
|---|
| 134 | args_v = <|[\Expr\] arg.eval(CT_, theta) | arg <- sequential(args) |> |
|---|
| 135 | m = CT_.mbody(rec_v.tag, m_name) |
|---|
| 136 | theta' = {[\String, Expr\]"this" |-> rec_v asif Expr} UNION |
|---|
| 137 | {[\String, Expr\] x.name |-> e | (x,e) <- m.params.zip[\Expr\](args_v)} |
|---|
| 138 | |
|---|
| 139 | m.body.eval(CT_, theta') |
|---|
| 140 | end |
|---|
| 141 | end |
|---|
| 142 | |
|---|
| 143 | object Cast(typ: Type, term: Expr) extends Expr |
|---|
| 144 | getter asString() = ("(" typ.asString ")" term.asString) |
|---|
| 145 | |
|---|
| 146 | opr =(self, other: Cast) = (typ = other.typ) AND (term = other.term) |
|---|
| 147 | |
|---|
| 148 | eval(CT_: ClassTable, theta: Map[\String, Expr\]): Expr = do |
|---|
| 149 | cast_v = cast[\New\](term.eval(CT_, theta)) |
|---|
| 150 | if (CT_ VDASH (cast_v.tag < typ)) then cast_v |
|---|
| 151 | else fail("Class cast exception: " cast_v.typ |
|---|
| 152 | " is not a subtype of " typ) end |
|---|
| 153 | end |
|---|
| 154 | end |
|---|
| 155 | |
|---|
| 156 | (* Types *) |
|---|
| 157 | object Type(name: String) |
|---|
| 158 | getter asString() = name |
|---|
| 159 | opr =(self, other:Type) = (name = other.name) |
|---|
| 160 | end |
|---|
| 161 | |
|---|
| 162 | |
|---|
| 163 | (* Syntactic Subcomponents *) |
|---|
| 164 | object Decl(typ: Type, name: String) |
|---|
| 165 | getter asString() = typ " " name ";" |
|---|
| 166 | end |
|---|
| 167 | object Cons(tag: Type, params: List[\Decl\], |
|---|
| 168 | super: List[\Var\], this: List[\Init\]) |
|---|
| 169 | end |
|---|
| 170 | object Init(left: String, right: String) end |
|---|
| 171 | |
|---|
| 172 | object Meth(return: Type, name: String, params: List[\Decl\], |
|---|
| 173 | body: Expr) |
|---|
| 174 | end |
|---|
| 175 | |
|---|
| 176 | (* Operators *) |
|---|
| 177 | opr VDASH(context: (ClassTable, Map[\String, Expr\]), terms: EvalThunk) = do |
|---|
| 178 | (terms.t1.eval(context) = terms.t2) |
|---|
| 179 | end |
|---|
| 180 | |
|---|
| 181 | opr VDASH(context: ClassTable, types: SubtypeThunk) = do |
|---|
| 182 | context.subtype(types.typ1, types.typ2) |
|---|
| 183 | end |
|---|
| 184 | |
|---|
| 185 | object EvalThunk(t1: Expr, t2: Expr) end |
|---|
| 186 | object SubtypeThunk(typ1: Type, typ2: Type) end |
|---|
| 187 | |
|---|
| 188 | opr ->(t1: Expr, t2: Expr) = EvalThunk(t1, t2) |
|---|
| 189 | |
|---|
| 190 | opr <(typ1: Type, typ2: Type) = SubtypeThunk(typ1, typ2) |
|---|
| 191 | |
|---|
| 192 | (* Testing *) |
|---|
| 193 | run() = do |
|---|
| 194 | obj = Type("Object") |
|---|
| 195 | newObj = New(obj, <|[\Expr\] |>) |
|---|
| 196 | x = Var("x") |
|---|
| 197 | y = Var("y") |
|---|
| 198 | this = Var("this") |
|---|
| 199 | c = Type("c") |
|---|
| 200 | n = New(c, <|newObj asif Expr|>) |
|---|
| 201 | d = Decl(obj,"_x") |
|---|
| 202 | dx = Decl(obj, "x") |
|---|
| 203 | dy = Decl(obj, "y") |
|---|
| 204 | i = Init("x","_x") |
|---|
| 205 | e = <|d|> |
|---|
| 206 | k = Cons(c, e, <|[\Var\] |>, <| i |>) |
|---|
| 207 | m = Meth(obj, "m", <|dy|>, y) |
|---|
| 208 | m' = Meth(obj, "n", <|d|>, Proj(this, "x")) |
|---|
| 209 | l = Class("c", obj, <|dx|>, k, <|m, m'|>) |
|---|
| 210 | t = {[\String,Class\]"c" |-> l} |
|---|
| 211 | p = Proj(x, "x") |
|---|
| 212 | v = Invk(x, "m", <|n asif Expr|>) |
|---|
| 213 | cst1 = Cast(c, x) |
|---|
| 214 | cst2 = Cast(obj, x) |
|---|
| 215 | v' = Invk(x, "n", <|n asif Expr|>) |
|---|
| 216 | CT_ = ClassTable(t) |
|---|
| 217 | theta0 = {[\String, Expr\]} |
|---|
| 218 | theta1 = {[\String,Expr\]"x" |-> n asif Expr, "y" |-> newObj} |
|---|
| 219 | |
|---|
| 220 | assert((CT_, theta0) VDASH (n -> n)) |
|---|
| 221 | assert((CT_, theta1) VDASH (x -> n)) |
|---|
| 222 | assert((CT_, theta1) VDASH (y -> newObj)) |
|---|
| 223 | assert((CT_, theta1) VDASH (p -> newObj)) |
|---|
| 224 | assert((CT_, theta1) VDASH (v -> n)) |
|---|
| 225 | assert((CT_, theta1) VDASH (v' -> newObj)) |
|---|
| 226 | assert((CT_, theta1) VDASH (cst1 -> n)) |
|---|
| 227 | assert((CT_, theta1) VDASH (cst2 -> n)) |
|---|
| 228 | end |
|---|
| 229 | |
|---|
| 230 | end |
|---|