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