| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | package com.sun.fortress.interpreter.glue; |
|---|
| 19 | |
|---|
| 20 | import static com.sun.fortress.exceptions.InterpreterBug.bug; |
|---|
| 21 | import static com.sun.fortress.exceptions.ProgramError.error; |
|---|
| 22 | import static com.sun.fortress.exceptions.ProgramError.errorMsg; |
|---|
| 23 | import com.sun.fortress.interpreter.evaluator.values.FValue; |
|---|
| 24 | import com.sun.fortress.interpreter.evaluator.values.NativeConstructor; |
|---|
| 25 | import com.sun.fortress.nodes.*; |
|---|
| 26 | import com.sun.fortress.nodes_util.NodeFactory; |
|---|
| 27 | import com.sun.fortress.nodes_util.NodeUtil; |
|---|
| 28 | import com.sun.fortress.useful.Pair; |
|---|
| 29 | import edu.rice.cs.plt.tuple.Option; |
|---|
| 30 | |
|---|
| 31 | import java.util.Hashtable; |
|---|
| 32 | import java.util.List; |
|---|
| 33 | import java.util.Map; |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | public abstract class NativeApp implements Applicable { |
|---|
| 46 | protected Applicable a; |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | public abstract int getArity(); |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | |
|---|
| 64 | protected void init(Applicable app, boolean isFunctionalMethod) { |
|---|
| 65 | if (this.a != null) { |
|---|
| 66 | bug("Duplicate NativeApp.init call."); |
|---|
| 67 | } |
|---|
| 68 | this.a = app; |
|---|
| 69 | int aty = NodeUtil.getParams(app).size(); |
|---|
| 70 | |
|---|
| 71 | |
|---|
| 72 | |
|---|
| 73 | if (isFunctionalMethod) aty--; |
|---|
| 74 | if (aty != getArity()) { |
|---|
| 75 | error(app, "Arity of type " + aty + " does not match native arity " + getArity()); |
|---|
| 76 | } |
|---|
| 77 | if (NodeUtil.getReturnType(app) == null || NodeUtil.getReturnType(app).isNone()) { |
|---|
| 78 | error(app, "Please specify a Fortress return type."); |
|---|
| 79 | } |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | |
|---|
| 83 | public Expr getBody() { |
|---|
| 84 | return null; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | public FnHeader getHeader() { |
|---|
| 88 | return a.getHeader(); |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | public List<Param> getParams() { |
|---|
| 92 | return a.getHeader().getParams(); |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | public Option<Type> getReturnType() { |
|---|
| 96 | return a.getHeader().getReturnType(); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | public List<StaticParam> getStaticParams() { |
|---|
| 100 | return a.getHeader().getStaticParams(); |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | public IdOrOpOrAnonymousName getName() { |
|---|
| 104 | return a.getHeader().getName(); |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | public Option<WhereClause> getWhereClause() { |
|---|
| 108 | return a.getHeader().getWhereClause(); |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | public String at() { |
|---|
| 112 | return a.at(); |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | public String stringName() { |
|---|
| 116 | return a.stringName(); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | public String toString() { |
|---|
| 120 | return (a.stringName() + "(native " + this.getClass().getSimpleName() + ")"); |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | public <RetType> RetType accept(NodeVisitor<RetType> visitor) { |
|---|
| 124 | return visitor.forId(NodeFactory.makeId(NodeFactory.makeSpan(""), "")); |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | public void accept(NodeVisitor_void visitor) { |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | public int generateHashCode() { |
|---|
| 131 | return 0; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | public String serialize() { |
|---|
| 135 | return bug(this, errorMsg("Cannot serialize NativeApp ", this)); |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | public void serialize(java.io.Writer writer) { |
|---|
| 139 | bug(this, errorMsg("Cannot serialize NativeApp ", this)); |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | public void walk(TreeWalker w) { |
|---|
| 143 | bug(this, errorMsg("Cannot walk NativeApp ", this)); |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | |
|---|
| 148 | |
|---|
| 149 | |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | |
|---|
| 154 | |
|---|
| 155 | public abstract FValue applyToArgs(List<FValue> args); |
|---|
| 156 | |
|---|
| 157 | |
|---|
| 158 | |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | |
|---|
| 170 | public static Applicable checkAndLoadNative(Applicable defn, boolean isFunctionalMethod) { |
|---|
| 171 | Option<Expr> optBody = NodeUtil.getBody(defn); |
|---|
| 172 | if (optBody.isNone()) return defn; |
|---|
| 173 | Expr body = optBody.unwrap(); |
|---|
| 174 | Expr fn; |
|---|
| 175 | Expr arg; |
|---|
| 176 | if (body instanceof Juxt && ((Juxt) body).isTight()) { |
|---|
| 177 | List<Expr> juxts = ((Juxt) body).getExprs(); |
|---|
| 178 | if (juxts.size() != 2) return defn; |
|---|
| 179 | fn = juxts.get(0); |
|---|
| 180 | arg = juxts.get(1); |
|---|
| 181 | } else if (body instanceof MathPrimary) { |
|---|
| 182 | MathPrimary mp = (MathPrimary) body; |
|---|
| 183 | List<MathItem> args = mp.getRest(); |
|---|
| 184 | if (args.size() != 1) return defn; |
|---|
| 185 | fn = mp.getFront(); |
|---|
| 186 | MathItem mi = args.get(0); |
|---|
| 187 | if (mi instanceof ExprMI) arg = ((ExprMI) mi).getExpr(); |
|---|
| 188 | else return defn; |
|---|
| 189 | } else |
|---|
| 190 | return defn; |
|---|
| 191 | if (!(fn instanceof VarRef)) return defn; |
|---|
| 192 | if (!(arg instanceof StringLiteralExpr)) return defn; |
|---|
| 193 | Id name = ((VarRef) fn).getVarId(); |
|---|
| 194 | if (!name.getText().equals("builtinPrimitive")) return defn; |
|---|
| 195 | String str = ((StringLiteralExpr) arg).getText(); |
|---|
| 196 | Pair<String, Applicable> key = new Pair<String, Applicable>(str, defn); |
|---|
| 197 | synchronized (cache) { |
|---|
| 198 | NativeApp res = cache.get(key); |
|---|
| 199 | if (res != null) return res; |
|---|
| 200 | try { |
|---|
| 201 | |
|---|
| 202 | Class nativeAct = Class.forName(str); |
|---|
| 203 | res = (NativeApp) nativeAct.newInstance(); |
|---|
| 204 | res.init(defn, isFunctionalMethod); |
|---|
| 205 | cache.put(key, res); |
|---|
| 206 | return res; |
|---|
| 207 | } |
|---|
| 208 | catch (java.lang.ClassNotFoundException x) { |
|---|
| 209 | return bug(defn, "Native class " + str + " not found.", x); |
|---|
| 210 | } |
|---|
| 211 | catch (java.lang.InstantiationException x) { |
|---|
| 212 | return bug(defn, "Native class " + str + " has no nullary constructor.", x); |
|---|
| 213 | } |
|---|
| 214 | catch (java.lang.IllegalAccessException x) { |
|---|
| 215 | return bug(defn, "Native class " + str + " cannot be accessed.", x); |
|---|
| 216 | } |
|---|
| 217 | catch (java.lang.ClassCastException x) { |
|---|
| 218 | return bug(defn, "Native class " + str + " is not a NativeApp.", x); |
|---|
| 219 | } |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | public static Applicable checkAndLoadNative(Applicable defn) { |
|---|
| 224 | return checkAndLoadNative(defn, false); |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | static public void reset() { |
|---|
| 228 | cache = new Hashtable<Pair<String, Applicable>, NativeApp>(); |
|---|
| 229 | NativeConstructor.unregisterAllConstructors(); |
|---|
| 230 | } |
|---|
| 231 | |
|---|
| 232 | static Map<Pair<String, Applicable>, NativeApp> cache; |
|---|
| 233 | } |
|---|