icode: introduce intermediate code representation
[nit.git] / src / compiling / compiling_base.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 # Common things for NIT compilation and C generation
18 package compiling_base
19
20 import mmloader
21 private import utils
22 import primitive_info
23
24 redef class ToolContext
25 readable writable var _global: Bool = false
26 readable writable var _compdir: nullable String = null
27 readable writable var _clibdir: nullable String = null
28 readable writable var _bindir: nullable String = null
29 readable writable var _output_file: nullable String = null
30 readable writable var _boost: Bool = false
31 readable writable var _no_cc: Bool = false
32 readable writable var _ext_prefix: String = ""
33 end
34
35 # Class used to generate files.
36 # Note that in fact it is not a visitor.
37 # Note also that this class is unefficient and poorly designed thus requires love.
38 class CompilerVisitor
39 # Add a line in the current declaration block
40 fun add_decl(s: String...)
41 do
42 add_line_to(_ctx.decls, s)
43 end
44
45 # Add a line in the current instr block
46 fun add_instr(s: String...)
47 do
48 add_line_to(_ctx.instrs, s)
49 end
50
51 fun add_line_to(a: Array[String], s: Array[String])
52 do
53 if _indent_level >= 8 then
54 a.add("\t\t")
55 else
56 for i in [0.._indent_level[ do
57 a.add(" ")
58 end
59 end
60 for i in s do
61 a.add(i)
62 end
63 a.add("\n")
64 end
65
66 # Add a assignment between a variable and an expression
67 fun add_assignment(v: String, s: String)
68 do
69 if v != s then
70 add_instr(v, " = ", s, ";")
71 end
72 end
73
74 # C outputs written outside the current C function.
75 readable writable var _out_contexts: Array[CContext] = new Array[CContext]
76
77 # Return a unique new number for the instance
78 fun new_number: Int
79 do
80 var res = _number_cpt
81 _number_cpt = res + 1
82 return res
83 end
84 # next number for new_number
85 var _number_cpt: Int = 0
86
87 # Add an indent level.
88 # New decl and instr will be indented.
89 fun indent do _indent_level += 1
90
91 # Remove an indent level.
92 fun unindent
93 do
94 _indent_level -= 1
95 if _indent_level < 0 then _indent_level = 0
96 end
97
98 # Return a big string containing all decl and instr
99 redef fun to_s
100 do
101 var out = new Array[String]
102 out.append(_ctx.decls)
103 out.append(_ctx.instrs)
104 return out.to_s
105 end
106
107 # The processed module
108 readable var _module: MMModule
109
110 # Where instr and decl are stored
111 readable writable var _ctx: CContext = new CContext
112
113 # The current indent lever
114 readable writable var _indent_level: Int = 0
115
116 # The ToolContext info
117 readable var _tc: ToolContext
118
119 # Create a new CompilerVisitor based on a module
120 init(module: MMModule, tc: ToolContext)
121 do
122 _module = module
123 _tc = tc
124 end
125 end
126
127 # Where instr and decl are stored for a module
128 # Note that this class is as badly designed as CompilerVisitor
129 class CContext
130 readable var _decls: Array[String] = new Array[String]
131 readable var _instrs: Array[String] = new Array[String]
132
133 fun append(c: CContext)
134 do
135 _instrs.append(c.decls)
136 _instrs.append(c.instrs)
137 end
138
139 fun merge(c: CContext)
140 do
141 _decls.append(c.decls)
142 _instrs.append(c.instrs)
143 end
144
145 init do end
146 end
147
148 redef class MMGlobalProperty
149 # C symbol refering a method inocation
150 fun meth_call: String
151 do
152 return "CALL_{intro.cname}"
153 end
154
155 # C symbol refering an attribure access
156 fun attr_access: String
157 do
158 return "ATTR_{intro.cname}"
159 end
160 end
161
162 redef class MMGlobalClass
163 # C symbol refering the identifier of the class
164 fun id_id: String
165 do
166 return "ID_{intro.name}"
167 end
168
169 # C symbol refering the color of the class (for subtype tests)
170 fun color_id: String
171 do
172 return "COLOR_{intro.name}"
173 end
174
175 # C symbol refering the init table position of the class (for constructor linearization)
176 fun init_table_pos_id: String
177 do
178 return "INIT_TABLE_POS_{intro.name}"
179 end
180 end
181
182 redef class MMLocalProperty
183 # Cacher result of cname
184 var _cname_cache: nullable String
185
186 # The mangled name of the method
187 fun cname: String
188 do
189 var cname = _cname_cache
190 if cname == null then
191 cname = cmangle(module.name, local_class.name, name)
192 _cname_cache = cname
193 end
194 return cname
195 end
196
197 # C macro used to get the function for the call of a super property
198 fun super_meth_call: String
199 do
200 return "CALL_SUPER_{cname}"
201 end
202 end
203