literal: promote `as_X` from annotation
[nit.git] / src / literal.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 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 # Parsing of literal values in the abstract syntax tree.
18 module literal
19
20 import phase
21
22 redef class ToolContext
23 var literal_phase: Phase = new LiteralPhase(self, null)
24 end
25
26 private class LiteralPhase
27 super Phase
28
29 redef fun process_nmodule(nmodule) do nmodule.do_literal(toolcontext)
30 end
31
32 redef class AModule
33 # Visit the module to compute the real value of the literal-related node of the AST.
34 # Warnings and errors are displayed on the toolcontext.
35 fun do_literal(toolcontext: ToolContext)
36 do
37 var v = new LiteralVisitor(toolcontext)
38 v.enter_visit(self)
39 end
40 end
41
42 private class LiteralVisitor
43 super Visitor
44
45 var toolcontext: ToolContext
46
47 redef fun visit(n)
48 do
49 n.accept_literal(self)
50 n.visit_all(self)
51 end
52 end
53
54 redef class ANode
55 private fun accept_literal(v: LiteralVisitor) do end
56 end
57
58 redef class AExpr
59 # Get `self` as a `String`.
60 # Return null if not a string.
61 fun as_string: nullable String
62 do
63 if not self isa AStringFormExpr then return null
64 return self.value.as(not null)
65 end
66
67 # Get `self` as an `Int`.
68 # Return null if not an integer.
69 fun as_int: nullable Int
70 do
71 if not self isa AIntExpr then return null
72 return self.value.as(not null)
73 end
74
75 # Get `self` as a single identifier.
76 # Return null if not a single identifier.
77 fun as_id: nullable String
78 do
79 if self isa AMethidExpr then
80 return self.collect_text
81 end
82 if not self isa ACallExpr then return null
83 if not self.n_expr isa AImplicitSelfExpr then return null
84 if not self.n_args.n_exprs.is_empty then return null
85 return self.n_id.text
86 end
87 end
88
89
90 redef class AIntExpr
91 # The value of the literal int once computed.
92 var value: nullable Int
93 end
94
95 redef class ADecIntExpr
96 redef fun accept_literal(v)
97 do
98 self.value = self.n_number.text.to_i
99 end
100 end
101
102 redef class AHexIntExpr
103 redef fun accept_literal(v)
104 do
105 self.value = self.n_hex_number.text.substring_from(2).to_hex
106 end
107 end
108
109 redef class AFloatExpr
110 # The value of the literal float once computed.
111 var value: nullable Float
112 redef fun accept_literal(v)
113 do
114 self.value = self.n_float.text.to_f
115 end
116 end
117
118 redef class ACharExpr
119 # The value of the literal char once computed.
120 var value: nullable Char
121 redef fun accept_literal(v)
122 do
123 var txt = self.n_char.text.unescape_nit
124 if txt.length != 3 then
125 v.toolcontext.error(self.hot_location, "Invalid character literal {txt}")
126 return
127 end
128 self.value = txt.chars[1]
129 end
130 end
131
132 redef class AStringFormExpr
133 # The value of the literal string once computed.
134 var value: nullable String
135 redef fun accept_literal(v)
136 do
137 var txt = self.n_string.text
138 var behead = 1
139 var betail = 1
140 if txt.chars[0] == txt.chars[1] and txt.length >= 6 then
141 behead = 3
142 betail = 3
143 if txt.chars[0] == '"' and txt.chars[3] == '\n' then behead = 4 # ignore first \n in """
144 end
145 self.value = txt.substring(behead, txt.length - behead - betail).unescape_nit
146 end
147 end