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 }