syntax: handle labels for for, while and closures
[nit.git] / src / primitive_info.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 primitive_info
19
20 #FIXME Split this package into 2: one in metamodel and one in compiling
21
22 import metamodel
23
24 redef class MMLocalClass
25 # Cached primitive_info result
26 var _primitive_info_cache: nullable PrimitiveInfo = null
27
28 # If primitive_info result cached?
29 var _primitive_info_b: Bool = false
30
31 # Return the primitive information of the class.
32 # Return null if the class is not primitive
33 # FIXME: Only here since there is no universal type yet
34 fun primitive_info: nullable PrimitiveInfo
35 do
36 if _primitive_info_b == true then return _primitive_info_cache
37
38 var ctypes = once primitive_ctypes
39 if ctypes.has_key(name) then
40 _primitive_info_cache = ctypes[name]
41 _primitive_info_b = true
42 return _primitive_info_cache
43 end
44 var i = ctypes.iterator
45 while i.is_ok do
46 var n = i.key
47 if module.has_global_class_named(n) then
48 var c = module.class_by_name(n)
49 if cshe < c then
50 _primitive_info_cache = i.item
51 _primitive_info_b = true
52 return _primitive_info_cache
53 end
54 end
55 i.next
56 end
57 _primitive_info_b = true
58 return null
59 end
60
61 # Static information of primitive types
62 private fun primitive_ctypes: HashMap[Symbol, PrimitiveInfo]
63 do
64 var res = new HashMap[Symbol, PrimitiveInfo]
65 var pnames = ["Int", "Char", "Bool", "Float", "NativeString", "NativeArray", "Pointer"]
66 var tagged = [true, true, true, false, false, false, false]
67 var cnames = ["bigint", "char", "int", "float", "char *", "val_t *", "void *"]
68 for i in [0..pnames.length[ do
69 var n = pnames[i].to_symbol
70 var pi = new PrimitiveInfo(n, tagged[i], cnames[i])
71 res[n] = pi
72 end
73 return res
74 end
75 end
76
77 # Information about a primitive class
78 class PrimitiveInfo
79 # The name of the class
80 readable var _name: Symbol
81
82 # Is the class tagged (aka not boxed)
83 readable var _tagged: Bool
84
85 # The corresponding c type for the primitive value
86 readable var _cname: String
87
88 private init(n: Symbol, t: Bool, c: String)
89 do
90 _name = n
91 _tagged = t
92 _cname = c
93 end
94 end
95
96 redef class MMType
97 # The corresponding c type
98 fun cname: String
99 do
100 var pi = local_class.primitive_info
101 if pi == null then
102 return "val_t"
103 else
104 return pi.cname
105 end
106 end
107
108 # The default c value for uninitialized types.
109 # Return "null" for non primitive types and something more specific for primitive types
110 fun default_cvalue: String
111 do
112 var pi = local_class.primitive_info
113 if pi != null and pi.tagged then
114 return "TAG_{local_class.name}(({pi.cname})0)"
115 else
116 return "NIT_NULL"
117 end
118 end
119
120 # Box (or tag) a primitive value
121 # Is identity if not primitive
122 fun boxtype(s: String): String
123 do
124 var pi = local_class.primitive_info
125 if pi == null then
126 return s
127 else if pi.tagged then
128 return "TAG_{local_class.name}({s})"
129 else
130 return "BOX_{local_class.name}({s})"
131 end
132 end
133
134 # Unbox (or untag) a primitive value
135 # Is identity if not primitive
136 fun unboxtype(s: String): String
137 do
138 var pi = local_class.primitive_info
139 if pi == null then
140 return s
141 else if pi.tagged then
142 return "UNTAG_{local_class.name}({s})"
143 else
144 return "UNBOX_{local_class.name}({s})"
145 end
146 end
147 end
148