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 ** FPod is the read/write fcode representation of sys::Pod. It's main job in
12 ** life is to manage all the pod-wide constant tables for names, literals,
13 ** type/slot references and type/slot definitions.
14 **
15 final class FPod : CPod, FConst
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Constructor
20 //////////////////////////////////////////////////////////////////////////
21
22 new make(FPodNamespace ns, Str podName, Zip zip)
23 {
24 this.ns = ns
25 this.name = podName
26 this.zip = zip
27 this.names = FTable.makeStrs(this)
28 this.typeRefs = FTable.makeTypeRefs(this)
29 this.fieldRefs = FTable.makeFieldRefs(this)
30 this.methodRefs = FTable.makeMethodRefs(this)
31 this.ints = FTable.makeInts(this)
32 this.floats = FTable.makeFloats(this)
33 this.strs = FTable.makeStrs(this)
34 this.durations = FTable.makeDurations(this)
35 this.uris = FTable.makeStrs(this)
36 }
37
38 //////////////////////////////////////////////////////////////////////////
39 // CPod
40 //////////////////////////////////////////////////////////////////////////
41
42 override CType resolveType(Str name, Bool checked)
43 {
44 t := ftypesByName[name]
45 if (t != null) return t
46 if (checked) throw UnknownTypeErr.make("${this.name}::$name")
47 return null
48 }
49
50 override CType[] types()
51 {
52 return ftypes
53 }
54
55 CType toType(Int index)
56 {
57 if (index == 0xffff) return null
58 r := typeRef(index)
59
60 Str sig
61 if (r.isGenericInstance)
62 sig = r.sig
63 else
64 sig = n(r.podName) + "::" + n(r.typeName)
65 return ns.resolveType(sig)
66 }
67
68 CType[] resolveTypes(Int[] indexes)
69 {
70 ctypes := CType[,]
71 ctypes.capacity = indexes.size
72 indexes.map(ctypes) |Int index->Obj| { return toType(index) }
73 return ctypes
74 }
75
76 //////////////////////////////////////////////////////////////////////////
77 // Convenience
78 //////////////////////////////////////////////////////////////////////////
79
80 Str n(Int index) { return (Str)names[index] }
81 FTypeRef typeRef(Int index) { return (FTypeRef)typeRefs[index] }
82 FFieldRef fieldRef(Int index) { return (FFieldRef)fieldRefs[index] }
83 FMethodRef methodRef(Int index) { return (FMethodRef)methodRefs[index] }
84 Int integer(Int index) { return (Int)ints[index] }
85 Float float(Int index) { return (Float)floats[index] }
86 Str str(Int index) { return (Str)strs[index] }
87 Duration duration(Int index) { return (Duration)durations[index] }
88 Str uri(Int index) { return (Str)uris[index] }
89
90 Str typeRefStr(Int index) { return typeRef(index).format(this) }
91 Str fieldRefStr(Int index) { return fieldRef(index).format(this) }
92 Str methodRefStr(Int index) { return methodRef(index).format(this) }
93
94 //////////////////////////////////////////////////////////////////////////
95 // Compile Utils
96 //////////////////////////////////////////////////////////////////////////
97
98 Int addName(Str val)
99 {
100 return names.add(val)
101 }
102
103 Int addTypeRef(CType t)
104 {
105 p := addName(t.pod.name)
106 n := addName(t.name)
107 sig := t.isParameterized ? t.signature : ""
108 return typeRefs.add(FTypeRef.make(p, n, sig))
109 }
110
111 Int addFieldRef(CField field)
112 {
113 p := addTypeRef(field.parent)
114 n := addName(field.name)
115 t := addTypeRef(field.fieldType)
116 return fieldRefs.add(FFieldRef.make(p, n, t))
117 }
118
119 Int addMethodRef(CMethod method, Int argCount := null)
120 {
121 // if this is a generic instantiation, we want to call
122 // against the original generic method using it's raw
123 // types, since that is how the system library will
124 // implement the type
125 if (method.isParameterized) method = method.generic
126
127 p := addTypeRef(method.parent)
128 n := addName(method.name)
129 r := addTypeRef(method.inheritedReturnType.raw) // CLR can't deal with covariance
130 params := (Int[])method.params.map(Int[,]) |CParam x->Obj| { return addTypeRef(x.paramType.raw) }
131 if (argCount != null && argCount < params.size)
132 params = params[0...argCount]
133 return methodRefs.add(FMethodRef.make(p, n, r, params))
134 }
135
136 Void dump()
137 {
138 p := FPrinter.make(this)
139 p.showCode = true
140 p.ftypes
141 }
142
143 //////////////////////////////////////////////////////////////////////////
144 // Read
145 //////////////////////////////////////////////////////////////////////////
146
147 **
148 ** Read the just the pod and type meta-data, but
149 ** not each type's full definition
150 **
151 Void read()
152 {
153 echo(" FPod.reading [$zip.file]...")
154
155 // read tables
156 names.read(in(`/names.def`))
157 typeRefs.read(in(`/typeRefs.def`))
158 fieldRefs.read(in(`/fieldRefs.def`))
159 methodRefs.read(in(`/methodRefs.def`))
160 ints.read(in(`/ints.def`))
161 floats.read(in(`/floats.def`))
162 strs.read(in(`/strs.def`))
163 durations.read(in(`/durations.def`))
164 uris.read(in(`/uris.def`))
165
166 // read pod meta-data
167 in := in(`/pod.def`)
168 readPodMeta(in)
169 in.close
170
171 // read type meta-data
172 in = this.in(`/types.def`)
173 ftypes = FType[,]
174 ftypesByName = Str:FType[:]
175 in.readU2.times |,|
176 {
177 ftype := FType.make(this).readMeta(in)
178 ftypes.add(ftype)
179 ftypesByName[ftype.name] = ftype
180 ns.types[ftype.qname] = ftype
181 }
182 in.close
183 }
184
185 **
186 ** Read the entire pod into memory (including full type specifications)
187 **
188 Void readFully()
189 {
190 ftypes.each |FType t| { t.read }
191 }
192
193 //////////////////////////////////////////////////////////////////////////
194 // Write
195 //////////////////////////////////////////////////////////////////////////
196
197 **
198 ** Write the tables and type files out to zip storage
199 **
200 Void write(Zip zip := this.zip)
201 {
202 this.zip = zip
203
204 // write non-empty tables
205 if (!names.isEmpty) names.write(out(`/names.def`))
206 if (!typeRefs.isEmpty) typeRefs.write(out(`/typeRefs.def`))
207 if (!fieldRefs.isEmpty) fieldRefs.write(out(`/fieldRefs.def`))
208 if (!methodRefs.isEmpty) methodRefs.write(out(`/methodRefs.def`))
209 if (!ints.isEmpty) ints.write(out(`/ints.def`))
210 if (!floats.isEmpty) floats.write(out(`/floats.def`))
211 if (!strs.isEmpty) strs.write(out(`/strs.def`))
212 if (!durations.isEmpty) durations.write(out(`/durations.def`))
213 if (!uris.isEmpty) uris.write(out(`/uris.def`))
214
215 // write pod meta-data
216 out := out(`/pod.def`)
217 writePodMeta(out)
218 out.close
219
220 // write type meta-data
221 out = this.out(`/types.def`)
222 out.writeI2(ftypes.size)
223 ftypes.each |FType t| { t.writeMeta(out) }
224 out.close
225
226 // write type full fcode
227 ftypes.each |FType t| { t.write }
228 }
229
230 //////////////////////////////////////////////////////////////////////////
231 // Pod Meta
232 //////////////////////////////////////////////////////////////////////////
233
234 Void readPodMeta(InStream in)
235 {
236 if (in.readU4 != FCodeMagic)
237 throw IOErr.make("Invalid fcode magic number")
238 if (in.readU4 != FCodeVersion)
239 throw IOErr.make("Unsupported fcode version")
240
241 name = in.readUtf
242 version = Version.fromStr(in.readUtf)
243 depends = Depend[,]
244 in.readU1.times |,| { depends.add(Depend.fromStr(in.readUtf)) }
245 fattrs = FAttr[,]
246 in.readU2.times |,| { fattrs.add(FAttr.make.read(in)) }
247 }
248
249 Void writePodMeta(OutStream out)
250 {
251 out.writeI4(FConst.FCodeMagic)
252 out.writeI4(FConst.FCodeVersion)
253 out.writeUtf(name)
254 out.writeUtf(version.toStr)
255 out.write(depends.size)
256 depends.each |Depend d| { out.writeUtf(d.toStr) }
257 out.writeI2(fattrs.size)
258 fattrs.each |FAttr a| { a.write(out) }
259 }
260
261 //////////////////////////////////////////////////////////////////////////
262 // Zip
263 //////////////////////////////////////////////////////////////////////////
264
265 **
266 ** Get input stream to read the specified file from zip storage.
267 **
268 InStream in(Uri uri)
269 {
270 file := zip.contents[uri]
271 if (file == null) return null
272 return file.in
273 }
274
275 **
276 ** Get output stream to write the specified file to zip storage.
277 **
278 OutStream out(Uri uri) { return zip.writeNext(uri) }
279
280 //////////////////////////////////////////////////////////////////////////
281 // Fields
282 //////////////////////////////////////////////////////////////////////////
283
284 override Namespace ns // compiler's namespace
285 override Str name // pod's unique name
286 override Version version // pod version
287 Depend[] depends // pod dependencies
288 FAttr[] fattrs // pod attributes
289 Zip zip // zipped storage
290 FType[] ftypes // pod's declared types
291 FTable names // identifier names: foo
292 FTable typeRefs // types refs: [pod,type,sig]
293 FTable fieldRefs // fields refs: [parent,name,type]
294 FTable methodRefs // methods refs: [parent,name,ret,params]
295 FTable ints // Int literals
296 FTable floats // Float literals
297 FTable strs // Str literals
298 FTable durations // Duration literals
299 FTable uris // Uri literals
300 Str:FType ftypesByName // if loaded
301
302 }
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 ** FPod is the read/write fcode representation of sys::Pod. It's main job in
12 ** life is to manage all the pod-wide constant tables for names, literals,
13 ** type/slot references and type/slot definitions.
14 **
15 final class FPod : CPod, FConst
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Constructor
20 //////////////////////////////////////////////////////////////////////////
21
22 new make(FPodNamespace ns, Str podName, Zip zip)
23 {
24 this.ns = ns
25 this.name = podName
26 this.zip = zip
27 this.names = FTable.makeStrs(this)
28 this.typeRefs = FTable.makeTypeRefs(this)
29 this.fieldRefs = FTable.makeFieldRefs(this)
30 this.methodRefs = FTable.makeMethodRefs(this)
31 this.ints = FTable.makeInts(this)
32 this.floats = FTable.makeFloats(this)
33 this.strs = FTable.makeStrs(this)
34 this.durations = FTable.makeDurations(this)
35 this.uris = FTable.makeStrs(this)
36 }
37
38 //////////////////////////////////////////////////////////////////////////
39 // CPod
40 //////////////////////////////////////////////////////////////////////////
41
42 override CType resolveType(Str name, Bool checked)
43 {
44 t := ftypesByName[name]
45 if (t != null) return t
46 if (checked) throw UnknownTypeErr.make("${this.name}::$name")
47 return null
48 }
49
50 override CType[] types()
51 {
52 return ftypes
53 }
54
55 CType toType(Int index)
56 {
57 if (index == 0xffff) return null
58 r := typeRef(index)
59
60 Str sig
61 if (r.isGenericInstance)
62 sig = r.sig
63 else
64 sig = n(r.podName) + "::" + n(r.typeName)
65 return ns.resolveType(sig)
66 }
67
68 CType[] resolveTypes(Int[] indexes)
69 {
70 ctypes := CType[,]
71 ctypes.capacity = indexes.size
72 indexes.map(ctypes) |Int index->Obj| { return toType(index) }
73 return ctypes
74 }
75
76 //////////////////////////////////////////////////////////////////////////
77 // Convenience
78 //////////////////////////////////////////////////////////////////////////
79
80 Str n(Int index) { return (Str)names[index] }
81 FTypeRef typeRef(Int index) { return (FTypeRef)typeRefs[index] }
82 FFieldRef fieldRef(Int index) { return (FFieldRef)fieldRefs[index] }
83 FMethodRef methodRef(Int index) { return (FMethodRef)methodRefs[index] }
84 Int integer(Int index) { return (Int)ints[index] }
85 Float float(Int index) { return (Float)floats[index] }
86 Str str(Int index) { return (Str)strs[index] }
87 Duration duration(Int index) { return (Duration)durations[index] }
88 Str uri(Int index) { return (Str)uris[index] }
89
90 Str typeRefStr(Int index) { return typeRef(index).format(this) }
91 Str fieldRefStr(Int index) { return fieldRef(index).format(this) }
92 Str methodRefStr(Int index) { return methodRef(index).format(this) }
93
94 //////////////////////////////////////////////////////////////////////////
95 // Compile Utils
96 //////////////////////////////////////////////////////////////////////////
97
98 Int addName(Str val)
99 {
100 return names.add(val)
101 }
102
103 Int addTypeRef(CType t)
104 {
105 p := addName(t.pod.name)
106 n := addName(t.name)
107 sig := t.isParameterized ? t.signature : ""
108 return typeRefs.add(FTypeRef.make(p, n, sig))
109 }
110
111 Int addFieldRef(CField field)
112 {
113 p := addTypeRef(field.parent)
114 n := addName(field.name)
115 t := addTypeRef(field.fieldType)
116 return fieldRefs.add(FFieldRef.make(p, n, t))
117 }
118
119 Int addMethodRef(CMethod method, Int argCount := null)
120 {
121 // if this is a generic instantiation, we want to call
122 // against the original generic method using it's raw
123 // types, since that is how the system library will
124 // implement the type
125 if (method.isParameterized) method = method.generic
126
127 p := addTypeRef(method.parent)
128 n := addName(method.name)
129 r := addTypeRef(method.inheritedReturnType.raw) // CLR can't deal with covariance
130 params := (Int[])method.params.map(Int[,]) |CParam x->Obj| { return addTypeRef(x.paramType.raw) }
131 if (argCount != null && argCount < params.size)
132 params = params[0...argCount]
133 return methodRefs.add(FMethodRef.make(p, n, r, params))
134 }
135
136 Void dump()
137 {
138 p := FPrinter.make(this)
139 p.showCode = true
140 p.ftypes
141 }
142
143 //////////////////////////////////////////////////////////////////////////
144 // Read
145 //////////////////////////////////////////////////////////////////////////
146
147 **
148 ** Read the just the pod and type meta-data, but
149 ** not each type's full definition
150 **
151 Void read()
152 {
153 echo(" FPod.reading [$zip.file]...")
154
155 // read tables
156 names.read(in(`/names.def`))
157 typeRefs.read(in(`/typeRefs.def`))
158 fieldRefs.read(in(`/fieldRefs.def`))
159 methodRefs.read(in(`/methodRefs.def`))
160 ints.read(in(`/ints.def`))
161 floats.read(in(`/floats.def`))
162 strs.read(in(`/strs.def`))
163 durations.read(in(`/durations.def`))
164 uris.read(in(`/uris.def`))
165
166 // read pod meta-data
167 in := in(`/pod.def`)
168 readPodMeta(in)
169 in.close
170
171 // read type meta-data
172 in = this.in(`/types.def`)
173 ftypes = FType[,]
174 ftypesByName = Str:FType[:]
175 in.readU2.times |,|
176 {
177 ftype := FType.make(this).readMeta(in)
178 ftypes.add(ftype)
179 ftypesByName[ftype.name] = ftype
180 ns.types[ftype.qname] = ftype
181 }
182 in.close
183 }
184
185 **
186 ** Read the entire pod into memory (including full type specifications)
187 **
188 Void readFully()
189 {
190 ftypes.each |FType t| { t.read }
191 }
192
193 //////////////////////////////////////////////////////////////////////////
194 // Write
195 //////////////////////////////////////////////////////////////////////////
196
197 **
198 ** Write the tables and type files out to zip storage
199 **
200 Void write(Zip zip := this.zip)
201 {
202 this.zip = zip
203
204 // write non-empty tables
205 if (!names.isEmpty) names.write(out(`/names.def`))
206 if (!typeRefs.isEmpty) typeRefs.write(out(`/typeRefs.def`))
207 if (!fieldRefs.isEmpty) fieldRefs.write(out(`/fieldRefs.def`))
208 if (!methodRefs.isEmpty) methodRefs.write(out(`/methodRefs.def`))
209 if (!ints.isEmpty) ints.write(out(`/ints.def`))
210 if (!floats.isEmpty) floats.write(out(`/floats.def`))
211 if (!strs.isEmpty) strs.write(out(`/strs.def`))
212 if (!durations.isEmpty) durations.write(out(`/durations.def`))
213 if (!uris.isEmpty) uris.write(out(`/uris.def`))
214
215 // write pod meta-data
216 out := out(`/pod.def`)
217 writePodMeta(out)
218 out.close
219
220 // write type meta-data
221 out = this.out(`/types.def`)
222 out.writeI2(ftypes.size)
223 ftypes.each |FType t| { t.writeMeta(out) }
224 out.close
225
226 // write type full fcode
227 ftypes.each |FType t| { t.write }
228 }
229
230 //////////////////////////////////////////////////////////////////////////
231 // Pod Meta
232 //////////////////////////////////////////////////////////////////////////
233
234 Void readPodMeta(InStream in)
235 {
236 if (in.readU4 != FCodeMagic)
237 throw IOErr.make("Invalid fcode magic number")
238 if (in.readU4 != FCodeVersion)
239 throw IOErr.make("Unsupported fcode version")
240
241 name = in.readUtf
242 version = Version.fromStr(in.readUtf)
243 depends = Depend[,]
244 in.readU1.times |,| { depends.add(Depend.fromStr(in.readUtf)) }
245 fattrs = FAttr[,]
246 in.readU2.times |,| { fattrs.add(FAttr.make.read(in)) }
247 }
248
249 Void writePodMeta(OutStream out)
250 {
251 out.writeI4(FConst.FCodeMagic)
252 out.writeI4(FConst.FCodeVersion)
253 out.writeUtf(name)
254 out.writeUtf(version.toStr)
255 out.write(depends.size)
256 depends.each |Depend d| { out.writeUtf(d.toStr) }
257 out.writeI2(fattrs.size)
258 fattrs.each |FAttr a| { a.write(out) }
259 }
260
261 //////////////////////////////////////////////////////////////////////////
262 // Zip
263 //////////////////////////////////////////////////////////////////////////
264
265 **
266 ** Get input stream to read the specified file from zip storage.
267 **
268 InStream in(Uri uri)
269 {
270 file := zip.contents[uri]
271 if (file == null) return null
272 return file.in
273 }
274
275 **
276 ** Get output stream to write the specified file to zip storage.
277 **
278 OutStream out(Uri uri) { return zip.writeNext(uri) }
279
280 //////////////////////////////////////////////////////////////////////////
281 // Fields
282 //////////////////////////////////////////////////////////////////////////
283
284 override Namespace ns // compiler's namespace
285 override Str name // pod's unique name
286 override Version version // pod version
287 Depend[] depends // pod dependencies
288 FAttr[] fattrs // pod attributes
289 Zip zip // zipped storage
290 FType[] ftypes // pod's declared types
291 FTable names // identifier names: foo
292 FTable typeRefs // types refs: [pod,type,sig]
293 FTable fieldRefs // fields refs: [parent,name,type]
294 FTable methodRefs // methods refs: [parent,name,ret,params]
295 FTable ints // Int literals
296 FTable floats // Float literals
297 FTable strs // Str literals
298 FTable durations // Duration literals
299 FTable uris // Uri literals
300 Str:FType ftypesByName // if loaded
301
302 }
More Info
Slots
- addFieldRef
- addMethodRef
- addName
- addTypeRef
- depends
- dump
- duration
- durations
- fattrs
- fieldRef
- fieldRefStr
- fieldRefs
- float
- floats
- ftypes
- ftypesByName
- in
- integer
- ints
- make
- methodRef
- methodRefStr
- methodRefs
- n
- name
- names
- ns
- out
- read
- readFully
- readPodMeta
- resolveType
- resolveTypes
- str
- strs
- toType
- typeRef
- typeRefStr
- typeRefs
- types
- uri
- uris
- version
- write
- writePodMeta
- zip