First NIT release and new clean mercurial repository
[nit.git] / src / compiling / compiling_global.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Compute and generate tables for classes and modules.
18 package compiling_global
19
20 #import compiling_base
21 private import compiling_methods
22 private import syntax
23
24 # Something that store color of table elements
25 class ColorContext
26 attr _colors: HashMap[TableElt, Int]
27
28 # The color of a table element.
29 meth color(e: TableElt): Int
30 do
31 return _colors[e]
32 end
33
34 # Is a table element already colored?
35 meth has_color(e: TableElt): Bool
36 do
37 return _colors != null and _colors.has_key(e)
38 end
39
40 # Assign a color to a table element.
41 meth color=(e: TableElt, c: Int)
42 do
43 if _colors == null then _colors = new HashMap[TableElt, Int]
44 _colors[e] = c
45 var idx = c
46 for i in [0..e.length[ do
47 _colors[e.item(i)] = idx
48 idx = idx + 1
49 end
50 end
51 end
52
53 # All information and results of the global analysis.
54 class GlobalAnalysis
55 special ColorContext
56 # Associate global classes to compiled classes
57 readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass]
58
59 # The main module of the program globally analysed
60 readable attr _module: MMModule
61
62 # FIXME: do something better.
63 readable writable attr _max_class_table_length: Int
64
65 init(module: MMSrcModule)
66 do
67 _compiled_classes = new HashMap[MMGlobalClass, CompiledClass]
68 _module = module
69 end
70 end
71
72 redef class CompilerVisitor
73 # The global analysis result, if any
74 readable writable attr _global_analysis: GlobalAnalysis
75 end
76
77 # A compiled class is a class in a program
78 class CompiledClass
79 special ColorContext
80 # The corresponding local class in the main module of the prgram
81 readable attr _local_class: MMLocalClass
82
83 # The identifier of the class
84 readable writable attr _id: Int
85
86 # The full class table of the class
87 readable writable attr _class_table: Array[TableElt]
88
89 # The full instance table of the class
90 readable writable attr _instance_table: Array[TableElt]
91
92 # The proper class table part (no superclasses but all refinements)
93 readable writable attr _class_layout: TableEltComposite
94
95 # The proper instance table part (no superclasses but all refinements)
96 readable writable attr _instance_layout: TableEltComposite
97
98 init(c: MMLocalClass) do _local_class = c
99 end
100
101 redef class MMGlobalProperty
102 # The position of the property in the local class table part
103 # FIXME: It's ugly. store this somewhere else please
104 readable writable attr _pos_of: Int
105 end
106
107 redef class MMSrcLocalClass
108 # The table element of the attribute position (for accessor simulation)
109 readable attr _base_attr_pos: TableEltBaseAttrPos
110
111 # The table element of the subtype check
112 readable attr _class_color_pos: TableEltClassColorPos
113
114 # The proper local class table part (nor superclasses nor refinments)
115 readable attr _class_layout: Array[LocalTableElt]
116
117 # The proper local instance table part (nor superclasses nor refinments)
118 readable attr _instance_layout: Array[LocalTableElt]
119
120 # Build the local layout of the class and feed the module table
121 meth build_layout_in(tc: ToolContext, module_table: Array[LocalTableElt])
122 do
123 var intro_methods = new Array[MMGlobalProperty] # FIXME: Remove this
124 var intro_attributes = new Array[MMGlobalProperty] # FIXME: Remove this
125 var clt = new Array[LocalTableElt]
126 _class_layout = clt
127 var ilt = new Array[LocalTableElt]
128 _instance_layout = ilt
129
130 if global.intro == self then
131 module_table.add(new TableEltClassIdPos(self))
132 _class_color_pos = new TableEltClassColorPos(self)
133 module_table.add(_class_color_pos)
134 #clt.add(_class_color_pos)
135 clt.add(new TableEltClassInitTablePos(self))
136 end
137 for p in src_local_properties do
138 var pg = p.global
139 if pg.intro == p then
140 if p isa MMSrcAttribute then
141 pg.pos_of = intro_attributes.length
142 intro_attributes.add(pg)
143 ilt.add(new TableEltAttrPos(p))
144 else if p isa MMSrcMethod then
145 pg.pos_of = intro_methods.length
146 intro_methods.add(pg)
147 clt.add(new TableEltMethPos(p))
148 end
149 end
150 if p isa MMSrcMethod and p.need_super then
151 clt.add(new TableEltSuperPos(p))
152 end
153 end
154 if tc.attr_sim and not intro_attributes.is_empty then
155 _base_attr_pos = new TableEltBaseAttrPos(self)
156 clt.add(_base_attr_pos)
157 else
158 module_table.append(ilt)
159 end
160 module_table.append(clt)
161 end
162 end
163
164 redef class MMSrcModule
165 # The local table of the module (refers things introduced in the module)
166 attr _local_table: Array[LocalTableElt]
167
168 # Builds the local tables and local classes layouts
169 meth local_analysis(tc: ToolContext)
170 do
171 var lt = new Array[LocalTableElt]
172 _local_table = lt
173 for c in src_local_classes do
174 c.build_layout_in(tc, lt)
175 end
176 end
177
178 # Do the complete global analysis
179 meth global_analysis(cctx: ToolContext): GlobalAnalysis
180 do
181 #print "Do the complete global analysis"
182 var ga = new GlobalAnalysis(self)
183 var smallest_classes = new Array[MMLocalClass]
184 var global_properties = new HashSet[MMGlobalProperty]
185 var ctab = new Array[TableElt]
186 var itab = new Array[TableElt]
187
188 ctab.add(new TableEltClassSelfId)
189 itab.add(new TableEltVftPointer)
190
191 var pclassid = -1
192 var classid = 3
193
194 # We have to work on ALL the classes of the module
195 var classes = new Array[MMLocalClass]
196 for c in local_classes do
197 c.compute_super_classes
198 classes.add(c)
199 end
200 (new ClassSorter).sort(classes)
201
202 for c in classes do
203 # Finish processing the class (if invisible)
204 c.compute_ancestors
205 c.inherit_global_properties
206
207 # Associate a CompiledClass to the class
208 var cc = new CompiledClass(c)
209 ga.compiled_classes[c.global] = cc
210
211 # Assign a unique class identifier
212 # (negative are for primitive classes)
213 var gc = c.global
214 var bm = gc.module
215 if c.primitive_info != null then
216 cc.id = pclassid
217 pclassid = pclassid - 4
218 else
219 cc.id = classid
220 classid = classid + 4
221 end
222
223 # Register is the class is a leaf
224 if c.cshe.direct_smallers.is_empty then
225 smallest_classes.add(c)
226 end
227
228 # Store the colortableelt in the class table pool
229 var bc = c.global.intro
230 assert bc isa MMSrcLocalClass
231 ctab.add(bc.class_color_pos)
232 end
233
234 # Compute core and crown classes for colorization
235 var crown_classes = new HashSet[MMLocalClass]
236 var core_classes = new HashSet[MMLocalClass]
237 for c in smallest_classes do
238 while c.cshe.direct_greaters.length == 1 do
239 c = c.cshe.direct_greaters.first
240 end
241 crown_classes.add(c)
242 core_classes.add_all(c.cshe.greaters_and_self)
243 end
244 #print("nbclasses: {classes.length} leaves: {smallest_classes.length} crown: {crown_classes.length} core: {core_classes.length}")
245
246 # Colorize core color for typechecks
247 colorize(ga, ctab, crown_classes, 0)
248
249 # Compute tables for typechecks
250 var maxcolor = 0
251 for c in classes do
252 var cc = ga.compiled_classes[c.global]
253 if core_classes.has(c) then
254 # For core classes, just build the table
255 cc.class_table = build_tables(ga, c, ctab)
256 if maxcolor < cc.class_table.length then maxcolor = cc.class_table.length
257 else
258 # For other classes, it's easier: just append to the parent tables
259 var sc = c.cshe.direct_greaters.first
260 var scc = ga.compiled_classes[sc.global]
261 cc.class_table = scc.class_table.to_a
262 var bc = c.global.intro
263 assert bc isa MMSrcLocalClass
264 var colpos = bc.class_color_pos
265 var colposcolor = cc.class_table.length
266 ga.color(colpos) = colposcolor
267 cc.class_table.add(colpos)
268 if maxcolor < colposcolor then maxcolor = colposcolor
269 end
270 end
271 ga.max_class_table_length = maxcolor + 1
272
273 # Fill class table and instance tables pools
274 for c in classes do
275 var cc = ga.compiled_classes[c.global]
276 var cte = new TableEltComposite(cc)
277 var ite = new TableEltComposite(cc)
278 for sc in c.crhe.greaters_and_self do
279 if sc isa MMSrcLocalClass then
280 cte.add(sc, sc.class_layout)
281 ite.add(sc, sc.instance_layout)
282 end
283 cc.class_layout = cte
284 cc.instance_layout = ite
285 end
286
287 if core_classes.has(c) then
288 if cte.length > 0 then
289 ctab.add(cte)
290 end
291 if not cctx.attr_sim and ite.length > 0 then
292 itab.add(ite)
293 end
294 end
295 end
296
297 # Colorize all elements in pools tables
298 colorize(ga, ctab, crown_classes, maxcolor+1)
299 colorize(ga, itab, crown_classes, 0)
300
301 # Build class and instance tables now things are colored
302 ga.max_class_table_length = 0
303 for c in classes do
304 var cc = ga.compiled_classes[c.global]
305 if core_classes.has(c) then
306 # For core classes, just build the table
307 cc.class_table = build_tables(ga, c, ctab)
308 cc.instance_table = build_tables(ga, c, itab)
309 else
310 # For other classes, it's easier: just append to the parent tables
311 var sc = c.cshe.direct_greaters.first
312 var scc = ga.compiled_classes[sc.global]
313 cc.class_table = scc.class_table.to_a
314 var bc = c.global.intro
315 assert bc isa MMSrcLocalClass
316 var colpos = bc.class_color_pos
317 cc.class_table[ga.color(colpos)] = colpos
318 while cc.class_table.length <= maxcolor do
319 cc.class_table.add(null)
320 end
321 append_to_table(ga, cc.class_table, cc.class_layout)
322 cc.instance_table = scc.instance_table.to_a
323 append_to_table(ga, cc.instance_table, cc.instance_layout)
324 end
325
326 if cctx.attr_sim then
327 cc.instance_table = build_tables(ga, c, itab)
328 for sc in c.cshe.greaters_and_self do
329 var scc = ga.compiled_classes[sc.global]
330 append_to_table(cc, cc.instance_table, scc.instance_layout)
331 end
332 end
333 end
334
335 return ga
336 end
337
338 private meth append_to_table(cc: ColorContext, table: Array[TableElt], cmp: TableEltComposite)
339 do
340 for j in [0..cmp.length[ do
341 var e = cmp.item(j)
342 cc.color(e) = table.length
343 table.add(e)
344 end
345 end
346
347 private meth build_tables(ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]): Array[TableElt]
348 do
349 var tab = new HashMap[Int, TableElt]
350 var len = 0
351 for e in elts do
352 if e.is_related_to(c) then
353 var col = ga.color(e)
354 var l = col + e.length
355 tab[col] = e
356 if len < l then
357 len = l
358 end
359 end
360 end
361 var res = new Array[TableElt]
362 var i = 0
363 while i < len do
364 if tab.has_key(i) then
365 var e = tab[i]
366 for j in [0..e.length[ do
367 res[i] = e.item(j)
368 i = i + 1
369 end
370 else
371 res[i] = null
372 i = i + 1
373 end
374 end
375 return res
376 end
377
378 # Perform coloring
379 meth colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int)
380 do
381 var colors = new HashMap[Int, Array[TableElt]]
382 var rel_classes = new Array[MMLocalClass]
383 for e in elts do
384 var color = -1
385 var len = e.length
386 if ga.has_color(e) then
387 color = ga.color(e)
388 else
389 rel_classes.clear
390 for c in classes do
391 if e.is_related_to(c) then
392 rel_classes.add(c)
393 end
394 end
395 var trycolor = startcolor
396 while trycolor != color do
397 color = trycolor
398 for c in rel_classes do
399 var idx = 0
400 while idx < len do
401 if colors.has_key(trycolor + idx) and not free_color(colors[trycolor + idx], c) then
402 trycolor = trycolor + idx + 1
403 idx = 0
404 else
405 idx = idx + 1
406 end
407 end
408 end
409 end
410 ga.color(e) = color
411 end
412 for idx in [0..len[ do
413 if colors.has_key(color + idx) then
414 colors[color + idx].add(e)
415 else
416 colors[color + idx] = [e]
417 end
418 end
419 end
420 end
421
422 private meth free_color(es: Array[TableElt], c: MMLocalClass): Bool
423 do
424 for e2 in es do
425 if e2.is_related_to(c) then
426 return false
427 end
428 end
429 return true
430 end
431
432 # Compile module and class tables
433 meth compile_tables_to_c(v: CompilerVisitor)
434 do
435 for m in mhe.greaters_and_self do
436 assert m isa MMSrcModule
437 m.compile_local_table_to_c(v)
438 end
439
440 for c in local_classes do
441 c.compile_tables_to_c(v)
442 end
443 var s = "classtable_t TAG2VFT[4] = \{NULL"
444 for t in ["Int","Char","Bool"] do
445 if has_global_class_named(t.to_symbol) then
446 s.append(", (const classtable_t)VFT_{t}")
447 else
448 s.append(", NULL")
449 end
450 end
451 s.append("};")
452 v.add_instr(s)
453 end
454
455 # Declare class table (for _sep.h)
456 meth declare_class_tables_to_c(v: CompilerVisitor)
457 do
458 for c in local_classes do
459 if c.global.module == self then
460 c.declare_tables_to_c(v)
461 end
462 end
463 end
464
465 # Compile main part (for _table.c)
466 meth compile_main_part(v: CompilerVisitor)
467 do
468 v.add_instr("int main(int argc, char **argv) \{")
469 v.indent
470 v.add_instr("prepare_signals();")
471 v.add_instr("glob_argc = argc; glob_argv = argv;")
472 var sysname = once "Sys".to_symbol
473 if not has_global_class_named(sysname) then
474 print("No main")
475 else
476 var sys = class_by_name(sysname).get_type
477 var main = sys.select_method(once "init".to_symbol)
478 if main == null then
479 main = sys.select_method(once "main".to_symbol)
480 end
481 if main == null then
482 print("No main")
483 else
484 v.add_instr("G_sys = NEW_Sys();")
485 v.add_instr("{main.cname}(G_sys);")
486 end
487 end
488 v.add_instr("return 0;")
489 v.unindent
490 v.add_instr("}")
491 end
492
493 # Compile sep files
494 meth compile_mod_to_c(v: CompilerVisitor)
495 do
496 if not v.tc.global then
497 v.add_decl("extern const int SFT_{name}[];")
498 end
499 var i = 0
500 for e in _local_table do
501 if v.tc.global then
502 v.add_decl("#define {e.symbol} {e.value(v.global_analysis)}")
503 else
504 v.add_decl("#define {e.symbol} SFT_{name}[{i}]")
505 i = i + 1
506 end
507 end
508 for c in src_local_classes do
509 for p in c.src_local_properties do
510 var pg = p.global
511 if pg.intro == p and p isa MMAttribute then
512 if v.tc.attr_sim then
513 var bc = pg.local_class
514 assert bc isa MMSrcLocalClass
515 var s = bc.base_attr_pos.symbol
516 v.add_decl("#define {pg.attr_access}(recv) ATTRS(recv, {s}, {pg.pos_of})")
517 else
518 v.add_decl("#define {pg.attr_access}(recv) ATTR(recv, {pg.color_id})")
519 end
520 end
521 assert p isa MMSrcLocalProperty
522 p.compile_property_to_c(v)
523 end
524 end
525 end
526
527 # Compile module file for the current module
528 meth compile_local_table_to_c(v: CompilerVisitor)
529 do
530 if v.tc.global or _local_table.is_empty then
531 return
532 end
533
534 v.add_instr("const int SFT_{name}[{_local_table.length}] = \{")
535 v.indent
536 for e in _local_table do
537 v.add_instr(e.value(v.global_analysis) + ",")
538 end
539 v.unindent
540 v.add_instr("\};")
541 end
542 end
543
544 class TableElt
545 meth is_related_to(c: MMLocalClass): Bool is abstract
546 meth length: Int do return 1
547 meth item(i: Int): TableElt do return self
548 meth compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
549 end
550
551 class LocalTableElt
552 special TableElt
553 meth symbol: String is abstract
554 meth value(ga: GlobalAnalysis): String is abstract
555 end
556
557 class TableEltPropPos
558 special LocalTableElt
559 attr _property: MMSrcLocalProperty
560 redef meth symbol do return _property.global.color_id
561 redef meth value(ga) do return "{ga.color(self)} /* Property {_property} */"
562
563 init(p: MMSrcLocalProperty)
564 do
565 _property = p
566 end
567 end
568
569 class TableEltMethPos
570 special TableEltPropPos
571 redef meth compile_to_c(v, c)
572 do
573 var p = c[_property.global]
574 return p.cname
575 end
576 init(p) do super
577 end
578
579 class TableEltSuperPos
580 special TableEltPropPos
581 redef meth symbol do return _property.color_id_for_super
582 redef meth compile_to_c(v, c)
583 do
584 var pc = _property.local_class
585 var g = _property.global
586 var lin = c.che.linear_extension
587 var found = false
588 for s in lin do
589 #print "{c.module}::{c} for {pc.module}::{pc}::{_property} try {s.module}:{s}"
590 if s == pc then
591 found = true
592 else if found and c.che < s then
593 var p = s[g]
594 if p != null and p isa MMConcreteProperty then
595 #print "found {s.module}::{s}::{p}"
596 return p.cname
597 end
598 end
599 end
600 assert false
601 return null
602 end
603
604 init(p) do super
605 end
606
607 class TableEltAttrPos
608 special TableEltPropPos
609 redef meth compile_to_c(v, c)
610 do
611 var ga = v.global_analysis
612 var p = c[_property.global]
613 return "/* {ga.color(self)}: Attribute {c}::{p} */"
614 end
615
616 init(p) do super
617 end
618
619 class TableEltClassPos
620 special LocalTableElt
621 attr _local_class: MMLocalClass
622 redef meth is_related_to(c)
623 do
624 var bc = c.module[_local_class.global]
625 return c.cshe <= bc
626 end
627
628 init(c: MMLocalClass)
629 do
630 _local_class = c
631 end
632 end
633
634 class TableEltClassIdPos
635 special TableEltClassPos
636 redef meth symbol do return _local_class.global.id_id
637 redef meth value(ga)
638 do
639 return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
640 end
641
642 init(c) do super
643 end
644
645 class TableEltClassInitTablePos
646 special TableEltClassPos
647 redef meth symbol do return _local_class.global.init_table_pos_id
648 redef meth value(ga)
649 do
650 return "{ga.color(self)} /* Color of {_local_class} */"
651 end
652 redef meth compile_to_c(v, c)
653 do
654 var ga = v.global_analysis
655 var cc = ga.compiled_classes[_local_class.global]
656 var linext = c.cshe.reverse_linear_extension
657 var i = 0
658 while linext[i].global != _local_class.global do
659 i += 1
660 end
661 return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
662 end
663
664 init(c) do super
665 end
666
667 class TableEltClassColorPos
668 special TableEltClassPos
669 redef meth symbol do return _local_class.global.color_id
670 redef meth value(ga)
671 do
672 return "{ga.color(self)} /* Color of {_local_class} */"
673 end
674 redef meth compile_to_c(v, c)
675 do
676 var ga = v.global_analysis
677 var cc = ga.compiled_classes[_local_class.global]
678 return "{cc.id} /* {ga.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */"
679 end
680
681 init(c) do super
682 end
683
684 class TableEltBaseAttrPos
685 special LocalTableElt
686 attr _local_class: MMSrcLocalClass
687 redef meth symbol do return "COLOR_{_local_class.module}_{_local_class.name}_BASEATTR"
688 redef meth value(ga)
689 do
690 return "{ga.color(self)} /* BaseAttrPos of {_local_class} */"
691 end
692
693 redef meth compile_to_c(v, c)
694 do
695 var ga = v.global_analysis
696 var cc = ga.compiled_classes[c.global]
697 return "{cc.color(_local_class.instance_layout.first)} /* {ga.color(self)}: Base attribut offset of {_local_class.module}::{_local_class} in {c} */"
698 end
699
700 init(c: MMSrcLocalClass)
701 do
702 _local_class = c
703 end
704 end
705
706 class TableEltComposite
707 special TableElt
708 attr _table: Array[LocalTableElt]
709 attr _cc: CompiledClass
710 attr _offsets: HashMap[MMLocalClass, Int]
711 redef meth length do return _table.length
712 redef meth is_related_to(c) do return c.cshe <= _cc.local_class
713
714 meth add(c: MMLocalClass, tab: Array[LocalTableElt])
715 do
716 _offsets[c] = _table.length
717 _table.append(tab)
718 end
719
720 redef meth item(i) do return _table[i]
721
722 redef meth compile_to_c(v, c) do abort
723
724 init(cc: CompiledClass)
725 do
726 _cc = cc
727 _table = new Array[LocalTableElt]
728 _offsets = new HashMap[MMLocalClass, Int]
729 end
730 end
731
732 class TableEltClassSelfId
733 special TableElt
734 redef meth is_related_to(c) do return true
735 redef meth compile_to_c(v, c)
736 do
737 var ga = v.global_analysis
738 return "{v.global_analysis.compiled_classes[c.global].id} /* {ga.color(self)}: Identity */"
739 end
740
741 init do end
742 end
743
744 class TableEltVftPointer
745 special TableElt
746 redef meth is_related_to(c) do return true
747 redef meth compile_to_c(v, c)
748 do
749 var ga = v.global_analysis
750 return "/* {ga.color(self)}: Pointer to the classtable */"
751 end
752
753 init do end
754 end
755
756 # Used to sort local class in a deterministic total order
757 # The total order superset the class refinement and the class specialisation relations
758 class ClassSorter
759 special AbstractSorter[MMLocalClass]
760 redef meth compare(a, b) do return a.compare(b)
761 init do end
762 end
763
764 redef class MMLocalClass
765 # Comparaison in a total order that superset the class refinement and the class specialisation relations
766 meth compare(b: MMLocalClass): Int
767 do
768 var a = self
769 if a == b then
770 return 0
771 else if a.module.mhe < b.module then
772 return 1
773 else if b.module.mhe < a.module then
774 return -1
775 end
776 var ar = a.cshe.rank
777 var br = b.cshe.rank
778 if ar > br then
779 return 1
780 else if br > ar then
781 return -1
782 else
783 return b.name.to_s <=> a.name.to_s
784 end
785 end
786
787 # Declaration and macros related to the class table
788 meth declare_tables_to_c(v: CompilerVisitor)
789 do
790 v.add_decl("")
791 var pi = primitive_info
792 v.add_decl("extern const classtable_elt_t VFT_{name}[];")
793 if pi == null then
794 # v.add_decl("val_t NEW_{name}(void);")
795 else if not pi.tagged then
796 var t = pi.cname
797 var tbox = "struct TBOX_{name}"
798 v.add_decl("{tbox} \{ const classtable_elt_t * vft; {t} val;};")
799 v.add_decl("val_t BOX_{name}({t} val);")
800 v.add_decl("#define UNBOX_{name}(x) ((({tbox} *)(VAL2OBJ(x)))->val)")
801 end
802 end
803
804 # Compilation of table and new (or box)
805 meth compile_tables_to_c(v: CompilerVisitor)
806 do
807 var cc = v.global_analysis.compiled_classes[self.global]
808 var ctab = cc.class_table
809 var clen = ctab.length
810 if v.global_analysis.max_class_table_length > ctab.length then
811 clen = v.global_analysis.max_class_table_length
812 end
813
814 v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
815 v.indent
816 for e in ctab do
817 if e == null then
818 v.add_instr("\{0} /* Class Hole :( */,")
819 else
820 v.add_instr("\{(int) {e.compile_to_c(v, self)}},")
821 end
822 end
823 if clen > ctab.length then
824 v.add_instr("\{0},"*(clen-ctab.length))
825 end
826 v.unindent
827 v.add_instr("};")
828 var itab = cc.instance_table
829 for e in itab do
830 if e == null then
831 v.add_instr("/* Instance Hole :( */")
832 else
833 v.add_instr(e.compile_to_c(v, self))
834 end
835 end
836
837 var pi = primitive_info
838 if pi == null then
839 v.clear
840 var s = "val_t NEW_{name}(void)"
841 v.add_instr(s + " \{")
842 v.indent
843 var ctx_old = v.ctx
844 v.ctx = new CContext
845
846 v.method_params = ["OBJ2VAL(obj)"]
847
848 v.add_instr("obj_t obj;")
849 v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
850 v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
851 for g in global_properties do
852 var p = self[g]
853 var t = p.signature.return_type
854 if p isa MMAttribute and t != null then
855 # FIXME: Not compatible with sep compilation
856 var pi = p.concrete_property
857 assert pi isa MMSrcAttribute
858 var np = pi.node
859 assert np isa AAttrPropdef
860 var ne = np.n_expr
861 if ne != null then
862 var e = ne.compile_expr(v)
863 v.add_instr("{p.global.attr_access}(obj) = {e};")
864 else
865 var pi = t.local_class.primitive_info
866 if pi != null and pi.tagged then
867 var default = t.default_cvalue
868 v.add_instr("{p.global.attr_access}(obj) = {default};")
869 end
870 end
871 end
872 end
873 v.add_instr("return OBJ2VAL(obj);")
874 ctx_old.append(v.ctx)
875 v.ctx = ctx_old
876 v.unindent
877 v.add_instr("}")
878
879 var init_table_size = cshe.greaters.length + 1
880 var init_table_decl = "int init_table[{init_table_size}] = \{0{", 0" * (init_table_size-1)}};"
881
882 for g in global_properties do
883 var p = self[g]
884 if not p.global.is_init or p.global.intro.local_class.global != global then continue
885 v.clear
886 var params = new Array[String]
887 var args = ["self"]
888 for i in [0..p.signature.arity[ do
889 params.add("val_t p{i}")
890 args.add("p{i}")
891 end
892 args.add("init_table")
893 var s = "val_t NEW_{p.global.intro.cname}({params.join(", ")})"
894 v.add_instr(s + " \{")
895 v.indent
896 v.add_instr(init_table_decl)
897 v.add_instr("val_t self = NEW_{name}();")
898 v.add_instr("{p.concrete_property.cname}({args.join(", ")});")
899 v.add_instr("return self;")
900 v.unindent
901 v.add_instr("}")
902 end
903 else if not pi.tagged then
904 var t = pi.cname
905 var tbox = "struct TBOX_{name}"
906 v.add_instr("val_t BOX_{name}({t} val) \{")
907 v.indent
908 v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
909 v.add_instr("box->vft = VFT_{name};")
910 v.add_instr("box->val = val;")
911 v.add_instr("return OBJ2VAL(box);")
912 v.unindent
913 v.add_instr("}")
914 end
915 end
916 end
917