| 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 |
import static com.sun.fortress.exceptions.ProgramError.errorMsg; |
|---|
| 20 |
|
|---|
| 21 |
import java.util.List; |
|---|
| 22 |
|
|---|
| 23 |
import com.sun.fortress.exceptions.UnificationError; |
|---|
| 24 |
import com.sun.fortress.interpreter.evaluator.Environment; |
|---|
| 25 |
import com.sun.fortress.interpreter.evaluator.types.FType; |
|---|
| 26 |
import com.sun.fortress.nodes.IdOrOpOrAnonymousName; |
|---|
| 27 |
import com.sun.fortress.nodes_util.NodeUtil; |
|---|
| 28 |
import com.sun.fortress.useful.HasAt; |
|---|
| 29 |
|
|---|
| 30 |
abstract public class Fcn extends FValue { |
|---|
| 31 |
/** |
|---|
| 32 |
* Need to know the environment so we can resolve |
|---|
| 33 |
* overloading/shadowing properly. |
|---|
| 34 |
*/ |
|---|
| 35 |
Environment within; |
|---|
| 36 |
|
|---|
| 37 |
/** |
|---|
| 38 |
* Need to make type information mutable due to |
|---|
| 39 |
* multi-phase initialization protocol. |
|---|
| 40 |
*/ |
|---|
| 41 |
private volatile FType ftype; |
|---|
| 42 |
|
|---|
| 43 |
protected Fcn(Environment within) { |
|---|
| 44 |
this.within = within; |
|---|
| 45 |
within.bless(); |
|---|
| 46 |
} |
|---|
| 47 |
|
|---|
| 48 |
public Environment getWithin() { |
|---|
| 49 |
return within; |
|---|
| 50 |
} |
|---|
| 51 |
|
|---|
| 52 |
/** |
|---|
| 53 |
* Getter for ftype. Should always be non-null, but right now |
|---|
| 54 |
* FGenericFunction never calls setFtype and this returns null in |
|---|
| 55 |
* that case. This leads to extensive bugs particularly when a |
|---|
| 56 |
* generic function is overloaded along with non-generic siblings, |
|---|
| 57 |
* or when a generic function is passed as an argument to an |
|---|
| 58 |
* overloaded function without providing an explicit type |
|---|
| 59 |
* instantiation. Delete "&& false" to enable checking if you're |
|---|
| 60 |
* trying to fix this bug. |
|---|
| 61 |
*/ |
|---|
| 62 |
public FType type() { |
|---|
| 63 |
if (ftype==null && false) { |
|---|
| 64 |
throw new NullPointerException(errorMsg("No type information for ", this, |
|---|
| 65 |
" ", this.getClass())); |
|---|
| 66 |
} |
|---|
| 67 |
return ftype; |
|---|
| 68 |
} |
|---|
| 69 |
|
|---|
| 70 |
/** |
|---|
| 71 |
* Finish initializing Fcn, if necessary. |
|---|
| 72 |
* |
|---|
| 73 |
* There used to be a HasFinishInitializing interface for this, |
|---|
| 74 |
* but after cleaning up the code a bit it became clear that we |
|---|
| 75 |
* should just let it apply to any Fcn. |
|---|
| 76 |
*/ |
|---|
| 77 |
public void finishInitializing() { |
|---|
| 78 |
// By default, nothing need be done. |
|---|
| 79 |
} |
|---|
| 80 |
|
|---|
| 81 |
public void setFtype(FType ftype) { |
|---|
| 82 |
if (this.ftype != null) |
|---|
| 83 |
throw new IllegalStateException("Cannot set twice"); |
|---|
| 84 |
setFtypeUnconditionally(ftype); |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
public void setFtypeUnconditionally(FType ftype) { |
|---|
| 88 |
this.ftype = ftype; |
|---|
| 89 |
} |
|---|
| 90 |
|
|---|
| 91 |
protected FValue check(FValue x) { |
|---|
| 92 |
return x; |
|---|
| 93 |
} |
|---|
| 94 |
|
|---|
| 95 |
final public FValue apply(List<FValue> args, HasAt loc, Environment envForInference) { |
|---|
| 96 |
List<FValue> unwrapped = conditionallyUnwrapTupledArgs(args); |
|---|
| 97 |
try { |
|---|
| 98 |
return check(applyInner(unwrapped, loc, envForInference)); |
|---|
| 99 |
} catch (UnificationError u) { |
|---|
| 100 |
if (unwrapped != args) { |
|---|
| 101 |
try { |
|---|
| 102 |
return check(applyInner(args, loc, envForInference)); |
|---|
| 103 |
} catch (UnificationError u1) { |
|---|
| 104 |
throw u; |
|---|
| 105 |
} |
|---|
| 106 |
} |
|---|
| 107 |
throw u; |
|---|
| 108 |
} |
|---|
| 109 |
} |
|---|
| 110 |
|
|---|
| 111 |
protected List<FValue> conditionallyUnwrapTupledArgs(List<FValue> args) { |
|---|
| 112 |
// TODO This ought not be necessary. |
|---|
| 113 |
if (args.size() == 1 && (args.get(0) instanceof FTuple)) { |
|---|
| 114 |
args = ((FTuple) args.get(0)).getVals(); |
|---|
| 115 |
} |
|---|
| 116 |
return args; |
|---|
| 117 |
} |
|---|
| 118 |
|
|---|
| 119 |
abstract public FValue applyInner(List<FValue> args, HasAt loc, Environment envForInference); |
|---|
| 120 |
|
|---|
| 121 |
public boolean hasSelfDotMethodInvocation() { |
|---|
| 122 |
return false; |
|---|
| 123 |
} |
|---|
| 124 |
|
|---|
| 125 |
abstract public IdOrOpOrAnonymousName getFnName(); |
|---|
| 126 |
|
|---|
| 127 |
/** |
|---|
| 128 |
* Returns the name if this "function" is regarded as a method. |
|---|
| 129 |
* For functions, just returns the name. |
|---|
| 130 |
*/ |
|---|
| 131 |
public String asMethodName() { |
|---|
| 132 |
return NodeUtil.nameString(getFnName()); |
|---|
| 133 |
} |
|---|
| 134 |
|
|---|
| 135 |
} |
|---|