Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use System.Exception | |
| 3 | ||
| 4 | use Logging | |
| 5 | ||
| 6 | use Semantic.LEAST_UPPER_BOUND_MAP | |
| 7 | use Semantic.Types.Type | |
| 8 | ||
| 9 | use IR.Values | |
| 10 | use IR.VALUE_BOXER | |
| 11 | ||
| 12 | use Ghul.Pipes | |
| 13 | ||
| 14 | // Compiles tuple and list/array (`SEQUENCE`) literal expressions. | |
| 15 | // Split out of COMPILE_EXPRESSIONS, which delegates pre(tuple), | |
| 16 | // visit(tuple) and the inner sequence compile here. The | |
| 17 | // exception-handling and walk orchestration for visit(sequence) | |
| 18 | // stays on the visitor; visit_sequence is the enclosed logic. | |
| 19 | class COMPILE_TUPLES is | |
| 20 | _logger: Logger | |
| 21 | _innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup | |
| 22 | _value_boxer: VALUE_BOXER | |
| 23 | _visitor: COMPILE_EXPRESSIONS | |
| 24 | _placeholder_resolver: Semantic.SETTLED_PLACEHOLDER_RESOLVER | |
| 25 | _match_propagator: Semantic.MATCH_PROPAGATOR | |
| 26 | ||
| 27 | init( | |
| 28 | logger: Logger, | |
| 29 | innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup, | |
| 30 | value_boxer: VALUE_BOXER, | |
| 31 | visitor: COMPILE_EXPRESSIONS | |
| 32 | ) is | |
| 33 | super.init() | |
| 34 | ||
| 35 | _logger = logger | |
| 36 | _innate_symbol_lookup = innate_symbol_lookup | |
| 37 | _value_boxer = value_boxer | |
| 38 | _visitor = visitor | |
| 39 | _placeholder_resolver = Semantic.SETTLED_PLACEHOLDER_RESOLVER() | |
| 40 | _match_propagator = Semantic.MATCH_PROPAGATOR(logger) | |
| 41 | si | |
| 42 | ||
| 43 | pre_tuple(tuple: Trees.Expressions.TUPLE) -> bool is | |
| 44 | if tuple.elements.expressions.count == 1 then | |
| 45 | // Single-element TUPLE is a parenthesised expression | |
| 46 | // (TUPLE.visit unwraps its value). Forward whatever | |
| 47 | // constraint applies to the outer expression directly | |
| 48 | // to the inner one — splitting a value-tuple constraint | |
| 49 | // across a phantom 1-tuple slot would push the wrong | |
| 50 | // element type down into the inner expression. | |
| 51 | if tuple.expected_type? then | |
| 52 | let forward_pack = tuple.compile_expressions_state.pack_marker | |
| 53 | ||
| 54 | tuple.elements.expressions[0].set_expected_type(tuple.expected_type, tuple.expected_type_error_message) | |
| 55 | ||
| 56 | if forward_pack > 0 then | |
| 57 | tuple.set_expects_pack(forward_pack - 1) | |
| 58 | fi | |
| 59 | else | |
| 60 | tuple.elements.expressions[0].clear_expected_type() | |
| 61 | fi | |
| 62 | elif let tuple.expected_type? /\ expected_type.is_value_tuple then | |
| 63 | for (element, type) in tuple.elements |> zip(expected_type.arguments) do | |
| 64 | element.set_expected_type(type, tuple.expected_type_error_message) | |
| 65 | od | |
| 66 | else | |
| 67 | for element in tuple.elements do | |
| 68 | element.clear_expected_type() | |
| 69 | od | |
| 70 | fi | |
| 71 | ||
| 72 | return false | |
| 73 | si | |
| 74 | ||
| 75 | visit_tuple(tuple: Trees.Expressions.TUPLE) is | |
| 76 | // A type ascription on a parenthesised group only means | |
| 77 | // something when the group turns out to be a lambda's | |
| 78 | // destructured parameter, which consumes it before any | |
| 79 | // value is compiled. Reaching here with one still attached | |
| 80 | // means the group is an ordinary tuple value, where the | |
| 81 | // ascription has no effect and would otherwise be dropped | |
| 82 | // in silence. | |
| 83 | if let tuple.type_expression? then | |
| 84 | _logger.error(type_expression.location, "type not allowed here") | |
| 85 | fi | |
| 86 | ||
| 87 | let names: Collections.LIST[string]? mut = Collections.LIST[string]() | |
| 88 | let values = Collections.LIST[Value]() | |
| 89 | let types = Collections.LIST[Type]() | |
| 90 | ||
| 91 | let element_constraints: Collections.List[Type]? mut = null | |
| 92 | let expected_type_error_message: string? mut = null | |
| 93 | ||
| 94 | if let tuple.expected_type? /\ expected_type.is_value_tuple then | |
| 95 | element_constraints = expected_type.arguments | |
| 96 | expected_type_error_message = tuple.expected_type_error_message | |
| 97 | fi | |
| 98 | ||
| 99 | if tuple.elements.expressions.count == 1 then | |
| 100 | // A single parenthesised element is a grouped expression, | |
| 101 | // not a tuple — there are no single-element tuples (a bare | |
| 102 | // `(x)` is just `x`). A named/typed sole element (`(x = 1)` | |
| 103 | // / `(x: int)`) is an attempt at one; report it rather than | |
| 104 | // collapsing to the element's unset value, which would | |
| 105 | // poison to ERROR and crash IL emission far downstream. | |
| 106 | if let element: Trees.Expressions.TUPLE_ELEMENT = tuple.elements.expressions[0] then | |
| 107 | _logger.error(element.location, "single-element tuples are not supported; a tuple needs two or more elements") | |
| 108 | tuple.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), tuple.location) | |
| 109 | else | |
| 110 | tuple.compile_expressions_state.value = tuple.elements.expressions[0].value | |
| 111 | fi | |
| 112 | return | |
| 113 | elif tuple.elements.expressions.count == 0 then | |
| 114 | tuple.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), tuple.location) | |
| 115 | ||
| 116 | _logger.error(tuple.location, "empty tuple") | |
| 117 | return | |
| 118 | elif tuple.elements.expressions.count > Semantic.Lookups.INNATE_TYPE_LIMITS.MAX_TUPLE_ELEMENTS then | |
| 119 | tuple.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), tuple.location) | |
| 120 | ||
| 121 | _logger.error( | |
| 122 | tuple.location, | |
| 123 | "a tuple literal cannot have more than {Semantic.Lookups.INNATE_TYPE_LIMITS.MAX_TUPLE_ELEMENTS} elements") | |
| 124 | return | |
| 125 | fi | |
| 126 | ||
| 127 | let seen_any_named mut = false | |
| 128 | ||
| 129 | for (index, v) in tuple.elements |> index() do | |
| 130 | let element_type_constraint = | |
| 131 | if element_constraints? then | |
| 132 | element_constraints[index] | |
| 133 | else | |
| 134 | null | |
| 135 | fi | |
| 136 | ||
| 137 | if isa Trees.Expressions.TUPLE_ELEMENT(v) then | |
| 138 | let element = v | |
| 139 | ||
| 140 | seen_any_named = true | |
| 141 | names.add(element.name.name) | |
| 142 | ||
| 143 | // An attribute pragma only makes sense on a lambda | |
| 144 | // parameter — reaching here means the parenthesised | |
| 145 | // list was never rewritten into one (no `->`/`=>`/ | |
| 146 | // `is`/`rec` followed), so this is a genuine tuple | |
| 147 | // literal instead. | |
| 148 | if element.pragmas? then | |
| 149 | for pragma in element.pragmas do | |
| 150 | _logger.error(pragma.location, "attribute is not allowed here") | |
| 151 | od | |
| 152 | fi | |
| 153 | ||
| 154 | if element.initializer? then | |
| 155 | if Value.check_is_consumable(_logger, element.initializer.location, element.initializer.value) then | |
| 156 | if element.type_expression.type? then | |
| 157 | let expr_type = element.type_expression.type | |
| 158 | let type = | |
| 159 | if element_type_constraint? then | |
| 160 | element_type_constraint | |
| 161 | else | |
| 162 | expr_type | |
| 163 | fi | |
| 164 | ||
| 165 | let init_value = element.initializer!.value! | |
| 166 | ||
| 167 | if element.type_expression.check_is_not_reference(_logger, "tuple element cannot be a reference") then | |
| 168 | if !type.is_assignable_from(init_value.type!) then | |
| 169 | _logger.error(element.location, "{init_value.type} is not assignable to {type}") | |
| 170 | elif element_type_constraint? /\ !element_type_constraint.is_assignable_from(expr_type) then | |
| 171 | _logger.error( | |
| 172 | element.type_expression.location, | |
| 173 | string.format(expected_type_error_message!, [expr_type, element_type_constraint]:object)) | |
| 174 | fi | |
| 175 | fi | |
| 176 | ||
| 177 | types.add(type) | |
| 178 | values.add(_value_boxer.box_if_needed(init_value, type)) | |
| 179 | ||
| 180 | elif element_type_constraint? then | |
| 181 | let type = element_type_constraint | |
| 182 | let init_value = element.initializer!.value! | |
| 183 | ||
| 184 | if !type.is_assignable_from(init_value.type!) then | |
| 185 | _logger.error( | |
| 186 | element.location, | |
| 187 | string.format(expected_type_error_message!, [init_value.type!, type]:object)) | |
| 188 | fi | |
| 189 | ||
| 190 | types.add(type) | |
| 191 | values.add(_value_boxer.box_if_needed(init_value, type)) | |
| 192 | else | |
| 193 | let init_value = element.initializer!.value! | |
| 194 | types.add(init_value.type!) | |
| 195 | values.add(init_value) | |
| 196 | fi | |
| 197 | ||
| 198 | continue | |
| 199 | fi | |
| 200 | else | |
| 201 | _logger.error(element.location, "tuple element must have a value") | |
| 202 | fi | |
| 203 | ||
| 204 | values.add(IR.Values.DUMMY(Semantic.Types.ERROR(), element.location)) | |
| 205 | types.add(Semantic.Types.ERROR()) | |
| 206 | ||
| 207 | elif Value.check_is_consumable(_logger, v.location, v.value) then | |
| 208 | let v_value = v.value! | |
| 209 | ||
| 210 | if v.is_identifier then | |
| 211 | // An unnamed element that is a plain identifier | |
| 212 | // takes its name from that identifier: `(a, b)` | |
| 213 | // is `(a = a, b = b)`. TUPLE_ELEMENT_NAME owns | |
| 214 | // the underscore-strip corner cases. | |
| 215 | let identifier_name = v.try_copy_as_identifer()!.name | |
| 216 | let is_field_symbol = | |
| 217 | isa IR.Values.Load.SYMBOL(v_value) /\ | |
| 218 | v_value.has_symbol /\ | |
| 219 | v_value.symbol.is_field | |
| 220 | ||
| 221 | names.add(TUPLE_ELEMENT_NAME.infer(identifier_name, is_field_symbol)) | |
| 222 | seen_any_named = true | |
| 223 | else | |
| 224 | names.add("{index}") | |
| 225 | fi | |
| 226 | ||
| 227 | if element_type_constraint? then | |
| 228 | let type = element_type_constraint | |
| 229 | ||
| 230 | if !type.is_assignable_from(v_value.type!) then | |
| 231 | _logger.error( | |
| 232 | v.location, | |
| 233 | string.format(expected_type_error_message!, [v_value.type!, type]:object)) | |
| 234 | fi | |
| 235 | ||
| 236 | types.add(type) | |
| 237 | values.add(_value_boxer.box_if_needed(v_value, type)) | |
| 238 | else | |
| 239 | types.add(v_value.type!) | |
| 240 | values.add(v_value) | |
| 241 | fi | |
| 242 | else | |
| 243 | values.add(IR.Values.DUMMY(Semantic.Types.ERROR(), v.location)) | |
| 244 | types.add(Semantic.Types.ERROR()) | |
| 245 | fi | |
| 246 | ||
| 247 | debug_unindent() | |
| 248 | od | |
| 249 | ||
| 250 | if !seen_any_named then | |
| 251 | names = null | |
| 252 | fi | |
| 253 | ||
| 254 | let type = _innate_symbol_lookup.get_tuple_type(_placeholder_resolver.resolve_all(types), names) | |
| 255 | tuple.compile_expressions_state.value = TUPLE(type, values) | |
| 256 | si | |
| 257 | ||
| 258 | visit_sequence(sequence: Trees.Expressions.SEQUENCE) is | |
| 259 | let type: Type? mut = _ | |
| 260 | let have_explicit_type: bool mut = _ | |
| 261 | ||
| 262 | let elements = Collections.LIST[Trees.Expressions.Expression](sequence.elements) | |
| 263 | ||
| 264 | let constraint_type: Type? mut = _ | |
| 265 | if let sequence.expected_type? then | |
| 266 | constraint_type = expected_type.get_element_type() | |
| 267 | fi | |
| 268 | ||
| 269 | if !isa Trees.TypeExpressions.INFER(sequence.type_expression) then | |
| 270 | if sequence.type_expression.type? then | |
| 271 | type = sequence.type_expression.type | |
| 272 | ||
| 273 | have_explicit_type = true | |
| 274 | else | |
| 275 | // FIXME probably not needed - type pass will have given an error | |
| 276 | _logger.error(sequence.type_expression.location, "bad explicit type expression") | |
| 277 | return | |
| 278 | fi | |
| 279 | elif elements.count == 0 then | |
| 280 | if constraint_type? then | |
| 281 | type = constraint_type | |
| 282 | have_explicit_type = true | |
| 283 | else | |
| 284 | // No elements to infer from and no constraint pushed by | |
| 285 | // the surrounding context: fall back to an object | |
| 286 | // element type, the same as a literal whose elements | |
| 287 | // are all null. | |
| 288 | _logger.hint( | |
| 289 | sequence.location, | |
| 290 | "infer-object-from-list-literal", | |
| 291 | "list literal element type inferred as object", | |
| 292 | sequence.location, | |
| 293 | "help: give the literal an explicit type") | |
| 294 | ||
| 295 | type = _innate_symbol_lookup.get_object_type() | |
| 296 | fi | |
| 297 | else | |
| 298 | let seen_any mut = false | |
| 299 | let seen_error mut = false | |
| 300 | let all_tuple_literals mut = elements.count > 0 // assume all tuples until proved otherwise | |
| 301 | let tuples_element_count mut = -1 | |
| 302 | let any_tuple_argument_is_null mut = false | |
| 303 | let lub = LEAST_UPPER_BOUND_MAP() | |
| 304 | let seen_empty_literal mut = false | |
| 305 | ||
| 306 | for v in elements do | |
| 307 | // An empty literal with nothing around it to say what | |
| 308 | // it holds takes its type from its siblings, so it | |
| 309 | // stays out of their join and is re-walked at the | |
| 310 | // element type they settle on. | |
| 311 | if CONTEXTLESS_EMPTY_LITERAL.is_expression(v) then | |
| 312 | seen_empty_literal = true | |
| 313 | all_tuple_literals = false | |
| 314 | continue | |
| 315 | fi | |
| 316 | ||
| 317 | let is_tuple = | |
| 318 | v.is_tuple_literal \/ | |
| 319 | (v.value? /\ v.value.type? /\ (v.value.type.is_value_tuple \/ isa Semantic.Types.TUPLE(v.value.type)) /\ !v.value.type.is_optional) | |
| 320 | ||
| 321 | if !is_tuple then | |
| 322 | all_tuple_literals = false | |
| 323 | fi | |
| 324 | ||
| 325 | if let v.value? /\ value.type? then | |
| 326 | if value.check_is_consumable(_logger, v.location) then | |
| 327 | if value.type!.is_inferred then | |
| 328 | // A placeholder answers `is_null`, so it is | |
| 329 | // added to the join here, ahead of the null | |
| 330 | // literal's own handling. | |
| 331 | lub.add(value.type!) | |
| 332 | elif !value.type!.is_null then | |
| 333 | seen_any = true | |
| 334 | lub.add(value.type!) | |
| 335 | elif value.type!.is_error then | |
| 336 | seen_error = true | |
| 337 | fi | |
| 338 | ||
| 339 | if is_tuple then | |
| 340 | if tuples_element_count == -1 then | |
| 341 | tuples_element_count = value.type!.arguments.count | |
| 342 | elif value.type!.arguments.count != tuples_element_count then | |
| 343 | all_tuple_literals = false | |
| 344 | fi | |
| 345 | ||
| 346 | // `Types.NULL.matches` answers true against | |
| 347 | // any type, so a naive structural LUB over | |
| 348 | // the whole tuple types below judges a | |
| 349 | // `null`-carrying tuple argument position | |
| 350 | // "the same as" a value-carrying one at a | |
| 351 | // sibling element and picks one arbitrarily, | |
| 352 | // instead of widening that position to its | |
| 353 | // optional carrier. Route around the naive | |
| 354 | // LUB and straight to the per-position | |
| 355 | // TUPLE_ELEMENT_LUB whenever that can happen. | |
| 356 | if value.type!.arguments |> any(a => a.is_null) then | |
| 357 | any_tuple_argument_is_null = true | |
| 358 | fi | |
| 359 | fi | |
| 360 | else | |
| 361 | seen_error = true | |
| 362 | fi | |
| 363 | else | |
| 364 | seen_error = true | |
| 365 | fi | |
| 366 | od | |
| 367 | ||
| 368 | // With no sibling to take a type from, the empty literals | |
| 369 | // join as they are. | |
| 370 | if seen_empty_literal /\ !seen_any then | |
| 371 | for v in elements do | |
| 372 | if CONTEXTLESS_EMPTY_LITERAL.is_expression(v) /\ v.value? /\ v.value.type? then | |
| 373 | seen_any = true | |
| 374 | lub.add(v.value.type) | |
| 375 | fi | |
| 376 | od | |
| 377 | ||
| 378 | seen_empty_literal = false | |
| 379 | fi | |
| 380 | ||
| 381 | if !type? then | |
| 382 | type = lub.get_result() | |
| 383 | ||
| 384 | // The join waits for an element whose type is still | |
| 385 | // being inferred - a local assigned later in the body - | |
| 386 | // so the literal waits with it rather than settling | |
| 387 | // whatever it is assigned to at a type that element may | |
| 388 | // not fit. | |
| 389 | if type? /\ type.is_inferred /\ !constraint_type? then | |
| 390 | _logger.mark_consumed_any() | |
| 391 | _logger.error(sequence.location, "cannot infer type here") | |
| 392 | ||
| 393 | sequence.compile_expressions_state.value = DUMMY(_innate_symbol_lookup.get_array_type(Semantic.Types.ERROR()), sequence.location) | |
| 394 | return | |
| 395 | fi | |
| 396 | ||
| 397 | if all_tuple_literals /\ (!type? \/ !type.is_value_tuple \/ any_tuple_argument_is_null) then | |
| 398 | let tuple_types = Collections.LIST[Type]() | |
| 399 | ||
| 400 | for element in elements do | |
| 401 | if let element.value? /\ value.type? then | |
| 402 | tuple_types.add(value.type) | |
| 403 | fi | |
| 404 | od | |
| 405 | ||
| 406 | // The join builds a tuple of as many elements as | |
| 407 | // the widest element has, so an element that is | |
| 408 | // not a usable tuple - one already reported, or | |
| 409 | // one past the element limit - has no tuple type | |
| 410 | // to join into. The element's own diagnostic is | |
| 411 | // the one worth keeping. | |
| 412 | if | |
| 413 | tuple_types |> any(t => | |
| 414 | t.is_error \/ | |
| 415 | t.arguments.count == 0 \/ | |
| 416 | t.arguments.count > | |
| 417 | Semantic.Lookups.INNATE_TYPE_LIMITS.MAX_TUPLE_ELEMENTS) | |
| 418 | then | |
| 419 | sequence.compile_expressions_state.value = | |
| 420 | DUMMY(_innate_symbol_lookup.get_array_type(Semantic.Types.ERROR()), sequence.location) | |
| 421 | ||
| 422 | return | |
| 423 | fi | |
| 424 | ||
| 425 | type = Semantic.TUPLE_ELEMENT_LUB(_innate_symbol_lookup).combine(tuple_types, lub.element_names) | |
| 426 | ||
| 427 | let use retry_site = RETRY_SITE_STATS.enter("tuples.sequence_element_rewalk", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 428 | // going to walk the elements again, so roll back | |
| 429 | // and re-speculate to avoid duplicate / misleading | |
| 430 | // error messages | |
| 431 | _logger.roll_back() | |
| 432 | _logger.speculate() | |
| 433 | ||
| 434 | // re-walk the type expression if present, to avoid | |
| 435 | // hiding any error message it may generate | |
| 436 | ||
| 437 | sequence.type_expression.walk(_visitor) | |
| 438 | ||
| 439 | for e in sequence.elements do | |
| 440 | e.set_expected_type(type, "element type {{0}} not compatible with inferred list type {{1}}") | |
| 441 | _visitor.rewalk(e) | |
| 442 | od | |
| 443 | elif seen_empty_literal /\ type? /\ isa Semantic.Types.ARRAY(type) then | |
| 444 | let use retry_site = RETRY_SITE_STATS.enter("tuples.sequence_empty_element_rewalk", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 445 | ||
| 446 | _logger.roll_back() | |
| 447 | _logger.speculate() | |
| 448 | ||
| 449 | sequence.type_expression.walk(_visitor) | |
| 450 | ||
| 451 | for e in sequence.elements do | |
| 452 | e.set_expected_type(type, "element type {{0}} not compatible with inferred list type {{1}}") | |
| 453 | _visitor.rewalk(e) | |
| 454 | od | |
| 455 | fi | |
| 456 | fi | |
| 457 | ||
| 458 | // Reconcile bottom-up LUB with any constraint pushed | |
| 459 | // by the parent context. Prefer the more-specific | |
| 460 | // bottom-up type when it satisfies the constraint — | |
| 461 | // that preserves the runtime allocation precision the | |
| 462 | // covariance idiom relies on (e.g. `let ao: object[] | |
| 463 | // = ["a", "b"];` should produce a string[] at run | |
| 464 | // time, even though the variable is declared | |
| 465 | // object[]). When the LUB doesn't satisfy the | |
| 466 | // constraint, fall back to the constraint's element | |
| 467 | // type and drive per-element mismatch errors via the | |
| 468 | // post-walk assignability check. | |
| 469 | if constraint_type? then | |
| 470 | if !type? \/ !constraint_type.is_assignable_from(type) then | |
| 471 | type = constraint_type | |
| 472 | have_explicit_type = true | |
| 473 | fi | |
| 474 | fi | |
| 475 | ||
| 476 | if !type? then | |
| 477 | if seen_error then | |
| 478 | sequence.compile_expressions_state.value = DUMMY(_innate_symbol_lookup.get_array_type(Semantic.Types.ERROR()), sequence.location) | |
| 479 | return | |
| 480 | elif seen_any then | |
| 481 | _logger.hint( | |
| 482 | sequence.location, | |
| 483 | "infer-object-from-list-literal", | |
| 484 | "list literal element type inferred as object", | |
| 485 | sequence.location, | |
| 486 | "help: give the literal an explicit type") | |
| 487 | type = _innate_symbol_lookup.get_object_type() | |
| 488 | else | |
| 489 | _logger.error(sequence.location, "cannot infer type of list literal with only null elements") | |
| 490 | ||
| 491 | sequence.compile_expressions_state.value = DUMMY(_innate_symbol_lookup.get_array_type(Semantic.Types.ERROR()), sequence.location) | |
| 492 | return | |
| 493 | fi | |
| 494 | fi | |
| 495 | fi | |
| 496 | ||
| 497 | let values = Collections.LIST[Value](sequence.elements.expressions.count) | |
| 498 | ||
| 499 | for v in sequence.elements do | |
| 500 | if let v.value? /\ value.type? then | |
| 501 | let u = value.type | |
| 502 | ||
| 503 | // An element whose own type is still being inferred - a | |
| 504 | // local the body types from its uses - is one of those | |
| 505 | // uses, so the element type the literal settled on is | |
| 506 | // pushed back to it as a bound. The propagation recurses | |
| 507 | // into generic arguments, so an element with a | |
| 508 | // placeholder anywhere inside it is one to push into. | |
| 509 | if u.contains_inferred then | |
| 510 | _match_propagator.propagate_match(type, u) | |
| 511 | ||
| 512 | values.add(v.value!) | |
| 513 | ||
| 514 | continue | |
| 515 | fi | |
| 516 | ||
| 517 | // FIXME should push explicit type into element as constraint and retry | |
| 518 | if have_explicit_type /\ !type.is_assignable_from(u) then | |
| 519 | _logger.error(v.location, "element not compatible with explicit type") | |
| 520 | fi | |
| 521 | ||
| 522 | values.add(v.value!) | |
| 523 | else | |
| 524 | values.add(DUMMY(Semantic.Types.ERROR(), v.location)) | |
| 525 | fi | |
| 526 | od | |
| 527 | ||
| 528 | sequence.compile_expressions_state.value = | |
| 529 | SEQUENCE(_innate_symbol_lookup.get_array_type(type), type, values) | |
| 530 | si | |
| 531 | si | |
| 532 | si |