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