/// <summary> /// Parameterize the specified field (reuse if generic /// parameterization isn't necessary). /// </summary> internal Field parameterize(Field f) { // if not generic, short circuit and reuse original Type of = f.type(); if (!of.isGenericParameter()) return f; // create new parameterized version of = parameterize(of); Field pf = new Field(this, f.m_name, f.m_flags, f.m_facets, f.m_lineNum, of); pf.m_reflect = f.m_reflect; return pf; }
/// <summary> /// Figure out the map type: /// 1) if t was explicit then use it (check that it was a map type) /// 2) if we have field typed as a map , then use its definition /// 3) if inferred is false, then drop back to Obj:Obj /// 4) If inferred is true then return null and we'll infer the common key/val types /// </summary> private MapType toMapType(Type t, Field curField, bool infer) { if (t != null) { try { return (MapType)t; } catch (System.InvalidCastException) { throw err("Invalid map type: " + t); } } if (curField != null) { Type ft = curField.type().toNonNullable(); if (ft is MapType) return (MapType)ft; } if (infer) return null; return defaultMapType; }
/// <summary> /// Figure out the type of the list: /// 1) if t was explicit then use it /// 2) if we have field typed as a list, then use its definition /// 3) if inferred is false, then drop back to list of Obj /// 4) If inferred is true then return null and we'll infer the common type /// </summary> private Type toListOfType(Type t, Field curField, bool infer) { if (t != null) return t; if (curField != null) { Type ft = curField.type().toNonNullable(); if (ft is ListType) return ((ListType)ft).m_v; } if (infer) return null; return Sys.ObjType.toNullable(); }
/// <summary> /// obj := literal | simple | complex /// </summary> private object readObj(Field curField, Type peekType, bool root) { // literals are stand alone if (Token.isLiteral(curt)) { object val = tokenizer.m_val; consume(); return val; } // [ is always list/map collection if (curt == Token.LBRACKET) return readCollection(curField, peekType); // at this point all remaining options must start // with a type signature - if peekType is non-null // then we've already read the type signature int line = tokenizer.m_line; Type t = (peekType != null) ? peekType : readType(); // type: type#" // simple: type( // list/map: type[ // complex: type || type{ if (curt == Token.LPAREN) return readSimple(line, t); else if (curt == Token.POUND) return readTypeOrSlotLiteral(line, t); else if (curt == Token.LBRACKET) return readCollection(curField, t); else return readComplex(line, t, root); }
////////////////////////////////////////////////////////////////////////// // Collection ////////////////////////////////////////////////////////////////////////// /// <summary> /// collection := list | map /// </summary> private object readCollection(Field curField, Type t) { // opening [ consume(Token.LBRACKET, "Expecting '['"); // if this could be a map type signature: // [qname:qname] // [qname:qname][] // [qname:qname][][] ... // or it could just be the type signature of // of a embedded simple, complex, or list Type peekType = null; if (curt == Token.ID && t == null) { // peek at the type peekType = readType(); // if we have [mapType] then this is non-inferred type signature if (curt == Token.RBRACKET && peekType is MapType) { t = peekType; peekType = null; consume(); while (curt == Token.LRBRACKET) { consume(); t = t.toListOf(); } if (curt == Token.QUESTION) { consume(); t = t.toNullable(); } if (curt == Token.POUND) { consume(); return t; } consume(Token.LBRACKET, "Expecting '['"); } } // handle special case of [,] if (curt == Token.COMMA && peekType == null) { consume(); consume(Token.RBRACKET, "Expecting ']'"); return new List(toListOfType(t, curField, false)); } // handle special case of [:] if (curt == Token.COLON && peekType == null) { consume(); consume(Token.RBRACKET, "Expecting ']'"); return new Map(toMapType(t, curField, false)); } // read first list item or first map key object first = readObj(null, peekType, false); // now we can distinguish b/w list and map if (curt == Token.COLON) return readMap(toMapType(t, curField, true), first); else return readList(toListOfType(t, curField, true), first); }
void complexSet(object obj, Field field, object val, int line) { try { if (field.isConst()) field.set(obj, OpUtil.toImmutable(val), false); else field.set(obj, val); } catch (System.Exception ex) { throw err("Cannot set field " + field.qname() + ": " + ex, line, ex); } }