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