1.1 --- a/src/sys/js/fan/Method.js Wed Feb 15 08:55:43 2012 -0500
1.2 +++ b/src/sys/js/fan/Method.js Wed Feb 15 10:38:21 2012 -0500
1.3 @@ -16,8 +16,10 @@
1.4 // Constructor
1.5 //////////////////////////////////////////////////////////////////////////
1.6
1.7 -fan.sys.Method.prototype.$ctor = function(parent, name, flags, returns, params, facets)
1.8 +fan.sys.Method.prototype.$ctor = function(parent, name, flags, returns, params, facets, generic)
1.9 {
1.10 + if (generic === undefined) generic = null;
1.11 +
1.12 this.m_parent = parent;
1.13 this.m_name = name;
1.14 this.m_qname = parent.qname() + "." + name;
1.15 @@ -28,6 +30,23 @@
1.16 this.m_$name = this.$$name(name);
1.17 this.m_$qname = this.m_parent.m_$qname + '.' + this.m_$name;
1.18 this.m_facets = new fan.sys.Facets(facets);
1.19 + this.m_mask = (generic != null) ? 0 : fan.sys.Method.toMask(parent, returns, params);
1.20 + this.m_generic = generic;
1.21 +}
1.22 +
1.23 +fan.sys.Method.GENERIC = 0x01;
1.24 +fan.sys.Method.toMask = function(parent, returns, params)
1.25 +{
1.26 + // we only use generics in Sys
1.27 + if (parent.pod().$name() != "sys") return 0;
1.28 +
1.29 + var p = returns.isGenericParameter() ? 1 : 0;
1.30 + for (var i=0; i<params.size(); ++i)
1.31 + p |= params.get(i).m_type.isGenericParameter() ? 1 : 0;
1.32 +
1.33 + var mask = 0;
1.34 + if (p != 0) mask |= fan.sys.Method.GENERIC;
1.35 + return mask;
1.36 }
1.37
1.38 //////////////////////////////////////////////////////////////////////////
1.39 @@ -61,6 +80,14 @@
1.40 fan.sys.Method.prototype.func = function() { return this.m_func; }
1.41
1.42 //////////////////////////////////////////////////////////////////////////
1.43 +// Generics
1.44 +//////////////////////////////////////////////////////////////////////////
1.45 +
1.46 +fan.sys.Method.prototype.isGenericMethod = function() { return (this.m_mask & fan.sys.Method.GENERIC) != 0; }
1.47 +fan.sys.Method.prototype.isGenericInstance = function() { return this.m_generic != null; }
1.48 +fan.sys.Method.prototype.getGenericMethod = function() { return this.m_generic; }
1.49 +
1.50 +//////////////////////////////////////////////////////////////////////////
1.51 // Call Conveniences
1.52 //////////////////////////////////////////////////////////////////////////
1.53
2.1 --- a/src/sys/js/fan/Param.js Wed Feb 15 08:55:43 2012 -0500
2.2 +++ b/src/sys/js/fan/Param.js Wed Feb 15 10:38:21 2012 -0500
2.3 @@ -19,7 +19,7 @@
2.4 fan.sys.Param.prototype.$ctor = function(name, type, hasDefault)
2.5 {
2.6 this.m_name = name;
2.7 - this.m_type = fan.sys.Type.find(type);
2.8 + this.m_type = (type instanceof fan.sys.Type) ? type : fan.sys.Type.find(type);
2.9 this.m_hasDefault = hasDefault;
2.10 }
2.11
3.1 --- a/src/sys/js/fan/Type.js Wed Feb 15 08:55:43 2012 -0500
3.2 +++ b/src/sys/js/fan/Type.js Wed Feb 15 10:38:21 2012 -0500
3.3 @@ -126,7 +126,7 @@
3.4
3.5 fan.sys.Type.prototype.isGenericParameter = function()
3.6 {
3.7 - return this.pod() == fan.sys.Pod.$sysPod && this.$name().length == 1;
3.8 + return this.m_pod.m_name === "sys" && this.m_name.length === 1;
3.9 }
3.10
3.11 /*
3.12 @@ -142,7 +142,7 @@
3.13 }
3.14 */
3.15
3.16 -fan.sys.Type.isGeneric = function() { return this.isGenericType(); }
3.17 +fan.sys.Type.prototype.isGeneric = function() { return this.isGenericType(); }
3.18
3.19 /*
3.20 public Map params()
3.21 @@ -150,42 +150,43 @@
3.22 if (noParams == null) noParams = Sys.emptyStrTypeMap;
3.23 return (Map)noParams;
3.24 }
3.25 +*/
3.26
3.27 -public Type parameterize(Map params)
3.28 +fan.sys.Type.prototype.parameterize = function(params)
3.29 {
3.30 - if (this == Sys.ListType)
3.31 + if (this instanceof fan.sys.ListType)
3.32 {
3.33 - Type v = (Type)params.get("V");
3.34 - if (v == null) throw ArgErr.make("List.parameterize - V undefined").val;
3.35 + var v = params.get("V");
3.36 + if (v == null) throw fan.sys.ArgErr.make("List.parameterize - V undefined");
3.37 return v.toListOf();
3.38 }
3.39
3.40 - if (this == Sys.MapType)
3.41 + if (this instanceof fan.sys.MapType)
3.42 {
3.43 - Type v = (Type)params.get("V");
3.44 - Type k = (Type)params.get("K");
3.45 - if (v == null) throw ArgErr.make("Map.parameterize - V undefined").val;
3.46 - if (k == null) throw ArgErr.make("Map.parameterize - K undefined").val;
3.47 - return new MapType(k, v);
3.48 + var v = params.get("V");
3.49 + var k = params.get("K");
3.50 + if (v == null) throw fan.sys.ArgErr.make("Map.parameterize - V undefined");
3.51 + if (k == null) throw fan.sys.ArgErr.make("Map.parameterize - K undefined");
3.52 + return new fan.sys.MapType(k, v);
3.53 }
3.54
3.55 - if (this == Sys.FuncType)
3.56 - {
3.57 - Type r = (Type)params.get("R");
3.58 - if (r == null) throw ArgErr.make("Map.parameterize - R undefined").val;
3.59 - ArrayList p = new ArrayList();
3.60 - for (int i='A'; i<='H'; ++i)
3.61 - {
3.62 - Type x = (Type)params.get(FanStr.ascii[i]);
3.63 - if (x == null) break;
3.64 - p.add(x);
3.65 - }
3.66 - return new FuncType((Type[])p.toArray(new Type[p.size()]), r);
3.67 - }
3.68 + // TODO FIXIT
3.69 + // if (this == Sys.FuncType)
3.70 + // {
3.71 + // Type r = (Type)params.get("R");
3.72 + // if (r == null) throw ArgErr.make("Map.parameterize - R undefined");
3.73 + // ArrayList p = new ArrayList();
3.74 + // for (int i='A'; i<='H'; ++i)
3.75 + // {
3.76 + // Type x = (Type)params.get(FanStr.ascii[i]);
3.77 + // if (x == null) break;
3.78 + // p.add(x);
3.79 + // }
3.80 + // return new FuncType((Type[])p.toArray(new Type[p.size()]), r);
3.81 + // }
3.82
3.83 - throw UnsupportedErr.make("not generic: " + this).val;
3.84 + throw fan.sys.UnsupportedErr.make("not generic: " + this);
3.85 }
3.86 -*/
3.87
3.88 fan.sys.Type.prototype.toListOf = function()
3.89 {
3.90 @@ -234,31 +235,20 @@
3.91
3.92 fan.sys.Type.prototype.slots = function()
3.93 {
3.94 - // TODO FIXIT: include inheritance; cache
3.95 - var acc = [];
3.96 - for (var i in this.m_slots)
3.97 - acc.push(this.m_slots[i]);
3.98 - return fan.sys.List.make(fan.sys.Slot.$type, acc);
3.99 + this.doReflect();
3.100 + return this.m_slotList;
3.101 }
3.102
3.103 fan.sys.Type.prototype.methods = function()
3.104 {
3.105 - // TODO FIXIT: include inheritance; cache
3.106 - var acc = [];
3.107 - for (var i in this.m_slots)
3.108 - if (this.m_slots[i] instanceof fan.sys.Method)
3.109 - acc.push(this.m_slots[i]);
3.110 - return fan.sys.List.make(fan.sys.Method.$type, acc);
3.111 + this.doReflect();
3.112 + return this.m_methodList;
3.113 }
3.114
3.115 fan.sys.Type.prototype.fields = function()
3.116 {
3.117 - // TODO FIXIT: include inheritance; cache
3.118 - var acc = [];
3.119 - for (var i in this.m_slots)
3.120 - if (this.m_slots[i] instanceof fan.sys.Field)
3.121 - acc.push(this.m_slots[i]);
3.122 - return fan.sys.List.make(fan.sys.Field.$type, acc);
3.123 + this.doReflect();
3.124 + return this.m_fieldList;
3.125 }
3.126
3.127 fan.sys.Type.prototype.slot = function(name, checked)
3.128 @@ -453,8 +443,32 @@
3.129 // Util
3.130 //////////////////////////////////////////////////////////////////////////
3.131
3.132 +fan.sys.Type.prototype.doReflect = function()
3.133 +{
3.134 + if (this.m_slotList != null) return;
3.135 +
3.136 + var slots = [];
3.137 + var fields = [];
3.138 + var methods = [];
3.139 +
3.140 + for (var i in this.m_slots)
3.141 + {
3.142 + slot = this.m_slots[i]
3.143 + slots.push(slot);
3.144 + if (slot instanceof fan.sys.Field) fields.push(slot);
3.145 + else if (slot instanceof fan.sys.Method) methods.push(slot);
3.146 + }
3.147 +
3.148 + this.m_slotList = fan.sys.List.make(fan.sys.Slot.$type, slots);
3.149 + this.m_fieldList = fan.sys.List.make(fan.sys.Field.$type, fields);
3.150 + this.m_methodList = fan.sys.List.make(fan.sys.Method.$type, methods);
3.151 +}
3.152 +
3.153 fan.sys.Type.prototype.$slot = function(name)
3.154 {
3.155 + // reflect
3.156 + this.doReflect();
3.157 +
3.158 // check self first
3.159 var slot = this.m_slots[name];
3.160 if (slot != null) return slot;
3.161 @@ -575,19 +589,173 @@
3.162 fan.sys.NullableType.prototype.doc = function() { return this.m_root.doc(); }
3.163
3.164 /*************************************************************************
3.165 + * GenericType
3.166 + ************************************************************************/
3.167 +
3.168 +fan.sys.GenericType = fan.sys.Obj.$extend(fan.sys.Type)
3.169 +fan.sys.GenericType.prototype.$ctor = function(v) {}
3.170 +
3.171 +fan.sys.GenericType.prototype.doReflect = function()
3.172 +{
3.173 + try
3.174 + {
3.175 +
3.176 + if (this.m_slotList != null) return;
3.177 +
3.178 + // ensure master type is reflected
3.179 + var master = this.base();
3.180 + master.doReflect();
3.181 + var masterSlots = master.slots();
3.182 +
3.183 + // allocate slot data structures
3.184 + var slots = [];
3.185 + var fields = [];
3.186 + var methods = [];
3.187 +
3.188 + // parameterize master's slots
3.189 + for (var i=0; i<masterSlots.size(); i++)
3.190 + {
3.191 + var slot = masterSlots.get(i);
3.192 + if (slot instanceof fan.sys.Method)
3.193 + {
3.194 + slot = this.parameterizeMethod(slot);
3.195 + methods.push(slot);
3.196 + }
3.197 + else
3.198 + {
3.199 + slot = this.parameterizeField(slot);
3.200 + fields.push(slot);
3.201 + }
3.202 + slots.push(slot);
3.203 + this.m_slots[slot.m_name] = slot;
3.204 + }
3.205 +
3.206 + this.m_slotList = fan.sys.List.make(fan.sys.Slot.$type, slots);
3.207 + this.m_fieldList = fan.sys.List.make(fan.sys.Field.$type, fields);
3.208 + this.m_methodList = fan.sys.List.make(fan.sys.Method.$type, methods);
3.209 +
3.210 + }
3.211 + catch (err)
3.212 + {
3.213 + println(err);
3.214 + println(err.stack);
3.215 + println(err.stackTrace);
3.216 + println(err.javaException);
3.217 + }
3.218 +}
3.219 +
3.220 +fan.sys.GenericType.prototype.parameterizeField = function(f)
3.221 +{
3.222 + // if not generic, short circuit and reuse original
3.223 + var t = f.type();
3.224 + if (!t.isGenericParameter()) return f;
3.225 +
3.226 + // create new parameterized version
3.227 + t = this.parameterizeType(t);
3.228 + //var pf = new Field(this, f.name, f.flags, f.facets, f.lineNum, t);
3.229 + var pf = new fan.sys.File(this, f.m_name, f.m_flags, f.m_type, f.m_facets);
3.230 + //pf.reflect = f.reflect;
3.231 + return pf;
3.232 +}
3.233 +
3.234 +fan.sys.GenericType.prototype.parameterizeMethod = function(m)
3.235 +{
3.236 + // if not generic, short circuit and reuse original
3.237 + if (!m.isGenericMethod()) return m;
3.238 +
3.239 + // new signature
3.240 + var func = m.m_func;
3.241 + var ret;
3.242 + var params = fan.sys.List.make(fan.sys.Param.$type);
3.243 +
3.244 + // parameterize return type
3.245 + if (func.returns().isGenericParameter())
3.246 + ret = this.parameterizeType(func.returns());
3.247 + else
3.248 + ret = func.returns();
3.249 +
3.250 + // narrow params (or just reuse if not parameterized)
3.251 + var arity = m.params().size();
3.252 + for (var i=0; i<arity; ++i)
3.253 + {
3.254 + var p = m.params().get(i);
3.255 + if (p.m_type.isGenericParameter())
3.256 + {
3.257 + //params.add(new fan.sys.Param(p.name, parameterize(p.type), p.mask));
3.258 + params.add(new fan.sys.Param(p.m_name, this.parameterizeType(p.m_type), p.m_hasDefault));
3.259 + }
3.260 + else
3.261 + {
3.262 + params.add(p);
3.263 + }
3.264 + }
3.265 +
3.266 + //var pm = new Method(this, m.name, m.flags, m.facets, m.lineNum, ret, m.inheritedReturns, params, m);
3.267 + var pm = new fan.sys.Method(this, m.m_name, m.m_flags, ret, params, m.m_facets, m)
3.268 + //pm.reflect = m.reflect;
3.269 + return pm;
3.270 +}
3.271 +
3.272 +fan.sys.GenericType.prototype.parameterizeType = function(t)
3.273 +{
3.274 + var nullable = t.isNullable();
3.275 + var nn = t.toNonNullable();
3.276 + if (nn instanceof fan.sys.ListType)
3.277 + t = this.parameterizeListType(nn);
3.278 + //else if (nn instanceof fan.sys.FuncType)
3.279 + // t = parameterizeFuncType((FuncType)nn);
3.280 + else
3.281 + t = this.doParameterize(nn);
3.282 + return nullable ? t.toNullable() : t;
3.283 +}
3.284 +
3.285 +fan.sys.GenericType.prototype.parameterizeListType = function(t)
3.286 +{
3.287 + return this.doParameterize(t.v).toListOf();
3.288 +}
3.289 +
3.290 +// /**
3.291 +// * Recursively parameterize the params of a method type.
3.292 +// */
3.293 +// final FuncType parameterizeFuncType(FuncType t)
3.294 +// {
3.295 +// Type[] params = new Type[t.params.length];
3.296 +// for (int i=0; i<params.length; ++i)
3.297 +// {
3.298 +// Type param = t.params[i];
3.299 +// if (param.isGenericParameter()) param = doParameterize(param);
3.300 +// params[i] = param;
3.301 +// }
3.302 +//
3.303 +// Type ret = t.ret;
3.304 +// if (ret.isGenericParameter()) ret = doParameterize(ret);
3.305 +//
3.306 +// return new FuncType(params, ret);
3.307 +// }
3.308 +
3.309 +fan.sys.GenericType.prototype.doParameterize = function(t) {}
3.310 +
3.311 +/*************************************************************************
3.312 * ListType
3.313 ************************************************************************/
3.314
3.315 -fan.sys.ListType = fan.sys.Obj.$extend(fan.sys.Type)
3.316 +fan.sys.ListType = fan.sys.Obj.$extend(fan.sys.GenericType)
3.317 fan.sys.ListType.prototype.$ctor = function(v)
3.318 {
3.319 this.v = v;
3.320 + this.m_qname = "sys::List";
3.321 + this.m_pod = fan.sys.Pod.find("sys");
3.322 + this.m_name = "List";
3.323 + this.m_base = fan.sys.List.$type;
3.324 this.m_mixins = fan.sys.Type.$type.emptyList();
3.325 + this.m_slots = {};
3.326 }
3.327
3.328 -fan.sys.ListType.prototype.base = function() { return fan.sys.List.$type; }
3.329 -fan.sys.ListType.prototype.signature = function() { return this.v.signature() + '[]'; }
3.330 -fan.sys.ListType.prototype.$slot = function(name) { return fan.sys.List.$type.$slot(name); }
3.331 +fan.sys.ListType.prototype.signature = function()
3.332 +{
3.333 + return this.v.signature() + '[]';
3.334 +}
3.335 +
3.336 fan.sys.ListType.prototype.equals = function(that)
3.337 {
3.338 if (that instanceof fan.sys.ListType)
3.339 @@ -636,6 +804,13 @@
3.340 fan.sys.ListType.prototype.facets = function() { return fan.sys.List.$type.facets(); }
3.341 fan.sys.ListType.prototype.facet = function(type, checked) { return fan.sys.List.$type.facet(type, checked); }
3.342
3.343 +fan.sys.ListType.prototype.doParameterize = function(t)
3.344 +{
3.345 + if (t == fan.sys.Sys.VType) return this.v;
3.346 + if (t == fan.sys.Sys.LType) return this;
3.347 + throw new Error(t.toString());
3.348 +}
3.349 +
3.350 /*************************************************************************
3.351 * MapType
3.352 ************************************************************************/
3.353 @@ -646,6 +821,9 @@
3.354 {
3.355 this.k = k;
3.356 this.v = v;
3.357 + this.m_qname = "sys::Map";
3.358 + this.m_pod = fan.sys.Pod.find("sys");
3.359 + this.m_name = "Map";
3.360 this.m_mixins = fan.sys.Type.$type.emptyList();
3.361 }
3.362
4.1 --- a/src/sys/js/fanx/TypeParser.js Wed Feb 15 08:55:43 2012 -0500
4.2 +++ b/src/sys/js/fanx/TypeParser.js Wed Feb 15 10:38:21 2012 -0500
4.3 @@ -45,14 +45,24 @@
4.4 if (this.cur == '|')
4.5 type = this.loadFunc();
4.6
4.7 - // [java] is java FFI
4.8 - else if (this.cur == '[' && this.sig.indexOf("[java]") != -1) //sig.regionMatches(pos, "[java]", 0, 6))
4.9 - //type = loadFFI();
4.10 - throw fan.sys.ArgErr.make("Java types not allowed '" + this.sig + "'");
4.11 + // [ is either [ffi]xxx or [K:V] map
4.12 + else if (this.cur == '[')
4.13 + {
4.14 + var ffi = true;
4.15 + for (var i=this.pos+1; i<this.len; i++)
4.16 + {
4.17 + var ch = this.sig.charAt(i);
4.18 + if (this.isIdChar(ch)) continue;
4.19 + ffi = (ch == ']');
4.20 + break;
4.21 + }
4.22
4.23 - // [...] is map
4.24 - else if (this.cur == '[')
4.25 - type = this.loadMap();
4.26 + if (ffi)
4.27 + //type = loadFFI();
4.28 + throw fan.sys.ArgErr.make("Java types not allowed '" + this.sig + "'");
4.29 + else
4.30 + type = this.loadMap();
4.31 + }
4.32
4.33 // otherwise must be basic[]
4.34 else
4.35 @@ -71,6 +81,11 @@
4.36 this.consume('[');
4.37 this.consume(']');
4.38 type = type.toListOf();
4.39 + if (this.cur == '?')
4.40 + {
4.41 + consume('?');
4.42 + type = type.toNullable();
4.43 + }
4.44 }
4.45
4.46 // nullable
4.47 @@ -198,8 +213,7 @@
4.48 var typeName;
4.49 try
4.50 {
4.51 - var colon = sig.indexOf(":");
4.52 - if (sig.charAt(colon+1) != ':') throw new Exception();
4.53 + var colon = sig.indexOf("::");
4.54 podName = sig.substring(0, colon);
4.55 typeName = sig.substring(colon+2);
4.56 if (podName.length == 0 || typeName.length == 0) throw fan.sys.Err.make("");