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