
1 // 2 // Copyright (c) 2006, Brian Frank and Andy Frank 3 // Licensed under the Academic Free License version 3.0 4 // 5 // History: 6 // 26 Dec 05 Brian Frank Creation 7 // 19 Aug 06 Brian Frank Ported from Java to Fan 8 // 9 10 ** 11 ** FType is the read/write fcode representation of sys::Type. 12 ** 13 class FType : CType 14 { 15 16 ////////////////////////////////////////////////////////////////////////// 17 // Constructor 18 ////////////////////////////////////////////////////////////////////////// 19 20 new make(FPod fpod) 21 { 22 this.fpod = fpod 23 this.fattrs = FAttr[,] 24 } 25 26 ////////////////////////////////////////////////////////////////////////// 27 // CType 28 ////////////////////////////////////////////////////////////////////////// 29 30 override Namespace ns() { return fpod.ns } 31 override FPod pod() { return fpod } 32 override Str name() { return fpod.n(fpod.typeRef(self).typeName) } 33 override Str qname() { return "${fpod.name}::${name}" } 34 override Str signature() { return qname } 35 override Str toStr() { return signature } 36 37 override CType base 38 { 39 get 40 { 41 if (@base == null) @base = fpod.toType(fbase) 42 return @base 43 } 44 } 45 46 override CType[] mixins 47 { 48 get 49 { 50 if (@mixins == null) @mixins = fpod.resolveTypes(fmixins) 51 return @mixins 52 } 53 } 54 55 override Str:CSlot slots 56 { 57 get 58 { 59 if (@slots == null) reflect 60 return @slots 61 } 62 } 63 64 override Bool isGeneric() 65 { 66 return fpod.name == "sys" && (name == "List" || name == "Map" || name == "Func") 67 } 68 69 override Bool isParameterized() { return false } 70 71 override Bool isGenericParameter() 72 { 73 return fpod.name == "sys" && name.size == 1 74 } 75 76 override ListType toListOf() 77 { 78 if (listOf == null) listOf = ListType.make(this) 79 return listOf 80 } 81 82 ////////////////////////////////////////////////////////////////////////// 83 // Reflection 84 ////////////////////////////////////////////////////////////////////////// 85 86 private Void reflect() 87 { 88 // lazy read from the pod file 89 read 90 91 // map all the declared fields and methods 92 @slots = Str:CSlot[:] 93 ffields.each |FField f| { slots[f.name] = f } 94 fmethods.each |FMethod m| 95 { 96 f := (FField)slots[m.name] 97 if (f != null) 98 { 99 // if already mapped to field must be getter/setter 100 if ((m.flags & FConst.Getter) != 0) 101 f.getter = m 102 else if ((m.flags & FConst.Setter) != 0) 103 f.setter = m 104 else 105 throw Err.make("Conflicting slots: $f and $m") 106 } 107 else 108 { 109 slots[m.name] = m 110 } 111 } 112 113 // inherited slots 114 if (base != null) inherit(base) 115 mixins.each |CType t| { inherit(t) } 116 } 117 118 private Void inherit(CType t) 119 { 120 t.slots.each |CSlot newSlot| 121 { 122 // if slot already mapped, skip it 123 if (@slots[newSlot.name] != null) return 124 125 // we never inherit constructors, private slots, 126 // or internal slots outside of the pod 127 if (newSlot.isCtor || newSlot.isPrivate || 128 (newSlot.isInternal && newSlot.parent.pod != t.pod)) 129 return 130 131 // inherit it 132 @slots[newSlot.name] = newSlot 133 } 134 } 135 136 ////////////////////////////////////////////////////////////////////////// 137 // Meta IO 138 ////////////////////////////////////////////////////////////////////////// 139 140 Void writeMeta(OutStream out) 141 { 142 out.writeI2(self) 143 out.writeI2(fbase) 144 out.writeI2(fmixins.size) 145 fmixins.each |Int m| { out.writeI2(m) } 146 out.writeI4(flags & FConst.FlagsMask) 147 } 148 149 FType readMeta(InStream in) 150 { 151 self = in.readU2 152 fbase = in.readU2 153 fmixins = Int[,] 154 in.readU2.times |,| { fmixins.add(in.readU2) } 155 flags = in.readU4 156 return this 157 } 158 159 ////////////////////////////////////////////////////////////////////////// 160 // Body IO 161 ////////////////////////////////////////////////////////////////////////// 162 163 Uri uri() 164 { 165 return Uri.fromStr("/" + fpod.n(fpod.typeRef(self).typeName) + ".fcode") 166 } 167 168 Void write() 169 { 170 out := fpod.out(uri) 171 172 out.writeI2(ffields.size) 173 ffields.each |FField f| { f.write(out) } 174 175 out.writeI2(fmethods.size) 176 fmethods.each |FMethod m| { m.write(out) } 177 178 out.writeI2(fattrs.size) 179 fattrs.each |FAttr a| { a.write(out) } 180 181 out.close 182 } 183 184 Void read() 185 { 186 in := fpod.in(uri) 187 188 ffields = FField[,] 189 in.readU2.times |,| { ffields.add(FField.make(this).read(in)) } 190 191 fmethods = FMethod[,] 192 in.readU2.times |,| { fmethods.add(FMethod.make(this).read(in)) } 193 194 fattrs = FAttr[,] 195 in.readU2.times |,| { fattrs.add(FAttr.make.read(in)) } 196 197 in.close 198 } 199 200 ////////////////////////////////////////////////////////////////////////// 201 // Fields 202 ////////////////////////////////////////////////////////////////////////// 203 204 override Int flags // bitmask 205 Bool hollow := true // have we only read meta-data 206 FPod fpod // parent pod 207 Int self // self typeRef index 208 Int fbase // base typeRef index 209 Int[] fmixins // mixin typeRef indexes 210 FField[] ffields // fields 211 FMethod[] fmethods // methods 212 FAttr[] fattrs // type attributes 213 ListType listOf // CType.listOf cache 214 215 }