Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use Logging | |
| 3 | ||
| 4 | use Semantic.Lookups.InnateSymbolLookup | |
| 5 | use Semantic.Types.Type | |
| 6 | ||
| 7 | use IR.Values | |
| 8 | ||
| 9 | // Lowers literal and `_` (default-value) expressions to IR values. | |
| 10 | // Split out of COMPILE_EXPRESSIONS, which delegates each | |
| 11 | // visit(<literal>) here. | |
| 12 | class COMPILE_LITERALS is | |
| 13 | _logger: Logger | |
| 14 | _innate_symbol_lookup: InnateSymbolLookup | |
| 15 | _numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER | |
| 16 | _symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS | |
| 17 | ||
| 18 | init( | |
| 19 | logger: Logger, | |
| 20 | innate_symbol_lookup: InnateSymbolLookup, | |
| 21 | numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER, | |
| 22 | symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS | |
| 23 | ) is | |
| 24 | super.init() | |
| 25 | ||
| 26 | _logger = logger | |
| 27 | _innate_symbol_lookup = innate_symbol_lookup | |
| 28 | _numeric_literal_classifier = numeric_literal_classifier | |
| 29 | _symbol_use_locations = symbol_use_locations | |
| 30 | si | |
| 31 | ||
| 32 | visit_integer(integer: Trees.Expressions.Literals.INTEGER) is | |
| 33 | let value = _numeric_literal_classifier.classify(integer.location, integer.value_string) | |
| 34 | ||
| 35 | if !value? then | |
| 36 | integer.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), integer.location) | |
| 37 | return | |
| 38 | fi | |
| 39 | ||
| 40 | integer.compile_expressions_state.value = value | |
| 41 | si | |
| 42 | ||
| 43 | visit_float(float: Trees.Expressions.Literals.FLOAT) is | |
| 44 | let value_string = float.value_string | |
| 45 | let kind = FLOAT_LITERAL_SUFFIX.kind(value_string) | |
| 46 | let stripped = FLOAT_LITERAL_SUFFIX.strip(value_string) | |
| 47 | ||
| 48 | if kind == FloatLiteralKind.DECIMAL then | |
| 49 | if stripped.contains('e') \/ stripped.contains('E') then | |
| 50 | _logger.error(float.location, "exponent notation not supported in decimal literal") | |
| 51 | float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location) | |
| 52 | return | |
| 53 | fi | |
| 54 | ||
| 55 | let decomp = Literal.DECIMAL.decompose(stripped) | |
| 56 | ||
| 57 | if decomp.error? then | |
| 58 | _logger.error(float.location, decomp.error!) | |
| 59 | float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location) | |
| 60 | return | |
| 61 | fi | |
| 62 | ||
| 63 | float.compile_expressions_state.value = Literal.DECIMAL( | |
| 64 | stripped, | |
| 65 | _innate_symbol_lookup.get_decimal_type(), | |
| 66 | decomp.lo, | |
| 67 | decomp.mid, | |
| 68 | decomp.hi, | |
| 69 | decomp.scale | |
| 70 | ) | |
| 71 | return | |
| 72 | fi | |
| 73 | ||
| 74 | let is_single = kind == FloatLiteralKind.SINGLE | |
| 75 | ||
| 76 | let type = | |
| 77 | if is_single then | |
| 78 | _innate_symbol_lookup.get_single_type() | |
| 79 | else | |
| 80 | _innate_symbol_lookup.get_double_type() | |
| 81 | fi | |
| 82 | ||
| 83 | let parsed: double mut = _ | |
| 84 | ||
| 85 | if !double.try_parse(stripped, parsed ref) then | |
| 86 | _logger.error(float.location, "invalid floating-point literal {stripped}") | |
| 87 | return | |
| 88 | fi | |
| 89 | ||
| 90 | float.compile_expressions_state.value = | |
| 91 | Literal.NUMBER( | |
| 92 | if is_single then | |
| 93 | Literal.CONSTANT.R4(cast single(parsed)) | |
| 94 | else | |
| 95 | Literal.CONSTANT.R8(parsed) | |
| 96 | fi, | |
| 97 | type | |
| 98 | ) | |
| 99 | si | |
| 100 | ||
| 101 | visit_interpolation(interpolation: Trees.Expressions.STRING_INTERPOLATION) is | |
| 102 | interpolation.compile_expressions_state.value = IR.Values.BLOCK(_innate_symbol_lookup.get_string_type()) | |
| 103 | si | |
| 104 | ||
| 105 | visit_string(`string: Trees.Expressions.Literals.STRING) is | |
| 106 | `string.compile_expressions_state.value = Literal.STRING( | |
| 107 | `string.value_string, | |
| 108 | _innate_symbol_lookup.get_string_type() | |
| 109 | ) | |
| 110 | si | |
| 111 | ||
| 112 | visit_character(character: Trees.Expressions.Literals.CHARACTER) is | |
| 113 | let value_string = character.value_string | |
| 114 | let c: int mut = 0 | |
| 115 | ||
| 116 | if value_string.length < 1 \/ value_string.length > 1 then | |
| 117 | _logger.error(character.location, "invalid character literal") | |
| 118 | else | |
| 119 | c = cast int(value_string[0]) | |
| 120 | fi | |
| 121 | ||
| 122 | character.compile_expressions_state.value = Literal.NUMBER( | |
| 123 | c, | |
| 124 | _innate_symbol_lookup.get_char_type() | |
| 125 | ) | |
| 126 | si | |
| 127 | ||
| 128 | visit_boolean(boolean: Trees.Expressions.Literals.BOOLEAN) is | |
| 129 | let value_string = boolean.value_string | |
| 130 | ||
| 131 | let value: int mut | |
| 132 | ||
| 133 | if value_string =~ "true" then | |
| 134 | value = 1 | |
| 135 | elif value_string =~ "false" then | |
| 136 | value = 0 | |
| 137 | else | |
| 138 | throw System.Exception("invalid value for boolean literal: {value_string}") | |
| 139 | fi | |
| 140 | ||
| 141 | boolean.compile_expressions_state.value = Literal.NUMBER( | |
| 142 | value, | |
| 143 | _innate_symbol_lookup.get_bool_type() | |
| 144 | ) | |
| 145 | si | |
| 146 | ||
| 147 | visit_default(`default: Trees.Expressions.DEFAULT) is | |
| 148 | // `_[T]` pins the type explicitly; a bare `_` takes the | |
| 149 | // type pushed in by the parent context (assignment RHS, | |
| 150 | // return position, typed `let` initializer, call | |
| 151 | // argument) via set_constraint. | |
| 152 | let type: Semantic.Types.Type? mut = _ | |
| 153 | ||
| 154 | if `default.type_expression? then | |
| 155 | type = `default.type_expression.type | |
| 156 | elif `default.expected_type? then | |
| 157 | type = `default.expected_type | |
| 158 | fi | |
| 159 | ||
| 160 | if !type? then | |
| 161 | _logger.error(`default.location, "cannot infer type of default here") | |
| 162 | `default.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), `default.location) | |
| 163 | return | |
| 164 | fi | |
| 165 | ||
| 166 | if type.is_error then | |
| 167 | `default.compile_expressions_state.value = IR.Values.DUMMY(type, `default.location) | |
| 168 | return | |
| 169 | fi | |
| 170 | ||
| 171 | // A bare `_` never names its type, so hover over it is the | |
| 172 | // only place the reader can see what the context settled | |
| 173 | // on. `_[T]` says it already. | |
| 174 | if !`default.type_expression? then | |
| 175 | _symbol_use_locations.add_inferred_type_hover(`default.location, type) | |
| 176 | fi | |
| 177 | ||
| 178 | // A `_` for a `T ref` slot discards what the callee writes: it | |
| 179 | // is the address of a fresh local holding the default of `T`, | |
| 180 | // never a null reference the callee would write through. | |
| 181 | if let reference: Semantic.Types.REFERENCE = type then | |
| 182 | `default.compile_expressions_state.value = IR.Values.ADDRESS(IR.Values.DEFAULT(reference.arguments[0]), type) | |
| 183 | return | |
| 184 | fi | |
| 185 | ||
| 186 | `default.compile_expressions_state.value = IR.Values.DEFAULT(type) | |
| 187 | si | |
| 188 | si | |
| 189 | si |