1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 module vox.fe.ast.expr.literal;
5 
6 import vox.all;
7 
8 @(AstType.literal_int)
9 struct IntLiteralExprNode {
10 	mixin ExpressionNodeData!(AstType.literal_int, 0, AstNodeState.name_resolve_done);
11 	ulong value;
12 
13 	private enum Flags : ushort
14 	{
15 		isNegative = AstFlags.userFlag
16 	}
17 	bool isNegative() { return cast(bool)(flags & Flags.isNegative); }
18 	IsSigned isSigned() { return cast(IsSigned)isNegative; }
19 
20 	void negate(TokenIndex pos, ref CompilationContext context) {
21 		if (isNegative) {
22 			value = -(cast(long)value);
23 			flags &= ~cast(int)Flags.isNegative;
24 		} else {
25 			if (value <= 0x8000_0000_0000_0000) {
26 				value = -(cast(long)value);
27 				flags |= Flags.isNegative;
28 			}
29 			else {
30 				context.error(pos, "`-%s` results in signed integer overflow", value);
31 			}
32 		}
33 	}
34 }
35 
36 void print_literal_int(IntLiteralExprNode* node, ref AstPrintState state)
37 {
38 	if (node.isSigned)
39 		state.print("LITERAL int ", node.type.printer(state.context), " ", cast(long)node.value);
40 	else
41 		state.print("LITERAL int ", node.type.printer(state.context), " ", node.value);
42 }
43 
44 void type_check_literal_int(IntLiteralExprNode* node, ref TypeCheckState state)
45 {
46 	node.state = AstNodeState.type_check;
47 	if (node.type.isUndefined) {
48 		if (node.isSigned) {
49 			BasicType t = minSignedIntType(node.value);
50 			t = max(t, BasicType.t_i32);
51 			node.type = state.context.basicTypeNodes(t);
52 		} else {
53 			BasicType t = minUnsignedIntType(node.value);
54 			if (cast(uint)(node.value & 0x7FFF_FFFF) == node.value) t = BasicType.t_i32;
55 			node.type = state.context.basicTypeNodes(t);
56 		}
57 	}
58 	node.state = AstNodeState.type_check_done;
59 }
60 
61 IrIndex ir_gen_literal_int(CompilationContext* context, IntLiteralExprNode* n)
62 {
63 	CompilationContext* c = context;
64 	return c.constants.add(n.type.gen_ir_type(c), n.value);
65 }
66 
67 
68 @(AstType.literal_float)
69 struct FloatLiteralExprNode {
70 	mixin ExpressionNodeData!(AstType.literal_float, 0, AstNodeState.name_resolve_done);
71 	double value;
72 	void negate(TokenIndex pos, ref CompilationContext context) {
73 		value = -value;
74 	}
75 }
76 
77 void print_literal_float(FloatLiteralExprNode* node, ref AstPrintState state)
78 {
79 	state.print("LITERAL float ", node.type.printer(state.context), " ", node.value);
80 }
81 
82 void type_check_literal_float(FloatLiteralExprNode* node, ref TypeCheckState state)
83 {
84 	node.state = AstNodeState.type_check;
85 	if (node.type.isUndefined) node.type = CommonAstNodes.type_f64;
86 	node.state = AstNodeState.type_check_done;
87 }
88 
89 IrIndex ir_gen_literal_float(CompilationContext* context, FloatLiteralExprNode* node)
90 {
91 	if (node.type == CommonAstNodes.type_f32) {
92 		return context.constants.add(float(node.value));
93 	} else {
94 		assert(node.type == CommonAstNodes.type_f64);
95 		return context.constants.add(double(node.value));
96 	}
97 }
98 
99 
100 @(AstType.literal_null)
101 struct NullLiteralExprNode {
102 	mixin ExpressionNodeData!(AstType.literal_null, 0, AstNodeState.name_resolve_done);
103 }
104 
105 void print_literal_null(NullLiteralExprNode* node, ref AstPrintState state)
106 {
107 	state.print("LITERAL null");
108 }
109 
110 void type_check_literal_null(NullLiteralExprNode* node, ref TypeCheckState state)
111 {
112 	node.state = AstNodeState.type_check;
113 	node.type = CommonAstNodes.type_null;
114 	node.state = AstNodeState.type_check_done;
115 }
116 
117 IrIndex ir_gen_literal_null(CompilationContext* context, NullLiteralExprNode* n)
118 {
119 	CompilationContext* c = context;
120 	if (n.type.get_type(c).isPointer) {
121 		return c.constants.addZeroConstant(makeIrType(IrBasicType.i64));
122 	} else if (n.type.get_type(c).isSlice) {
123 		return c.constants.addZeroConstant(n.type.gen_ir_type(c));
124 	} else if (n.type.get_type(c).isTypeofNull) {
125 		return c.constants.addZeroConstant(makeIrType(IrBasicType.i64));
126 	} else c.internal_error(n.loc, "%s", n.type.printer(c));
127 }
128 
129 
130 @(AstType.literal_bool)
131 struct BoolLiteralExprNode {
132 	mixin ExpressionNodeData!(AstType.literal_bool, 0, AstNodeState.name_resolve_done);
133 	bool value;
134 }
135 
136 void print_literal_bool(BoolLiteralExprNode* node, ref AstPrintState state)
137 {
138 	if (node.value) state.print("TRUE ", node.type.printer(state.context));
139 	else state.print("FALSE ", node.type.printer(state.context));
140 }
141 
142 void type_check_literal_bool(BoolLiteralExprNode* node, ref TypeCheckState state)
143 {
144 	node.state = AstNodeState.type_check;
145 	node.type = CommonAstNodes.type_bool;
146 	node.state = AstNodeState.type_check_done;
147 }
148 
149 IrIndex ir_gen_literal_bool(CompilationContext* context, BoolLiteralExprNode* n)
150 {
151 	CompilationContext* c = context;
152 	return c.constants.add(makeIrType(IrBasicType.i8), (n.value != 0));
153 }
154 
155 void ir_gen_branch_literal_bool(ref IrGenState gen, IrIndex currentBlock, ref IrLabel trueExit, ref IrLabel falseExit, BoolLiteralExprNode* n)
156 {
157 	if (n.value)
158 		gen.builder.addJumpToLabel(currentBlock, trueExit);
159 	else
160 		gen.builder.addJumpToLabel(currentBlock, falseExit);
161 }
162 
163 
164 @(AstType.literal_string)
165 struct StringLiteralExprNode {
166 	mixin ExpressionNodeData!(AstType.literal_string, 0, AstNodeState.name_resolve_done);
167 	IrIndex irValue;
168 	string value;
169 }
170 
171 IrIndex makeStringLiteralIrConstant(string data, LinkIndex moduleSymIndex, CompilationContext* c)
172 {
173 	IrIndex irValue;
174 	// dont create empty global for empty string. Globals are required to have non-zero length
175 	if (data.length == 0)
176 	{
177 		irValue = c.constants.addZeroConstant(makeIrType(IrBasicType.i64)); // null ptr
178 	}
179 	else
180 	{
181 		irValue = c.globals.add();
182 		IrGlobal* global = c.globals.get(irValue);
183 		global.type = CommonAstNodes.type_u8Ptr.gen_ir_type(c);
184 
185 		ObjectSymbol sym = {
186 			kind : ObjectSymbolKind.isLocal,
187 			sectionIndex : c.builtinSections[ObjectSectionType.ro_data],
188 			moduleIndex : moduleSymIndex,
189 			flags : ObjectSymbolFlags.needsZeroTermination | ObjectSymbolFlags.isString,
190 			id : c.idMap.getOrReg(c, ":string"),
191 		};
192 		global.objectSymIndex = c.objSymTab.addSymbol(sym);
193 
194 		ObjectSymbol* globalSym = c.objSymTab.getSymbol(global.objectSymIndex);
195 		globalSym.setInitializer(cast(ubyte[])data);
196 	}
197 	IrIndex irValueLength = c.constants.add(makeIrType(IrBasicType.i64), data.length);
198 	return c.constants.addAggrecateConstant(CommonAstNodes.type_u8Slice.gen_ir_type(c), irValueLength, irValue);
199 }
200 
201 void print_literal_string(StringLiteralExprNode* node, ref AstPrintState state)
202 {
203 	state.print("LITERAL string ", node.type.printer(state.context), " ", node.value);
204 }
205 
206 void type_check_literal_string(StringLiteralExprNode* node, ref TypeCheckState state)
207 {
208 	node.state = AstNodeState.type_check;
209 	// done in parser
210 	node.state = AstNodeState.type_check_done;
211 }
212 
213 IrIndex ir_gen_literal_string(CompilationContext* context, StringLiteralExprNode* n)
214 {
215 	return n.irValue;
216 }
217 
218 
219 @(AstType.literal_array)
220 struct ArrayLiteralExprNode {
221 	mixin ExpressionNodeData!(AstType.literal_array, 0, AstNodeState.name_resolve_done);
222 	AstNodes items;
223 	IrIndex irValue;
224 }
225 
226 void print_literal_array(ArrayLiteralExprNode* node, ref AstPrintState state)
227 {
228 	state.print("LITERAL array ", node.type.printer(state.context), " ", node.items);
229 }
230 
231 void type_check_literal_array(ArrayLiteralExprNode* node, ref TypeCheckState state)
232 {
233 	node.state = AstNodeState.type_check;
234 	require_type_check(node.items, state);
235 	node.state = AstNodeState.type_check_done;
236 }
237 
238 
239 
240 AstIndex[SpecialKeyword.max+1] specialKeywordType = [
241 	SpecialKeyword.file          : CommonAstNodes.type_u8Slice,
242 	SpecialKeyword.line          : CommonAstNodes.type_u64,
243 	SpecialKeyword.function_name : CommonAstNodes.type_u8Slice,
244 	SpecialKeyword.module_name   : CommonAstNodes.type_u8Slice,
245 ];
246 
247 string[SpecialKeyword.max+1] specialKeywordName = [
248 	"__FILE__",
249 	"__LINE__",
250 	"__FUNCTION_NAME__",
251 	"__MODULE_NAME__",
252 ];
253 
254 /// __FILE__, __LINE__, __FUNCTION_NAME__, __MODULE_NAME__
255 @(AstType.literal_special)
256 struct SpecialLiteralExprNode {
257 	mixin ExpressionNodeData!(AstType.literal_special, 0, AstNodeState.type_check_done);
258 	IrIndex irValue;
259 
260 	this(TokenIndex loc, IrIndex irValue, SpecialKeyword subType)
261 	{
262 		this.loc = loc;
263 		this.astType = AstType.literal_special;
264 		this.state = AstNodeState.type_check_done;
265 		this.subType = subType;
266 		this.irValue = irValue;
267 		this.type = specialKeywordType[subType];
268 	}
269 }
270 
271 IrIndex eval_literal_special(SpecialKeyword kw, TokenIndex tok, ScopeIndex parentScope, CompilationContext* c) {
272 	final switch(kw) with(SpecialKeyword) {
273 		case file:
274 			ModuleDeclNode* mod = c.getModuleFromToken(tok);
275 			return c.get_file_name_constant(c.getAstNodeIndex(mod));
276 		case line:
277 			SourceLocation loc = c.tokenLoc(tok);
278 			return c.constants.add(makeIrType(IrBasicType.i64), loc.line+1);
279 		case function_name:
280 			AstIndex owner = find_innermost_owner(parentScope, AstType.decl_function, c);
281 			if (owner.isUndefined) return c.constants.addZeroConstant(CommonAstNodes.type_u8Slice.gen_ir_type(c));
282 			return c.get_function_name_constant(owner);
283 		case module_name:
284 			AstIndex owner = find_innermost_owner(parentScope, AstType.decl_module, c);
285 			c.assertf(owner.isDefined, "Can't find the module");
286 			return c.get_module_name_constant(owner);
287 	}
288 }
289 
290 void print_literal_special(SpecialLiteralExprNode* node, ref AstPrintState state)
291 {
292 	state.print("LITERAL ", specialKeywordName[node.subType], " ", node.type.printer(state.context));
293 }
294 
295 IrIndex ir_gen_literal_special(CompilationContext* context, SpecialLiteralExprNode* n)
296 {
297 	return n.irValue;
298 }