| 1 |
/******************************************************************************* |
|---|
| 2 |
Copyright 2008 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 |
package com.sun.fortress.interpreter.evaluator.values; |
|---|
| 19 |
|
|---|
| 20 |
import static com.sun.fortress.exceptions.ProgramError.error; |
|---|
| 21 |
import static com.sun.fortress.exceptions.ProgramError.errorMsg; |
|---|
| 22 |
|
|---|
| 23 |
import java.util.List; |
|---|
| 24 |
|
|---|
| 25 |
import com.sun.fortress.interpreter.evaluator.Environment; |
|---|
| 26 |
import com.sun.fortress.interpreter.evaluator.EvalType; |
|---|
| 27 |
import com.sun.fortress.interpreter.evaluator.Evaluator; |
|---|
| 28 |
import com.sun.fortress.interpreter.evaluator.scopes.Scope; |
|---|
| 29 |
import com.sun.fortress.interpreter.evaluator.types.BottomType; |
|---|
| 30 |
import com.sun.fortress.interpreter.evaluator.types.FType; |
|---|
| 31 |
import com.sun.fortress.interpreter.evaluator.types.FTypeArrow; |
|---|
| 32 |
import com.sun.fortress.interpreter.glue.NativeApp; |
|---|
| 33 |
import com.sun.fortress.nodes.Expr; |
|---|
| 34 |
import com.sun.fortress.nodes.FnAbsDeclOrDecl; |
|---|
| 35 |
import com.sun.fortress.nodes.IdOrOpOrAnonymousName; |
|---|
| 36 |
import com.sun.fortress.nodes.Modifier; |
|---|
| 37 |
import com.sun.fortress.nodes.ModifierOverride; |
|---|
| 38 |
import com.sun.fortress.nodes.Param; |
|---|
| 39 |
import com.sun.fortress.nodes.Type; |
|---|
| 40 |
import com.sun.fortress.nodes_util.Applicable; |
|---|
| 41 |
import com.sun.fortress.nodes_util.NodeUtil; |
|---|
| 42 |
import com.sun.fortress.useful.HasAt; |
|---|
| 43 |
import com.sun.fortress.useful.NI; |
|---|
| 44 |
import com.sun.fortress.useful.Useful; |
|---|
| 45 |
|
|---|
| 46 |
import com.sun.fortress.exceptions.transactions.AbortedException; |
|---|
| 47 |
import com.sun.fortress.exceptions.transactions.OrphanedException; |
|---|
| 48 |
import com.sun.fortress.exceptions.FortressException; |
|---|
| 49 |
|
|---|
| 50 |
import edu.rice.cs.plt.tuple.Option; |
|---|
| 51 |
|
|---|
| 52 |
/** |
|---|
| 53 |
* A Closure value is a function, plus some environment information. |
|---|
| 54 |
*/ |
|---|
| 55 |
public class Closure extends NonPrimitive implements Scope { |
|---|
| 56 |
|
|---|
| 57 |
protected FType returnType; |
|---|
| 58 |
protected List<FType> instArgs; |
|---|
| 59 |
protected Applicable def; |
|---|
| 60 |
|
|---|
| 61 |
public Closure(Environment e, Applicable fndef) { |
|---|
| 62 |
super(e); // TODO verify that this is the proper environment |
|---|
| 63 |
def = NativeApp.checkAndLoadNative(fndef); |
|---|
| 64 |
} |
|---|
| 65 |
|
|---|
| 66 |
public Closure(Environment e, Applicable fndef, boolean isFunctionalMethod) { |
|---|
| 67 |
super(e); // TODO verify that this is the proper environment |
|---|
| 68 |
def = NativeApp.checkAndLoadNative(fndef,isFunctionalMethod); |
|---|
| 69 |
} |
|---|
| 70 |
|
|---|
| 71 |
protected Closure(Environment e, Applicable fndef, List<FType> args) { |
|---|
| 72 |
super(e); |
|---|
| 73 |
def = NativeApp.checkAndLoadNative(fndef); |
|---|
| 74 |
instArgs = args; |
|---|
| 75 |
} |
|---|
| 76 |
|
|---|
| 77 |
/* |
|---|
| 78 |
* Just like the PartiallyDefinedMethod, but used a specific environemnt |
|---|
| 79 |
*/ |
|---|
| 80 |
public Closure(TraitMethod method, Environment environment) { |
|---|
| 81 |
super(environment); |
|---|
| 82 |
def = NativeApp.checkAndLoadNative(method.def); |
|---|
| 83 |
instArgs = method.instArgs; |
|---|
| 84 |
setParamsAndReturnType(method.getParameters(), method.returnType); |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
// public Closure(BetterEnv e, FnExpr x, Option<Type> return_type, |
|---|
| 88 |
// List<Param> params) { |
|---|
| 89 |
// super(e); |
|---|
| 90 |
// def = NativeApp.checkAndLoadNative(x); |
|---|
| 91 |
// EvalType et = new EvalType(e); |
|---|
| 92 |
// setParamsAndReturnType( |
|---|
| 93 |
// et.paramsToParameters(e, params), |
|---|
| 94 |
// return_type.isPresent() ? et.evalType(return_type.getVal()) : BottomType.ONLY |
|---|
| 95 |
// ); |
|---|
| 96 |
// } |
|---|
| 97 |
|
|---|
| 98 |
@Override |
|---|
| 99 |
public boolean isOverride() { |
|---|
| 100 |
if (def instanceof FnAbsDeclOrDecl) { |
|---|
| 101 |
List<Modifier> mods = ((FnAbsDeclOrDecl) def).getMods(); |
|---|
| 102 |
for (Modifier mod : mods) |
|---|
| 103 |
if (mod instanceof ModifierOverride) |
|---|
| 104 |
return true; |
|---|
| 105 |
} |
|---|
| 106 |
return false; |
|---|
| 107 |
} |
|---|
| 108 |
|
|---|
| 109 |
/* (non-Javadoc) |
|---|
| 110 |
* @see com.sun.fortress.interpreter.evaluator.values.Fcn#getFnName() |
|---|
| 111 |
*/ |
|---|
| 112 |
@Override |
|---|
| 113 |
public IdOrOpOrAnonymousName getFnName() { |
|---|
| 114 |
return def.getName(); |
|---|
| 115 |
} |
|---|
| 116 |
|
|---|
| 117 |
protected HasAt getAt() { |
|---|
| 118 |
return def; |
|---|
| 119 |
} |
|---|
| 120 |
|
|---|
| 121 |
public String stringName() { |
|---|
| 122 |
return def.stringName(); |
|---|
| 123 |
} |
|---|
| 124 |
|
|---|
| 125 |
public boolean hasSelfDotMethodInvocation() { |
|---|
| 126 |
return false; |
|---|
| 127 |
} |
|---|
| 128 |
|
|---|
| 129 |
public String selfName() { |
|---|
| 130 |
return NI.na(); |
|---|
| 131 |
} |
|---|
| 132 |
|
|---|
| 133 |
public String toString() { |
|---|
| 134 |
return ((instArgs == null ? s(def) : |
|---|
| 135 |
(s(def) + Useful.listInOxfords(instArgs))) + " " + |
|---|
| 136 |
(type() != null ? type() : "NULL")) + " " + def.at(); |
|---|
| 137 |
} |
|---|
| 138 |
|
|---|
| 139 |
public boolean seqv(FValue v) { |
|---|
| 140 |
if (!(v instanceof Closure)) return false; |
|---|
| 141 |
Closure c = (Closure) v; |
|---|
| 142 |
if (getDef() != c.getDef()) return false; |
|---|
| 143 |
if (type() != c.type()) return false; |
|---|
| 144 |
if (getEnv() == c.getEnv()) return true; |
|---|
| 145 |
// TODO: environment walking and matching. Worth it?? |
|---|
| 146 |
// We'd need to compute FV(body). |
|---|
| 147 |
return false; |
|---|
| 148 |
} |
|---|
| 149 |
|
|---|
| 150 |
public int hashCode() { |
|---|
| 151 |
return def.hashCode() + |
|---|
| 152 |
System.identityHashCode(getEnv()) + |
|---|
| 153 |
(instArgs == null ? 0 : instArgs.hashCode()); |
|---|
| 154 |
} |
|---|
| 155 |
|
|---|
| 156 |
public boolean equals(Object o) { |
|---|
| 157 |
if (this == o) return true; |
|---|
| 158 |
if (o.getClass().equals(this.getClass())) { |
|---|
| 159 |
Closure oc = (Closure) o; |
|---|
| 160 |
return def == oc.def && |
|---|
| 161 |
getEnv() == oc.getEnv() && |
|---|
| 162 |
(instArgs == null ? (oc.instArgs == null) : |
|---|
| 163 |
oc.instArgs == null ? false : instArgs.equals(oc.instArgs)); |
|---|
| 164 |
} |
|---|
| 165 |
return false; |
|---|
| 166 |
} |
|---|
| 167 |
|
|---|
| 168 |
private void setReturnType(FType rt) { |
|---|
| 169 |
// TODO need to get this test right |
|---|
| 170 |
if (this.returnType != null && !this.returnType.equals(rt)) { |
|---|
| 171 |
throw new IllegalStateException( |
|---|
| 172 |
"Attempted second set of closure return type"); |
|---|
| 173 |
} |
|---|
| 174 |
returnType = rt; |
|---|
| 175 |
} |
|---|
| 176 |
|
|---|
| 177 |
|
|---|
| 178 |
public Applicable getDef() { |
|---|
| 179 |
return def; |
|---|
| 180 |
} |
|---|
| 181 |
|
|---|
| 182 |
/** |
|---|
| 183 |
* @return Returns the closure_body. |
|---|
| 184 |
*/ |
|---|
| 185 |
public Expr getBody() { |
|---|
| 186 |
Option<Expr> optBody = NodeUtil.getBody(def); |
|---|
| 187 |
assert(optBody.isSome()); |
|---|
| 188 |
return optBody.unwrap(); |
|---|
| 189 |
} |
|---|
| 190 |
|
|---|
| 191 |
public Expr getBodyNull() { |
|---|
| 192 |
Option<Expr> optBody = NodeUtil.getBody(def); |
|---|
| 193 |
return optBody.unwrap(null); |
|---|
| 194 |
} |
|---|
| 195 |
|
|---|
| 196 |
|
|---|
| 197 |
public FValue applyInner(List<FValue> args, HasAt loc, |
|---|
| 198 |
Environment envForInference) { |
|---|
| 199 |
if (def instanceof NativeApp) { |
|---|
| 200 |
args = typecheckParams(args,loc); |
|---|
| 201 |
try { |
|---|
| 202 |
return ((NativeApp)def).applyToArgs(args); |
|---|
| 203 |
} catch (AbortedException ae) { |
|---|
| 204 |
throw ae; |
|---|
| 205 |
} catch (OrphanedException oe) { |
|---|
| 206 |
throw oe; |
|---|
| 207 |
} catch (FortressException fe) { |
|---|
| 208 |
throw fe; |
|---|
| 209 |
} catch (RuntimeException ex) { |
|---|
| 210 |
return error(loc, errorMsg("Wrapped exception ", ex.toString()), ex); |
|---|
| 211 |
} catch (Error ex) { |
|---|
| 212 |
return error(loc, errorMsg("Wrapped error ", ex.toString()), ex); |
|---|
| 213 |
} |
|---|
| 214 |
} else { |
|---|
| 215 |
Evaluator eval = new Evaluator(buildEnvFromParams(args, loc)); |
|---|
| 216 |
return eval.eval(getBody()); |
|---|
| 217 |
} |
|---|
| 218 |
} |
|---|
| 219 |
|
|---|
| 220 |
/** |
|---|
| 221 |
* The environment, sort of, in which the closure's name is bound. |
|---|
| 222 |
*/ |
|---|
| 223 |
public Environment getEnv() { |
|---|
| 224 |
return getWithin(); |
|---|
| 225 |
} |
|---|
| 226 |
|
|---|
| 227 |
/** |
|---|
| 228 |
* The environment used to evaluate the closure. |
|---|
| 229 |
*/ |
|---|
| 230 |
public Environment getEvalEnv() { |
|---|
| 231 |
return getWithin(); |
|---|
| 232 |
} |
|---|
| 233 |
|
|---|
| 234 |
/** |
|---|
| 235 |
* Call this for Closures, not setParams. |
|---|
| 236 |
* @param fparams |
|---|
| 237 |
* @param ft |
|---|
| 238 |
*/ |
|---|
| 239 |
public void setParamsAndReturnType(List<Parameter> fparams, FType ft) { |
|---|
| 240 |
setReturnType(ft); |
|---|
| 241 |
setParams(fparams); |
|---|
| 242 |
} |
|---|
| 243 |
|
|---|
| 244 |
protected void setValueType() { |
|---|
| 245 |
setFtype(FTypeArrow.make(getDomain(), returnType)); |
|---|
| 246 |
} |
|---|
| 247 |
|
|---|
| 248 |
public void finishInitializing() { |
|---|
| 249 |
// This needs to be done right with a generic. |
|---|
| 250 |
Applicable x = getDef(); |
|---|
| 251 |
List<Param> params = x.getParams(); |
|---|
| 252 |
Option<Type> rt = x.getReturnType(); |
|---|
| 253 |
Environment env = getEvalEnv(); // should need this for types, |
|---|
| 254 |
// below. |
|---|
| 255 |
FType ft = EvalType.getFTypeFromOption(rt, env, BottomType.ONLY); |
|---|
| 256 |
List<Parameter> fparams = EvalType.paramsToParameters(env, params); |
|---|
| 257 |
|
|---|
| 258 |
setParamsAndReturnType(fparams, ft); |
|---|
| 259 |
|
|---|
| 260 |
return; // this; |
|---|
| 261 |
} |
|---|
| 262 |
|
|---|
| 263 |
@Override |
|---|
| 264 |
boolean getFinished() { |
|---|
| 265 |
return returnType != null; |
|---|
| 266 |
} |
|---|
| 267 |
|
|---|
| 268 |
|
|---|
| 269 |
} |
|---|