Move local variable declarations in a structure.
[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 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)
477 # var initm = sys.select_method(once "init".to_symbol)
478 var mainm = sys.select_method(once "main".to_symbol)
479 if mainm == null then
480 print("No main")
481 else
482 #v.add_instr("G_sys = NEW_{initm.cname}();")
483 v.add_instr("G_sys = NEW_Sys();")
484 v.add_instr("{mainm.cname}(G_sys);")
485 end
486 end
487 v.add_instr("return 0;")
488 v.unindent
489 v.add_instr("}")
490 end
491
492 # Compile sep files
493 meth compile_mod_to_c(v: CompilerVisitor)
494 do
495 v.add_decl("extern const char *LOCATE_{name};")
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 p.compile_property_to_c(v)
522 end
523 end
524 end
525
526 # Compile module file for the current module
527 meth compile_local_table_to_c(v: CompilerVisitor)
528 do
529 v.add_instr("const char *LOCATE_{name} = \"{filename}\";")
530
531 if v.tc.global or _local_table.is_empty then
532 return
533 end
534
535 v.add_instr("const int SFT_{name}[{_local_table.length}] = \{")
536 v.indent
537 for e in _local_table do
538 v.add_instr(e.value(v.global_analysis) + ",")
539 end
540 v.unindent
541 v.add_instr("\};")
542 end
543 end
544
545 class TableElt
546 meth is_related_to(c: MMLocalClass): Bool is abstract
547 meth length: Int do return 1
548 meth item(i: Int): TableElt do return self
549 meth compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract
550 end
551
552 class LocalTableElt
553 special TableElt
554 meth symbol: String is abstract
555 meth value(ga: GlobalAnalysis): String is abstract
556 end
557
558 class TableEltPropPos
559 special LocalTableElt
560 attr _property: MMLocalProperty
561 redef meth symbol do return _property.global.color_id
562 redef meth value(ga) do return "{ga.color(self)} /* Property {_property} */"
563
564 init(p: MMLocalProperty)
565 do
566 _property = p
567 end
568 end
569
570 class TableEltMethPos
571 special TableEltPropPos
572 redef meth compile_to_c(v, c)
573 do
574 var p = c[_property.global]
575 return p.cname
576 end
577 init(p) do super
578 end
579
580 class TableEltSuperPos
581 special TableEltPropPos
582 redef meth symbol do return _property.color_id_for_super
583 redef meth compile_to_c(v, c)
584 do
585 var pc = _property.local_class
586 var g = _property.global
587 var lin = c.che.linear_extension
588 var found = false
589 for s in lin do
590 #print "{c.module}::{c} for {pc.module}::{pc}::{_property} try {s.module}:{s}"
591 if s == pc then
592 found = true
593 else if found and c.che < s then
594 var p = s[g]
595 if p != null then
596 #print "found {s.module}::{s}::{p}"
597 return p.cname
598 end
599 end
600 end
601 assert false
602 return null
603 end
604
605 init(p) do super
606 end
607
608 class TableEltAttrPos
609 special TableEltPropPos
610 redef meth compile_to_c(v, c)
611 do
612 var ga = v.global_analysis
613 var p = c[_property.global]
614 return "/* {ga.color(self)}: Attribute {c}::{p} */"
615 end
616
617 init(p) do super
618 end
619
620 class TableEltClassPos
621 special LocalTableElt
622 attr _local_class: MMLocalClass
623 redef meth is_related_to(c)
624 do
625 var bc = c.module[_local_class.global]
626 return c.cshe <= bc
627 end
628
629 init(c: MMLocalClass)
630 do
631 _local_class = c
632 end
633 end
634
635 class TableEltClassIdPos
636 special TableEltClassPos
637 redef meth symbol do return _local_class.global.id_id
638 redef meth value(ga)
639 do
640 return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */"
641 end
642
643 init(c) do super
644 end
645
646 class TableEltClassInitTablePos
647 special TableEltClassPos
648 redef meth symbol do return _local_class.global.init_table_pos_id
649 redef meth value(ga)
650 do
651 return "{ga.color(self)} /* Color of {_local_class} */"
652 end
653 redef meth compile_to_c(v, c)
654 do
655 var ga = v.global_analysis
656 var cc = ga.compiled_classes[_local_class.global]
657 var linext = c.cshe.reverse_linear_extension
658 var i = 0
659 while linext[i].global != _local_class.global do
660 i += 1
661 end
662 return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */"
663 end
664
665 init(c) do super
666 end
667
668 class TableEltClassColorPos
669 special TableEltClassPos
670 redef meth symbol do return _local_class.global.color_id
671 redef meth value(ga)
672 do
673 return "{ga.color(self)} /* Color of {_local_class} */"
674 end
675 redef meth compile_to_c(v, c)
676 do
677 var ga = v.global_analysis
678 var cc = ga.compiled_classes[_local_class.global]
679 return "{cc.id} /* {ga.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */"
680 end
681
682 init(c) do super
683 end
684
685 class TableEltBaseAttrPos
686 special LocalTableElt
687 attr _local_class: MMSrcLocalClass
688 redef meth symbol do return "COLOR_{_local_class.module}_{_local_class.name}_BASEATTR"
689 redef meth value(ga)
690 do
691 return "{ga.color(self)} /* BaseAttrPos of {_local_class} */"
692 end
693
694 redef meth compile_to_c(v, c)
695 do
696 var ga = v.global_analysis
697 var cc = ga.compiled_classes[c.global]
698 return "{cc.color(_local_class.instance_layout.first)} /* {ga.color(self)}: Base attribut offset of {_local_class.module}::{_local_class} in {c} */"
699 end
700
701 init(c: MMSrcLocalClass)
702 do
703 _local_class = c
704 end
705 end
706
707 class TableEltComposite
708 special TableElt
709 attr _table: Array[LocalTableElt]
710 attr _cc: CompiledClass
711 attr _offsets: HashMap[MMLocalClass, Int]
712 redef meth length do return _table.length
713 redef meth is_related_to(c) do return c.cshe <= _cc.local_class
714
715 meth add(c: MMLocalClass, tab: Array[LocalTableElt])
716 do
717 _offsets[c] = _table.length
718 _table.append(tab)
719 end
720
721 redef meth item(i) do return _table[i]
722
723 redef meth compile_to_c(v, c) do abort
724
725 init(cc: CompiledClass)
726 do
727 _cc = cc
728 _table = new Array[LocalTableElt]
729 _offsets = new HashMap[MMLocalClass, Int]
730 end
731 end
732
733 class TableEltClassSelfId
734 special TableElt
735 redef meth is_related_to(c) do return true
736 redef meth compile_to_c(v, c)
737 do
738 var ga = v.global_analysis
739 return "{v.global_analysis.compiled_classes[c.global].id} /* {ga.color(self)}: Identity */"
740 end
741
742 init do end
743 end
744
745 class TableEltVftPointer
746 special TableElt
747 redef meth is_related_to(c) do return true
748 redef meth compile_to_c(v, c)
749 do
750 var ga = v.global_analysis
751 return "/* {ga.color(self)}: Pointer to the classtable */"
752 end
753
754 init do end
755 end
756
757 # Used to sort local class in a deterministic total order
758 # The total order superset the class refinement and the class specialisation relations
759 class ClassSorter
760 special AbstractSorter[MMLocalClass]
761 redef meth compare(a, b) do return a.compare(b)
762 init do end
763 end
764
765 redef class MMLocalClass
766 # Comparaison in a total order that superset the class refinement and the class specialisation relations
767 meth compare(b: MMLocalClass): Int
768 do
769 var a = self
770 if a == b then
771 return 0
772 else if a.module.mhe < b.module then
773 return 1
774 else if b.module.mhe < a.module then
775 return -1
776 end
777 var ar = a.cshe.rank
778 var br = b.cshe.rank
779 if ar > br then
780 return 1
781 else if br > ar then
782 return -1
783 else
784 return b.name.to_s <=> a.name.to_s
785 end
786 end
787
788 # Declaration and macros related to the class table
789 meth declare_tables_to_c(v: CompilerVisitor)
790 do
791 v.add_decl("")
792 var pi = primitive_info
793 v.add_decl("extern const classtable_elt_t VFT_{name}[];")
794 if pi == null then
795 # v.add_decl("val_t NEW_{name}(void);")
796 else if not pi.tagged then
797 var t = pi.cname
798 var tbox = "struct TBOX_{name}"
799 v.add_decl("{tbox} \{ const classtable_elt_t * vft; {t} val;};")
800 v.add_decl("val_t BOX_{name}({t} val);")
801 v.add_decl("#define UNBOX_{name}(x) ((({tbox} *)(VAL2OBJ(x)))->val)")
802 end
803 end
804
805 # Compilation of table and new (or box)
806 meth compile_tables_to_c(v: CompilerVisitor)
807 do
808 var cc = v.global_analysis.compiled_classes[self.global]
809 var ctab = cc.class_table
810 var clen = ctab.length
811 if v.global_analysis.max_class_table_length > ctab.length then
812 clen = v.global_analysis.max_class_table_length
813 end
814
815 v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
816 v.indent
817 for e in ctab do
818 if e == null then
819 v.add_instr("\{0} /* Class Hole :( */,")
820 else
821 v.add_instr("\{(bigint) {e.compile_to_c(v, self)}},")
822 end
823 end
824 if clen > ctab.length then
825 v.add_instr("\{0},"*(clen-ctab.length))
826 end
827 v.unindent
828 v.add_instr("};")
829 var itab = cc.instance_table
830 for e in itab do
831 if e == null then
832 v.add_instr("/* Instance Hole :( */")
833 else
834 v.add_instr(e.compile_to_c(v, self))
835 end
836 end
837
838 var pi = primitive_info
839 if pi == null then
840 v.cfc = new CFunctionContext(v)
841 v.nmc = new NitMethodContext(null)
842 var s = "val_t NEW_{name}(void)"
843 v.add_instr(s + " \{")
844 v.indent
845 var ctx_old = v.ctx
846 v.ctx = new CContext
847
848 v.nmc.method_params = ["OBJ2VAL(obj)"]
849
850 v.add_instr("obj_t obj;")
851 v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
852 v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
853 for g in global_properties do
854 var p = self[g]
855 var t = p.signature.return_type
856 if p isa MMAttribute and t != null then
857 # FIXME: Not compatible with sep compilation
858 assert p isa MMSrcAttribute
859 var np = p.node
860 assert np isa AAttrPropdef
861 var ne = np.n_expr
862 if ne != null then
863 var e = ne.compile_expr(v)
864 v.add_instr("{p.global.attr_access}(obj) = {e};")
865 else
866 var pi = t.local_class.primitive_info
867 if pi != null and pi.tagged then
868 var default = t.default_cvalue
869 v.add_instr("{p.global.attr_access}(obj) = {default};")
870 end
871 end
872 end
873 end
874 v.add_instr("return OBJ2VAL(obj);")
875 v.cfc.generate_var_decls
876 ctx_old.append(v.ctx)
877 v.ctx = ctx_old
878 v.unindent
879 v.add_instr("}")
880
881 var init_table_size = cshe.greaters.length + 1
882 var init_table_decl = "int init_table[{init_table_size}] = \{0{", 0" * (init_table_size-1)}};"
883
884 for g in global_properties do
885 var p = self[g]
886 # FIXME skip invisible constructors
887 if not p.global.is_init then continue
888 var params = new Array[String]
889 var args = ["self"]
890 for i in [0..p.signature.arity[ do
891 params.add("val_t p{i}")
892 args.add("p{i}")
893 end
894 args.add("init_table")
895 var s = "val_t NEW_{self}_{p.global.intro.cname}({params.join(", ")})"
896 v.add_decl(s + ";")
897 v.add_instr(s + " \{")
898 v.indent
899 v.add_instr(init_table_decl)
900 v.add_instr("val_t self = NEW_{name}();")
901 v.add_instr("{p.cname}({args.join(", ")});")
902 v.add_instr("return self;")
903 v.unindent
904 v.add_instr("}")
905 end
906 else if not pi.tagged then
907 var t = pi.cname
908 var tbox = "struct TBOX_{name}"
909 v.add_instr("val_t BOX_{name}({t} val) \{")
910 v.indent
911 v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
912 v.add_instr("box->vft = VFT_{name};")
913 v.add_instr("box->val = val;")
914 v.add_instr("return OBJ2VAL(box);")
915 v.unindent
916 v.add_instr("}")
917 end
918 end
919 end
920