262228fd939c907bd67b57b9da807d701b16d9c3
[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 mmmodule.has_global_class_named(n) then
48 var c = mmmodule.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", "Pointer"]
66 var tagged = [true, true, true, false, false, false]
67 var cnames = ["bigint", "char", "int", "float", "char *", "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 # Is the type tagged?
109 fun is_tagged: Bool
110 do
111 if is_nullable then return false
112 var pi = local_class.primitive_info
113 return pi != null and pi.tagged
114 end
115
116 # The default c value for uninitialized types.
117 # Return "null" for non primitive types and something more specific for primitive types
118 fun default_cvalue: String
119 do
120 var pi = local_class.primitive_info
121 if pi != null and pi.tagged then
122 return "TAG_{local_class.name}(({pi.cname})0)"
123 else
124 return "NIT_NULL"
125 end
126 end
127
128 # Box (or tag) a primitive value
129 # Is identity if not primitive
130 fun boxtype(s: String): String
131 do
132 var pi = local_class.primitive_info
133 if pi == null then
134 return s
135 else if pi.tagged then
136 return "TAG_{local_class.name}({s})"
137 else
138 return "BOX_{local_class.name}({s})"
139 end
140 end
141
142 # Unbox (or untag) a primitive value
143 # Is identity if not primitive
144 fun unboxtype(s: String): String
145 do
146 var pi = local_class.primitive_info
147 if pi == null then
148 return s
149 else if pi.tagged then
150 return "UNTAG_{local_class.name}({s})"
151 else
152 return "UNBOX_{local_class.name}({s})"
153 end
154 end
155 end
156